1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* BGP routing information
3 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
4 * Copyright (C) 2016 Job Snijders <job@instituut.net>
21 #include "sockunion.h"
24 #include "workqueue.h"
29 #include "lib_errors.h"
31 #include "bgpd/bgpd.h"
32 #include "bgpd/bgp_table.h"
33 #include "bgpd/bgp_route.h"
34 #include "bgpd/bgp_attr.h"
35 #include "bgpd/bgp_debug.h"
36 #include "bgpd/bgp_errors.h"
37 #include "bgpd/bgp_aspath.h"
38 #include "bgpd/bgp_regex.h"
39 #include "bgpd/bgp_community.h"
40 #include "bgpd/bgp_community_alias.h"
41 #include "bgpd/bgp_ecommunity.h"
42 #include "bgpd/bgp_lcommunity.h"
43 #include "bgpd/bgp_clist.h"
44 #include "bgpd/bgp_packet.h"
45 #include "bgpd/bgp_filter.h"
46 #include "bgpd/bgp_fsm.h"
47 #include "bgpd/bgp_mplsvpn.h"
48 #include "bgpd/bgp_nexthop.h"
49 #include "bgpd/bgp_damp.h"
50 #include "bgpd/bgp_advertise.h"
51 #include "bgpd/bgp_zebra.h"
52 #include "bgpd/bgp_vty.h"
53 #include "bgpd/bgp_mpath.h"
54 #include "bgpd/bgp_nht.h"
55 #include "bgpd/bgp_updgrp.h"
56 #include "bgpd/bgp_label.h"
57 #include "bgpd/bgp_addpath.h"
58 #include "bgpd/bgp_mac.h"
59 #include "bgpd/bgp_network.h"
60 #include "bgpd/bgp_trace.h"
61 #include "bgpd/bgp_rpki.h"
64 #include "bgpd/rfapi/rfapi_backend.h"
65 #include "bgpd/rfapi/vnc_import_bgp.h"
66 #include "bgpd/rfapi/vnc_export_bgp.h"
68 #include "bgpd/bgp_encap_types.h"
69 #include "bgpd/bgp_encap_tlv.h"
70 #include "bgpd/bgp_evpn.h"
71 #include "bgpd/bgp_evpn_mh.h"
72 #include "bgpd/bgp_evpn_vty.h"
73 #include "bgpd/bgp_flowspec.h"
74 #include "bgpd/bgp_flowspec_util.h"
75 #include "bgpd/bgp_pbr.h"
77 #include "bgpd/bgp_route_clippy.c"
79 DEFINE_HOOK(bgp_snmp_update_stats
,
80 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
83 DEFINE_HOOK(bgp_rpki_prefix_status
,
84 (struct peer
*peer
, struct attr
*attr
,
85 const struct prefix
*prefix
),
86 (peer
, attr
, prefix
));
88 /* Extern from bgp_dump.c */
89 extern const char *bgp_origin_str
[];
90 extern const char *bgp_origin_long_str
[];
93 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
94 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
95 static const struct message bgp_pmsi_tnltype_str
[] = {
96 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
97 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
98 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
99 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
100 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
101 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
102 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
103 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
107 #define VRFID_NONE_STR "-"
108 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
110 DEFINE_HOOK(bgp_process
,
111 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
112 struct peer
*peer
, bool withdraw
),
113 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
115 /** Test if path is suppressed. */
116 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
118 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
121 return listcount(pi
->extra
->aggr_suppressors
) > 0;
124 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
125 safi_t safi
, const struct prefix
*p
,
126 struct prefix_rd
*prd
)
128 struct bgp_dest
*dest
;
129 struct bgp_dest
*pdest
= NULL
;
133 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
134 || (safi
== SAFI_EVPN
)) {
135 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
137 if (!bgp_dest_has_bgp_path_info_data(pdest
))
138 bgp_dest_set_bgp_table_info(
139 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
141 bgp_dest_unlock_node(pdest
);
142 table
= bgp_dest_get_bgp_table_info(pdest
);
145 dest
= bgp_node_get(table
, p
);
147 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
148 || (safi
== SAFI_EVPN
))
154 struct bgp_dest
*bgp_safi_node_lookup(struct bgp_table
*table
, safi_t safi
,
155 const struct prefix
*p
,
156 struct prefix_rd
*prd
)
158 struct bgp_dest
*dest
;
159 struct bgp_dest
*pdest
= NULL
;
164 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
165 || (safi
== SAFI_EVPN
)) {
166 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
170 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
171 bgp_dest_unlock_node(pdest
);
175 table
= bgp_dest_get_bgp_table_info(pdest
);
178 dest
= bgp_node_lookup(table
, p
);
183 /* Allocate bgp_path_info_extra */
184 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
186 struct bgp_path_info_extra
*new;
187 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
188 sizeof(struct bgp_path_info_extra
));
189 new->label
[0] = MPLS_INVALID_LABEL
;
191 new->bgp_fs_pbr
= NULL
;
192 new->bgp_fs_iprule
= NULL
;
196 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
198 struct bgp_path_info_extra
*e
;
200 if (!extra
|| !*extra
)
205 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
210 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
213 /* FIXME: since multiple e may have the same e->parent
214 * and e->parent->net is holding a refcount for each
215 * of them, we need to do some fudging here.
217 * WARNING: if bpi->net->lock drops to 0, bpi may be
218 * freed as well (because bpi->net was holding the
219 * last reference to bpi) => write after free!
223 bpi
= bgp_path_info_lock(bpi
);
224 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
225 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
228 bgp_path_info_unlock(bpi
);
230 bgp_path_info_unlock(e
->parent
);
235 bgp_unlock(e
->bgp_orig
);
238 peer_unlock(e
->peer_orig
);
240 if (e
->aggr_suppressors
)
241 list_delete(&e
->aggr_suppressors
);
244 bgp_evpn_path_mh_info_free(e
->mh_info
);
246 if ((*extra
)->bgp_fs_iprule
)
247 list_delete(&((*extra
)->bgp_fs_iprule
));
248 if ((*extra
)->bgp_fs_pbr
)
249 list_delete(&((*extra
)->bgp_fs_pbr
));
250 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
253 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
254 * allocated if required.
256 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
259 pi
->extra
= bgp_path_info_extra_new();
263 /* Free bgp route information. */
264 void bgp_path_info_free_with_caller(const char *name
,
265 struct bgp_path_info
*path
)
267 frrtrace(2, frr_bgp
, bgp_path_info_free
, path
, name
);
268 bgp_attr_unintern(&path
->attr
);
270 bgp_unlink_nexthop(path
);
271 bgp_path_info_extra_free(&path
->extra
);
272 bgp_path_info_mpath_free(&path
->mpath
);
274 bgp_addpath_free_info_data(&path
->tx_addpath
,
275 &path
->net
->tx_addpath
);
277 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
279 XFREE(MTYPE_BGP_ROUTE
, path
);
282 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
288 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
290 assert(path
&& path
->lock
> 0);
293 if (path
->lock
== 0) {
294 bgp_path_info_free(path
);
301 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
302 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
305 struct bgp_path_info
*old_pi
, *nextpi
;
306 bool set_flag
= false;
307 struct bgp
*bgp
= NULL
;
308 struct bgp_table
*table
= NULL
;
312 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
313 * then the route selection is deferred
315 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
318 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
319 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
320 table
= bgp_dest_table(dest
);
325 "Route %pBD(%s) is in workqueue and being processed, not deferred.",
326 dest
, bgp
? bgp
->name_pretty
: "(Unknown)");
332 table
= bgp_dest_table(dest
);
339 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
340 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
341 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
344 /* Route selection is deferred if there is a stale path which
345 * which indicates peer is in restart mode
347 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
348 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
351 /* If the peer is graceful restart capable and peer is
352 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
355 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
356 && BGP_PEER_RESTARTING_MODE(peer
)
358 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
366 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
369 if (set_flag
&& table
) {
370 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
371 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
372 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
373 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
374 if (BGP_DEBUG(update
, UPDATE_OUT
))
375 zlog_debug("DEFER route %pBD(%s), dest %p",
376 dest
, bgp
->name_pretty
, dest
);
383 void bgp_path_info_add_with_caller(const char *name
, struct bgp_dest
*dest
,
384 struct bgp_path_info
*pi
)
386 frrtrace(3, frr_bgp
, bgp_path_info_add
, dest
, pi
, name
);
387 struct bgp_path_info
*top
;
389 top
= bgp_dest_get_bgp_path_info(dest
);
395 bgp_dest_set_bgp_path_info(dest
, pi
);
397 bgp_path_info_lock(pi
);
398 bgp_dest_lock_node(dest
);
399 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
400 bgp_dest_set_defer_flag(dest
, false);
401 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
404 /* Do the actual removal of info from RIB, for use by bgp_process
405 completion callback *only* */
406 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
409 pi
->next
->prev
= pi
->prev
;
411 pi
->prev
->next
= pi
->next
;
413 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
415 bgp_path_info_mpath_dequeue(pi
);
416 bgp_path_info_unlock(pi
);
417 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
418 bgp_dest_unlock_node(dest
);
421 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
423 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
424 /* set of previous already took care of pcount */
425 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
428 /* undo the effects of a previous call to bgp_path_info_delete; typically
429 called when a route is deleted and then quickly re-added before the
430 deletion has been processed */
431 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
433 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
434 /* unset of previous already took care of pcount */
435 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
438 /* Adjust pcount as required */
439 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
441 struct bgp_table
*table
;
443 assert(dest
&& bgp_dest_table(dest
));
444 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
446 table
= bgp_dest_table(dest
);
448 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
451 if (!BGP_PATH_COUNTABLE(pi
)
452 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
454 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
456 /* slight hack, but more robust against errors. */
457 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
458 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
460 flog_err(EC_LIB_DEVELOPMENT
,
461 "Asked to decrement 0 prefix count for peer");
462 } else if (BGP_PATH_COUNTABLE(pi
)
463 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
464 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
465 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
469 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
470 struct bgp_path_info
*pi2
)
472 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
475 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
476 * This is here primarily to keep prefix-count in check.
478 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
481 SET_FLAG(pi
->flags
, flag
);
483 /* early bath if we know it's not a flag that changes countability state
485 if (!CHECK_FLAG(flag
,
486 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
489 bgp_pcount_adjust(dest
, pi
);
492 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
495 UNSET_FLAG(pi
->flags
, flag
);
497 /* early bath if we know it's not a flag that changes countability state
499 if (!CHECK_FLAG(flag
,
500 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
503 bgp_pcount_adjust(dest
, pi
);
506 /* Get MED value. If MED value is missing and "bgp bestpath
507 missing-as-worst" is specified, treat it as the worst value. */
508 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
510 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
513 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
520 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
525 if (pi
->sub_type
== BGP_ROUTE_IMPORTED
&&
526 bgp_get_imported_bpi_ultimate(pi
))
527 peer
= bgp_get_imported_bpi_ultimate(pi
)->peer
;
531 if (pi
->addpath_rx_id
)
532 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)", peer
->host
,
535 snprintf(buf
, buf_len
, "path %s", peer
->host
);
540 * Get the ultimate path info.
542 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
544 struct bgp_path_info
*bpi_ultimate
;
546 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
549 for (bpi_ultimate
= info
;
550 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
551 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
557 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
559 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
560 struct bgp_path_info
*exist
, int *paths_eq
,
561 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
562 char *pfx_buf
, afi_t afi
, safi_t safi
,
563 enum bgp_path_selection_reason
*reason
)
565 const struct prefix
*new_p
;
566 struct attr
*newattr
, *existattr
;
567 enum bgp_peer_sort new_sort
;
568 enum bgp_peer_sort exist_sort
;
574 uint32_t exist_weight
;
575 uint32_t newm
, existm
;
576 struct in_addr new_id
;
577 struct in_addr exist_id
;
580 int internal_as_route
;
583 int igp_metric_ret
= 0;
584 int peer_sort_ret
= -1;
585 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
586 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
588 uint32_t exist_mm_seq
;
595 bool new_origin
, exist_origin
;
596 struct bgp_path_info
*bpi_ultimate
;
597 struct peer
*peer_new
, *peer_exist
;
603 *reason
= bgp_path_selection_none
;
605 zlog_debug("%s: new is NULL", pfx_buf
);
610 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
616 *reason
= bgp_path_selection_first
;
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf
, bgp
->name_pretty
, new_buf
);
624 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
629 exist_buf
, exist
->flags
);
633 existattr
= exist
->attr
;
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
644 if (bgp_attr_get_community(newattr
) &&
645 community_include(bgp_attr_get_community(newattr
),
646 COMMUNITY_LLGR_STALE
)) {
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf
, new_buf
, exist_buf
);
654 if (bgp_attr_get_community(existattr
) &&
655 community_include(bgp_attr_get_community(existattr
),
656 COMMUNITY_LLGR_STALE
)) {
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf
, new_buf
, exist_buf
);
664 new_p
= bgp_dest_get_prefix(new->net
);
666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
669 if ((safi
== SAFI_EVPN
)
670 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
671 /* This is an error condition described in RFC 7432 Section
673 * states that in this scenario "the PE MUST alert the operator"
675 * does not state what other action to take. In order to provide
677 * consistency in this scenario we are going to prefer the path
681 if (newattr
->sticky
!= existattr
->sticky
) {
683 prefix2str(new_p
, pfx_buf
,
685 * PREFIX2STR_BUFFER
);
686 bgp_path_info_path_with_addpath_rx_str(
687 new, new_buf
, sizeof(new_buf
));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist
, exist_buf
, sizeof(exist_buf
));
692 if (newattr
->sticky
&& !existattr
->sticky
) {
693 *reason
= bgp_path_selection_evpn_sticky_mac
;
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf
, new_buf
, exist_buf
);
701 if (!newattr
->sticky
&& existattr
->sticky
) {
702 *reason
= bgp_path_selection_evpn_sticky_mac
;
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf
, new_buf
, exist_buf
);
711 new_esi
= bgp_evpn_attr_get_esi(newattr
);
712 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
713 if (bgp_evpn_is_esi_valid(new_esi
) &&
714 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
728 char esi_buf
[ESI_STR_LEN
];
730 if (bgp_evpn_is_path_local(bgp
, new)) {
731 *reason
= bgp_path_selection_evpn_local_path
;
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf
, new_buf
, exist_buf
,
736 esi_to_str(new_esi
, esi_buf
,
740 if (bgp_evpn_is_path_local(bgp
, exist
)) {
741 *reason
= bgp_path_selection_evpn_local_path
;
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf
, new_buf
, exist_buf
,
746 esi_to_str(new_esi
, esi_buf
,
752 new_mm_seq
= mac_mobility_seqnum(newattr
);
753 exist_mm_seq
= mac_mobility_seqnum(existattr
);
755 if (new_mm_seq
> exist_mm_seq
) {
756 *reason
= bgp_path_selection_evpn_seq
;
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
765 if (new_mm_seq
< exist_mm_seq
) {
766 *reason
= bgp_path_selection_evpn_seq
;
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
778 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
779 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
780 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
781 old_proxy
!= new_proxy
) {
783 *reason
= bgp_path_selection_evpn_non_proxy
;
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf
, new_buf
, exist_buf
);
791 *reason
= bgp_path_selection_evpn_non_proxy
;
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf
, new_buf
, exist_buf
);
800 * if sequence numbers are the same path with the lowest IP
803 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
805 *reason
= bgp_path_selection_evpn_lower_ip
;
808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
809 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
810 &new->attr
->nexthop
);
814 *reason
= bgp_path_selection_evpn_lower_ip
;
817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
818 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
819 &new->attr
->nexthop
);
824 /* 1. Weight check. */
825 new_weight
= newattr
->weight
;
826 exist_weight
= existattr
->weight
;
828 if (new_weight
> exist_weight
) {
829 *reason
= bgp_path_selection_weight
;
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf
, new_buf
, exist_buf
, new_weight
,
837 if (new_weight
< exist_weight
) {
838 *reason
= bgp_path_selection_weight
;
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf
, new_buf
, exist_buf
, new_weight
,
846 /* 2. Local preference check. */
847 new_pref
= exist_pref
= bgp
->default_local_pref
;
849 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
850 new_pref
= newattr
->local_pref
;
851 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
852 exist_pref
= existattr
->local_pref
;
854 if (new_pref
> exist_pref
) {
855 *reason
= bgp_path_selection_local_pref
;
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf
, new_buf
, exist_buf
, new_pref
,
864 if (new_pref
< exist_pref
) {
865 *reason
= bgp_path_selection_local_pref
;
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf
, new_buf
, exist_buf
, new_pref
,
874 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
875 * extensions defined in this document, the following step is inserted
876 * after the LOCAL_PREF comparison step in the BGP decision process:
877 * When comparing a pair of routes for a BGP destination, the
878 * route with the ACCEPT_OWN community attached is preferred over
879 * the route that does not have the community.
880 * This extra step MUST only be invoked during the best path selection
881 * process of VPN-IP routes.
883 if (safi
== SAFI_MPLS_VPN
&&
884 (CHECK_FLAG(new->peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
) ||
885 CHECK_FLAG(exist
->peer
->af_flags
[afi
][safi
],
886 PEER_FLAG_ACCEPT_OWN
))) {
887 bool new_accept_own
= false;
888 bool exist_accept_own
= false;
889 uint32_t accept_own
= COMMUNITY_ACCEPT_OWN
;
891 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
892 new_accept_own
= community_include(
893 bgp_attr_get_community(newattr
), accept_own
);
894 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
895 exist_accept_own
= community_include(
896 bgp_attr_get_community(existattr
), accept_own
);
898 if (new_accept_own
&& !exist_accept_own
) {
899 *reason
= bgp_path_selection_accept_own
;
902 "%s: %s wins over %s due to accept-own",
903 pfx_buf
, new_buf
, exist_buf
);
907 if (!new_accept_own
&& exist_accept_own
) {
908 *reason
= bgp_path_selection_accept_own
;
911 "%s: %s loses to %s due to accept-own",
912 pfx_buf
, new_buf
, exist_buf
);
917 /* Tie-breaker - AIGP (Metric TLV) attribute */
918 if (CHECK_FLAG(newattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
919 CHECK_FLAG(existattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
920 CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_AIGP
)) {
921 uint64_t new_aigp
= bgp_attr_get_aigp_metric(newattr
);
922 uint64_t exist_aigp
= bgp_attr_get_aigp_metric(existattr
);
924 if (new_aigp
< exist_aigp
) {
925 *reason
= bgp_path_selection_aigp
;
928 "%s: %s wins over %s due to AIGP %" PRIu64
930 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
935 if (new_aigp
> exist_aigp
) {
936 *reason
= bgp_path_selection_aigp
;
939 "%s: %s loses to %s due to AIGP %" PRIu64
941 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
947 /* 3. Local route check. We prefer:
949 * - BGP_ROUTE_AGGREGATE
950 * - BGP_ROUTE_REDISTRIBUTE
952 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
953 new->sub_type
== BGP_ROUTE_IMPORTED
);
954 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
955 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
957 if (new_origin
&& !exist_origin
) {
958 *reason
= bgp_path_selection_local_route
;
961 "%s: %s wins over %s due to preferred BGP_ROUTE type",
962 pfx_buf
, new_buf
, exist_buf
);
966 if (!new_origin
&& exist_origin
) {
967 *reason
= bgp_path_selection_local_route
;
970 "%s: %s loses to %s due to preferred BGP_ROUTE type",
971 pfx_buf
, new_buf
, exist_buf
);
975 /* Here if these are imported routes then get ultimate pi for
978 new = bgp_get_imported_bpi_ultimate(new);
979 exist
= bgp_get_imported_bpi_ultimate(exist
);
981 existattr
= exist
->attr
;
983 /* 4. AS path length check. */
984 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
985 int exist_hops
= aspath_count_hops(existattr
->aspath
);
986 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
988 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
991 aspath_hops
= aspath_count_hops(newattr
->aspath
);
992 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
994 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
995 *reason
= bgp_path_selection_confed_as_path
;
998 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
999 pfx_buf
, new_buf
, exist_buf
,
1001 (exist_hops
+ exist_confeds
));
1005 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
1006 *reason
= bgp_path_selection_confed_as_path
;
1009 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1010 pfx_buf
, new_buf
, exist_buf
,
1012 (exist_hops
+ exist_confeds
));
1016 int newhops
= aspath_count_hops(newattr
->aspath
);
1018 if (newhops
< exist_hops
) {
1019 *reason
= bgp_path_selection_as_path
;
1022 "%s: %s wins over %s due to aspath hopcount %d < %d",
1023 pfx_buf
, new_buf
, exist_buf
,
1024 newhops
, exist_hops
);
1028 if (newhops
> exist_hops
) {
1029 *reason
= bgp_path_selection_as_path
;
1032 "%s: %s loses to %s due to aspath hopcount %d > %d",
1033 pfx_buf
, new_buf
, exist_buf
,
1034 newhops
, exist_hops
);
1040 /* 5. Origin check. */
1041 if (newattr
->origin
< existattr
->origin
) {
1042 *reason
= bgp_path_selection_origin
;
1044 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1045 pfx_buf
, new_buf
, exist_buf
,
1046 bgp_origin_long_str
[newattr
->origin
],
1047 bgp_origin_long_str
[existattr
->origin
]);
1051 if (newattr
->origin
> existattr
->origin
) {
1052 *reason
= bgp_path_selection_origin
;
1054 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1055 pfx_buf
, new_buf
, exist_buf
,
1056 bgp_origin_long_str
[newattr
->origin
],
1057 bgp_origin_long_str
[existattr
->origin
]);
1062 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
1063 && aspath_count_hops(existattr
->aspath
) == 0);
1064 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
1065 && aspath_count_confeds(existattr
->aspath
) > 0
1066 && aspath_count_hops(newattr
->aspath
) == 0
1067 && aspath_count_hops(existattr
->aspath
) == 0);
1069 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1070 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1071 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1072 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1073 || internal_as_route
) {
1074 new_med
= bgp_med_value(new->attr
, bgp
);
1075 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1077 if (new_med
< exist_med
) {
1078 *reason
= bgp_path_selection_med
;
1081 "%s: %s wins over %s due to MED %d < %d",
1082 pfx_buf
, new_buf
, exist_buf
, new_med
,
1087 if (new_med
> exist_med
) {
1088 *reason
= bgp_path_selection_med
;
1091 "%s: %s loses to %s due to MED %d > %d",
1092 pfx_buf
, new_buf
, exist_buf
, new_med
,
1098 if (exist
->sub_type
== BGP_ROUTE_IMPORTED
) {
1099 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
1100 peer_exist
= bpi_ultimate
->peer
;
1102 peer_exist
= exist
->peer
;
1104 if (new->sub_type
== BGP_ROUTE_IMPORTED
) {
1105 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
1106 peer_new
= bpi_ultimate
->peer
;
1108 peer_new
= new->peer
;
1110 /* 7. Peer type check. */
1111 new_sort
= peer_new
->sort
;
1112 exist_sort
= peer_exist
->sort
;
1114 if (new_sort
== BGP_PEER_EBGP
1115 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1116 *reason
= bgp_path_selection_peer
;
1119 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1120 pfx_buf
, new_buf
, exist_buf
);
1121 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1126 if (exist_sort
== BGP_PEER_EBGP
1127 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1128 *reason
= bgp_path_selection_peer
;
1131 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1132 pfx_buf
, new_buf
, exist_buf
);
1133 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1138 /* 8. IGP metric check. */
1142 newm
= new->extra
->igpmetric
;
1144 existm
= exist
->extra
->igpmetric
;
1146 if (newm
< existm
) {
1147 if (debug
&& peer_sort_ret
< 0)
1149 "%s: %s wins over %s due to IGP metric %u < %u",
1150 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1154 if (newm
> existm
) {
1155 if (debug
&& peer_sort_ret
< 0)
1157 "%s: %s loses to %s due to IGP metric %u > %u",
1158 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1162 /* 9. Same IGP metric. Compare the cluster list length as
1163 representative of IGP hops metric. Rewrite the metric value
1164 pair (newm, existm) with the cluster list length. Prefer the
1165 path with smaller cluster list length. */
1166 if (newm
== existm
) {
1167 if (peer_sort_lookup(peer_new
) == BGP_PEER_IBGP
&&
1168 peer_sort_lookup(peer_exist
) == BGP_PEER_IBGP
&&
1169 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1170 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1171 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1173 if (newm
< existm
) {
1174 if (debug
&& peer_sort_ret
< 0)
1176 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1177 pfx_buf
, new_buf
, exist_buf
,
1182 if (newm
> existm
) {
1183 if (debug
&& peer_sort_ret
< 0)
1185 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1186 pfx_buf
, new_buf
, exist_buf
,
1193 /* 10. confed-external vs. confed-internal */
1194 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1195 if (new_sort
== BGP_PEER_CONFED
1196 && exist_sort
== BGP_PEER_IBGP
) {
1197 *reason
= bgp_path_selection_confed
;
1200 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1201 pfx_buf
, new_buf
, exist_buf
);
1202 if (!CHECK_FLAG(bgp
->flags
,
1203 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1208 if (exist_sort
== BGP_PEER_CONFED
1209 && new_sort
== BGP_PEER_IBGP
) {
1210 *reason
= bgp_path_selection_confed
;
1213 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1214 pfx_buf
, new_buf
, exist_buf
);
1215 if (!CHECK_FLAG(bgp
->flags
,
1216 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1222 /* 11. Maximum path check. */
1223 if (newm
== existm
) {
1224 /* If one path has a label but the other does not, do not treat
1225 * them as equals for multipath
1232 newl
= new->extra
->num_labels
;
1234 existl
= exist
->extra
->num_labels
;
1235 if (((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0])) !=
1237 bgp_is_valid_label(&exist
->extra
->label
[0]))) ||
1241 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1242 pfx_buf
, new_buf
, exist_buf
);
1243 } else if (CHECK_FLAG(bgp
->flags
,
1244 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1247 * For the two paths, all comparison steps till IGP
1249 * have succeeded - including AS_PATH hop count. Since
1251 * bestpath as-path multipath-relax' knob is on, we
1253 * an exact match of AS_PATH. Thus, mark the paths are
1255 * That will trigger both these paths to get into the
1263 "%s: %s and %s are equal via multipath-relax",
1264 pfx_buf
, new_buf
, exist_buf
);
1265 } else if (peer_new
->sort
== BGP_PEER_IBGP
) {
1266 if (aspath_cmp(new->attr
->aspath
,
1267 exist
->attr
->aspath
)) {
1272 "%s: %s and %s are equal via matching aspaths",
1273 pfx_buf
, new_buf
, exist_buf
);
1275 } else if (peer_new
->as
== peer_exist
->as
) {
1280 "%s: %s and %s are equal via same remote-as",
1281 pfx_buf
, new_buf
, exist_buf
);
1285 * TODO: If unequal cost ibgp multipath is enabled we can
1286 * mark the paths as equal here instead of returning
1289 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1290 * if either step 7 or 10 (peer type checks) yielded a winner,
1291 * that result was returned immediately. Returning from step 10
1292 * ignored the return value computed in steps 8 and 9 (IGP
1293 * metric checks). In order to preserve that behavior, if
1294 * peer_sort_ret is set, return that rather than igp_metric_ret.
1296 ret
= peer_sort_ret
;
1297 if (peer_sort_ret
< 0) {
1298 ret
= igp_metric_ret
;
1302 "%s: %s wins over %s after IGP metric comparison",
1303 pfx_buf
, new_buf
, exist_buf
);
1306 "%s: %s loses to %s after IGP metric comparison",
1307 pfx_buf
, new_buf
, exist_buf
);
1309 *reason
= bgp_path_selection_igp_metric
;
1315 * At this point, the decision whether to set *paths_eq = 1 has been
1316 * completed. If we deferred returning because of bestpath peer-type
1317 * relax configuration, return now.
1319 if (peer_sort_ret
>= 0)
1320 return peer_sort_ret
;
1322 /* 12. If both paths are external, prefer the path that was received
1323 first (the oldest one). This step minimizes route-flap, since a
1324 newer path won't displace an older one, even if it was the
1325 preferred route based on the additional decision criteria below. */
1326 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1327 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1328 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1329 *reason
= bgp_path_selection_older
;
1332 "%s: %s wins over %s due to oldest external",
1333 pfx_buf
, new_buf
, exist_buf
);
1337 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1338 *reason
= bgp_path_selection_older
;
1341 "%s: %s loses to %s due to oldest external",
1342 pfx_buf
, new_buf
, exist_buf
);
1347 /* 13. Router-ID comparison. */
1348 /* If one of the paths is "stale", the corresponding peer router-id will
1349 * be 0 and would always win over the other path. If originator id is
1350 * used for the comparison, it will decide which path is better.
1352 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1353 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1355 new_id
.s_addr
= peer_new
->remote_id
.s_addr
;
1356 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1357 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1359 exist_id
.s_addr
= peer_exist
->remote_id
.s_addr
;
1361 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1362 *reason
= bgp_path_selection_router_id
;
1365 "%s: %s wins over %s due to Router-ID comparison",
1366 pfx_buf
, new_buf
, exist_buf
);
1370 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1371 *reason
= bgp_path_selection_router_id
;
1374 "%s: %s loses to %s due to Router-ID comparison",
1375 pfx_buf
, new_buf
, exist_buf
);
1379 /* 14. Cluster length comparison. */
1380 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1381 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1383 if (new_cluster
< exist_cluster
) {
1384 *reason
= bgp_path_selection_cluster_length
;
1387 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1388 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1393 if (new_cluster
> exist_cluster
) {
1394 *reason
= bgp_path_selection_cluster_length
;
1397 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1398 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1403 /* 15. Neighbor address comparison. */
1404 /* Do this only if neither path is "stale" as stale paths do not have
1405 * valid peer information (as the connection may or may not be up).
1407 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1408 *reason
= bgp_path_selection_stale
;
1411 "%s: %s wins over %s due to latter path being STALE",
1412 pfx_buf
, new_buf
, exist_buf
);
1416 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1417 *reason
= bgp_path_selection_stale
;
1420 "%s: %s loses to %s due to former path being STALE",
1421 pfx_buf
, new_buf
, exist_buf
);
1425 /* locally configured routes to advertise do not have su_remote */
1426 if (peer_new
->su_remote
== NULL
) {
1427 *reason
= bgp_path_selection_local_configured
;
1431 if (peer_exist
->su_remote
== NULL
) {
1432 *reason
= bgp_path_selection_local_configured
;
1436 ret
= sockunion_cmp(peer_new
->su_remote
, peer_exist
->su_remote
);
1439 *reason
= bgp_path_selection_neighbor_ip
;
1442 "%s: %s loses to %s due to Neighor IP comparison",
1443 pfx_buf
, new_buf
, exist_buf
);
1448 *reason
= bgp_path_selection_neighbor_ip
;
1451 "%s: %s wins over %s due to Neighor IP comparison",
1452 pfx_buf
, new_buf
, exist_buf
);
1456 *reason
= bgp_path_selection_default
;
1458 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1459 pfx_buf
, new_buf
, exist_buf
);
1465 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1466 struct bgp_path_info
*exist
, int *paths_eq
)
1468 enum bgp_path_selection_reason reason
;
1469 char pfx_buf
[PREFIX2STR_BUFFER
];
1471 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1472 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1475 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1476 * is preferred, or 0 if they are the same (usually will only occur if
1477 * multipath is enabled
1478 * This version is compatible with */
1479 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1480 struct bgp_path_info
*exist
, char *pfx_buf
,
1481 afi_t afi
, safi_t safi
,
1482 enum bgp_path_selection_reason
*reason
)
1486 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1500 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1501 const struct prefix
*p
,
1502 struct attr
*attr
, afi_t afi
,
1505 struct bgp_filter
*filter
;
1506 enum filter_type ret
= FILTER_PERMIT
;
1508 filter
= &peer
->filter
[afi
][safi
];
1510 #define FILTER_EXIST_WARN(F, f, filter) \
1511 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1512 zlog_debug("%s: Could not find configured input %s-list %s!", \
1513 peer->host, #f, F##_IN_NAME(filter));
1515 if (DISTRIBUTE_IN_NAME(filter
)) {
1516 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1518 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1525 if (PREFIX_LIST_IN_NAME(filter
)) {
1526 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1528 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1535 if (FILTER_LIST_IN_NAME(filter
)) {
1536 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1538 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1539 == AS_FILTER_DENY
) {
1546 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1547 char pfxprint
[PREFIX2STR_BUFFER
];
1549 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1550 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1551 ret
== FILTER_PERMIT
? "permit" : "deny");
1555 #undef FILTER_EXIST_WARN
1558 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1559 const struct prefix
*p
,
1560 struct attr
*attr
, afi_t afi
,
1563 struct bgp_filter
*filter
;
1564 enum filter_type ret
= FILTER_PERMIT
;
1566 filter
= &peer
->filter
[afi
][safi
];
1568 #define FILTER_EXIST_WARN(F, f, filter) \
1569 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1570 zlog_debug("%s: Could not find configured output %s-list %s!", \
1571 peer->host, #f, F##_OUT_NAME(filter));
1573 if (DISTRIBUTE_OUT_NAME(filter
)) {
1574 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1576 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1583 if (PREFIX_LIST_OUT_NAME(filter
)) {
1584 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1586 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1593 if (FILTER_LIST_OUT_NAME(filter
)) {
1594 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1596 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1597 == AS_FILTER_DENY
) {
1603 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1604 char pfxprint
[PREFIX2STR_BUFFER
];
1606 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1607 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1608 ret
== FILTER_PERMIT
? "permit" : "deny");
1613 #undef FILTER_EXIST_WARN
1616 /* If community attribute includes no_export then return 1. */
1617 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1619 if (bgp_attr_get_community(attr
)) {
1620 /* NO_ADVERTISE check. */
1621 if (community_include(bgp_attr_get_community(attr
),
1622 COMMUNITY_NO_ADVERTISE
))
1625 /* NO_EXPORT check. */
1626 if (peer
->sort
== BGP_PEER_EBGP
&&
1627 community_include(bgp_attr_get_community(attr
),
1628 COMMUNITY_NO_EXPORT
))
1631 /* NO_EXPORT_SUBCONFED check. */
1632 if (peer
->sort
== BGP_PEER_EBGP
1633 || peer
->sort
== BGP_PEER_CONFED
)
1634 if (community_include(bgp_attr_get_community(attr
),
1635 COMMUNITY_NO_EXPORT_SUBCONFED
))
1641 /* Route reflection loop check. */
1642 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1644 struct in_addr cluster_id
;
1645 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1648 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1649 cluster_id
= peer
->bgp
->cluster_id
;
1651 cluster_id
= peer
->bgp
->router_id
;
1653 if (cluster_loop_check(cluster
, cluster_id
))
1659 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1661 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1662 if (peer
->local_role
== ROLE_PROVIDER
||
1663 peer
->local_role
== ROLE_RS_SERVER
)
1665 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1669 if (peer
->local_role
== ROLE_CUSTOMER
||
1670 peer
->local_role
== ROLE_PEER
||
1671 peer
->local_role
== ROLE_RS_CLIENT
) {
1672 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1673 attr
->otc
= peer
->as
;
1678 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1680 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1681 if (peer
->local_role
== ROLE_CUSTOMER
||
1682 peer
->local_role
== ROLE_RS_CLIENT
||
1683 peer
->local_role
== ROLE_PEER
)
1687 if (peer
->local_role
== ROLE_PROVIDER
||
1688 peer
->local_role
== ROLE_PEER
||
1689 peer
->local_role
== ROLE_RS_SERVER
) {
1690 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1691 attr
->otc
= peer
->bgp
->as
;
1696 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1698 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1701 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1702 struct attr
*attr
, afi_t afi
, safi_t safi
,
1703 const char *rmap_name
, mpls_label_t
*label
,
1704 uint32_t num_labels
, struct bgp_dest
*dest
)
1706 struct bgp_filter
*filter
;
1707 struct bgp_path_info rmap_path
= { 0 };
1708 struct bgp_path_info_extra extra
= { 0 };
1709 route_map_result_t ret
;
1710 struct route_map
*rmap
= NULL
;
1712 filter
= &peer
->filter
[afi
][safi
];
1714 /* Apply default weight value. */
1715 if (peer
->weight
[afi
][safi
])
1716 attr
->weight
= peer
->weight
[afi
][safi
];
1719 rmap
= route_map_lookup_by_name(rmap_name
);
1724 if (ROUTE_MAP_IN_NAME(filter
)) {
1725 rmap
= ROUTE_MAP_IN(filter
);
1732 /* Route map apply. */
1734 memset(&rmap_path
, 0, sizeof(rmap_path
));
1735 /* Duplicate current value to new structure for modification. */
1736 rmap_path
.peer
= peer
;
1737 rmap_path
.attr
= attr
;
1738 rmap_path
.extra
= &extra
;
1739 rmap_path
.net
= dest
;
1741 extra
.num_labels
= num_labels
;
1742 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1743 memcpy(extra
.label
, label
,
1744 num_labels
* sizeof(mpls_label_t
));
1746 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1748 /* Apply BGP route map to the attribute. */
1749 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1751 peer
->rmap_type
= 0;
1753 if (ret
== RMAP_DENYMATCH
)
1759 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1760 struct attr
*attr
, afi_t afi
, safi_t safi
,
1761 const char *rmap_name
)
1763 struct bgp_path_info rmap_path
;
1764 route_map_result_t ret
;
1765 struct route_map
*rmap
= NULL
;
1769 * So if we get to this point and have no rmap_name
1770 * we want to just show the output as it currently
1776 /* Apply default weight value. */
1777 if (peer
->weight
[afi
][safi
])
1778 attr
->weight
= peer
->weight
[afi
][safi
];
1780 rmap
= route_map_lookup_by_name(rmap_name
);
1783 * If we have a route map name and we do not find
1784 * the routemap that means we have an implicit
1790 memset(&rmap_path
, 0, sizeof(rmap_path
));
1791 /* Route map apply. */
1792 /* Duplicate current value to new structure for modification. */
1793 rmap_path
.peer
= peer
;
1794 rmap_path
.attr
= attr
;
1796 rmap_type
= peer
->rmap_type
;
1797 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1799 /* Apply BGP route map to the attribute. */
1800 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1802 peer
->rmap_type
= rmap_type
;
1804 if (ret
== RMAP_DENYMATCH
)
1806 * caller has multiple error paths with bgp_attr_flush()
1813 /* If this is an EBGP peer with remove-private-AS */
1814 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1815 struct peer
*peer
, struct attr
*attr
)
1817 if (peer
->sort
== BGP_PEER_EBGP
1818 && (peer_af_flag_check(peer
, afi
, safi
,
1819 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1820 || peer_af_flag_check(peer
, afi
, safi
,
1821 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1822 || peer_af_flag_check(peer
, afi
, safi
,
1823 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1824 || peer_af_flag_check(peer
, afi
, safi
,
1825 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1826 // Take action on the entire aspath
1827 if (peer_af_flag_check(peer
, afi
, safi
,
1828 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1829 || peer_af_flag_check(peer
, afi
, safi
,
1830 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1831 if (peer_af_flag_check(
1833 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1834 attr
->aspath
= aspath_replace_private_asns(
1835 attr
->aspath
, bgp
->as
, peer
->as
);
1838 * Even if the aspath consists of just private ASNs we
1839 * need to walk the AS-Path to maintain all instances
1840 * of the peer's ASN to break possible loops.
1843 attr
->aspath
= aspath_remove_private_asns(
1844 attr
->aspath
, peer
->as
);
1847 // 'all' was not specified so the entire aspath must be private
1849 // for us to do anything
1850 else if (aspath_private_as_check(attr
->aspath
)) {
1851 if (peer_af_flag_check(
1853 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1854 attr
->aspath
= aspath_replace_private_asns(
1855 attr
->aspath
, bgp
->as
, peer
->as
);
1858 * Walk the aspath to retain any instances of
1861 attr
->aspath
= aspath_remove_private_asns(
1862 attr
->aspath
, peer
->as
);
1867 /* If this is an EBGP peer with as-override */
1868 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1869 struct peer
*peer
, struct attr
*attr
)
1871 struct aspath
*aspath
;
1873 if (peer
->sort
== BGP_PEER_EBGP
&&
1874 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1875 if (attr
->aspath
->refcnt
)
1876 aspath
= aspath_dup(attr
->aspath
);
1878 aspath
= attr
->aspath
;
1880 attr
->aspath
= aspath_intern(
1881 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1883 aspath_free(aspath
);
1887 void bgp_attr_add_llgr_community(struct attr
*attr
)
1889 struct community
*old
;
1890 struct community
*new;
1891 struct community
*merge
;
1892 struct community
*llgr
;
1894 old
= bgp_attr_get_community(attr
);
1895 llgr
= community_str2com("llgr-stale");
1900 merge
= community_merge(community_dup(old
), llgr
);
1902 if (old
->refcnt
== 0)
1903 community_free(&old
);
1905 new = community_uniq_sort(merge
);
1906 community_free(&merge
);
1908 new = community_dup(llgr
);
1911 community_free(&llgr
);
1913 bgp_attr_set_community(attr
, new);
1916 void bgp_attr_add_gshut_community(struct attr
*attr
)
1918 struct community
*old
;
1919 struct community
*new;
1920 struct community
*merge
;
1921 struct community
*gshut
;
1923 old
= bgp_attr_get_community(attr
);
1924 gshut
= community_str2com("graceful-shutdown");
1929 merge
= community_merge(community_dup(old
), gshut
);
1931 if (old
->refcnt
== 0)
1932 community_free(&old
);
1934 new = community_uniq_sort(merge
);
1935 community_free(&merge
);
1937 new = community_dup(gshut
);
1940 community_free(&gshut
);
1941 bgp_attr_set_community(attr
, new);
1943 /* When we add the graceful-shutdown community we must also
1944 * lower the local-preference */
1945 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1946 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1950 /* Notify BGP Conditional advertisement scanner process. */
1951 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1953 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1954 afi_t afi
= SUBGRP_AFI(subgrp
);
1955 safi_t safi
= SUBGRP_SAFI(subgrp
);
1956 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1958 if (!ADVERTISE_MAP_NAME(filter
))
1961 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1964 peer
->advmap_table_change
= true;
1968 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1970 if (family
== AF_INET
) {
1971 attr
->nexthop
.s_addr
= INADDR_ANY
;
1972 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1974 if (family
== AF_INET6
)
1975 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1976 if (family
== AF_EVPN
)
1977 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1980 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1981 struct update_subgroup
*subgrp
,
1982 const struct prefix
*p
, struct attr
*attr
,
1983 struct attr
*post_attr
)
1985 struct bgp_filter
*filter
;
1988 struct peer
*onlypeer
;
1990 struct attr
*piattr
;
1991 route_map_result_t ret
;
1996 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1997 bool nh_reset
= false;
2000 if (DISABLE_BGP_ANNOUNCE
)
2003 afi
= SUBGRP_AFI(subgrp
);
2004 safi
= SUBGRP_SAFI(subgrp
);
2005 peer
= SUBGRP_PEER(subgrp
);
2007 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
2008 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
2011 filter
= &peer
->filter
[afi
][safi
];
2012 bgp
= SUBGRP_INST(subgrp
);
2013 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
2016 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
2017 peer
->pmax_out
[afi
][safi
] != 0 &&
2018 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
2019 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
2020 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
2021 zlog_debug("%s reached maximum prefix to be send (%u)",
2022 peer
->host
, peer
->pmax_out
[afi
][safi
]);
2027 #ifdef ENABLE_BGP_VNC
2028 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
2029 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
2030 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
2033 * direct and direct_ext type routes originate internally even
2034 * though they can have peer pointers that reference other
2037 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2043 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
2044 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
2045 && (pi
->type
== ZEBRA_ROUTE_BGP
)
2046 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2048 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2053 /* With addpath we may be asked to TX all kinds of paths so make sure
2055 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
2056 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
2057 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
2061 /* If this is not the bestpath then check to see if there is an enabled
2063 * feature that requires us to advertise it */
2064 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2065 if (!bgp_addpath_capable(pi
, peer
, afi
, safi
))
2068 /* Aggregate-address suppress check. */
2069 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
2073 * If we are doing VRF 2 VRF leaking via the import
2074 * statement, we want to prevent the route going
2075 * off box as that the RT and RD created are localy
2076 * significant and globaly useless.
2078 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
2079 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
2082 /* If it's labeled safi, make sure the route has a valid label. */
2083 if (safi
== SAFI_LABELED_UNICAST
) {
2084 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
2085 if (!bgp_is_valid_label(&label
)) {
2086 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2087 zlog_debug("u%" PRIu64
":s%" PRIu64
2088 " %pFX is filtered - no label (%p)",
2089 subgrp
->update_group
->id
, subgrp
->id
,
2095 /* Do not send back route to sender. */
2096 if (onlypeer
&& from
== onlypeer
) {
2100 /* Do not send the default route in the BGP table if the neighbor is
2101 * configured for default-originate */
2102 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2103 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2104 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2106 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2110 /* Transparency check. */
2111 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2112 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2117 /* If community is not disabled check the no-export and local. */
2118 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2119 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2120 zlog_debug("%s: community filter check fail for %pFX",
2125 /* If the attribute has originator-id and it is same as remote
2127 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2128 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2129 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2131 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2136 /* ORF prefix-list filter check */
2137 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2138 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2139 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2140 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2141 if (peer
->orf_plist
[afi
][safi
]) {
2142 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2144 if (bgp_debug_update(NULL
, p
,
2145 subgrp
->update_group
, 0))
2147 "%pBP [Update:SEND] %pFX is filtered via ORF",
2153 /* Output filter check. */
2154 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2155 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2156 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2161 /* AS path loop check. */
2162 if (peer
->as_path_loop_detection
&&
2163 aspath_loop_check(piattr
->aspath
, peer
->as
)) {
2164 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2166 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2171 /* If we're a CONFED we need to loop check the CONFED ID too */
2172 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2173 if (aspath_loop_check_confed(piattr
->aspath
, bgp
->confed_id
)) {
2174 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2176 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2177 peer
, bgp
->confed_id
);
2182 /* Route-Reflect check. */
2183 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2188 /* IBGP reflection check. */
2189 if (reflect
&& !samepeer_safe
) {
2190 /* A route from a Client peer. */
2191 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2192 PEER_FLAG_REFLECTOR_CLIENT
)) {
2193 /* Reflect to all the Non-Client peers and also to the
2194 Client peers other than the originator. Originator
2196 is already done. So there is noting to do. */
2197 /* no bgp client-to-client reflection check. */
2198 if (CHECK_FLAG(bgp
->flags
,
2199 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2200 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2201 PEER_FLAG_REFLECTOR_CLIENT
))
2204 /* A route from a Non-client peer. Reflect to all other
2206 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2207 PEER_FLAG_REFLECTOR_CLIENT
))
2212 /* For modify attribute, copy it to temporary structure.
2213 * post_attr comes from BGP conditional advertisements, where
2214 * attributes are already processed by advertise-map route-map,
2215 * and this needs to be saved instead of overwriting from the
2223 /* If local-preference is not set. */
2224 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2225 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2226 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2227 attr
->local_pref
= bgp
->default_local_pref
;
2230 /* If originator-id is not set and the route is to be reflected,
2231 set the originator id */
2233 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2234 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2235 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2238 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2240 if (peer
->sort
== BGP_PEER_EBGP
2241 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2242 if (from
!= bgp
->peer_self
&& !transparent
2243 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2244 PEER_FLAG_MED_UNCHANGED
))
2246 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2249 /* Since the nexthop attribute can vary per peer, it is not explicitly
2251 * in announce check, only certain flags and length (or number of
2253 * -- for IPv6/MP_REACH) are set here in order to guide the update
2255 * code in setting the nexthop(s) on a per peer basis in
2257 * Typically, the source nexthop in the attribute is preserved but in
2259 * scenarios where we know it will always be overwritten, we reset the
2260 * nexthop to "0" in an attempt to achieve better Update packing. An
2261 * example of this is when a prefix from each of 2 IBGP peers needs to
2263 * announced to an EBGP peer (and they have the same attributes barring
2267 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2269 #define NEXTHOP_IS_V6 \
2270 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2271 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2272 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2273 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2275 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2277 * the peer (group) is configured to receive link-local nexthop
2279 * and it is available in the prefix OR we're not reflecting the route,
2280 * link-local nexthop address is valid and
2281 * the peer (group) to whom we're going to announce is on a shared
2283 * and this is either a self-originated route or the peer is EBGP.
2284 * By checking if nexthop LL address is valid we are sure that
2285 * we do not announce LL address as `::`.
2287 if (NEXTHOP_IS_V6
) {
2288 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2289 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2290 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2291 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2292 || (!reflect
&& !transparent
2293 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2294 && peer
->shared_network
2295 && (from
== bgp
->peer_self
2296 || peer
->sort
== BGP_PEER_EBGP
))) {
2297 if (safi
== SAFI_MPLS_VPN
)
2298 attr
->mp_nexthop_len
=
2299 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
;
2301 attr
->mp_nexthop_len
=
2302 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2305 /* Clear off link-local nexthop in source, whenever it is not
2307 * ensure more prefixes share the same attribute for
2310 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2311 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2312 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2315 if (bgp_check_role_applicability(afi
, safi
) &&
2316 bgp_otc_egress(peer
, attr
))
2319 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2320 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2322 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2323 filter
->advmap
.aname
&&
2324 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2325 struct bgp_path_info rmap_path
= {0};
2326 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2327 struct attr dummy_attr
= *attr
;
2329 /* Fill temp path_info */
2330 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2331 pi
, peer
, &dummy_attr
);
2333 struct route_map
*amap
=
2334 route_map_lookup_by_name(filter
->advmap
.aname
);
2336 ret
= route_map_apply(amap
, p
, &rmap_path
);
2338 bgp_attr_flush(&dummy_attr
);
2341 * The conditional advertisement mode is Withdraw and this
2342 * prefix is a conditional prefix. Don't advertise it
2344 if (ret
== RMAP_PERMITMATCH
)
2348 /* Route map & unsuppress-map apply. */
2350 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2351 struct bgp_path_info rmap_path
= {0};
2352 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2353 struct attr dummy_attr
= {0};
2355 /* Fill temp path_info */
2356 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2359 /* don't confuse inbound and outbound setting */
2360 RESET_FLAG(attr
->rmap_change_flags
);
2363 * The route reflector is not allowed to modify the attributes
2364 * of the reflected IBGP routes unless explicitly allowed.
2366 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2367 && !CHECK_FLAG(bgp
->flags
,
2368 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2370 rmap_path
.attr
= &dummy_attr
;
2373 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2375 if (bgp_path_suppressed(pi
))
2376 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2379 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2382 bgp_attr_flush(&dummy_attr
);
2383 peer
->rmap_type
= 0;
2385 if (ret
== RMAP_DENYMATCH
) {
2386 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2388 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2390 bgp_path_suppressed(pi
)
2391 ? UNSUPPRESS_MAP_NAME(filter
)
2392 : ROUTE_MAP_OUT_NAME(filter
));
2393 bgp_attr_flush(rmap_path
.attr
);
2398 /* RFC 8212 to prevent route leaks.
2399 * This specification intends to improve this situation by requiring the
2400 * explicit configuration of both BGP Import and Export Policies for any
2401 * External BGP (EBGP) session such as customers, peers, or
2402 * confederation boundaries for all enabled address families. Through
2403 * codification of the aforementioned requirement, operators will
2404 * benefit from consistent behavior across different BGP
2407 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2408 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2409 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2410 NULL
) > FIFTEENMINUTE2USEC
||
2411 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2413 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2414 monotime(&bgp
->ebgprequirespolicywarning
);
2419 /* draft-ietf-idr-deprecate-as-set-confed-set
2420 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2421 * Eventually, This document (if approved) updates RFC 4271
2422 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2423 * and obsoletes RFC 6472.
2425 if (peer
->bgp
->reject_as_sets
)
2426 if (aspath_check_as_sets(attr
->aspath
))
2429 /* If neighbor soo is configured, then check if the route has
2430 * SoO extended community and validate against the configured
2431 * one. If they match, do not announce, to prevent routing
2434 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2435 peer
->soo
[afi
][safi
]) {
2436 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2437 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2439 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2440 ECOMMUNITY_SITE_ORIGIN
) ||
2441 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2442 ECOMMUNITY_SITE_ORIGIN
) ||
2443 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2444 ECOMMUNITY_SITE_ORIGIN
)) &&
2445 ecommunity_include(ecomm
, ecomm_soo
)) {
2446 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2448 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2449 peer
, p
, ecommunity_str(ecomm_soo
));
2454 /* Codification of AS 0 Processing */
2455 if (aspath_check_as_zero(attr
->aspath
))
2458 if (bgp_in_graceful_shutdown(bgp
)) {
2459 if (peer
->sort
== BGP_PEER_IBGP
2460 || peer
->sort
== BGP_PEER_CONFED
) {
2461 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2462 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2464 bgp_attr_add_gshut_community(attr
);
2468 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2469 * Capability" to a neighbor MUST perform the following upon receiving
2470 * a route from that neighbor with the "LLGR_STALE" community, or upon
2471 * attaching the "LLGR_STALE" community itself per Section 4.2:
2473 * The route SHOULD NOT be advertised to any neighbor from which the
2474 * Long-lived Graceful Restart Capability has not been received.
2476 if (bgp_attr_get_community(attr
) &&
2477 community_include(bgp_attr_get_community(attr
),
2478 COMMUNITY_LLGR_STALE
) &&
2479 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2480 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2483 /* After route-map has been applied, we check to see if the nexthop to
2484 * be carried in the attribute (that is used for the announcement) can
2485 * be cleared off or not. We do this in all cases where we would be
2486 * setting the nexthop to "ourselves". For IPv6, we only need to
2488 * the global nexthop here; the link-local nexthop would have been
2490 * already, and if not, it is required by the update formation code.
2491 * Also see earlier comments in this function.
2494 * If route-map has performed some operation on the nexthop or the peer
2495 * configuration says to pass it unchanged, we cannot reset the nexthop
2496 * here, so only attempt to do it if these aren't true. Note that the
2497 * route-map handler itself might have cleared the nexthop, if for
2499 * it is configured as 'peer-address'.
2501 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2502 piattr
->rmap_change_flags
)
2504 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2505 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2506 /* We can reset the nexthop, if setting (or forcing) it to
2508 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2509 PEER_FLAG_NEXTHOP_SELF
)
2510 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2511 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2513 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2514 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2515 subgroup_announce_reset_nhop(
2516 (peer_cap_enhe(peer
, afi
, safi
)
2522 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2523 /* Can also reset the nexthop if announcing to EBGP, but
2525 * no peer in the subgroup is on a shared subnet.
2526 * Note: 3rd party nexthop currently implemented for
2529 if ((p
->family
== AF_INET
) &&
2530 (!bgp_subgrp_multiaccess_check_v4(
2533 subgroup_announce_reset_nhop(
2534 (peer_cap_enhe(peer
, afi
, safi
)
2541 if ((p
->family
== AF_INET6
) &&
2542 (!bgp_subgrp_multiaccess_check_v6(
2543 piattr
->mp_nexthop_global
,
2545 subgroup_announce_reset_nhop(
2546 (peer_cap_enhe(peer
, afi
, safi
)
2555 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2557 * This flag is used for leaked vpn-vrf routes
2559 int family
= p
->family
;
2561 if (peer_cap_enhe(peer
, afi
, safi
))
2564 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2566 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2567 __func__
, p
, family2str(family
));
2568 subgroup_announce_reset_nhop(family
, attr
);
2573 /* If IPv6/MP and nexthop does not have any override and happens
2575 * be a link-local address, reset it so that we don't pass along
2577 * source's link-local IPv6 address to recipients who may not be
2579 * the same interface.
2581 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2582 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2583 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2588 /* If this is an iBGP, send Origin Validation State (OVS)
2589 * extended community (rfc8097).
2591 if (peer
->sort
== BGP_PEER_IBGP
) {
2592 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2594 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2596 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2597 bgp_attr_set_ecommunity(
2598 attr
, ecommunity_add_origin_validation_state(
2600 bgp_attr_get_ecommunity(attr
)));
2604 * When the next hop is set to ourselves, if all multipaths have
2605 * link-bandwidth announce the cumulative bandwidth as that makes
2606 * the most sense. However, don't modify if the link-bandwidth has
2607 * been explicitly set by user policy.
2610 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2611 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2612 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2613 bgp_attr_set_ecommunity(
2615 ecommunity_replace_linkbw(
2616 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2619 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2624 static void bgp_route_select_timer_expire(struct event
*thread
)
2626 struct afi_safi_info
*info
;
2631 info
= EVENT_ARG(thread
);
2636 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2637 XFREE(MTYPE_TMP
, info
);
2639 /* Best path selection */
2640 bgp_best_path_select_defer(bgp
, afi
, safi
);
2643 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2644 struct bgp_maxpaths_cfg
*mpath_cfg
,
2645 struct bgp_path_info_pair
*result
, afi_t afi
,
2648 struct bgp_path_info
*new_select
;
2649 struct bgp_path_info
*old_select
;
2650 struct bgp_path_info
*pi
;
2651 struct bgp_path_info
*pi1
;
2652 struct bgp_path_info
*pi2
;
2653 struct bgp_path_info
*nextpi
= NULL
;
2654 int paths_eq
, do_mpath
, debug
;
2655 struct list mp_list
;
2656 char pfx_buf
[PREFIX2STR_BUFFER
];
2657 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2659 bgp_mp_list_init(&mp_list
);
2661 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2663 debug
= bgp_debug_bestpath(dest
);
2666 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2668 dest
->reason
= bgp_path_selection_none
;
2669 /* bgp deterministic-med */
2671 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2673 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2674 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2676 bgp_path_info_unset_flag(dest
, pi1
,
2677 BGP_PATH_DMED_SELECTED
);
2679 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2681 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2683 if (BGP_PATH_HOLDDOWN(pi1
))
2685 if (pi1
->peer
!= bgp
->peer_self
&&
2686 !CHECK_FLAG(pi1
->peer
->sflags
,
2687 PEER_STATUS_NSF_WAIT
)) {
2688 if (!peer_established(pi1
->peer
))
2694 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2695 if (CHECK_FLAG(pi2
->flags
,
2696 BGP_PATH_DMED_CHECK
))
2698 if (BGP_PATH_HOLDDOWN(pi2
))
2700 if (pi2
->peer
!= bgp
->peer_self
2703 PEER_STATUS_NSF_WAIT
))
2704 if (pi2
->peer
->status
2708 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2710 && !aspath_cmp_left_confed(
2715 if (bgp_path_info_cmp(
2716 bgp
, pi2
, new_select
,
2717 &paths_eq
, mpath_cfg
, debug
,
2720 bgp_path_info_unset_flag(
2722 BGP_PATH_DMED_SELECTED
);
2726 bgp_path_info_set_flag(
2727 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2730 bgp_path_info_set_flag(dest
, new_select
,
2731 BGP_PATH_DMED_CHECK
);
2732 bgp_path_info_set_flag(dest
, new_select
,
2733 BGP_PATH_DMED_SELECTED
);
2736 bgp_path_info_path_with_addpath_rx_str(
2737 new_select
, path_buf
, sizeof(path_buf
));
2739 "%pBD(%s): %s is the bestpath from AS %u",
2740 dest
, bgp
->name_pretty
, path_buf
,
2741 aspath_get_first_as(
2742 new_select
->attr
->aspath
));
2747 /* Check old selected route and new selected route. */
2750 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2751 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2752 enum bgp_path_selection_reason reason
;
2754 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2757 if (BGP_PATH_HOLDDOWN(pi
)) {
2758 /* reap REMOVED routes, if needs be
2759 * selected route must stay for a while longer though
2761 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2762 && (pi
!= old_select
))
2763 bgp_path_info_reap(dest
, pi
);
2767 "%s: %pBD(%s) pi from %s in holddown",
2768 __func__
, dest
, bgp
->name_pretty
,
2774 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2775 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2776 if (!peer_established(pi
->peer
)) {
2780 "%s: %pBD(%s) non self peer %s not estab state",
2788 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2789 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2790 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2792 zlog_debug("%s: %pBD(%s) pi %s dmed", __func__
,
2793 dest
, bgp
->name_pretty
,
2798 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2800 reason
= dest
->reason
;
2801 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2802 debug
, pfx_buf
, afi
, safi
,
2804 if (new_select
== NULL
&&
2805 reason
!= bgp_path_selection_none
)
2806 dest
->reason
= reason
;
2811 /* Now that we know which path is the bestpath see if any of the other
2813 * qualify as multipaths
2817 bgp_path_info_path_with_addpath_rx_str(
2818 new_select
, path_buf
, sizeof(path_buf
));
2820 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2822 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2823 dest
, bgp
->name_pretty
, path_buf
,
2824 old_select
? old_select
->peer
->host
: "NONE");
2827 if (do_mpath
&& new_select
) {
2828 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2829 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2832 bgp_path_info_path_with_addpath_rx_str(
2833 pi
, path_buf
, sizeof(path_buf
));
2835 if (pi
== new_select
) {
2838 "%pBD(%s): %s is the bestpath, add to the multipath list",
2839 dest
, bgp
->name_pretty
,
2841 bgp_mp_list_add(&mp_list
, pi
);
2845 if (BGP_PATH_HOLDDOWN(pi
))
2848 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2849 && !CHECK_FLAG(pi
->peer
->sflags
,
2850 PEER_STATUS_NSF_WAIT
))
2851 if (!peer_established(pi
->peer
))
2854 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2857 "%pBD(%s): %s has the same nexthop as the bestpath, skip it",
2858 dest
, bgp
->name_pretty
,
2863 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2864 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2870 "%pBD(%s): %s is equivalent to the bestpath, add to the multipath list",
2871 dest
, bgp
->name_pretty
,
2873 bgp_mp_list_add(&mp_list
, pi
);
2878 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2880 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2881 bgp_mp_list_clear(&mp_list
);
2883 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2885 result
->old
= old_select
;
2886 result
->new = new_select
;
2892 * A new route/change in bestpath of an existing route. Evaluate the path
2893 * for advertisement to the subgroup.
2895 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2896 struct bgp_path_info
*selected
,
2897 struct bgp_dest
*dest
,
2898 uint32_t addpath_tx_id
)
2900 const struct prefix
*p
;
2901 struct peer
*onlypeer
;
2908 p
= bgp_dest_get_prefix(dest
);
2909 afi
= SUBGRP_AFI(subgrp
);
2910 safi
= SUBGRP_SAFI(subgrp
);
2911 bgp
= SUBGRP_INST(subgrp
);
2912 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2915 if (BGP_DEBUG(update
, UPDATE_OUT
))
2916 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2918 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2919 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2920 PEER_STATUS_ORF_WAIT_REFRESH
))
2923 memset(&attr
, 0, sizeof(attr
));
2924 /* It's initialized in bgp_announce_check() */
2926 /* Announcement to the subgroup. If the route is filtered withdraw it.
2927 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2928 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2931 advertise
= bgp_check_advertise(bgp
, dest
);
2934 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2936 /* Route is selected, if the route is already installed
2937 * in FIB, then it is advertised
2940 if (!bgp_check_withdrawal(bgp
, dest
)) {
2941 struct attr
*adv_attr
=
2942 bgp_attr_intern(&attr
);
2944 bgp_adj_out_set_subgroup(dest
, subgrp
,
2948 bgp_adj_out_unset_subgroup(
2949 dest
, subgrp
, 1, addpath_tx_id
);
2952 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2956 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2958 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2963 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2964 * This is called at the end of route processing.
2966 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2968 struct bgp_path_info
*pi
;
2970 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2971 if (BGP_PATH_HOLDDOWN(pi
))
2973 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2974 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2979 * Has the route changed from the RIB's perspective? This is invoked only
2980 * if the route selection returns the same best route as earlier - to
2981 * determine if we need to update zebra or not.
2983 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2985 struct bgp_path_info
*mpinfo
;
2987 /* If this is multipath, check all selected paths for any nexthop
2988 * change or attribute change. Some attribute changes (e.g., community)
2989 * aren't of relevance to the RIB, but we'll update zebra to ensure
2990 * we handle the case of BGP nexthop change. This is the behavior
2991 * when the best path has an attribute change anyway.
2993 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2994 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2995 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2999 * If this is multipath, check all selected paths for any nexthop change
3001 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
3002 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
3003 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
3004 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
3008 /* Nothing has changed from the RIB's perspective. */
3012 struct bgp_process_queue
{
3014 STAILQ_HEAD(, bgp_dest
) pqueue
;
3015 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3017 unsigned int queued
;
3020 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
3021 safi_t safi
, struct bgp_dest
*dest
,
3022 struct bgp_path_info
*new_select
,
3023 struct bgp_path_info
*old_select
)
3025 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3027 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
3030 if (advertise_type5_routes(bgp
, afi
) && new_select
3031 && is_route_injectable_into_evpn(new_select
)) {
3033 /* apply the route-map */
3034 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
3035 route_map_result_t ret
;
3036 struct bgp_path_info rmap_path
;
3037 struct bgp_path_info_extra rmap_path_extra
;
3038 struct attr dummy_attr
;
3040 dummy_attr
= *new_select
->attr
;
3042 /* Fill temp path_info */
3043 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3044 new_select
, new_select
->peer
,
3047 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3049 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3052 if (ret
== RMAP_DENYMATCH
) {
3053 bgp_attr_flush(&dummy_attr
);
3054 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3057 bgp_evpn_advertise_type5_route(
3058 bgp
, p
, &dummy_attr
, afi
, safi
);
3060 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3063 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3064 && is_route_injectable_into_evpn(old_select
))
3065 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3069 * Utility to determine whether a particular path_info should use
3070 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3071 * in a path where we basically _know_ this is a BGP-LU route.
3073 static bool bgp_lu_need_null_label(struct bgp
*bgp
,
3074 const struct bgp_path_info
*new_select
,
3075 afi_t afi
, mpls_label_t
*label
)
3077 /* Certain types get imp null; so do paths where the nexthop is
3080 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3081 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3082 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3083 goto need_null_label
;
3084 else if (new_select
->extra
&&
3085 bgp_is_valid_label(&new_select
->extra
->label
[0]))
3090 if (!!CHECK_FLAG(bgp
->flags
, BGP_FLAG_LU_EXPLICIT_NULL
))
3091 /* Disable PHP : explicit-null */
3092 *label
= afi
== AFI_IP
? MPLS_LABEL_IPV4_EXPLICIT_NULL
3093 : MPLS_LABEL_IPV6_EXPLICIT_NULL
;
3095 /* Enforced PHP popping: implicit-null */
3096 *label
= MPLS_LABEL_IMPLICIT_NULL
;
3102 * old_select = The old best path
3103 * new_select = the new best path
3105 * if (!old_select && new_select)
3106 * We are sending new information on.
3108 * if (old_select && new_select) {
3109 * if (new_select != old_select)
3110 * We have a new best path send a change
3112 * We've received a update with new attributes that needs
3116 * if (old_select && !new_select)
3117 * We have no eligible route that we can announce or the rn
3120 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3121 afi_t afi
, safi_t safi
)
3123 struct bgp_path_info
*new_select
;
3124 struct bgp_path_info
*old_select
;
3125 struct bgp_path_info_pair old_and_new
;
3127 mpls_label_t mpls_label_null
;
3129 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3131 debug
= bgp_debug_bestpath(dest
);
3134 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3135 __func__
, dest
, bgp
->name_pretty
);
3138 /* Is it end of initial update? (after startup) */
3140 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3141 sizeof(bgp
->update_delay_zebra_resume_time
));
3143 bgp
->main_zebra_update_hold
= 0;
3144 FOREACH_AFI_SAFI (afi
, safi
) {
3145 if (bgp_fibupd_safi(safi
))
3146 bgp_zebra_announce_table(bgp
, afi
, safi
);
3148 bgp
->main_peers_update_hold
= 0;
3150 bgp_start_routeadv(bgp
);
3154 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3156 debug
= bgp_debug_bestpath(dest
);
3158 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__
,
3159 dest
, bgp
->name_pretty
, afi2str(afi
),
3162 /* The best path calculation for the route is deferred if
3163 * BGP_NODE_SELECT_DEFER is set
3165 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3166 if (BGP_DEBUG(update
, UPDATE_OUT
))
3167 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3168 dest
, bgp
->name_pretty
);
3172 /* Best path selection. */
3173 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3175 old_select
= old_and_new
.old
;
3176 new_select
= old_and_new
.new;
3178 /* Do we need to allocate or free labels?
3179 * Right now, since we only deal with per-prefix labels, it is not
3180 * necessary to do this upon changes to best path. Exceptions:
3181 * - label index has changed -> recalculate resulting label
3182 * - path_info sub_type changed -> switch to/from null label value
3183 * - no valid label (due to removed static label binding) -> get new one
3185 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3188 || bgp_label_index_differs(new_select
, old_select
)
3189 || new_select
->sub_type
!= old_select
->sub_type
3190 || !bgp_is_valid_label(&dest
->local_label
)) {
3191 /* control label imposition for local routes,
3192 * aggregate and redistributed routes
3194 mpls_label_null
= MPLS_LABEL_IMPLICIT_NULL
;
3195 if (bgp_lu_need_null_label(bgp
, new_select
, afi
,
3196 &mpls_label_null
)) {
3199 BGP_NODE_REGISTERED_FOR_LABEL
)
3202 BGP_NODE_LABEL_REQUESTED
))
3203 bgp_unregister_for_label(dest
);
3204 dest
->local_label
= mpls_lse_encode(
3205 mpls_label_null
, 0, 0, 1);
3206 bgp_set_valid_label(&dest
->local_label
);
3208 bgp_register_for_label(dest
,
3211 } else if (CHECK_FLAG(dest
->flags
,
3212 BGP_NODE_REGISTERED_FOR_LABEL
)
3213 || CHECK_FLAG(dest
->flags
,
3214 BGP_NODE_LABEL_REQUESTED
)) {
3215 bgp_unregister_for_label(dest
);
3217 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3218 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3219 bgp_unregister_for_label(dest
);
3224 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3225 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3226 safi2str(safi
), old_select
, new_select
);
3228 /* If best route remains the same and this is not due to user-initiated
3229 * clear, see exactly what needs to be done.
3231 if (old_select
&& old_select
== new_select
3232 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3233 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3234 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3235 if (bgp_zebra_has_route_changed(old_select
)) {
3236 #ifdef ENABLE_BGP_VNC
3237 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3238 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3240 if (bgp_fibupd_safi(safi
)
3241 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3243 if (new_select
->type
== ZEBRA_ROUTE_BGP
3244 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3245 || new_select
->sub_type
3246 == BGP_ROUTE_IMPORTED
))
3248 bgp_zebra_announce(dest
, p
, old_select
,
3253 /* If there is a change of interest to peers, reannounce the
3255 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3256 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3257 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3258 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3260 /* unicast routes must also be annouced to
3261 * labeled-unicast update-groups */
3262 if (safi
== SAFI_UNICAST
)
3263 group_announce_route(bgp
, afi
,
3264 SAFI_LABELED_UNICAST
, dest
,
3267 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3268 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3271 /* advertise/withdraw type-5 routes */
3272 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3273 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3274 bgp_process_evpn_route_injection(
3275 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3277 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3278 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3279 bgp_zebra_clear_route_change_flags(dest
);
3280 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3284 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3286 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3288 /* bestpath has changed; bump version */
3289 if (old_select
|| new_select
) {
3290 bgp_bump_version(dest
);
3292 if (!bgp
->t_rmap_def_originate_eval
) {
3296 update_group_refresh_default_originate_route_map
,
3297 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3298 &bgp
->t_rmap_def_originate_eval
);
3303 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3306 zlog_debug("%s: setting SELECTED flag", __func__
);
3307 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3308 bgp_path_info_unset_flag(dest
, new_select
,
3309 BGP_PATH_ATTR_CHANGED
);
3310 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3311 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3314 #ifdef ENABLE_BGP_VNC
3315 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3316 if (old_select
!= new_select
) {
3318 vnc_import_bgp_exterior_del_route(bgp
, p
,
3320 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3323 vnc_import_bgp_exterior_add_route(bgp
, p
,
3325 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3331 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3333 /* unicast routes must also be annouced to labeled-unicast update-groups
3335 if (safi
== SAFI_UNICAST
)
3336 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3340 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3341 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3343 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3344 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3345 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3346 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3348 /* if this is an evpn imported type-5 prefix,
3349 * we need to withdraw the route first to clear
3350 * the nh neigh and the RMAC entry.
3353 is_route_parent_evpn(old_select
))
3354 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3356 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3358 /* Withdraw the route from the kernel. */
3359 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3360 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3361 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3362 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3364 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3368 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3371 /* Clear any route change flags. */
3372 bgp_zebra_clear_route_change_flags(dest
);
3374 /* Reap old select bgp_path_info, if it has been removed */
3375 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3376 bgp_path_info_reap(dest
, old_select
);
3378 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3382 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3383 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3385 struct bgp_dest
*dest
;
3387 struct afi_safi_info
*thread_info
;
3389 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3390 struct event
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3392 thread_info
= EVENT_ARG(t
);
3393 XFREE(MTYPE_TMP
, thread_info
);
3394 EVENT_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3397 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3398 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3399 get_afi_safi_str(afi
, safi
, false),
3400 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3403 /* Process the route list */
3404 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3405 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3406 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3407 dest
= bgp_route_next(dest
)) {
3408 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3411 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3412 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3413 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3416 /* If iteration stopped before the entire table was traversed then the
3417 * node needs to be unlocked.
3420 bgp_dest_unlock_node(dest
);
3424 /* Send EOR message when all routes are processed */
3425 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3426 bgp_send_delayed_eor(bgp
);
3427 /* Send route processing complete message to RIB */
3428 bgp_zebra_update(bgp
, afi
, safi
,
3429 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3433 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3435 thread_info
->afi
= afi
;
3436 thread_info
->safi
= safi
;
3437 thread_info
->bgp
= bgp
;
3439 /* If there are more routes to be processed, start the
3442 event_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3443 BGP_ROUTE_SELECT_DELAY
,
3444 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3447 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3449 struct bgp_process_queue
*pqnode
= data
;
3450 struct bgp
*bgp
= pqnode
->bgp
;
3451 struct bgp_table
*table
;
3452 struct bgp_dest
*dest
;
3455 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3456 bgp_process_main_one(bgp
, NULL
, 0, 0);
3457 /* should always have dedicated wq call */
3458 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3462 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3463 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3464 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3465 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3466 table
= bgp_dest_table(dest
);
3467 /* note, new DESTs may be added as part of processing */
3468 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3470 bgp_dest_unlock_node(dest
);
3471 bgp_table_unlock(table
);
3477 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3479 struct bgp_process_queue
*pqnode
= data
;
3481 bgp_unlock(pqnode
->bgp
);
3483 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3486 void bgp_process_queue_init(struct bgp
*bgp
)
3488 if (!bgp
->process_queue
) {
3491 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3492 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3495 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3496 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3497 bgp
->process_queue
->spec
.max_retries
= 0;
3498 bgp
->process_queue
->spec
.hold
= 50;
3499 /* Use a higher yield value of 50ms for main queue processing */
3500 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3503 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3505 struct bgp_process_queue
*pqnode
;
3507 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3508 sizeof(struct bgp_process_queue
));
3510 /* unlocked in bgp_processq_del */
3511 pqnode
->bgp
= bgp_lock(bgp
);
3512 STAILQ_INIT(&pqnode
->pqueue
);
3517 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3519 #define ARBITRARY_PROCESS_QLEN 10000
3520 struct work_queue
*wq
= bgp
->process_queue
;
3521 struct bgp_process_queue
*pqnode
;
3522 int pqnode_reuse
= 0;
3524 /* already scheduled for processing? */
3525 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3528 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3531 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3532 if (BGP_DEBUG(update
, UPDATE_OUT
))
3533 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3538 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3539 if (BGP_DEBUG(update
, UPDATE_OUT
))
3541 "Soft reconfigure table in progress for route %p",
3549 /* Add route nodes to an existing work queue item until reaching the
3550 limit only if is from the same BGP view and it's not an EOIU marker
3552 if (work_queue_item_count(wq
)) {
3553 struct work_queue_item
*item
= work_queue_last_item(wq
);
3554 pqnode
= item
->data
;
3556 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3557 || pqnode
->bgp
!= bgp
3558 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3559 pqnode
= bgp_processq_alloc(bgp
);
3563 pqnode
= bgp_processq_alloc(bgp
);
3564 /* all unlocked in bgp_process_wq */
3565 bgp_table_lock(bgp_dest_table(dest
));
3567 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3568 bgp_dest_lock_node(dest
);
3570 /* can't be enqueued twice */
3571 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3572 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3576 work_queue_add(wq
, pqnode
);
3581 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3583 struct bgp_process_queue
*pqnode
;
3585 if (bgp
->process_queue
== NULL
)
3588 pqnode
= bgp_processq_alloc(bgp
);
3590 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3591 work_queue_add(bgp
->process_queue
, pqnode
);
3594 static void bgp_maximum_prefix_restart_timer(struct event
*thread
)
3598 peer
= EVENT_ARG(thread
);
3599 peer
->t_pmax_restart
= NULL
;
3601 if (bgp_debug_neighbor_events(peer
))
3603 "%s Maximum-prefix restart timer expired, restore peering",
3606 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3607 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3610 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3614 bool filtered
= false;
3615 struct bgp_dest
*dest
;
3616 struct bgp_adj_in
*ain
;
3617 struct attr attr
= {};
3618 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3620 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3621 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3622 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3626 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3630 if (bgp_input_modifier(
3631 peer
, rn_p
, &attr
, afi
, safi
,
3632 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3640 bgp_attr_flush(&attr
);
3647 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3651 iana_safi_t pkt_safi
;
3652 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3653 PEER_FLAG_MAX_PREFIX_FORCE
))
3654 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3655 + peer
->pcount
[afi
][safi
]
3656 : peer
->pcount
[afi
][safi
];
3658 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3661 if (pcount
> peer
->pmax
[afi
][safi
]) {
3662 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3663 PEER_STATUS_PREFIX_LIMIT
)
3668 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3669 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3670 peer
->pmax
[afi
][safi
]);
3671 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3673 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3674 PEER_FLAG_MAX_PREFIX_WARNING
))
3677 /* Convert AFI, SAFI to values for packet. */
3678 pkt_afi
= afi_int2iana(afi
);
3679 pkt_safi
= safi_int2iana(safi
);
3683 ndata
[0] = (pkt_afi
>> 8);
3685 ndata
[2] = pkt_safi
;
3686 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3687 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3688 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3689 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3691 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3692 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3693 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3697 /* Dynamic peers will just close their connection. */
3698 if (peer_dynamic_neighbor(peer
))
3701 /* restart timer start */
3702 if (peer
->pmax_restart
[afi
][safi
]) {
3703 peer
->v_pmax_restart
=
3704 peer
->pmax_restart
[afi
][safi
] * 60;
3706 if (bgp_debug_neighbor_events(peer
))
3708 "%pBP Maximum-prefix restart timer started for %d secs",
3709 peer
, peer
->v_pmax_restart
);
3711 BGP_TIMER_ON(peer
->t_pmax_restart
,
3712 bgp_maximum_prefix_restart_timer
,
3713 peer
->v_pmax_restart
);
3718 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3719 PEER_STATUS_PREFIX_LIMIT
);
3722 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3723 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3724 PEER_STATUS_PREFIX_THRESHOLD
)
3729 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3730 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3731 peer
->pmax
[afi
][safi
]);
3732 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3733 PEER_STATUS_PREFIX_THRESHOLD
);
3735 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3736 PEER_STATUS_PREFIX_THRESHOLD
);
3740 /* Unconditionally remove the route from the RIB, without taking
3741 * damping into consideration (eg, because the session went down)
3743 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3744 struct peer
*peer
, afi_t afi
, safi_t safi
)
3747 struct bgp
*bgp
= NULL
;
3748 bool delete_route
= false;
3750 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3753 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3754 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3756 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3759 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3760 delete_route
= true;
3761 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3762 delete_route
= true;
3764 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3765 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3766 bgp
= pi
->peer
->bgp
;
3767 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3772 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3773 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3776 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3777 struct peer
*peer
, afi_t afi
, safi_t safi
,
3778 struct prefix_rd
*prd
)
3780 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3782 /* apply dampening, if result is suppressed, we'll be retaining
3783 * the bgp_path_info in the RIB for historical reference.
3785 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3786 && peer
->sort
== BGP_PEER_EBGP
)
3787 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3788 == BGP_DAMP_SUPPRESSED
) {
3789 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3794 #ifdef ENABLE_BGP_VNC
3795 if (safi
== SAFI_MPLS_VPN
) {
3796 struct bgp_dest
*pdest
= NULL
;
3797 struct bgp_table
*table
= NULL
;
3799 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3800 (struct prefix
*)prd
);
3801 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3802 table
= bgp_dest_get_bgp_table_info(pdest
);
3804 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3805 peer
->bgp
, prd
, table
, p
, pi
);
3807 bgp_dest_unlock_node(pdest
);
3809 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3810 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3812 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3813 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3818 /* If this is an EVPN route, process for un-import. */
3819 if (safi
== SAFI_EVPN
)
3820 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3822 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3825 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3826 struct peer
*peer
, struct attr
*attr
,
3827 struct bgp_dest
*dest
)
3829 struct bgp_path_info
*new;
3831 /* Make new BGP info. */
3832 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3834 new->instance
= instance
;
3835 new->sub_type
= sub_type
;
3838 new->uptime
= monotime(NULL
);
3843 /* Check if received nexthop is valid or not. */
3844 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3845 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3846 struct bgp_dest
*dest
)
3849 bool is_bgp_static_route
=
3850 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3853 /* If `bgp allow-martian-nexthop` is turned on, return next-hop
3856 if (bgp
->allow_martian
)
3860 * Only validated for unicast and multicast currently.
3861 * Also valid for EVPN where the nexthop is an IP address.
3862 * If we are a bgp static route being checked then there is
3863 * no need to check to see if the nexthop is martian as
3864 * that it should be ok.
3866 if (is_bgp_static_route
||
3867 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3870 /* If NEXT_HOP is present, validate it. */
3871 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3872 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3873 !ipv4_unicast_valid(&attr
->nexthop
) ||
3874 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3878 /* If MP_NEXTHOP is present, validate it. */
3879 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3880 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3881 * it is not an IPv6 link-local address.
3883 * If we receive an UPDATE with nexthop length set to 32 bytes
3884 * we shouldn't discard an UPDATE if it's set to (::).
3885 * The link-local (2st) is validated along the code path later.
3887 if (attr
->mp_nexthop_len
) {
3888 switch (attr
->mp_nexthop_len
) {
3889 case BGP_ATTR_NHLEN_IPV4
:
3890 case BGP_ATTR_NHLEN_VPNV4
:
3891 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3893 !ipv4_unicast_valid(
3894 &attr
->mp_nexthop_global_in
) ||
3895 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3899 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3900 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3901 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3902 &attr
->mp_nexthop_global
)
3903 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3904 || IN6_IS_ADDR_MULTICAST(
3905 &attr
->mp_nexthop_global
)
3906 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3909 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3910 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3911 || IN6_IS_ADDR_MULTICAST(
3912 &attr
->mp_nexthop_global
)
3913 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3926 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3928 struct community
*old
;
3929 struct community
*new;
3930 struct community
*merge
;
3931 struct community
*no_export
;
3933 old
= bgp_attr_get_community(attr
);
3934 no_export
= community_str2com("no-export");
3939 merge
= community_merge(community_dup(old
), no_export
);
3942 community_free(&old
);
3944 new = community_uniq_sort(merge
);
3945 community_free(&merge
);
3947 new = community_dup(no_export
);
3950 community_free(&no_export
);
3952 bgp_attr_set_community(attr
, new);
3955 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3956 struct attr
*attr
, const struct prefix
*prefix
,
3959 struct listnode
*node
, *nnode
;
3961 bool accept_own_found
= false;
3963 if (safi
!= SAFI_MPLS_VPN
)
3966 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3967 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3970 /* The route in question carries the ACCEPT_OWN community */
3971 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3972 struct community
*comm
= bgp_attr_get_community(attr
);
3974 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3975 accept_own_found
= true;
3978 /* The route in question is targeted to one or more destination VRFs
3979 * on the router (as determined by inspecting the Route Target(s)).
3981 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3982 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3985 if (accept_own_found
&&
3987 bgp
->vpn_policy
[afi
]
3988 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3989 bgp_attr_get_ecommunity(attr
))) {
3990 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3992 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3995 /* Treat this route as imported, because it's leaked
3996 * already from another VRF, and we got an updated
3997 * version from route-reflector with ACCEPT_OWN
4000 *sub_type
= BGP_ROUTE_IMPORTED
;
4009 void bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4010 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4011 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4012 uint32_t num_labels
, int soft_reconfig
,
4013 struct bgp_route_evpn
*evpn
)
4016 int aspath_loop_count
= 0;
4017 struct bgp_dest
*dest
;
4019 struct attr new_attr
;
4020 struct attr
*attr_new
;
4021 struct bgp_path_info
*pi
;
4022 struct bgp_path_info
*new = NULL
;
4023 struct bgp_path_info_extra
*extra
;
4025 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4027 int do_loop_check
= 1;
4028 int has_valid_label
= 0;
4030 bool force_evpn_import
= false;
4031 safi_t orig_safi
= safi
;
4032 bool leak_success
= true;
4035 if (frrtrace_enabled(frr_bgp
, process_update
)) {
4036 char pfxprint
[PREFIX2STR_BUFFER
];
4038 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
4039 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
4043 #ifdef ENABLE_BGP_VNC
4044 int vnc_implicit_withdraw
= 0;
4047 const struct prefix
*bgp_nht_param_prefix
;
4049 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4050 if (orig_safi
== SAFI_LABELED_UNICAST
)
4051 safi
= SAFI_UNICAST
;
4053 memset(&new_attr
, 0, sizeof(new_attr
));
4054 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4055 new_attr
.label
= MPLS_INVALID_LABEL
;
4058 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4059 /* TODO: Check to see if we can get rid of "is_valid_label" */
4060 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4061 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4063 has_valid_label
= bgp_is_valid_label(label
);
4065 if (has_valid_label
)
4066 assert(label
!= NULL
);
4069 /* When peer's soft reconfiguration enabled. Record input packet in
4071 if (!soft_reconfig
&&
4072 CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
) &&
4073 peer
!= bgp
->peer_self
) {
4075 * If the trigger is not from soft_reconfig and if
4076 * PEER_FLAG_SOFT_RECONFIG is enabled for the peer, then attr
4077 * will not be interned. In which case, it is ok to update the
4078 * attr->evpn_overlay, so that, this can be stored in adj_in.
4080 if ((afi
== AFI_L2VPN
) && evpn
) {
4081 memcpy(&attr
->evpn_overlay
, evpn
,
4082 sizeof(struct bgp_route_evpn
));
4084 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4087 /* Update permitted loop count */
4088 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4089 allowas_in
= peer
->allowas_in
[afi
][safi
];
4091 /* Check previously received route. */
4092 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4093 if (pi
->peer
== peer
&& pi
->type
== type
4094 && pi
->sub_type
== sub_type
4095 && pi
->addpath_rx_id
== addpath_id
)
4098 /* AS path local-as loop check. */
4099 if (peer
->change_local_as
) {
4101 aspath_loop_count
= allowas_in
;
4102 else if (!CHECK_FLAG(peer
->flags
,
4103 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4104 aspath_loop_count
= 1;
4106 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4107 > aspath_loop_count
) {
4108 peer
->stat_pfx_aspath_loop
++;
4109 reason
= "as-path contains our own AS;";
4114 /* If the peer is configured for "allowas-in origin" and the last ASN in
4116 * as-path is our ASN then we do not need to call aspath_loop_check
4118 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4119 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4122 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4123 bgp_nht_param_prefix
= NULL
;
4125 bgp_nht_param_prefix
= p
;
4127 /* AS path loop check. */
4128 if (do_loop_check
) {
4129 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4130 peer
->allowas_in
[afi
][safi
]) {
4131 peer
->stat_pfx_aspath_loop
++;
4132 reason
= "as-path contains our own AS;";
4137 /* If we're a CONFED we need to loop check the CONFED ID too */
4138 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4139 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4140 peer
->allowas_in
[afi
][safi
]) {
4141 peer
->stat_pfx_aspath_loop
++;
4142 reason
= "as-path contains our own confed AS;";
4146 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4147 * enabled, then take care of that too.
4149 bool accept_own
= false;
4151 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4152 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4154 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4156 peer
->stat_pfx_originator_loop
++;
4157 reason
= "originator is us;";
4162 /* Route reflector cluster ID check. */
4163 if (bgp_cluster_filter(peer
, attr
)) {
4164 peer
->stat_pfx_cluster_loop
++;
4165 reason
= "reflected from the same cluster;";
4169 /* Apply incoming filter. */
4170 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4171 peer
->stat_pfx_filter
++;
4176 /* If the route has Node Target Extended Communities, check
4177 * if it's allowed to be installed locally.
4179 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4180 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4182 if (ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
4183 ECOMMUNITY_NODE_TARGET
) &&
4184 !ecommunity_node_target_match(ecomm
, &peer
->local_id
)) {
4186 "Node-Target Extended Communities do not contain own BGP Identifier;";
4191 /* RFC 8212 to prevent route leaks.
4192 * This specification intends to improve this situation by requiring the
4193 * explicit configuration of both BGP Import and Export Policies for any
4194 * External BGP (EBGP) session such as customers, peers, or
4195 * confederation boundaries for all enabled address families. Through
4196 * codification of the aforementioned requirement, operators will
4197 * benefit from consistent behavior across different BGP
4200 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4201 if (!bgp_inbound_policy_exists(peer
,
4202 &peer
->filter
[afi
][safi
])) {
4203 reason
= "inbound policy missing";
4204 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4205 NULL
) > FIFTEENMINUTE2USEC
||
4206 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4208 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4209 monotime(&bgp
->ebgprequirespolicywarning
);
4214 /* draft-ietf-idr-deprecate-as-set-confed-set
4215 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4216 * Eventually, This document (if approved) updates RFC 4271
4217 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4218 * and obsoletes RFC 6472.
4220 if (peer
->bgp
->reject_as_sets
)
4221 if (aspath_check_as_sets(attr
->aspath
)) {
4223 "as-path contains AS_SET or AS_CONFED_SET type;";
4229 * If bgp_update is called with soft_reconfig set then
4230 * attr is interned. In this case, do not overwrite the
4231 * attr->evpn_overlay with evpn directly. Instead memcpy
4232 * evpn to new_atr.evpn_overlay before it is interned.
4234 if (soft_reconfig
&& (afi
== AFI_L2VPN
) && evpn
)
4235 memcpy(&new_attr
.evpn_overlay
, evpn
,
4236 sizeof(struct bgp_route_evpn
));
4238 /* Apply incoming route-map.
4239 * NB: new_attr may now contain newly allocated values from route-map
4241 * commands, so we need bgp_attr_flush in the error paths, until we
4243 * the attr (which takes over the memory references) */
4244 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4247 peer
->stat_pfx_filter
++;
4248 reason
= "route-map;";
4249 bgp_attr_flush(&new_attr
);
4253 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4254 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4255 /* remove from RIB previous entry */
4256 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4259 if (peer
->sort
== BGP_PEER_EBGP
) {
4262 * A BGP speaker receiving an announcement tagged with the
4263 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4264 * NO_EXPORT community as defined in RFC1997, or a
4265 * similar community, to prevent propagation of the
4266 * prefix outside the local AS. The community to prevent
4267 * propagation SHOULD be chosen according to the operator's
4270 if (bgp_attr_get_community(&new_attr
) &&
4271 community_include(bgp_attr_get_community(&new_attr
),
4272 COMMUNITY_BLACKHOLE
))
4273 bgp_attr_add_no_export_community(&new_attr
);
4275 /* If we receive the graceful-shutdown community from an eBGP
4276 * peer we must lower local-preference */
4277 if (bgp_attr_get_community(&new_attr
) &&
4278 community_include(bgp_attr_get_community(&new_attr
),
4280 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4281 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4283 /* If graceful-shutdown is configured globally or
4284 * per neighbor, then add the GSHUT community to
4285 * all paths received from eBGP peers. */
4286 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4287 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4288 bgp_attr_add_gshut_community(&new_attr
);
4291 /* next hop check. */
4292 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4293 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4295 peer
->stat_pfx_nh_invalid
++;
4296 reason
= "martian or self next-hop;";
4297 bgp_attr_flush(&new_attr
);
4301 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4302 peer
->stat_pfx_nh_invalid
++;
4303 reason
= "self mac;";
4304 bgp_attr_flush(&new_attr
);
4308 if (bgp_check_role_applicability(afi
, safi
) &&
4309 bgp_otc_filter(peer
, &new_attr
)) {
4310 reason
= "failing otc validation";
4311 bgp_attr_flush(&new_attr
);
4315 /* If neighbor soo is configured, tag all incoming routes with
4316 * this SoO tag and then filter out advertisements in
4317 * subgroup_announce_check() if it matches the configured SoO
4318 * on the other peer.
4320 if (peer
->soo
[afi
][safi
]) {
4321 struct ecommunity
*old_ecomm
=
4322 bgp_attr_get_ecommunity(&new_attr
);
4323 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4324 struct ecommunity
*new_ecomm
;
4327 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4330 if (!old_ecomm
->refcnt
)
4331 ecommunity_free(&old_ecomm
);
4333 new_ecomm
= ecommunity_dup(ecomm_soo
);
4336 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4339 attr_new
= bgp_attr_intern(&new_attr
);
4341 /* If the update is implicit withdraw. */
4343 pi
->uptime
= monotime(NULL
);
4344 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4346 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4348 /* Same attribute comes in. */
4349 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4351 && (!has_valid_label
4352 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4353 num_labels
* sizeof(mpls_label_t
))
4355 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4356 BGP_CONFIG_DAMPENING
)
4357 && peer
->sort
== BGP_PEER_EBGP
4358 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4359 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4360 bgp_debug_rdpfxpath2str(
4361 afi
, safi
, prd
, p
, label
,
4362 num_labels
, addpath_id
? 1 : 0,
4363 addpath_id
, evpn
, pfx_buf
,
4365 zlog_debug("%pBP rcvd %s", peer
,
4369 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4370 != BGP_DAMP_SUPPRESSED
) {
4371 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4373 bgp_process(bgp
, dest
, afi
, safi
);
4375 } else /* Duplicate - odd */
4377 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4378 if (!peer
->rcvd_attr_printed
) {
4380 "%pBP rcvd UPDATE w/ attr: %s",
4382 peer
->rcvd_attr_str
);
4383 peer
->rcvd_attr_printed
= 1;
4386 bgp_debug_rdpfxpath2str(
4387 afi
, safi
, prd
, p
, label
,
4388 num_labels
, addpath_id
? 1 : 0,
4389 addpath_id
, evpn
, pfx_buf
,
4392 "%pBP rcvd %s...duplicate ignored",
4396 /* graceful restart STALE flag unset. */
4397 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4398 bgp_path_info_unset_flag(
4399 dest
, pi
, BGP_PATH_STALE
);
4400 bgp_dest_set_defer_flag(dest
, false);
4401 bgp_process(bgp
, dest
, afi
, safi
);
4405 bgp_dest_unlock_node(dest
);
4406 bgp_attr_unintern(&attr_new
);
4411 /* Withdraw/Announce before we fully processed the withdraw */
4412 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4413 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4414 bgp_debug_rdpfxpath2str(
4415 afi
, safi
, prd
, p
, label
, num_labels
,
4416 addpath_id
? 1 : 0, addpath_id
, evpn
,
4417 pfx_buf
, sizeof(pfx_buf
));
4419 "%pBP rcvd %s, flapped quicker than processing",
4423 bgp_path_info_restore(dest
, pi
);
4426 * If the BGP_PATH_REMOVED flag is set, then EVPN
4427 * routes would have been unimported already when a
4428 * prior BGP withdraw processing happened. Such routes
4429 * need to be imported again, so flag accordingly.
4431 force_evpn_import
= true;
4433 /* implicit withdraw, decrement aggregate and pcount
4434 * here. only if update is accepted, they'll increment
4437 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4440 /* Received Logging. */
4441 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4442 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4443 num_labels
, addpath_id
? 1 : 0,
4444 addpath_id
, evpn
, pfx_buf
,
4446 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4449 /* graceful restart STALE flag unset. */
4450 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4451 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4452 bgp_dest_set_defer_flag(dest
, false);
4455 /* The attribute is changed. */
4456 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4458 /* Update bgp route dampening information. */
4459 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4460 && peer
->sort
== BGP_PEER_EBGP
) {
4461 /* This is implicit withdraw so we should update
4464 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4465 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4467 #ifdef ENABLE_BGP_VNC
4468 if (safi
== SAFI_MPLS_VPN
) {
4469 struct bgp_dest
*pdest
= NULL
;
4470 struct bgp_table
*table
= NULL
;
4472 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4473 (struct prefix
*)prd
);
4474 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4475 table
= bgp_dest_get_bgp_table_info(pdest
);
4477 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4478 bgp
, prd
, table
, p
, pi
);
4480 bgp_dest_unlock_node(pdest
);
4482 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4483 && (safi
== SAFI_UNICAST
)) {
4484 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4486 * Implicit withdraw case.
4488 ++vnc_implicit_withdraw
;
4489 vnc_import_bgp_del_route(bgp
, p
, pi
);
4490 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4495 /* Special handling for EVPN update of an existing route. If the
4496 * extended community attribute has changed, we need to
4498 * the route using its existing extended community. It will be
4499 * subsequently processed for import with the new extended
4502 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4505 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4507 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4510 cmp
= ecommunity_cmp(
4511 bgp_attr_get_ecommunity(pi
->attr
),
4512 bgp_attr_get_ecommunity(attr_new
));
4514 if (bgp_debug_update(peer
, p
, NULL
, 1))
4516 "Change in EXT-COMM, existing %s new %s",
4518 bgp_attr_get_ecommunity(
4521 bgp_attr_get_ecommunity(
4523 if (safi
== SAFI_EVPN
)
4524 bgp_evpn_unimport_route(
4525 bgp
, afi
, safi
, p
, pi
);
4526 else /* SAFI_MPLS_VPN */
4527 vpn_leak_to_vrf_withdraw(pi
);
4532 /* Update to new attribute. */
4533 bgp_attr_unintern(&pi
->attr
);
4534 pi
->attr
= attr_new
;
4536 /* Update MPLS label */
4537 if (has_valid_label
) {
4538 extra
= bgp_path_info_extra_get(pi
);
4539 if (extra
->label
!= label
) {
4540 memcpy(&extra
->label
, label
,
4541 num_labels
* sizeof(mpls_label_t
));
4542 extra
->num_labels
= num_labels
;
4544 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4545 bgp_set_valid_label(&extra
->label
[0]);
4548 /* Update SRv6 SID */
4549 if (attr
->srv6_l3vpn
) {
4550 extra
= bgp_path_info_extra_get(pi
);
4551 if (sid_diff(&extra
->sid
[0].sid
,
4552 &attr
->srv6_l3vpn
->sid
)) {
4553 sid_copy(&extra
->sid
[0].sid
,
4554 &attr
->srv6_l3vpn
->sid
);
4555 extra
->num_sids
= 1;
4557 extra
->sid
[0].loc_block_len
= 0;
4558 extra
->sid
[0].loc_node_len
= 0;
4559 extra
->sid
[0].func_len
= 0;
4560 extra
->sid
[0].arg_len
= 0;
4561 extra
->sid
[0].transposition_len
= 0;
4562 extra
->sid
[0].transposition_offset
= 0;
4564 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4565 extra
->sid
[0].loc_block_len
=
4566 attr
->srv6_l3vpn
->loc_block_len
;
4567 extra
->sid
[0].loc_node_len
=
4568 attr
->srv6_l3vpn
->loc_node_len
;
4569 extra
->sid
[0].func_len
=
4570 attr
->srv6_l3vpn
->func_len
;
4571 extra
->sid
[0].arg_len
=
4572 attr
->srv6_l3vpn
->arg_len
;
4573 extra
->sid
[0].transposition_len
=
4575 ->transposition_len
;
4576 extra
->sid
[0].transposition_offset
=
4578 ->transposition_offset
;
4581 } else if (attr
->srv6_vpn
) {
4582 extra
= bgp_path_info_extra_get(pi
);
4583 if (sid_diff(&extra
->sid
[0].sid
,
4584 &attr
->srv6_vpn
->sid
)) {
4585 sid_copy(&extra
->sid
[0].sid
,
4586 &attr
->srv6_vpn
->sid
);
4587 extra
->num_sids
= 1;
4591 #ifdef ENABLE_BGP_VNC
4592 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4593 && (safi
== SAFI_UNICAST
)) {
4594 if (vnc_implicit_withdraw
) {
4596 * Add back the route with its new attributes
4598 * The route is still selected, until the route
4600 * queued by bgp_process actually runs. We have
4602 * update to the VNC side immediately to avoid
4604 * configuration changes (e.g., route-map
4606 * trigger re-importation of the entire RIB.
4608 vnc_import_bgp_add_route(bgp
, p
, pi
);
4609 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4614 /* Update bgp route dampening information. */
4615 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4616 && peer
->sort
== BGP_PEER_EBGP
) {
4617 /* Now we do normal update dampening. */
4618 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4619 if (ret
== BGP_DAMP_SUPPRESSED
) {
4620 bgp_dest_unlock_node(dest
);
4625 /* Nexthop reachability check - for unicast and
4626 * labeled-unicast.. */
4627 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4628 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4629 || (safi
== SAFI_EVPN
&&
4630 bgp_evpn_is_prefix_nht_supported(p
))) {
4631 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4632 && peer
->ttl
== BGP_DEFAULT_TTL
4633 && !CHECK_FLAG(peer
->flags
,
4634 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4635 && !CHECK_FLAG(bgp
->flags
,
4636 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4641 struct bgp
*bgp_nexthop
= bgp
;
4643 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4644 bgp_nexthop
= pi
->extra
->bgp_orig
;
4646 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4648 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4649 safi
, pi
, NULL
, connected
,
4650 bgp_nht_param_prefix
) ||
4651 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4652 bgp_path_info_set_flag(dest
, pi
,
4655 if (BGP_DEBUG(nht
, NHT
)) {
4656 zlog_debug("%s(%pI4): NH unresolved",
4658 (in_addr_t
*)&attr_new
->nexthop
);
4660 bgp_path_info_unset_flag(dest
, pi
,
4665 bgp_path_info_set_flag(dest
, pi
,
4666 BGP_PATH_ACCEPT_OWN
);
4668 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4671 #ifdef ENABLE_BGP_VNC
4672 if (safi
== SAFI_MPLS_VPN
) {
4673 struct bgp_dest
*pdest
= NULL
;
4674 struct bgp_table
*table
= NULL
;
4676 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4677 (struct prefix
*)prd
);
4678 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4679 table
= bgp_dest_get_bgp_table_info(pdest
);
4681 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4682 bgp
, prd
, table
, p
, pi
);
4684 bgp_dest_unlock_node(pdest
);
4688 /* If this is an EVPN route and some attribute has changed,
4689 * or we are explicitly told to perform a route import, process
4690 * route for import. If the extended community has changed, we
4692 * have done the un-import earlier and the import would result
4694 * route getting injected into appropriate L2 VNIs. If it is
4696 * some other attribute change, the import will result in
4698 * the attributes for the route in the VNI(s).
4700 if (safi
== SAFI_EVPN
&&
4701 (!same_attr
|| force_evpn_import
) &&
4702 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4703 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4705 /* Process change. */
4706 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4708 bgp_process(bgp
, dest
, afi
, safi
);
4709 bgp_dest_unlock_node(dest
);
4711 if (SAFI_UNICAST
== safi
4712 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4713 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4715 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4717 if ((SAFI_MPLS_VPN
== safi
)
4718 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4719 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4722 #ifdef ENABLE_BGP_VNC
4723 if (SAFI_MPLS_VPN
== safi
) {
4724 mpls_label_t label_decoded
= decode_label(label
);
4726 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4727 type
, sub_type
, &label_decoded
);
4729 if (SAFI_ENCAP
== safi
) {
4730 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4731 type
, sub_type
, NULL
);
4734 if ((safi
== SAFI_MPLS_VPN
) &&
4735 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4736 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4738 bgp_unlink_nexthop(pi
);
4739 bgp_path_info_delete(dest
, pi
);
4742 } // End of implicit withdraw
4744 /* Received Logging. */
4745 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4746 if (!peer
->rcvd_attr_printed
) {
4747 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4748 peer
->rcvd_attr_str
);
4749 peer
->rcvd_attr_printed
= 1;
4752 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4753 addpath_id
? 1 : 0, addpath_id
, evpn
,
4754 pfx_buf
, sizeof(pfx_buf
));
4755 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4758 /* Make new BGP info. */
4759 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4761 /* Update MPLS label */
4762 if (has_valid_label
) {
4763 extra
= bgp_path_info_extra_get(new);
4764 if (extra
->label
!= label
) {
4765 memcpy(&extra
->label
, label
,
4766 num_labels
* sizeof(mpls_label_t
));
4767 extra
->num_labels
= num_labels
;
4769 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4770 bgp_set_valid_label(&extra
->label
[0]);
4773 /* Update SRv6 SID */
4774 if (safi
== SAFI_MPLS_VPN
) {
4775 extra
= bgp_path_info_extra_get(new);
4776 if (attr
->srv6_l3vpn
) {
4777 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4778 extra
->num_sids
= 1;
4780 extra
->sid
[0].loc_block_len
=
4781 attr
->srv6_l3vpn
->loc_block_len
;
4782 extra
->sid
[0].loc_node_len
=
4783 attr
->srv6_l3vpn
->loc_node_len
;
4784 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4785 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4786 extra
->sid
[0].transposition_len
=
4787 attr
->srv6_l3vpn
->transposition_len
;
4788 extra
->sid
[0].transposition_offset
=
4789 attr
->srv6_l3vpn
->transposition_offset
;
4790 } else if (attr
->srv6_vpn
) {
4791 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4792 extra
->num_sids
= 1;
4796 /* Nexthop reachability check. */
4797 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4798 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4799 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4800 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4801 && peer
->ttl
== BGP_DEFAULT_TTL
4802 && !CHECK_FLAG(peer
->flags
,
4803 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4804 && !CHECK_FLAG(bgp
->flags
,
4805 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4810 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4812 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4813 connected
, bgp_nht_param_prefix
) ||
4814 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4815 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4817 if (BGP_DEBUG(nht
, NHT
))
4818 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4819 &attr_new
->nexthop
);
4820 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4824 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4826 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4829 /* If maximum prefix count is configured and current prefix
4832 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4833 reason
= "maximum-prefix overflow";
4834 bgp_attr_flush(&new_attr
);
4839 new->addpath_rx_id
= addpath_id
;
4841 /* Increment prefix */
4842 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4844 /* Register new BGP information. */
4845 bgp_path_info_add(dest
, new);
4847 /* route_node_get lock */
4848 bgp_dest_unlock_node(dest
);
4850 #ifdef ENABLE_BGP_VNC
4851 if (safi
== SAFI_MPLS_VPN
) {
4852 struct bgp_dest
*pdest
= NULL
;
4853 struct bgp_table
*table
= NULL
;
4855 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4856 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4857 table
= bgp_dest_get_bgp_table_info(pdest
);
4859 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4860 bgp
, prd
, table
, p
, new);
4862 bgp_dest_unlock_node(pdest
);
4866 /* If this is an EVPN route, process for import. */
4867 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4868 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4870 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4872 /* Process change. */
4873 bgp_process(bgp
, dest
, afi
, safi
);
4875 if (SAFI_UNICAST
== safi
4876 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4877 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4878 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4880 if ((SAFI_MPLS_VPN
== safi
)
4881 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4882 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4884 #ifdef ENABLE_BGP_VNC
4885 if (SAFI_MPLS_VPN
== safi
) {
4886 mpls_label_t label_decoded
= decode_label(label
);
4888 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4889 sub_type
, &label_decoded
);
4891 if (SAFI_ENCAP
== safi
) {
4892 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4896 if ((safi
== SAFI_MPLS_VPN
) &&
4897 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4898 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4900 bgp_unlink_nexthop(new);
4901 bgp_path_info_delete(dest
, new);
4906 /* This BGP update is filtered. Log the reason then update BGP
4910 bgp_unlink_nexthop(new);
4911 bgp_path_info_delete(dest
, new);
4912 bgp_path_info_extra_free(&new->extra
);
4913 XFREE(MTYPE_BGP_ROUTE
, new);
4916 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4918 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4919 if (!peer
->rcvd_attr_printed
) {
4920 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4921 peer
->rcvd_attr_str
);
4922 peer
->rcvd_attr_printed
= 1;
4925 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4926 addpath_id
? 1 : 0, addpath_id
, evpn
,
4927 pfx_buf
, sizeof(pfx_buf
));
4928 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4929 peer
, pfx_buf
, reason
);
4933 /* If this is an EVPN route, un-import it as it is now filtered.
4935 if (safi
== SAFI_EVPN
)
4936 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4938 if (SAFI_UNICAST
== safi
4939 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4940 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4942 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4944 if ((SAFI_MPLS_VPN
== safi
)
4945 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4947 vpn_leak_to_vrf_withdraw(pi
);
4950 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4953 bgp_dest_unlock_node(dest
);
4955 #ifdef ENABLE_BGP_VNC
4957 * Filtered update is treated as an implicit withdrawal (see
4959 * a few lines above)
4961 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4962 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4970 void bgp_withdraw(struct peer
*peer
, const struct prefix
*p
,
4971 uint32_t addpath_id
, afi_t afi
, safi_t safi
, int type
,
4972 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4973 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4976 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4977 struct bgp_dest
*dest
;
4978 struct bgp_path_info
*pi
;
4980 #ifdef ENABLE_BGP_VNC
4981 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4982 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4990 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4992 /* If peer is soft reconfiguration enabled. Record input packet for
4993 * further calculation.
4995 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4996 * routes that are filtered. This tanks out Quagga RS pretty badly due
4998 * the iteration over all RS clients.
4999 * Since we need to remove the entry from adj_in anyway, do that first
5001 * if there was no entry, we don't need to do anything more.
5003 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
5004 && peer
!= bgp
->peer_self
)
5005 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
5006 peer
->stat_pfx_dup_withdraw
++;
5008 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5009 bgp_debug_rdpfxpath2str(
5010 afi
, safi
, prd
, p
, label
, num_labels
,
5011 addpath_id
? 1 : 0, addpath_id
, NULL
,
5012 pfx_buf
, sizeof(pfx_buf
));
5014 "%s withdrawing route %s not in adj-in",
5015 peer
->host
, pfx_buf
);
5017 bgp_dest_unlock_node(dest
);
5021 /* Lookup withdrawn route. */
5022 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5023 if (pi
->peer
== peer
&& pi
->type
== type
5024 && pi
->sub_type
== sub_type
5025 && pi
->addpath_rx_id
== addpath_id
)
5029 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5030 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5031 addpath_id
? 1 : 0, addpath_id
, NULL
,
5032 pfx_buf
, sizeof(pfx_buf
));
5033 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
5037 /* Withdraw specified route from routing table. */
5038 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
5039 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
5040 if (SAFI_UNICAST
== safi
5041 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5042 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5043 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5045 if ((SAFI_MPLS_VPN
== safi
)
5046 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5048 vpn_leak_to_vrf_withdraw(pi
);
5050 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5051 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5052 addpath_id
? 1 : 0, addpath_id
, NULL
,
5053 pfx_buf
, sizeof(pfx_buf
));
5054 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
5057 /* Unlock bgp_node_get() lock. */
5058 bgp_dest_unlock_node(dest
);
5063 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
5066 struct update_subgroup
*subgrp
;
5067 subgrp
= peer_subgroup(peer
, afi
, safi
);
5068 subgroup_default_originate(subgrp
, withdraw
);
5073 * bgp_stop_announce_route_timer
5075 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5077 if (!paf
->t_announce_route
)
5080 EVENT_OFF(paf
->t_announce_route
);
5084 * bgp_announce_route_timer_expired
5086 * Callback that is invoked when the route announcement timer for a
5089 static void bgp_announce_route_timer_expired(struct event
*t
)
5091 struct peer_af
*paf
;
5097 if (!peer_established(peer
))
5100 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5103 peer_af_announce_route(paf
, 1);
5105 /* Notify BGP conditional advertisement scanner percess */
5106 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5110 * bgp_announce_route
5112 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5114 * if force is true we will force an update even if the update
5115 * limiting code is attempted to kick in.
5117 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5119 struct peer_af
*paf
;
5120 struct update_subgroup
*subgrp
;
5122 paf
= peer_af_find(peer
, afi
, safi
);
5125 subgrp
= PAF_SUBGRP(paf
);
5128 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5129 * or a refresh has already been triggered.
5131 if (!subgrp
|| paf
->t_announce_route
)
5135 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5138 * Start a timer to stagger/delay the announce. This serves
5139 * two purposes - announcement can potentially be combined for
5140 * multiple peers and the announcement doesn't happen in the
5143 event_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5144 (subgrp
->peer_count
== 1)
5145 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5146 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5147 &paf
->t_announce_route
);
5151 * Announce routes from all AF tables to a peer.
5153 * This should ONLY be called when there is a need to refresh the
5154 * routes to the peer based on a policy change for this peer alone
5155 * or a route refresh request received from the peer.
5156 * The operation will result in splitting the peer from its existing
5157 * subgroups and putting it in new subgroups.
5159 void bgp_announce_route_all(struct peer
*peer
)
5164 FOREACH_AFI_SAFI (afi
, safi
)
5165 bgp_announce_route(peer
, afi
, safi
, false);
5168 /* Flag or unflag bgp_dest to determine whether it should be treated by
5169 * bgp_soft_reconfig_table_task.
5170 * Flag if flag is true. Unflag if flag is false.
5172 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5174 struct bgp_dest
*dest
;
5175 struct bgp_adj_in
*ain
;
5180 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5181 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5182 if (ain
->peer
!= NULL
)
5185 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5186 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5188 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5192 static void bgp_soft_reconfig_table_update(struct peer
*peer
,
5193 struct bgp_dest
*dest
,
5194 struct bgp_adj_in
*ain
, afi_t afi
,
5195 safi_t safi
, struct prefix_rd
*prd
)
5197 struct bgp_path_info
*pi
;
5198 uint32_t num_labels
= 0;
5199 mpls_label_t
*label_pnt
= NULL
;
5200 struct bgp_route_evpn evpn
;
5202 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5203 if (pi
->peer
== peer
)
5206 if (pi
&& pi
->extra
)
5207 num_labels
= pi
->extra
->num_labels
;
5209 label_pnt
= &pi
->extra
->label
[0];
5211 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5214 memset(&evpn
, 0, sizeof(evpn
));
5216 bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5217 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, prd
,
5218 label_pnt
, num_labels
, 1, &evpn
);
5221 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5222 struct bgp_table
*table
,
5223 struct prefix_rd
*prd
)
5225 struct bgp_dest
*dest
;
5226 struct bgp_adj_in
*ain
;
5229 table
= peer
->bgp
->rib
[afi
][safi
];
5231 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5232 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5233 if (ain
->peer
!= peer
)
5236 bgp_soft_reconfig_table_update(peer
, dest
, ain
, afi
,
5241 /* Do soft reconfig table per bgp table.
5242 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5243 * when BGP_NODE_SOFT_RECONFIG is set,
5244 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5245 * Schedule a new thread to continue the job.
5246 * Without splitting the full job into several part,
5247 * vtysh waits for the job to finish before responding to a BGP command
5249 static void bgp_soft_reconfig_table_task(struct event
*thread
)
5251 uint32_t iter
, max_iter
;
5252 struct bgp_dest
*dest
;
5253 struct bgp_adj_in
*ain
;
5255 struct bgp_table
*table
;
5256 struct prefix_rd
*prd
;
5257 struct listnode
*node
, *nnode
;
5259 table
= EVENT_ARG(thread
);
5262 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5263 if (table
->soft_reconfig_init
) {
5264 /* first call of the function with a new srta structure.
5265 * Don't do any treatment this time on nodes
5266 * in order vtysh to respond quickly
5271 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5272 dest
= bgp_route_next(dest
)) {
5273 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5276 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5278 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5279 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5281 if (ain
->peer
!= peer
)
5284 bgp_soft_reconfig_table_update(
5285 peer
, dest
, ain
, table
->afi
,
5292 /* we're either starting the initial iteration,
5293 * or we're going to continue an ongoing iteration
5295 if (dest
|| table
->soft_reconfig_init
) {
5296 table
->soft_reconfig_init
= false;
5297 event_add_event(bm
->master
, bgp_soft_reconfig_table_task
, table
,
5298 0, &table
->soft_reconfig_thread
);
5301 /* we're done, clean up the background iteration context info and
5302 schedule route annoucement
5304 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5305 listnode_delete(table
->soft_reconfig_peers
, peer
);
5306 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5309 list_delete(&table
->soft_reconfig_peers
);
5313 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5315 * - bgp cannot be NULL
5316 * - if table and peer are NULL, cancel all threads within the bgp instance
5317 * - if table is NULL and peer is not,
5318 * remove peer in all threads within the bgp instance
5319 * - if peer is NULL, cancel all threads matching table within the bgp instance
5321 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5322 const struct bgp_table
*table
,
5323 const struct peer
*peer
)
5326 struct listnode
*node
, *nnode
;
5328 struct bgp_table
*ntable
;
5333 FOREACH_AFI_SAFI (afi
, safi
) {
5334 ntable
= bgp
->rib
[afi
][safi
];
5337 if (table
&& table
!= ntable
)
5340 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5342 if (peer
&& peer
!= npeer
)
5344 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5347 if (!ntable
->soft_reconfig_peers
5348 || !list_isempty(ntable
->soft_reconfig_peers
))
5351 list_delete(&ntable
->soft_reconfig_peers
);
5352 bgp_soft_reconfig_table_flag(ntable
, false);
5353 EVENT_OFF(ntable
->soft_reconfig_thread
);
5358 * Returns false if the peer is not configured for soft reconfig in
5360 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5362 struct bgp_dest
*dest
;
5363 struct bgp_table
*table
;
5364 struct listnode
*node
, *nnode
;
5366 struct peer_af
*paf
;
5368 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5371 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5372 && (safi
!= SAFI_EVPN
)) {
5373 table
= peer
->bgp
->rib
[afi
][safi
];
5377 table
->soft_reconfig_init
= true;
5379 if (!table
->soft_reconfig_peers
)
5380 table
->soft_reconfig_peers
= list_new();
5382 /* add peer to the table soft_reconfig_peers if not already
5385 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5391 listnode_add(table
->soft_reconfig_peers
, peer
);
5393 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5394 * on table would start back at the beginning.
5396 bgp_soft_reconfig_table_flag(table
, true);
5398 if (!table
->soft_reconfig_thread
)
5399 event_add_event(bm
->master
,
5400 bgp_soft_reconfig_table_task
, table
, 0,
5401 &table
->soft_reconfig_thread
);
5402 /* Cancel bgp_announce_route_timer_expired threads.
5403 * bgp_announce_route_timer_expired threads have been scheduled
5404 * to announce routes as soon as the soft_reconfigure process
5406 * In this case, soft_reconfigure is also scheduled by using
5407 * a thread but is planned after the
5408 * bgp_announce_route_timer_expired threads. It means that,
5409 * without cancelling the threads, the route announcement task
5410 * would run before the soft reconfiguration one. That would
5411 * useless and would block vtysh during several seconds. Route
5412 * announcements are rescheduled as soon as the soft_reconfigure
5415 paf
= peer_af_find(peer
, afi
, safi
);
5417 bgp_stop_announce_route_timer(paf
);
5419 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5420 dest
= bgp_route_next(dest
)) {
5421 table
= bgp_dest_get_bgp_table_info(dest
);
5426 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5427 struct prefix_rd prd
;
5429 prd
.family
= AF_UNSPEC
;
5431 memcpy(&prd
.val
, p
->u
.val
, 8);
5433 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5440 struct bgp_clear_node_queue
{
5441 struct bgp_dest
*dest
;
5444 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5446 struct bgp_clear_node_queue
*cnq
= data
;
5447 struct bgp_dest
*dest
= cnq
->dest
;
5448 struct peer
*peer
= wq
->spec
.data
;
5449 struct bgp_path_info
*pi
;
5451 afi_t afi
= bgp_dest_table(dest
)->afi
;
5452 safi_t safi
= bgp_dest_table(dest
)->safi
;
5454 assert(dest
&& peer
);
5457 /* It is possible that we have multiple paths for a prefix from a peer
5458 * if that peer is using AddPath.
5460 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5461 if (pi
->peer
!= peer
)
5464 /* graceful restart STALE flag set. */
5465 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5466 && peer
->nsf
[afi
][safi
])
5467 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5468 PEER_STATUS_ENHANCED_REFRESH
))
5469 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5470 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5471 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5473 /* If this is an EVPN route, process for
5475 if (safi
== SAFI_EVPN
)
5476 bgp_evpn_unimport_route(
5478 bgp_dest_get_prefix(dest
), pi
);
5479 /* Handle withdraw for VRF route-leaking and L3VPN */
5480 if (SAFI_UNICAST
== safi
5481 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5482 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5483 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5486 if (SAFI_MPLS_VPN
== safi
&&
5487 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5488 vpn_leak_to_vrf_withdraw(pi
);
5491 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5497 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5499 struct bgp_clear_node_queue
*cnq
= data
;
5500 struct bgp_dest
*dest
= cnq
->dest
;
5501 struct bgp_table
*table
= bgp_dest_table(dest
);
5503 bgp_dest_unlock_node(dest
);
5504 bgp_table_unlock(table
);
5505 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5508 static void bgp_clear_node_complete(struct work_queue
*wq
)
5510 struct peer
*peer
= wq
->spec
.data
;
5512 /* Tickle FSM to start moving again */
5513 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5515 peer_unlock(peer
); /* bgp_clear_route */
5518 static void bgp_clear_node_queue_init(struct peer
*peer
)
5520 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5522 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5523 #undef CLEAR_QUEUE_NAME_LEN
5525 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5526 peer
->clear_node_queue
->spec
.hold
= 10;
5527 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5528 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5529 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5530 peer
->clear_node_queue
->spec
.max_retries
= 0;
5532 /* we only 'lock' this peer reference when the queue is actually active
5534 peer
->clear_node_queue
->spec
.data
= peer
;
5537 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5538 struct bgp_table
*table
)
5540 struct bgp_dest
*dest
;
5541 int force
= peer
->bgp
->process_queue
? 0 : 1;
5544 table
= peer
->bgp
->rib
[afi
][safi
];
5546 /* If still no table => afi/safi isn't configured at all or smth. */
5550 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5551 struct bgp_path_info
*pi
, *next
;
5552 struct bgp_adj_in
*ain
;
5553 struct bgp_adj_in
*ain_next
;
5555 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5556 * queued for every clearing peer, regardless of whether it is
5557 * relevant to the peer at hand.
5559 * Overview: There are 3 different indices which need to be
5560 * scrubbed, potentially, when a peer is removed:
5562 * 1 peer's routes visible via the RIB (ie accepted routes)
5563 * 2 peer's routes visible by the (optional) peer's adj-in index
5564 * 3 other routes visible by the peer's adj-out index
5566 * 3 there is no hurry in scrubbing, once the struct peer is
5567 * removed from bgp->peer, we could just GC such deleted peer's
5568 * adj-outs at our leisure.
5570 * 1 and 2 must be 'scrubbed' in some way, at least made
5571 * invisible via RIB index before peer session is allowed to be
5572 * brought back up. So one needs to know when such a 'search' is
5577 * - there'd be a single global queue or a single RIB walker
5578 * - rather than tracking which route_nodes still need to be
5579 * examined on a peer basis, we'd track which peers still
5582 * Given that our per-peer prefix-counts now should be reliable,
5583 * this may actually be achievable. It doesn't seem to be a huge
5584 * problem at this time,
5586 * It is possible that we have multiple paths for a prefix from
5588 * if that peer is using AddPath.
5592 ain_next
= ain
->next
;
5594 if (ain
->peer
== peer
)
5595 bgp_adj_in_remove(dest
, ain
);
5600 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5602 if (pi
->peer
!= peer
)
5606 bgp_path_info_reap(dest
, pi
);
5608 struct bgp_clear_node_queue
*cnq
;
5610 /* both unlocked in bgp_clear_node_queue_del */
5611 bgp_table_lock(bgp_dest_table(dest
));
5612 bgp_dest_lock_node(dest
);
5614 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5615 sizeof(struct bgp_clear_node_queue
));
5617 work_queue_add(peer
->clear_node_queue
, cnq
);
5625 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5627 struct bgp_dest
*dest
;
5628 struct bgp_table
*table
;
5630 if (peer
->clear_node_queue
== NULL
)
5631 bgp_clear_node_queue_init(peer
);
5633 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5634 * Idle until it receives a Clearing_Completed event. This protects
5635 * against peers which flap faster than we can we clear, which could
5638 * a) race with routes from the new session being installed before
5639 * clear_route_node visits the node (to delete the route of that
5641 * b) resource exhaustion, clear_route_node likely leads to an entry
5642 * on the process_main queue. Fast-flapping could cause that queue
5646 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5647 * the unlock will happen upon work-queue completion; other wise, the
5648 * unlock happens at the end of this function.
5650 if (!peer
->clear_node_queue
->thread
)
5653 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5654 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5656 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5657 dest
= bgp_route_next(dest
)) {
5658 table
= bgp_dest_get_bgp_table_info(dest
);
5662 bgp_clear_route_table(peer
, afi
, safi
, table
);
5665 /* unlock if no nodes got added to the clear-node-queue. */
5666 if (!peer
->clear_node_queue
->thread
)
5670 void bgp_clear_route_all(struct peer
*peer
)
5675 FOREACH_AFI_SAFI (afi
, safi
)
5676 bgp_clear_route(peer
, afi
, safi
);
5678 #ifdef ENABLE_BGP_VNC
5679 rfapiProcessPeerDown(peer
);
5683 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5685 struct bgp_table
*table
;
5686 struct bgp_dest
*dest
;
5687 struct bgp_adj_in
*ain
;
5688 struct bgp_adj_in
*ain_next
;
5690 table
= peer
->bgp
->rib
[afi
][safi
];
5692 /* It is possible that we have multiple paths for a prefix from a peer
5693 * if that peer is using AddPath.
5695 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5699 ain_next
= ain
->next
;
5701 if (ain
->peer
== peer
)
5702 bgp_adj_in_remove(dest
, ain
);
5709 /* If any of the routes from the peer have been marked with the NO_LLGR
5710 * community, either as sent by the peer, or as the result of a configured
5711 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5712 * operation of [RFC4271].
5714 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5716 struct bgp_dest
*dest
;
5717 struct bgp_path_info
*pi
;
5718 struct bgp_table
*table
;
5720 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5721 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5722 dest
= bgp_route_next(dest
)) {
5723 struct bgp_dest
*rm
;
5725 /* look for neighbor in tables */
5726 table
= bgp_dest_get_bgp_table_info(dest
);
5730 for (rm
= bgp_table_top(table
); rm
;
5731 rm
= bgp_route_next(rm
))
5732 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5734 if (pi
->peer
!= peer
)
5737 peer
->af_sflags
[afi
][safi
],
5738 PEER_STATUS_LLGR_WAIT
) &&
5739 bgp_attr_get_community(pi
->attr
) &&
5741 bgp_attr_get_community(
5745 if (!CHECK_FLAG(pi
->flags
,
5750 * If this is VRF leaked route
5751 * process for withdraw.
5754 BGP_ROUTE_IMPORTED
&&
5755 peer
->bgp
->inst_type
==
5756 BGP_INSTANCE_TYPE_DEFAULT
)
5757 vpn_leak_to_vrf_withdraw(pi
);
5759 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5764 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5765 dest
= bgp_route_next(dest
))
5766 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5768 if (pi
->peer
!= peer
)
5770 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5771 PEER_STATUS_LLGR_WAIT
) &&
5772 bgp_attr_get_community(pi
->attr
) &&
5774 bgp_attr_get_community(pi
->attr
),
5777 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5779 if (safi
== SAFI_UNICAST
&&
5780 (peer
->bgp
->inst_type
==
5781 BGP_INSTANCE_TYPE_VRF
||
5782 peer
->bgp
->inst_type
==
5783 BGP_INSTANCE_TYPE_DEFAULT
))
5784 vpn_leak_from_vrf_withdraw(
5785 bgp_get_default(), peer
->bgp
,
5788 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5794 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5796 struct bgp_dest
*dest
, *ndest
;
5797 struct bgp_path_info
*pi
;
5798 struct bgp_table
*table
;
5800 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5801 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5802 dest
= bgp_route_next(dest
)) {
5803 table
= bgp_dest_get_bgp_table_info(dest
);
5807 for (ndest
= bgp_table_top(table
); ndest
;
5808 ndest
= bgp_route_next(ndest
)) {
5809 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5811 if (pi
->peer
!= peer
)
5815 peer
->af_sflags
[afi
][safi
],
5816 PEER_STATUS_ENHANCED_REFRESH
))
5817 && !CHECK_FLAG(pi
->flags
,
5821 BGP_PATH_UNUSEABLE
)) {
5822 if (bgp_debug_neighbor_events(
5825 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5829 bgp_dest_get_prefix(
5832 bgp_path_info_set_flag(
5840 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5841 dest
= bgp_route_next(dest
)) {
5842 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5844 if (pi
->peer
!= peer
)
5847 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5848 PEER_STATUS_ENHANCED_REFRESH
))
5849 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5850 && !CHECK_FLAG(pi
->flags
,
5851 BGP_PATH_UNUSEABLE
)) {
5852 if (bgp_debug_neighbor_events(peer
))
5854 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5857 bgp_dest_get_prefix(
5860 bgp_path_info_set_flag(dest
, pi
,
5868 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5870 if (peer
->sort
== BGP_PEER_IBGP
)
5873 if (peer
->sort
== BGP_PEER_EBGP
5874 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5875 || FILTER_LIST_OUT_NAME(filter
)
5876 || DISTRIBUTE_OUT_NAME(filter
)))
5881 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5883 if (peer
->sort
== BGP_PEER_IBGP
)
5886 if (peer
->sort
== BGP_PEER_EBGP
5887 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5888 || FILTER_LIST_IN_NAME(filter
)
5889 || DISTRIBUTE_IN_NAME(filter
)))
5894 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5897 struct bgp_dest
*dest
;
5898 struct bgp_path_info
*pi
;
5899 struct bgp_path_info
*next
;
5901 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5902 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5903 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5907 /* Unimport EVPN routes from VRFs */
5908 if (safi
== SAFI_EVPN
)
5909 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5912 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5913 && pi
->type
== ZEBRA_ROUTE_BGP
5914 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5915 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5916 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5918 if (bgp_fibupd_safi(safi
))
5919 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5922 bgp_path_info_reap(dest
, pi
);
5926 /* Delete all kernel routes. */
5927 void bgp_cleanup_routes(struct bgp
*bgp
)
5930 struct bgp_dest
*dest
;
5931 struct bgp_table
*table
;
5933 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5934 if (afi
== AFI_L2VPN
)
5936 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5939 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5941 if (afi
!= AFI_L2VPN
) {
5943 safi
= SAFI_MPLS_VPN
;
5944 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5945 dest
= bgp_route_next(dest
)) {
5946 table
= bgp_dest_get_bgp_table_info(dest
);
5947 if (table
!= NULL
) {
5948 bgp_cleanup_table(bgp
, table
, safi
);
5949 bgp_table_finish(&table
);
5950 bgp_dest_set_bgp_table_info(dest
, NULL
);
5951 bgp_dest_unlock_node(dest
);
5955 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5956 dest
= bgp_route_next(dest
)) {
5957 table
= bgp_dest_get_bgp_table_info(dest
);
5958 if (table
!= NULL
) {
5959 bgp_cleanup_table(bgp
, table
, safi
);
5960 bgp_table_finish(&table
);
5961 bgp_dest_set_bgp_table_info(dest
, NULL
);
5962 bgp_dest_unlock_node(dest
);
5967 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5968 dest
= bgp_route_next(dest
)) {
5969 table
= bgp_dest_get_bgp_table_info(dest
);
5970 if (table
!= NULL
) {
5971 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5972 bgp_table_finish(&table
);
5973 bgp_dest_set_bgp_table_info(dest
, NULL
);
5974 bgp_dest_unlock_node(dest
);
5979 void bgp_reset(void)
5982 bgp_zclient_reset();
5983 access_list_reset();
5984 prefix_list_reset();
5987 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5989 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5990 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5991 PEER_CAP_ADDPATH_AF_TX_RCV
));
5994 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5996 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5997 struct bgp_nlri
*packet
)
6005 bool addpath_capable
;
6006 uint32_t addpath_id
;
6009 lim
= pnt
+ packet
->length
;
6011 safi
= packet
->safi
;
6013 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
6015 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6016 syntactic validity. If the field is syntactically incorrect,
6017 then the Error Subcode is set to Invalid Network Field. */
6018 for (; pnt
< lim
; pnt
+= psize
) {
6019 /* Clear prefix structure. */
6020 memset(&p
, 0, sizeof(p
));
6022 if (addpath_capable
) {
6024 /* When packet overflow occurs return immediately. */
6025 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
6026 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6028 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
6029 addpath_id
= ntohl(addpath_id
);
6030 pnt
+= BGP_ADDPATH_ID_LEN
;
6033 /* Fetch prefix length. */
6034 p
.prefixlen
= *pnt
++;
6035 /* afi/safi validity already verified by caller,
6036 * bgp_update_receive */
6037 p
.family
= afi2family(afi
);
6039 /* Prefix length check. */
6040 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
6043 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
6044 peer
->host
, p
.prefixlen
, packet
->afi
);
6045 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
6048 /* Packet size overflow check. */
6049 psize
= PSIZE(p
.prefixlen
);
6051 /* When packet overflow occur return immediately. */
6052 if (pnt
+ psize
> lim
) {
6055 "%s [Error] Update packet error (prefix length %d overflows packet)",
6056 peer
->host
, p
.prefixlen
);
6057 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6060 /* Defensive coding, double-check the psize fits in a struct
6061 * prefix for the v4 and v6 afi's and unicast/multicast */
6062 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6065 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6066 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6067 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6070 /* Fetch prefix from NLRI packet. */
6071 memcpy(p
.u
.val
, pnt
, psize
);
6073 /* Check address. */
6074 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6075 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6076 /* From RFC4271 Section 6.3:
6078 * If a prefix in the NLRI field is semantically
6080 * (e.g., an unexpected multicast IP address),
6082 * be logged locally, and the prefix SHOULD be
6087 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6088 peer
->host
, &p
.u
.prefix4
);
6093 /* Check address. */
6094 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6095 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6098 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6099 peer
->host
, &p
.u
.prefix6
);
6103 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6106 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6107 peer
->host
, &p
.u
.prefix6
);
6113 /* Normal process. */
6115 bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6116 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6119 bgp_withdraw(peer
, &p
, addpath_id
, afi
, safi
,
6120 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6123 /* Do not send BGP notification twice when maximum-prefix count
6125 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6126 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6129 /* Packet length consistency check. */
6133 "%s [Error] Update packet error (prefix length mismatch with total length)",
6135 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6138 return BGP_NLRI_PARSE_OK
;
6141 static struct bgp_static
*bgp_static_new(void)
6143 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6146 static void bgp_static_free(struct bgp_static
*bgp_static
)
6148 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6149 route_map_counter_decrement(bgp_static
->rmap
.map
);
6151 if (bgp_static
->prd_pretty
)
6152 XFREE(MTYPE_BGP
, bgp_static
->prd_pretty
);
6153 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6154 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6157 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6158 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6160 struct bgp_dest
*dest
;
6161 struct bgp_path_info
*pi
;
6162 struct bgp_path_info
*new;
6163 struct bgp_path_info rmap_path
;
6165 struct attr
*attr_new
;
6166 route_map_result_t ret
;
6167 #ifdef ENABLE_BGP_VNC
6168 int vnc_implicit_withdraw
= 0;
6173 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6175 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6177 attr
.nexthop
= bgp_static
->igpnexthop
;
6178 attr
.med
= bgp_static
->igpmetric
;
6179 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6182 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6184 if (bgp_static
->igpmetric
)
6185 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6187 if (bgp_static
->atomic
)
6188 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6190 /* Store label index, if required. */
6191 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6192 attr
.label_index
= bgp_static
->label_index
;
6193 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6196 /* Apply route-map. */
6197 if (bgp_static
->rmap
.name
) {
6198 struct attr attr_tmp
= attr
;
6200 memset(&rmap_path
, 0, sizeof(rmap_path
));
6201 rmap_path
.peer
= bgp
->peer_self
;
6202 rmap_path
.attr
= &attr_tmp
;
6204 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6206 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6208 bgp
->peer_self
->rmap_type
= 0;
6210 if (ret
== RMAP_DENYMATCH
) {
6211 /* Free uninterned attribute. */
6212 bgp_attr_flush(&attr_tmp
);
6214 /* Unintern original. */
6215 aspath_unintern(&attr
.aspath
);
6216 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6217 bgp_dest_unlock_node(dest
);
6221 if (bgp_in_graceful_shutdown(bgp
))
6222 bgp_attr_add_gshut_community(&attr_tmp
);
6224 attr_new
= bgp_attr_intern(&attr_tmp
);
6227 if (bgp_in_graceful_shutdown(bgp
))
6228 bgp_attr_add_gshut_community(&attr
);
6230 attr_new
= bgp_attr_intern(&attr
);
6233 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6234 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6235 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6239 if (attrhash_cmp(pi
->attr
, attr_new
)
6240 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6241 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6242 bgp_dest_unlock_node(dest
);
6243 bgp_attr_unintern(&attr_new
);
6244 aspath_unintern(&attr
.aspath
);
6247 /* The attribute is changed. */
6248 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6250 /* Rewrite BGP route information. */
6251 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6252 bgp_path_info_restore(dest
, pi
);
6254 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6255 #ifdef ENABLE_BGP_VNC
6256 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6257 && (safi
== SAFI_UNICAST
)) {
6258 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6260 * Implicit withdraw case.
6261 * We have to do this before pi is
6264 ++vnc_implicit_withdraw
;
6265 vnc_import_bgp_del_route(bgp
, p
, pi
);
6266 vnc_import_bgp_exterior_del_route(
6271 bgp_attr_unintern(&pi
->attr
);
6272 pi
->attr
= attr_new
;
6273 pi
->uptime
= monotime(NULL
);
6274 #ifdef ENABLE_BGP_VNC
6275 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6276 && (safi
== SAFI_UNICAST
)) {
6277 if (vnc_implicit_withdraw
) {
6278 vnc_import_bgp_add_route(bgp
, p
, pi
);
6279 vnc_import_bgp_exterior_add_route(
6285 /* Nexthop reachability check. */
6286 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6287 && (safi
== SAFI_UNICAST
6288 || safi
== SAFI_LABELED_UNICAST
)) {
6290 struct bgp
*bgp_nexthop
= bgp
;
6292 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6293 bgp_nexthop
= pi
->extra
->bgp_orig
;
6295 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6296 afi
, safi
, pi
, NULL
,
6298 bgp_path_info_set_flag(dest
, pi
,
6301 if (BGP_DEBUG(nht
, NHT
)) {
6302 char buf1
[INET6_ADDRSTRLEN
];
6303 inet_ntop(p
->family
,
6307 "%s(%s): Route not in table, not advertising",
6310 bgp_path_info_unset_flag(
6311 dest
, pi
, BGP_PATH_VALID
);
6314 /* Delete the NHT structure if any, if we're
6316 * enabling/disabling import check. We
6317 * deregister the route
6318 * from NHT to avoid overloading NHT and the
6319 * process interaction
6321 bgp_unlink_nexthop(pi
);
6322 bgp_path_info_set_flag(dest
, pi
,
6325 /* Process change. */
6326 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6327 bgp_process(bgp
, dest
, afi
, safi
);
6329 if (SAFI_UNICAST
== safi
6330 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6332 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6333 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6337 bgp_dest_unlock_node(dest
);
6338 aspath_unintern(&attr
.aspath
);
6343 /* Make new BGP info. */
6344 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6346 /* Nexthop reachability check. */
6347 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6348 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6349 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6351 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6353 if (BGP_DEBUG(nht
, NHT
)) {
6354 char buf1
[INET6_ADDRSTRLEN
];
6356 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6359 "%s(%s): Route not in table, not advertising",
6362 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6365 /* Delete the NHT structure if any, if we're toggling between
6366 * enabling/disabling import check. We deregister the route
6367 * from NHT to avoid overloading NHT and the process interaction
6369 bgp_unlink_nexthop(new);
6371 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6374 /* Aggregate address increment. */
6375 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6377 /* Register new BGP information. */
6378 bgp_path_info_add(dest
, new);
6380 /* route_node_get lock */
6381 bgp_dest_unlock_node(dest
);
6383 /* Process change. */
6384 bgp_process(bgp
, dest
, afi
, safi
);
6386 if (SAFI_UNICAST
== safi
6387 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6388 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6389 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6392 /* Unintern original. */
6393 aspath_unintern(&attr
.aspath
);
6396 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6399 struct bgp_dest
*dest
;
6400 struct bgp_path_info
*pi
;
6402 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6404 /* Check selected route and self inserted route. */
6405 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6406 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6407 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6410 /* Withdraw static BGP route from routing table. */
6412 if (SAFI_UNICAST
== safi
6413 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6414 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6415 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6417 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6418 bgp_unlink_nexthop(pi
);
6419 bgp_path_info_delete(dest
, pi
);
6420 bgp_process(bgp
, dest
, afi
, safi
);
6423 /* Unlock bgp_node_lookup. */
6424 bgp_dest_unlock_node(dest
);
6428 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6430 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6431 afi_t afi
, safi_t safi
,
6432 struct prefix_rd
*prd
)
6434 struct bgp_dest
*dest
;
6435 struct bgp_path_info
*pi
;
6437 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6439 /* Check selected route and self inserted route. */
6440 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6441 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6442 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6445 /* Withdraw static BGP route from routing table. */
6447 #ifdef ENABLE_BGP_VNC
6448 rfapiProcessWithdraw(
6449 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6450 1); /* Kill, since it is an administrative change */
6452 if (SAFI_MPLS_VPN
== safi
6453 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6454 vpn_leak_to_vrf_withdraw(pi
);
6456 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6457 bgp_path_info_delete(dest
, pi
);
6458 bgp_process(bgp
, dest
, afi
, safi
);
6461 /* Unlock bgp_node_lookup. */
6462 bgp_dest_unlock_node(dest
);
6465 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6466 struct bgp_static
*bgp_static
, afi_t afi
,
6469 struct bgp_dest
*dest
;
6470 struct bgp_path_info
*new;
6471 struct attr
*attr_new
;
6472 struct attr attr
= {0};
6473 struct bgp_path_info
*pi
;
6474 #ifdef ENABLE_BGP_VNC
6475 mpls_label_t label
= 0;
6477 uint32_t num_labels
= 0;
6481 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6483 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6486 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6488 attr
.nexthop
= bgp_static
->igpnexthop
;
6489 attr
.med
= bgp_static
->igpmetric
;
6490 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6492 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6493 || (safi
== SAFI_ENCAP
)) {
6494 if (afi
== AFI_IP
) {
6495 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6496 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6499 if (afi
== AFI_L2VPN
) {
6500 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6501 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6502 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6503 &bgp_static
->gatewayIp
.u
.prefix4
,
6505 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6506 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6507 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6508 &bgp_static
->gatewayIp
.u
.prefix6
,
6511 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6512 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6513 struct bgp_encap_type_vxlan bet
;
6514 memset(&bet
, 0, sizeof(bet
));
6515 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6516 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6518 if (bgp_static
->router_mac
) {
6519 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6522 /* Apply route-map. */
6523 if (bgp_static
->rmap
.name
) {
6524 struct attr attr_tmp
= attr
;
6525 struct bgp_path_info rmap_path
;
6526 route_map_result_t ret
;
6528 rmap_path
.peer
= bgp
->peer_self
;
6529 rmap_path
.attr
= &attr_tmp
;
6531 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6533 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6535 bgp
->peer_self
->rmap_type
= 0;
6537 if (ret
== RMAP_DENYMATCH
) {
6538 /* Free uninterned attribute. */
6539 bgp_attr_flush(&attr_tmp
);
6541 /* Unintern original. */
6542 aspath_unintern(&attr
.aspath
);
6543 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6545 bgp_dest_unlock_node(dest
);
6549 attr_new
= bgp_attr_intern(&attr_tmp
);
6551 attr_new
= bgp_attr_intern(&attr
);
6554 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6555 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6556 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6560 if (attrhash_cmp(pi
->attr
, attr_new
)
6561 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6562 bgp_dest_unlock_node(dest
);
6563 bgp_attr_unintern(&attr_new
);
6564 aspath_unintern(&attr
.aspath
);
6567 /* The attribute is changed. */
6568 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6570 /* Rewrite BGP route information. */
6571 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6572 bgp_path_info_restore(dest
, pi
);
6574 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6575 bgp_attr_unintern(&pi
->attr
);
6576 pi
->attr
= attr_new
;
6577 pi
->uptime
= monotime(NULL
);
6578 #ifdef ENABLE_BGP_VNC
6580 label
= decode_label(&pi
->extra
->label
[0]);
6583 /* Process change. */
6584 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6585 bgp_process(bgp
, dest
, afi
, safi
);
6587 if (SAFI_MPLS_VPN
== safi
6588 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6589 vpn_leak_to_vrf_update(bgp
, pi
,
6592 #ifdef ENABLE_BGP_VNC
6593 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6594 pi
->attr
, afi
, safi
, pi
->type
,
6595 pi
->sub_type
, &label
);
6597 bgp_dest_unlock_node(dest
);
6598 aspath_unintern(&attr
.aspath
);
6604 /* Make new BGP info. */
6605 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6607 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6608 bgp_path_info_extra_get(new);
6610 new->extra
->label
[0] = bgp_static
->label
;
6611 new->extra
->num_labels
= num_labels
;
6613 #ifdef ENABLE_BGP_VNC
6614 label
= decode_label(&bgp_static
->label
);
6617 /* Aggregate address increment. */
6618 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6620 /* Register new BGP information. */
6621 bgp_path_info_add(dest
, new);
6622 /* route_node_get lock */
6623 bgp_dest_unlock_node(dest
);
6625 /* Process change. */
6626 bgp_process(bgp
, dest
, afi
, safi
);
6628 if (SAFI_MPLS_VPN
== safi
6629 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6630 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6632 #ifdef ENABLE_BGP_VNC
6633 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6634 safi
, new->type
, new->sub_type
, &label
);
6637 /* Unintern original. */
6638 aspath_unintern(&attr
.aspath
);
6641 /* Configure static BGP network. When user don't run zebra, static
6642 route should be installed as valid. */
6643 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6644 const char *ip_str
, afi_t afi
, safi_t safi
,
6645 const char *rmap
, int backdoor
, uint32_t label_index
)
6647 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6650 struct bgp_static
*bgp_static
;
6651 struct bgp_dest
*dest
;
6652 uint8_t need_update
= 0;
6654 /* Convert IP prefix string to struct prefix. */
6655 ret
= str2prefix(ip_str
, &p
);
6657 vty_out(vty
, "%% Malformed prefix\n");
6658 return CMD_WARNING_CONFIG_FAILED
;
6660 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6661 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6662 return CMD_WARNING_CONFIG_FAILED
;
6669 /* Set BGP static route configuration. */
6670 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6673 vty_out(vty
, "%% Can't find static route specified\n");
6674 return CMD_WARNING_CONFIG_FAILED
;
6677 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6679 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6680 && (label_index
!= bgp_static
->label_index
)) {
6682 "%% label-index doesn't match static route\n");
6683 bgp_dest_unlock_node(dest
);
6684 return CMD_WARNING_CONFIG_FAILED
;
6687 if ((rmap
&& bgp_static
->rmap
.name
)
6688 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6690 "%% route-map name doesn't match static route\n");
6691 bgp_dest_unlock_node(dest
);
6692 return CMD_WARNING_CONFIG_FAILED
;
6695 /* Update BGP RIB. */
6696 if (!bgp_static
->backdoor
)
6697 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6699 /* Clear configuration. */
6700 bgp_static_free(bgp_static
);
6701 bgp_dest_set_bgp_static_info(dest
, NULL
);
6702 bgp_dest_unlock_node(dest
);
6703 bgp_dest_unlock_node(dest
);
6706 /* Set BGP static route configuration. */
6707 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6708 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6710 /* Configuration change. */
6711 /* Label index cannot be changed. */
6712 if (bgp_static
->label_index
!= label_index
) {
6713 vty_out(vty
, "%% cannot change label-index\n");
6714 bgp_dest_unlock_node(dest
);
6715 return CMD_WARNING_CONFIG_FAILED
;
6718 /* Check previous routes are installed into BGP. */
6719 if (bgp_static
->valid
6720 && bgp_static
->backdoor
!= backdoor
)
6723 bgp_static
->backdoor
= backdoor
;
6726 XFREE(MTYPE_ROUTE_MAP_NAME
,
6727 bgp_static
->rmap
.name
);
6728 route_map_counter_decrement(
6729 bgp_static
->rmap
.map
);
6730 bgp_static
->rmap
.name
=
6731 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6732 bgp_static
->rmap
.map
=
6733 route_map_lookup_by_name(rmap
);
6734 route_map_counter_increment(
6735 bgp_static
->rmap
.map
);
6737 XFREE(MTYPE_ROUTE_MAP_NAME
,
6738 bgp_static
->rmap
.name
);
6739 route_map_counter_decrement(
6740 bgp_static
->rmap
.map
);
6741 bgp_static
->rmap
.map
= NULL
;
6742 bgp_static
->valid
= 0;
6744 bgp_dest_unlock_node(dest
);
6746 /* New configuration. */
6747 bgp_static
= bgp_static_new();
6748 bgp_static
->backdoor
= backdoor
;
6749 bgp_static
->valid
= 0;
6750 bgp_static
->igpmetric
= 0;
6751 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6752 bgp_static
->label_index
= label_index
;
6755 XFREE(MTYPE_ROUTE_MAP_NAME
,
6756 bgp_static
->rmap
.name
);
6757 route_map_counter_decrement(
6758 bgp_static
->rmap
.map
);
6759 bgp_static
->rmap
.name
=
6760 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6761 bgp_static
->rmap
.map
=
6762 route_map_lookup_by_name(rmap
);
6763 route_map_counter_increment(
6764 bgp_static
->rmap
.map
);
6766 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6769 bgp_static
->valid
= 1;
6771 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6773 if (!bgp_static
->backdoor
)
6774 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6780 void bgp_static_add(struct bgp
*bgp
)
6784 struct bgp_dest
*dest
;
6785 struct bgp_dest
*rm
;
6786 struct bgp_table
*table
;
6787 struct bgp_static
*bgp_static
;
6789 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6790 FOREACH_AFI_SAFI (afi
, safi
)
6791 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6792 dest
= bgp_route_next(dest
)) {
6793 if (!bgp_dest_has_bgp_path_info_data(dest
))
6796 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6797 || (safi
== SAFI_EVPN
)) {
6798 table
= bgp_dest_get_bgp_table_info(dest
);
6800 for (rm
= bgp_table_top(table
); rm
;
6801 rm
= bgp_route_next(rm
)) {
6803 bgp_dest_get_bgp_static_info(
6805 bgp_static_update_safi(
6806 bgp
, bgp_dest_get_prefix(rm
),
6807 bgp_static
, afi
, safi
);
6811 bgp
, bgp_dest_get_prefix(dest
),
6812 bgp_dest_get_bgp_static_info(dest
), afi
,
6816 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6819 /* Called from bgp_delete(). Delete all static routes from the BGP
6821 void bgp_static_delete(struct bgp
*bgp
)
6825 struct bgp_dest
*dest
;
6826 struct bgp_dest
*rm
;
6827 struct bgp_table
*table
;
6828 struct bgp_static
*bgp_static
;
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(
6848 bgp_static_withdraw_safi(
6849 bgp
, bgp_dest_get_prefix(rm
),
6851 (struct prefix_rd
*)
6852 bgp_dest_get_prefix(
6854 bgp_static_free(bgp_static
);
6855 bgp_dest_set_bgp_static_info(rm
,
6857 bgp_dest_unlock_node(rm
);
6860 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6861 bgp_static_withdraw(bgp
,
6862 bgp_dest_get_prefix(dest
),
6864 bgp_static_free(bgp_static
);
6865 bgp_dest_set_bgp_static_info(dest
, NULL
);
6866 bgp_dest_unlock_node(dest
);
6871 void bgp_static_redo_import_check(struct bgp
*bgp
)
6875 struct bgp_dest
*dest
;
6876 struct bgp_dest
*rm
;
6877 struct bgp_table
*table
;
6878 struct bgp_static
*bgp_static
;
6880 /* Use this flag to force reprocessing of the route */
6881 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6882 FOREACH_AFI_SAFI (afi
, safi
) {
6883 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6884 dest
= bgp_route_next(dest
)) {
6885 if (!bgp_dest_has_bgp_path_info_data(dest
))
6888 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6889 || (safi
== SAFI_EVPN
)) {
6890 table
= bgp_dest_get_bgp_table_info(dest
);
6892 for (rm
= bgp_table_top(table
); rm
;
6893 rm
= bgp_route_next(rm
)) {
6895 bgp_dest_get_bgp_static_info(
6897 bgp_static_update_safi(
6898 bgp
, bgp_dest_get_prefix(rm
),
6899 bgp_static
, afi
, safi
);
6902 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6903 bgp_static_update(bgp
,
6904 bgp_dest_get_prefix(dest
),
6905 bgp_static
, afi
, safi
);
6909 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6912 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6915 struct bgp_table
*table
;
6916 struct bgp_dest
*dest
;
6917 struct bgp_path_info
*pi
;
6919 /* Do not install the aggregate route if BGP is in the
6920 * process of termination.
6922 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6923 || (bgp
->peer_self
== NULL
))
6926 table
= bgp
->rib
[afi
][safi
];
6927 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6928 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6929 if (pi
->peer
== bgp
->peer_self
6930 && ((pi
->type
== ZEBRA_ROUTE_BGP
6931 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6932 || (pi
->type
!= ZEBRA_ROUTE_BGP
6934 == BGP_ROUTE_REDISTRIBUTE
))) {
6935 bgp_aggregate_decrement(
6936 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6938 bgp_unlink_nexthop(pi
);
6939 bgp_path_info_delete(dest
, pi
);
6940 bgp_process(bgp
, dest
, afi
, safi
);
6947 * Purge all networks and redistributed routes from routing table.
6948 * Invoked upon the instance going down.
6950 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6955 FOREACH_AFI_SAFI (afi
, safi
)
6956 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6961 * Currently this is used to set static routes for VPN and ENCAP.
6962 * I think it can probably be factored with bgp_static_set.
6964 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6965 const char *ip_str
, const char *rd_str
,
6966 const char *label_str
, const char *rmap_str
,
6967 int evpn_type
, const char *esi
, const char *gwip
,
6968 const char *ethtag
, const char *routermac
)
6970 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6973 struct prefix_rd prd
;
6974 struct bgp_dest
*pdest
;
6975 struct bgp_dest
*dest
;
6976 struct bgp_table
*table
;
6977 struct bgp_static
*bgp_static
;
6978 mpls_label_t label
= MPLS_INVALID_LABEL
;
6979 struct prefix gw_ip
;
6981 /* validate ip prefix */
6982 ret
= str2prefix(ip_str
, &p
);
6984 vty_out(vty
, "%% Malformed prefix\n");
6985 return CMD_WARNING_CONFIG_FAILED
;
6988 if ((afi
== AFI_L2VPN
)
6989 && (bgp_build_evpn_prefix(evpn_type
,
6990 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6991 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6992 return CMD_WARNING_CONFIG_FAILED
;
6995 ret
= str2prefix_rd(rd_str
, &prd
);
6997 vty_out(vty
, "%% Malformed rd\n");
6998 return CMD_WARNING_CONFIG_FAILED
;
7002 unsigned long label_val
;
7003 label_val
= strtoul(label_str
, NULL
, 10);
7004 encode_label(label_val
, &label
);
7007 if (safi
== SAFI_EVPN
) {
7008 if (esi
&& str2esi(esi
, NULL
) == 0) {
7009 vty_out(vty
, "%% Malformed ESI\n");
7010 return CMD_WARNING_CONFIG_FAILED
;
7012 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
7013 vty_out(vty
, "%% Malformed Router MAC\n");
7014 return CMD_WARNING_CONFIG_FAILED
;
7017 memset(&gw_ip
, 0, sizeof(gw_ip
));
7018 ret
= str2prefix(gwip
, &gw_ip
);
7020 vty_out(vty
, "%% Malformed GatewayIp\n");
7021 return CMD_WARNING_CONFIG_FAILED
;
7023 if ((gw_ip
.family
== AF_INET
7024 && is_evpn_prefix_ipaddr_v6(
7025 (struct prefix_evpn
*)&p
))
7026 || (gw_ip
.family
== AF_INET6
7027 && is_evpn_prefix_ipaddr_v4(
7028 (struct prefix_evpn
*)&p
))) {
7030 "%% GatewayIp family differs with IP prefix\n");
7031 return CMD_WARNING_CONFIG_FAILED
;
7035 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7036 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7037 bgp_dest_set_bgp_table_info(pdest
,
7038 bgp_table_init(bgp
, afi
, safi
));
7039 table
= bgp_dest_get_bgp_table_info(pdest
);
7041 dest
= bgp_node_get(table
, &p
);
7043 if (bgp_dest_has_bgp_path_info_data(dest
)) {
7044 vty_out(vty
, "%% Same network configuration exists\n");
7045 bgp_dest_unlock_node(dest
);
7047 /* New configuration. */
7048 bgp_static
= bgp_static_new();
7049 bgp_static
->backdoor
= 0;
7050 bgp_static
->valid
= 0;
7051 bgp_static
->igpmetric
= 0;
7052 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7053 bgp_static
->label
= label
;
7054 bgp_static
->prd
= prd
;
7056 bgp_static
->prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_str
);
7059 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7060 route_map_counter_decrement(bgp_static
->rmap
.map
);
7061 bgp_static
->rmap
.name
=
7062 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7063 bgp_static
->rmap
.map
=
7064 route_map_lookup_by_name(rmap_str
);
7065 route_map_counter_increment(bgp_static
->rmap
.map
);
7068 if (safi
== SAFI_EVPN
) {
7070 bgp_static
->eth_s_id
=
7073 str2esi(esi
, bgp_static
->eth_s_id
);
7076 bgp_static
->router_mac
=
7077 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7078 (void)prefix_str2mac(routermac
,
7079 bgp_static
->router_mac
);
7082 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7084 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7086 bgp_static
->valid
= 1;
7087 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7093 /* Configure static BGP network. */
7094 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7095 const char *ip_str
, const char *rd_str
,
7096 const char *label_str
, int evpn_type
, const char *esi
,
7097 const char *gwip
, const char *ethtag
)
7099 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7102 struct prefix_rd prd
;
7103 struct bgp_dest
*pdest
;
7104 struct bgp_dest
*dest
;
7105 struct bgp_table
*table
;
7106 struct bgp_static
*bgp_static
;
7107 mpls_label_t label
= MPLS_INVALID_LABEL
;
7109 /* Convert IP prefix string to struct prefix. */
7110 ret
= str2prefix(ip_str
, &p
);
7112 vty_out(vty
, "%% Malformed prefix\n");
7113 return CMD_WARNING_CONFIG_FAILED
;
7116 if ((afi
== AFI_L2VPN
)
7117 && (bgp_build_evpn_prefix(evpn_type
,
7118 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7119 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7120 return CMD_WARNING_CONFIG_FAILED
;
7122 ret
= str2prefix_rd(rd_str
, &prd
);
7124 vty_out(vty
, "%% Malformed rd\n");
7125 return CMD_WARNING_CONFIG_FAILED
;
7129 unsigned long label_val
;
7130 label_val
= strtoul(label_str
, NULL
, 10);
7131 encode_label(label_val
, &label
);
7134 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7135 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7136 bgp_dest_set_bgp_table_info(pdest
,
7137 bgp_table_init(bgp
, afi
, safi
));
7139 bgp_dest_unlock_node(pdest
);
7140 table
= bgp_dest_get_bgp_table_info(pdest
);
7142 dest
= bgp_node_lookup(table
, &p
);
7145 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7147 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7148 bgp_static_free(bgp_static
);
7149 bgp_dest_set_bgp_static_info(dest
, NULL
);
7150 bgp_dest_unlock_node(dest
);
7151 bgp_dest_unlock_node(dest
);
7153 vty_out(vty
, "%% Can't find the route\n");
7158 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7159 const char *rmap_name
)
7161 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7162 struct bgp_rmap
*rmap
;
7164 rmap
= &bgp
->table_map
[afi
][safi
];
7166 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7167 route_map_counter_decrement(rmap
->map
);
7168 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7169 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7170 route_map_counter_increment(rmap
->map
);
7172 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7173 route_map_counter_decrement(rmap
->map
);
7177 if (bgp_fibupd_safi(safi
))
7178 bgp_zebra_announce_table(bgp
, afi
, safi
);
7183 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7184 const char *rmap_name
)
7186 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7187 struct bgp_rmap
*rmap
;
7189 rmap
= &bgp
->table_map
[afi
][safi
];
7190 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7191 route_map_counter_decrement(rmap
->map
);
7194 if (bgp_fibupd_safi(safi
))
7195 bgp_zebra_announce_table(bgp
, afi
, safi
);
7200 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7203 if (bgp
->table_map
[afi
][safi
].name
) {
7204 vty_out(vty
, " table-map %s\n",
7205 bgp
->table_map
[afi
][safi
].name
);
7209 DEFUN (bgp_table_map
,
7212 "BGP table to RIB route download filter\n"
7213 "Name of the route map\n")
7216 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7217 argv
[idx_word
]->arg
);
7219 DEFUN (no_bgp_table_map
,
7220 no_bgp_table_map_cmd
,
7221 "no table-map WORD",
7223 "BGP table to RIB route download filter\n"
7224 "Name of the route map\n")
7227 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7228 argv
[idx_word
]->arg
);
7234 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7235 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7236 backdoor$backdoor}]",
7238 "Specify a network to announce via BGP\n"
7243 "Route-map to modify the attributes\n"
7244 "Name of the route map\n"
7245 "Label index to associate with the prefix\n"
7246 "Label index value\n"
7247 "Specify a BGP backdoor route\n")
7249 char addr_prefix_str
[BUFSIZ
];
7254 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7256 sizeof(addr_prefix_str
));
7258 vty_out(vty
, "%% Inconsistent address and mask\n");
7259 return CMD_WARNING_CONFIG_FAILED
;
7263 return bgp_static_set(
7264 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7265 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7266 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7269 DEFPY(ipv6_bgp_network
,
7270 ipv6_bgp_network_cmd
,
7271 "[no] network X:X::X:X/M$prefix \
7272 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7274 "Specify a network to announce via BGP\n"
7276 "Route-map to modify the attributes\n"
7277 "Name of the route map\n"
7278 "Label index to associate with the prefix\n"
7279 "Label index value\n")
7281 return bgp_static_set(
7282 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7283 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7286 static struct bgp_aggregate
*bgp_aggregate_new(void)
7288 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7291 void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7293 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7294 route_map_counter_decrement(aggregate
->suppress_map
);
7295 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7296 route_map_counter_decrement(aggregate
->rmap
.map
);
7297 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7301 * Helper function to avoid repeated code: prepare variables for a
7302 * `route_map_apply` call.
7304 * \returns `true` on route map match, otherwise `false`.
7306 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7307 struct bgp_aggregate
*aggregate
,
7308 struct bgp_path_info
*pi
)
7310 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7311 route_map_result_t rmr
= RMAP_DENYMATCH
;
7312 struct bgp_path_info rmap_path
= {};
7313 struct attr attr
= {};
7315 /* No route map entries created, just don't match. */
7316 if (aggregate
->suppress_map
== NULL
)
7319 /* Call route map matching and return result. */
7320 attr
.aspath
= aspath_empty(bgp
->asnotation
);
7321 rmap_path
.peer
= bgp
->peer_self
;
7322 rmap_path
.attr
= &attr
;
7324 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7325 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7326 bgp
->peer_self
->rmap_type
= 0;
7328 bgp_attr_flush(&attr
);
7329 aspath_unintern(&attr
.aspath
);
7331 return rmr
== RMAP_PERMITMATCH
;
7334 /** Test whether the aggregation has suppressed this path or not. */
7335 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7336 struct bgp_path_info
*pi
)
7338 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7341 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7345 * Suppress this path and keep the reference.
7347 * \returns `true` if needs processing otherwise `false`.
7349 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7350 struct bgp_path_info
*pi
)
7352 struct bgp_path_info_extra
*pie
;
7354 /* Path is already suppressed by this aggregation. */
7355 if (aggr_suppress_exists(aggregate
, pi
))
7358 pie
= bgp_path_info_extra_get(pi
);
7360 /* This is the first suppression, allocate memory and list it. */
7361 if (pie
->aggr_suppressors
== NULL
)
7362 pie
->aggr_suppressors
= list_new();
7364 listnode_add(pie
->aggr_suppressors
, aggregate
);
7366 /* Only mark for processing if suppressed. */
7367 if (listcount(pie
->aggr_suppressors
) == 1) {
7368 if (BGP_DEBUG(update
, UPDATE_OUT
))
7369 zlog_debug("aggregate-address suppressing: %pFX",
7370 bgp_dest_get_prefix(pi
->net
));
7372 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7380 * Unsuppress this path and remove the reference.
7382 * \returns `true` if needs processing otherwise `false`.
7384 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7385 struct bgp_path_info
*pi
)
7387 /* Path wasn't suppressed. */
7388 if (!aggr_suppress_exists(aggregate
, pi
))
7391 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7393 /* Unsuppress and free extra memory if last item. */
7394 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7395 if (BGP_DEBUG(update
, UPDATE_OUT
))
7396 zlog_debug("aggregate-address unsuppressing: %pFX",
7397 bgp_dest_get_prefix(pi
->net
));
7399 list_delete(&pi
->extra
->aggr_suppressors
);
7400 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7407 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7408 struct aspath
*aspath
,
7409 struct community
*comm
,
7410 struct ecommunity
*ecomm
,
7411 struct lcommunity
*lcomm
)
7413 static struct aspath
*ae
= NULL
;
7414 enum asnotation_mode asnotation
;
7416 asnotation
= bgp_get_asnotation(NULL
);
7419 ae
= aspath_empty(asnotation
);
7424 if (origin
!= pi
->attr
->origin
)
7427 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7430 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7433 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7436 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7439 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7445 static void bgp_aggregate_install(
7446 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7447 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7448 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7449 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7451 struct bgp_dest
*dest
;
7452 struct bgp_table
*table
;
7453 struct bgp_path_info
*pi
, *orig
, *new;
7456 table
= bgp
->rib
[afi
][safi
];
7458 dest
= bgp_node_get(table
, p
);
7460 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7461 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7462 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7466 * If we have paths with different MEDs, then don't install
7467 * (or uninstall) the aggregate route.
7469 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7470 goto uninstall_aggregate_route
;
7472 if (aggregate
->count
> 0) {
7474 * If the aggregate information has not changed
7475 * no need to re-install it again.
7477 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7478 ecommunity
, lcommunity
)) {
7479 bgp_dest_unlock_node(dest
);
7482 aspath_free(aspath
);
7484 community_free(&community
);
7486 ecommunity_free(&ecommunity
);
7488 lcommunity_free(&lcommunity
);
7494 * Mark the old as unusable
7497 bgp_path_info_delete(dest
, pi
);
7499 attr
= bgp_attr_aggregate_intern(
7500 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7501 aggregate
, atomic_aggregate
, p
);
7504 aspath_free(aspath
);
7505 community_free(&community
);
7506 ecommunity_free(&ecommunity
);
7507 lcommunity_free(&lcommunity
);
7508 bgp_dest_unlock_node(dest
);
7509 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7510 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7511 zlog_debug("%s: %pFX null attribute", __func__
,
7516 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7517 bgp
->peer_self
, attr
, dest
);
7519 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7521 bgp_path_info_add(dest
, new);
7522 bgp_process(bgp
, dest
, afi
, safi
);
7524 uninstall_aggregate_route
:
7525 for (pi
= orig
; pi
; pi
= pi
->next
)
7526 if (pi
->peer
== bgp
->peer_self
7527 && pi
->type
== ZEBRA_ROUTE_BGP
7528 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7531 /* Withdraw static BGP route from routing table. */
7533 bgp_path_info_delete(dest
, pi
);
7534 bgp_process(bgp
, dest
, afi
, safi
);
7538 bgp_dest_unlock_node(dest
);
7542 * Check if the current path has different MED than other known paths.
7544 * \returns `true` if the MED matched the others else `false`.
7546 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7547 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7549 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7551 /* This is the first route being analyzed. */
7552 if (!aggregate
->med_initialized
) {
7553 aggregate
->med_initialized
= true;
7554 aggregate
->med_mismatched
= false;
7555 aggregate
->med_matched_value
= cur_med
;
7557 /* Check if routes with different MED showed up. */
7558 if (cur_med
!= aggregate
->med_matched_value
)
7559 aggregate
->med_mismatched
= true;
7562 return !aggregate
->med_mismatched
;
7566 * Initializes and tests all routes in the aggregate address path for MED
7569 * \returns `true` if all MEDs are the same otherwise `false`.
7571 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7572 struct bgp
*bgp
, const struct prefix
*p
,
7573 afi_t afi
, safi_t safi
)
7575 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7576 const struct prefix
*dest_p
;
7577 struct bgp_dest
*dest
, *top
;
7578 struct bgp_path_info
*pi
;
7579 bool med_matched
= true;
7581 aggregate
->med_initialized
= false;
7583 top
= bgp_node_get(table
, p
);
7584 for (dest
= bgp_node_get(table
, p
); dest
;
7585 dest
= bgp_route_next_until(dest
, top
)) {
7586 dest_p
= bgp_dest_get_prefix(dest
);
7587 if (dest_p
->prefixlen
<= p
->prefixlen
)
7590 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7591 if (BGP_PATH_HOLDDOWN(pi
))
7593 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7595 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7596 med_matched
= false;
7603 bgp_dest_unlock_node(top
);
7609 * Toggles the route suppression status for this aggregate address
7612 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7613 struct bgp
*bgp
, const struct prefix
*p
,
7614 afi_t afi
, safi_t safi
, bool suppress
)
7616 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7617 const struct prefix
*dest_p
;
7618 struct bgp_dest
*dest
, *top
;
7619 struct bgp_path_info
*pi
;
7620 bool toggle_suppression
;
7622 /* We've found a different MED we must revert any suppressed routes. */
7623 top
= bgp_node_get(table
, p
);
7624 for (dest
= bgp_node_get(table
, p
); dest
;
7625 dest
= bgp_route_next_until(dest
, top
)) {
7626 dest_p
= bgp_dest_get_prefix(dest
);
7627 if (dest_p
->prefixlen
<= p
->prefixlen
)
7630 toggle_suppression
= false;
7631 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7632 if (BGP_PATH_HOLDDOWN(pi
))
7634 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7637 /* We are toggling suppression back. */
7639 /* Suppress route if not suppressed already. */
7640 if (aggr_suppress_path(aggregate
, pi
))
7641 toggle_suppression
= true;
7645 /* Install route if there is no more suppression. */
7646 if (aggr_unsuppress_path(aggregate
, pi
))
7647 toggle_suppression
= true;
7650 if (toggle_suppression
)
7651 bgp_process(bgp
, dest
, afi
, safi
);
7653 bgp_dest_unlock_node(top
);
7657 * Aggregate address MED matching incremental test: this function is called
7658 * when the initial aggregation occurred and we are only testing a single
7661 * In addition to testing and setting the MED validity it also installs back
7662 * suppressed routes (if summary is configured).
7664 * Must not be called in `bgp_aggregate_route`.
7666 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7667 struct bgp
*bgp
, const struct prefix
*p
,
7668 afi_t afi
, safi_t safi
,
7669 struct bgp_path_info
*pi
)
7671 /* MED matching disabled. */
7672 if (!aggregate
->match_med
)
7675 /* Aggregation with different MED, recheck if we have got equal MEDs
7678 if (aggregate
->med_mismatched
&&
7679 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7680 aggregate
->summary_only
)
7681 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7684 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7686 /* No mismatches, just quit. */
7687 if (!aggregate
->med_mismatched
)
7690 /* Route summarization is disabled. */
7691 if (!aggregate
->summary_only
)
7694 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7697 /* Update an aggregate as routes are added/removed from the BGP table */
7698 bool bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7699 safi_t safi
, struct bgp_aggregate
*aggregate
)
7701 struct bgp_table
*table
;
7702 struct bgp_dest
*top
;
7703 struct bgp_dest
*dest
;
7705 struct aspath
*aspath
= NULL
;
7706 struct community
*community
= NULL
;
7707 struct ecommunity
*ecommunity
= NULL
;
7708 struct lcommunity
*lcommunity
= NULL
;
7709 struct bgp_path_info
*pi
;
7710 unsigned long match
= 0;
7711 uint8_t atomic_aggregate
= 0;
7713 /* If the bgp instance is being deleted or self peer is deleted
7714 * then do not create aggregate route
7716 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
7717 bgp
->peer_self
== NULL
)
7720 /* Initialize and test routes for MED difference. */
7721 if (aggregate
->match_med
)
7722 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7725 * Reset aggregate count: we might've been called from route map
7726 * update so in that case we must retest all more specific routes.
7728 * \see `bgp_route_map_process_update`.
7730 aggregate
->count
= 0;
7731 aggregate
->incomplete_origin_count
= 0;
7732 aggregate
->incomplete_origin_count
= 0;
7733 aggregate
->egp_origin_count
= 0;
7735 /* ORIGIN attribute: If at least one route among routes that are
7736 aggregated has ORIGIN with the value INCOMPLETE, then the
7737 aggregated route must have the ORIGIN attribute with the value
7738 INCOMPLETE. Otherwise, if at least one route among routes that
7739 are aggregated has ORIGIN with the value EGP, then the aggregated
7740 route must have the origin attribute with the value EGP. In all
7741 other case the value of the ORIGIN attribute of the aggregated
7742 route is INTERNAL. */
7743 origin
= BGP_ORIGIN_IGP
;
7745 table
= bgp
->rib
[afi
][safi
];
7747 top
= bgp_node_get(table
, p
);
7748 for (dest
= bgp_node_get(table
, p
); dest
;
7749 dest
= bgp_route_next_until(dest
, top
)) {
7750 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7752 if (dest_p
->prefixlen
<= p
->prefixlen
)
7755 /* If suppress fib is enabled and route not installed
7756 * in FIB, skip the route
7758 if (!bgp_check_advertise(bgp
, dest
))
7763 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7764 if (BGP_PATH_HOLDDOWN(pi
))
7768 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7769 atomic_aggregate
= 1;
7771 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7775 * summary-only aggregate route suppress
7776 * aggregated route announcements.
7779 * Don't create summaries if MED didn't match
7780 * otherwise neither the specific routes and the
7781 * aggregation will be announced.
7783 if (aggregate
->summary_only
7784 && AGGREGATE_MED_VALID(aggregate
)) {
7785 if (aggr_suppress_path(aggregate
, pi
))
7790 * Suppress more specific routes that match the route
7794 * Don't suppress routes if MED matching is enabled and
7795 * it mismatched otherwise we might end up with no
7796 * routes for this path.
7798 if (aggregate
->suppress_map_name
7799 && AGGREGATE_MED_VALID(aggregate
)
7800 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7801 if (aggr_suppress_path(aggregate
, pi
))
7808 * If at least one route among routes that are
7809 * aggregated has ORIGIN with the value INCOMPLETE,
7810 * then the aggregated route MUST have the ORIGIN
7811 * attribute with the value INCOMPLETE. Otherwise, if
7812 * at least one route among routes that are aggregated
7813 * has ORIGIN with the value EGP, then the aggregated
7814 * route MUST have the ORIGIN attribute with the value
7817 switch (pi
->attr
->origin
) {
7818 case BGP_ORIGIN_INCOMPLETE
:
7819 aggregate
->incomplete_origin_count
++;
7821 case BGP_ORIGIN_EGP
:
7822 aggregate
->egp_origin_count
++;
7830 if (!aggregate
->as_set
)
7834 * as-set aggregate route generate origin, as path,
7835 * and community aggregation.
7837 /* Compute aggregate route's as-path.
7839 bgp_compute_aggregate_aspath_hash(aggregate
,
7842 /* Compute aggregate route's community.
7844 if (bgp_attr_get_community(pi
->attr
))
7845 bgp_compute_aggregate_community_hash(
7847 bgp_attr_get_community(pi
->attr
));
7849 /* Compute aggregate route's extended community.
7851 if (bgp_attr_get_ecommunity(pi
->attr
))
7852 bgp_compute_aggregate_ecommunity_hash(
7854 bgp_attr_get_ecommunity(pi
->attr
));
7856 /* Compute aggregate route's large community.
7858 if (bgp_attr_get_lcommunity(pi
->attr
))
7859 bgp_compute_aggregate_lcommunity_hash(
7861 bgp_attr_get_lcommunity(pi
->attr
));
7864 bgp_process(bgp
, dest
, afi
, safi
);
7866 if (aggregate
->as_set
) {
7867 bgp_compute_aggregate_aspath_val(aggregate
);
7868 bgp_compute_aggregate_community_val(aggregate
);
7869 bgp_compute_aggregate_ecommunity_val(aggregate
);
7870 bgp_compute_aggregate_lcommunity_val(aggregate
);
7874 bgp_dest_unlock_node(top
);
7877 if (aggregate
->incomplete_origin_count
> 0)
7878 origin
= BGP_ORIGIN_INCOMPLETE
;
7879 else if (aggregate
->egp_origin_count
> 0)
7880 origin
= BGP_ORIGIN_EGP
;
7882 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7883 origin
= aggregate
->origin
;
7885 if (aggregate
->as_set
) {
7886 if (aggregate
->aspath
)
7887 /* Retrieve aggregate route's as-path.
7889 aspath
= aspath_dup(aggregate
->aspath
);
7891 if (aggregate
->community
)
7892 /* Retrieve aggregate route's community.
7894 community
= community_dup(aggregate
->community
);
7896 if (aggregate
->ecommunity
)
7897 /* Retrieve aggregate route's ecommunity.
7899 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7901 if (aggregate
->lcommunity
)
7902 /* Retrieve aggregate route's lcommunity.
7904 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7907 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7908 ecommunity
, lcommunity
, atomic_aggregate
,
7914 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7915 safi_t safi
, struct bgp_aggregate
*aggregate
)
7917 struct bgp_table
*table
;
7918 struct bgp_dest
*top
;
7919 struct bgp_dest
*dest
;
7920 struct bgp_path_info
*pi
;
7921 unsigned long match
;
7923 table
= bgp
->rib
[afi
][safi
];
7925 /* If routes exists below this node, generate aggregate routes. */
7926 top
= bgp_node_get(table
, p
);
7927 for (dest
= bgp_node_get(table
, p
); dest
;
7928 dest
= bgp_route_next_until(dest
, top
)) {
7929 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7931 if (dest_p
->prefixlen
<= p
->prefixlen
)
7935 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7936 if (BGP_PATH_HOLDDOWN(pi
))
7939 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7943 * This route is suppressed: attempt to unsuppress it.
7945 * `aggr_unsuppress_path` will fail if this particular
7946 * aggregate route was not the suppressor.
7948 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7949 listcount(pi
->extra
->aggr_suppressors
)) {
7950 if (aggr_unsuppress_path(aggregate
, pi
))
7956 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7957 aggregate
->incomplete_origin_count
--;
7958 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7959 aggregate
->egp_origin_count
--;
7961 if (aggregate
->as_set
) {
7962 /* Remove as-path from aggregate.
7964 bgp_remove_aspath_from_aggregate_hash(
7968 if (bgp_attr_get_community(pi
->attr
))
7969 /* Remove community from aggregate.
7971 bgp_remove_comm_from_aggregate_hash(
7973 bgp_attr_get_community(
7976 if (bgp_attr_get_ecommunity(pi
->attr
))
7977 /* Remove ecommunity from aggregate.
7979 bgp_remove_ecomm_from_aggregate_hash(
7981 bgp_attr_get_ecommunity(
7984 if (bgp_attr_get_lcommunity(pi
->attr
))
7985 /* Remove lcommunity from aggregate.
7987 bgp_remove_lcomm_from_aggregate_hash(
7989 bgp_attr_get_lcommunity(
7994 /* If this node was suppressed, process the change. */
7996 bgp_process(bgp
, dest
, afi
, safi
);
7998 if (aggregate
->as_set
) {
7999 aspath_free(aggregate
->aspath
);
8000 aggregate
->aspath
= NULL
;
8001 if (aggregate
->community
)
8002 community_free(&aggregate
->community
);
8003 if (aggregate
->ecommunity
)
8004 ecommunity_free(&aggregate
->ecommunity
);
8005 if (aggregate
->lcommunity
)
8006 lcommunity_free(&aggregate
->lcommunity
);
8009 bgp_dest_unlock_node(top
);
8012 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
8013 const struct prefix
*aggr_p
,
8014 struct bgp_path_info
*pinew
, afi_t afi
,
8016 struct bgp_aggregate
*aggregate
)
8019 struct aspath
*aspath
= NULL
;
8020 uint8_t atomic_aggregate
= 0;
8021 struct community
*community
= NULL
;
8022 struct ecommunity
*ecommunity
= NULL
;
8023 struct lcommunity
*lcommunity
= NULL
;
8025 /* If the bgp instance is being deleted or self peer is deleted
8026 * then do not create aggregate route
8028 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8029 || (bgp
->peer_self
== NULL
))
8032 /* ORIGIN attribute: If at least one route among routes that are
8033 * aggregated has ORIGIN with the value INCOMPLETE, then the
8034 * aggregated route must have the ORIGIN attribute with the value
8035 * INCOMPLETE. Otherwise, if at least one route among routes that
8036 * are aggregated has ORIGIN with the value EGP, then the aggregated
8037 * route must have the origin attribute with the value EGP. In all
8038 * other case the value of the ORIGIN attribute of the aggregated
8039 * route is INTERNAL.
8041 origin
= BGP_ORIGIN_IGP
;
8046 * This must be called before `summary` check to avoid
8047 * "suppressing" twice.
8049 if (aggregate
->match_med
)
8050 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8053 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8054 aggr_suppress_path(aggregate
, pinew
);
8056 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8057 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8058 aggr_suppress_path(aggregate
, pinew
);
8060 switch (pinew
->attr
->origin
) {
8061 case BGP_ORIGIN_INCOMPLETE
:
8062 aggregate
->incomplete_origin_count
++;
8064 case BGP_ORIGIN_EGP
:
8065 aggregate
->egp_origin_count
++;
8073 if (aggregate
->incomplete_origin_count
> 0)
8074 origin
= BGP_ORIGIN_INCOMPLETE
;
8075 else if (aggregate
->egp_origin_count
> 0)
8076 origin
= BGP_ORIGIN_EGP
;
8078 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8079 origin
= aggregate
->origin
;
8081 if (aggregate
->as_set
) {
8082 /* Compute aggregate route's as-path.
8084 bgp_compute_aggregate_aspath(aggregate
,
8085 pinew
->attr
->aspath
);
8087 /* Compute aggregate route's community.
8089 if (bgp_attr_get_community(pinew
->attr
))
8090 bgp_compute_aggregate_community(
8091 aggregate
, bgp_attr_get_community(pinew
->attr
));
8093 /* Compute aggregate route's extended community.
8095 if (bgp_attr_get_ecommunity(pinew
->attr
))
8096 bgp_compute_aggregate_ecommunity(
8098 bgp_attr_get_ecommunity(pinew
->attr
));
8100 /* Compute aggregate route's large community.
8102 if (bgp_attr_get_lcommunity(pinew
->attr
))
8103 bgp_compute_aggregate_lcommunity(
8105 bgp_attr_get_lcommunity(pinew
->attr
));
8107 /* Retrieve aggregate route's as-path.
8109 if (aggregate
->aspath
)
8110 aspath
= aspath_dup(aggregate
->aspath
);
8112 /* Retrieve aggregate route's community.
8114 if (aggregate
->community
)
8115 community
= community_dup(aggregate
->community
);
8117 /* Retrieve aggregate route's ecommunity.
8119 if (aggregate
->ecommunity
)
8120 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8122 /* Retrieve aggregate route's lcommunity.
8124 if (aggregate
->lcommunity
)
8125 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8128 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8129 aspath
, community
, ecommunity
,
8130 lcommunity
, atomic_aggregate
, aggregate
);
8133 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8135 struct bgp_path_info
*pi
,
8136 struct bgp_aggregate
*aggregate
,
8137 const struct prefix
*aggr_p
)
8140 struct aspath
*aspath
= NULL
;
8141 uint8_t atomic_aggregate
= 0;
8142 struct community
*community
= NULL
;
8143 struct ecommunity
*ecommunity
= NULL
;
8144 struct lcommunity
*lcommunity
= NULL
;
8145 unsigned long match
= 0;
8147 /* If the bgp instance is being deleted or self peer is deleted
8148 * then do not create aggregate route
8150 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8151 || (bgp
->peer_self
== NULL
))
8154 if (BGP_PATH_HOLDDOWN(pi
))
8157 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8160 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8161 if (aggr_unsuppress_path(aggregate
, pi
))
8164 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8165 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8166 if (aggr_unsuppress_path(aggregate
, pi
))
8170 * This must be called after `summary`, `suppress-map` check to avoid
8171 * "unsuppressing" twice.
8173 if (aggregate
->match_med
)
8174 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8176 if (aggregate
->count
> 0)
8179 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8180 aggregate
->incomplete_origin_count
--;
8181 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8182 aggregate
->egp_origin_count
--;
8184 if (aggregate
->as_set
) {
8185 /* Remove as-path from aggregate.
8187 bgp_remove_aspath_from_aggregate(aggregate
,
8190 if (bgp_attr_get_community(pi
->attr
))
8191 /* Remove community from aggregate.
8193 bgp_remove_community_from_aggregate(
8194 aggregate
, bgp_attr_get_community(pi
->attr
));
8196 if (bgp_attr_get_ecommunity(pi
->attr
))
8197 /* Remove ecommunity from aggregate.
8199 bgp_remove_ecommunity_from_aggregate(
8200 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8202 if (bgp_attr_get_lcommunity(pi
->attr
))
8203 /* Remove lcommunity from aggregate.
8205 bgp_remove_lcommunity_from_aggregate(
8206 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8209 /* If this node was suppressed, process the change. */
8211 bgp_process(bgp
, pi
->net
, afi
, safi
);
8213 origin
= BGP_ORIGIN_IGP
;
8214 if (aggregate
->incomplete_origin_count
> 0)
8215 origin
= BGP_ORIGIN_INCOMPLETE
;
8216 else if (aggregate
->egp_origin_count
> 0)
8217 origin
= BGP_ORIGIN_EGP
;
8219 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8220 origin
= aggregate
->origin
;
8222 if (aggregate
->as_set
) {
8223 /* Retrieve aggregate route's as-path.
8225 if (aggregate
->aspath
)
8226 aspath
= aspath_dup(aggregate
->aspath
);
8228 /* Retrieve aggregate route's community.
8230 if (aggregate
->community
)
8231 community
= community_dup(aggregate
->community
);
8233 /* Retrieve aggregate route's ecommunity.
8235 if (aggregate
->ecommunity
)
8236 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8238 /* Retrieve aggregate route's lcommunity.
8240 if (aggregate
->lcommunity
)
8241 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8244 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8245 aspath
, community
, ecommunity
,
8246 lcommunity
, atomic_aggregate
, aggregate
);
8249 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8250 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8252 struct bgp_dest
*child
;
8253 struct bgp_dest
*dest
;
8254 struct bgp_aggregate
*aggregate
;
8255 struct bgp_table
*table
;
8257 table
= bgp
->aggregate
[afi
][safi
];
8259 /* No aggregates configured. */
8260 if (bgp_table_top_nolock(table
) == NULL
)
8263 if (p
->prefixlen
== 0)
8266 if (BGP_PATH_HOLDDOWN(pi
))
8269 /* If suppress fib is enabled and route not installed
8270 * in FIB, do not update the aggregate route
8272 if (!bgp_check_advertise(bgp
, pi
->net
))
8275 child
= bgp_node_get(table
, p
);
8277 /* Aggregate address configuration check. */
8278 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8279 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8281 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8282 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8283 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8287 bgp_dest_unlock_node(child
);
8290 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8291 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8293 struct bgp_dest
*child
;
8294 struct bgp_dest
*dest
;
8295 struct bgp_aggregate
*aggregate
;
8296 struct bgp_table
*table
;
8298 table
= bgp
->aggregate
[afi
][safi
];
8300 /* No aggregates configured. */
8301 if (bgp_table_top_nolock(table
) == NULL
)
8304 if (p
->prefixlen
== 0)
8307 child
= bgp_node_get(table
, p
);
8309 /* Aggregate address configuration check. */
8310 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8311 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8313 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8314 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8315 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8319 bgp_dest_unlock_node(child
);
8322 /* Aggregate route attribute. */
8323 #define AGGREGATE_SUMMARY_ONLY 1
8324 #define AGGREGATE_AS_SET 1
8325 #define AGGREGATE_AS_UNSET 0
8327 static const char *bgp_origin2str(uint8_t origin
)
8330 case BGP_ORIGIN_IGP
:
8332 case BGP_ORIGIN_EGP
:
8334 case BGP_ORIGIN_INCOMPLETE
:
8335 return "incomplete";
8340 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8343 case RPKI_NOT_BEING_USED
:
8353 assert(!"We should never get here this is a dev escape");
8357 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8358 afi_t afi
, safi_t safi
)
8360 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8363 struct bgp_dest
*dest
;
8364 struct bgp_aggregate
*aggregate
;
8366 /* Convert string to prefix structure. */
8367 ret
= str2prefix(prefix_str
, &p
);
8369 vty_out(vty
, "Malformed prefix\n");
8370 return CMD_WARNING_CONFIG_FAILED
;
8374 /* Old configuration check. */
8375 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8378 "%% There is no aggregate-address configuration.\n");
8379 return CMD_WARNING_CONFIG_FAILED
;
8382 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8383 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8384 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8385 NULL
, NULL
, 0, aggregate
);
8387 /* Unlock aggregate address configuration. */
8388 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8390 bgp_free_aggregate_info(aggregate
);
8391 bgp_dest_unlock_node(dest
);
8392 bgp_dest_unlock_node(dest
);
8397 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8398 safi_t safi
, const char *rmap
,
8399 uint8_t summary_only
, uint8_t as_set
,
8400 uint8_t origin
, bool match_med
,
8401 const char *suppress_map
)
8403 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8406 struct bgp_dest
*dest
;
8407 struct bgp_aggregate
*aggregate
;
8408 uint8_t as_set_new
= as_set
;
8410 if (suppress_map
&& summary_only
) {
8412 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8413 return CMD_WARNING_CONFIG_FAILED
;
8416 /* Convert string to prefix structure. */
8417 ret
= str2prefix(prefix_str
, &p
);
8419 vty_out(vty
, "Malformed prefix\n");
8420 return CMD_WARNING_CONFIG_FAILED
;
8424 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8425 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8426 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8428 return CMD_WARNING_CONFIG_FAILED
;
8431 /* Old configuration check. */
8432 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8433 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8436 vty_out(vty
, "There is already same aggregate network.\n");
8437 /* try to remove the old entry */
8438 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8440 vty_out(vty
, "Error deleting aggregate.\n");
8441 bgp_dest_unlock_node(dest
);
8442 return CMD_WARNING_CONFIG_FAILED
;
8446 /* Make aggregate address structure. */
8447 aggregate
= bgp_aggregate_new();
8448 aggregate
->summary_only
= summary_only
;
8449 aggregate
->match_med
= match_med
;
8451 /* Network operators MUST NOT locally generate any new
8452 * announcements containing AS_SET or AS_CONFED_SET. If they have
8453 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8454 * SHOULD withdraw those routes and re-announce routes for the
8455 * aggregate or component prefixes (i.e., the more-specific routes
8456 * subsumed by the previously aggregated route) without AS_SET
8457 * or AS_CONFED_SET in the updates.
8459 if (bgp
->reject_as_sets
) {
8460 if (as_set
== AGGREGATE_AS_SET
) {
8461 as_set_new
= AGGREGATE_AS_UNSET
;
8463 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8466 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8470 aggregate
->as_set
= as_set_new
;
8471 aggregate
->safi
= safi
;
8472 /* Override ORIGIN attribute if defined.
8473 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8474 * to IGP which is not what rfc4271 says.
8475 * This enables the same behavior, optionally.
8477 aggregate
->origin
= origin
;
8480 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8481 route_map_counter_decrement(aggregate
->rmap
.map
);
8482 aggregate
->rmap
.name
=
8483 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8484 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8485 route_map_counter_increment(aggregate
->rmap
.map
);
8489 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8490 route_map_counter_decrement(aggregate
->suppress_map
);
8492 aggregate
->suppress_map_name
=
8493 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8494 aggregate
->suppress_map
=
8495 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8496 route_map_counter_increment(aggregate
->suppress_map
);
8499 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8501 /* Aggregate address insert into BGP routing table. */
8502 if (!bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
)) {
8503 bgp_aggregate_free(aggregate
);
8504 bgp_dest_unlock_node(dest
);
8510 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8511 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8513 "|summary-only$summary_only"
8514 "|route-map RMAP_NAME$rmap_name"
8515 "|origin <egp|igp|incomplete>$origin_s"
8516 "|matching-MED-only$match_med"
8517 "|suppress-map RMAP_NAME$suppress_map"
8520 "Configure BGP aggregate entries\n"
8521 "Aggregate prefix\n"
8522 "Aggregate address\n"
8524 "Generate AS set path information\n"
8525 "Filter more specific routes from updates\n"
8526 "Apply route map to aggregate network\n"
8531 "Unknown heritage\n"
8532 "Only aggregate routes with matching MED\n"
8533 "Suppress the selected more specific routes\n"
8534 "Route map with the route selectors\n")
8536 const char *prefix_s
= NULL
;
8537 safi_t safi
= bgp_node_safi(vty
);
8538 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8539 int as_set
= AGGREGATE_AS_UNSET
;
8540 char prefix_buf
[PREFIX2STR_BUFFER
];
8543 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8546 vty_out(vty
, "%% Inconsistent address and mask\n");
8547 return CMD_WARNING_CONFIG_FAILED
;
8549 prefix_s
= prefix_buf
;
8551 prefix_s
= prefix_str
;
8554 if (strcmp(origin_s
, "egp") == 0)
8555 origin
= BGP_ORIGIN_EGP
;
8556 else if (strcmp(origin_s
, "igp") == 0)
8557 origin
= BGP_ORIGIN_IGP
;
8558 else if (strcmp(origin_s
, "incomplete") == 0)
8559 origin
= BGP_ORIGIN_INCOMPLETE
;
8563 as_set
= AGGREGATE_AS_SET
;
8565 /* Handle configuration removal, otherwise installation. */
8567 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8569 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8570 summary_only
!= NULL
, as_set
, origin
,
8571 match_med
!= NULL
, suppress_map
);
8574 void bgp_free_aggregate_info(struct bgp_aggregate
*aggregate
)
8576 if (aggregate
->community
)
8577 community_free(&aggregate
->community
);
8579 hash_clean_and_free(&aggregate
->community_hash
,
8580 bgp_aggr_community_remove
);
8582 if (aggregate
->ecommunity
)
8583 ecommunity_free(&aggregate
->ecommunity
);
8585 hash_clean_and_free(&aggregate
->ecommunity_hash
,
8586 bgp_aggr_ecommunity_remove
);
8588 if (aggregate
->lcommunity
)
8589 lcommunity_free(&aggregate
->lcommunity
);
8591 hash_clean_and_free(&aggregate
->lcommunity_hash
,
8592 bgp_aggr_lcommunity_remove
);
8594 if (aggregate
->aspath
)
8595 aspath_free(aggregate
->aspath
);
8597 hash_clean_and_free(&aggregate
->aspath_hash
, bgp_aggr_aspath_remove
);
8599 bgp_aggregate_free(aggregate
);
8602 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8603 "[no] aggregate-address X:X::X:X/M$prefix [{"
8605 "|summary-only$summary_only"
8606 "|route-map RMAP_NAME$rmap_name"
8607 "|origin <egp|igp|incomplete>$origin_s"
8608 "|matching-MED-only$match_med"
8609 "|suppress-map RMAP_NAME$suppress_map"
8612 "Configure BGP aggregate entries\n"
8613 "Aggregate prefix\n"
8614 "Generate AS set path information\n"
8615 "Filter more specific routes from updates\n"
8616 "Apply route map to aggregate network\n"
8621 "Unknown heritage\n"
8622 "Only aggregate routes with matching MED\n"
8623 "Suppress the selected more specific routes\n"
8624 "Route map with the route selectors\n")
8626 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8627 int as_set
= AGGREGATE_AS_UNSET
;
8630 if (strcmp(origin_s
, "egp") == 0)
8631 origin
= BGP_ORIGIN_EGP
;
8632 else if (strcmp(origin_s
, "igp") == 0)
8633 origin
= BGP_ORIGIN_IGP
;
8634 else if (strcmp(origin_s
, "incomplete") == 0)
8635 origin
= BGP_ORIGIN_INCOMPLETE
;
8639 as_set
= AGGREGATE_AS_SET
;
8641 /* Handle configuration removal, otherwise installation. */
8643 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8646 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8647 rmap_name
, summary_only
!= NULL
, as_set
,
8648 origin
, match_med
!= NULL
, suppress_map
);
8651 /* Redistribute route treatment. */
8652 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8653 const union g_addr
*nexthop
, ifindex_t ifindex
,
8654 enum nexthop_types_t nhtype
, uint8_t distance
,
8655 enum blackhole_type bhtype
, uint32_t metric
,
8656 uint8_t type
, unsigned short instance
,
8659 struct bgp_path_info
*new;
8660 struct bgp_path_info
*bpi
;
8661 struct bgp_path_info rmap_path
;
8662 struct bgp_dest
*bn
;
8664 struct attr
*new_attr
;
8666 route_map_result_t ret
;
8667 struct bgp_redist
*red
;
8669 /* Make default attribute. */
8670 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8672 * This must not be NULL to satisfy Coverity SA
8674 assert(attr
.aspath
);
8677 case NEXTHOP_TYPE_IFINDEX
:
8678 switch (p
->family
) {
8680 attr
.nexthop
.s_addr
= INADDR_ANY
;
8681 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8684 memset(&attr
.mp_nexthop_global
, 0,
8685 sizeof(attr
.mp_nexthop_global
));
8686 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8690 case NEXTHOP_TYPE_IPV4
:
8691 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8692 attr
.nexthop
= nexthop
->ipv4
;
8693 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8695 case NEXTHOP_TYPE_IPV6
:
8696 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8697 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8698 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8700 case NEXTHOP_TYPE_BLACKHOLE
:
8701 switch (p
->family
) {
8703 attr
.nexthop
.s_addr
= INADDR_ANY
;
8704 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8707 memset(&attr
.mp_nexthop_global
, 0,
8708 sizeof(attr
.mp_nexthop_global
));
8709 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8712 attr
.bh_type
= bhtype
;
8715 attr
.nh_type
= nhtype
;
8716 attr
.nh_ifindex
= ifindex
;
8719 attr
.distance
= distance
;
8720 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8724 bgp_attr_set_aigp_metric(&attr
, metric
);
8726 afi
= family2afi(p
->family
);
8728 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8730 struct attr attr_new
;
8732 /* Copy attribute for modification. */
8735 if (red
->redist_metric_flag
) {
8736 attr_new
.med
= red
->redist_metric
;
8737 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8740 /* Apply route-map. */
8741 if (red
->rmap
.name
) {
8742 memset(&rmap_path
, 0, sizeof(rmap_path
));
8743 rmap_path
.peer
= bgp
->peer_self
;
8744 rmap_path
.attr
= &attr_new
;
8746 SET_FLAG(bgp
->peer_self
->rmap_type
,
8747 PEER_RMAP_TYPE_REDISTRIBUTE
);
8749 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8751 bgp
->peer_self
->rmap_type
= 0;
8753 if (ret
== RMAP_DENYMATCH
) {
8754 /* Free uninterned attribute. */
8755 bgp_attr_flush(&attr_new
);
8757 /* Unintern original. */
8758 aspath_unintern(&attr
.aspath
);
8759 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8764 if (bgp_in_graceful_shutdown(bgp
))
8765 bgp_attr_add_gshut_community(&attr_new
);
8767 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8768 SAFI_UNICAST
, p
, NULL
);
8770 new_attr
= bgp_attr_intern(&attr_new
);
8772 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8773 if (bpi
->peer
== bgp
->peer_self
8774 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8778 /* Ensure the (source route) type is updated. */
8780 if (attrhash_cmp(bpi
->attr
, new_attr
)
8781 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8782 bgp_attr_unintern(&new_attr
);
8783 aspath_unintern(&attr
.aspath
);
8784 bgp_dest_unlock_node(bn
);
8787 /* The attribute is changed. */
8788 bgp_path_info_set_flag(bn
, bpi
,
8789 BGP_PATH_ATTR_CHANGED
);
8791 /* Rewrite BGP route information. */
8792 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8793 bgp_path_info_restore(bn
, bpi
);
8795 bgp_aggregate_decrement(
8796 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8797 bgp_attr_unintern(&bpi
->attr
);
8798 bpi
->attr
= new_attr
;
8799 bpi
->uptime
= monotime(NULL
);
8801 /* Process change. */
8802 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8804 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8805 bgp_dest_unlock_node(bn
);
8806 aspath_unintern(&attr
.aspath
);
8808 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8810 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8812 vpn_leak_from_vrf_update(
8813 bgp_get_default(), bgp
, bpi
);
8819 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8820 bgp
->peer_self
, new_attr
, bn
);
8821 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8823 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8824 bgp_path_info_add(bn
, new);
8825 bgp_dest_unlock_node(bn
);
8826 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8827 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8829 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8830 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8832 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8836 /* Unintern original. */
8837 aspath_unintern(&attr
.aspath
);
8840 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8841 unsigned short instance
)
8844 struct bgp_dest
*dest
;
8845 struct bgp_path_info
*pi
;
8846 struct bgp_redist
*red
;
8848 afi
= family2afi(p
->family
);
8850 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8852 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8853 SAFI_UNICAST
, p
, NULL
);
8855 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8856 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8860 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8861 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8863 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8866 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8867 bgp_path_info_delete(dest
, pi
);
8868 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8870 bgp_dest_unlock_node(dest
);
8874 /* Withdraw specified route type's route. */
8875 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8876 unsigned short instance
)
8878 struct bgp_dest
*dest
;
8879 struct bgp_path_info
*pi
;
8880 struct bgp_table
*table
;
8882 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8884 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8885 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8886 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8887 && pi
->instance
== instance
)
8891 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8892 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8894 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8897 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8898 pi
, afi
, SAFI_UNICAST
);
8899 bgp_path_info_delete(dest
, pi
);
8900 if (!CHECK_FLAG(bgp
->flags
,
8901 BGP_FLAG_DELETE_IN_PROGRESS
))
8902 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8904 bgp_path_info_reap(dest
, pi
);
8909 /* Static function to display route. */
8910 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8911 struct vty
*vty
, json_object
*json
, bool wide
)
8914 char buf
[INET6_ADDRSTRLEN
];
8916 if (p
->family
== AF_INET
) {
8918 len
= vty_out(vty
, "%pFX", p
);
8920 json_object_string_add(json
, "prefix",
8921 inet_ntop(p
->family
,
8924 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8925 json_object_string_addf(json
, "network", "%pFX", p
);
8926 json_object_int_add(json
, "version", dest
->version
);
8928 } else if (p
->family
== AF_ETHERNET
) {
8929 len
= vty_out(vty
, "%pFX", p
);
8930 } else if (p
->family
== AF_EVPN
) {
8932 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8934 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8935 } else if (p
->family
== AF_FLOWSPEC
) {
8936 route_vty_out_flowspec(vty
, p
, NULL
,
8938 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8939 NLRI_STRING_FORMAT_MIN
, json
);
8942 len
= vty_out(vty
, "%pFX", p
);
8944 json_object_string_add(json
, "prefix",
8945 inet_ntop(p
->family
,
8948 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8949 json_object_string_addf(json
, "network", "%pFX", p
);
8950 json_object_int_add(json
, "version", dest
->version
);
8955 len
= wide
? (45 - len
) : (17 - len
);
8957 vty_out(vty
, "\n%*s", 20, " ");
8959 vty_out(vty
, "%*s", len
, " ");
8963 enum bgp_display_type
{
8967 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8970 case bgp_path_selection_none
:
8971 return "Nothing to Select";
8972 case bgp_path_selection_first
:
8973 return "First path received";
8974 case bgp_path_selection_evpn_sticky_mac
:
8975 return "EVPN Sticky Mac";
8976 case bgp_path_selection_evpn_seq
:
8977 return "EVPN sequence number";
8978 case bgp_path_selection_evpn_lower_ip
:
8979 return "EVPN lower IP";
8980 case bgp_path_selection_evpn_local_path
:
8981 return "EVPN local ES path";
8982 case bgp_path_selection_evpn_non_proxy
:
8983 return "EVPN non proxy";
8984 case bgp_path_selection_weight
:
8986 case bgp_path_selection_local_pref
:
8987 return "Local Pref";
8988 case bgp_path_selection_accept_own
:
8989 return "Accept Own";
8990 case bgp_path_selection_local_route
:
8991 return "Local Route";
8992 case bgp_path_selection_aigp
:
8994 case bgp_path_selection_confed_as_path
:
8995 return "Confederation based AS Path";
8996 case bgp_path_selection_as_path
:
8998 case bgp_path_selection_origin
:
9000 case bgp_path_selection_med
:
9002 case bgp_path_selection_peer
:
9004 case bgp_path_selection_confed
:
9005 return "Confed Peer Type";
9006 case bgp_path_selection_igp_metric
:
9007 return "IGP Metric";
9008 case bgp_path_selection_older
:
9009 return "Older Path";
9010 case bgp_path_selection_router_id
:
9012 case bgp_path_selection_cluster_length
:
9013 return "Cluster length";
9014 case bgp_path_selection_stale
:
9015 return "Path Staleness";
9016 case bgp_path_selection_local_configured
:
9017 return "Locally configured route";
9018 case bgp_path_selection_neighbor_ip
:
9019 return "Neighbor IP";
9020 case bgp_path_selection_default
:
9021 return "Nothing left to compare";
9023 return "Invalid (internal error)";
9026 /* Print the short form route status for a bgp_path_info */
9027 static void route_vty_short_status_out(struct vty
*vty
,
9028 struct bgp_path_info
*path
,
9029 const struct prefix
*p
,
9030 json_object
*json_path
)
9032 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
9036 /* Route status display. */
9037 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9038 json_object_boolean_true_add(json_path
, "removed");
9040 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9041 json_object_boolean_true_add(json_path
, "stale");
9043 if (path
->extra
&& bgp_path_suppressed(path
))
9044 json_object_boolean_true_add(json_path
, "suppressed");
9046 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9047 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9048 json_object_boolean_true_add(json_path
, "valid");
9051 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9052 json_object_boolean_true_add(json_path
, "history");
9054 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9055 json_object_boolean_true_add(json_path
, "damped");
9057 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9058 json_object_boolean_true_add(json_path
, "bestpath");
9059 json_object_string_add(json_path
, "selectionReason",
9060 bgp_path_selection_reason2str(
9061 path
->net
->reason
));
9064 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9065 json_object_boolean_true_add(json_path
, "multipath");
9067 /* Internal route. */
9068 if ((path
->peer
->as
)
9069 && (path
->peer
->as
== path
->peer
->local_as
))
9070 json_object_string_add(json_path
, "pathFrom",
9073 json_object_string_add(json_path
, "pathFrom",
9079 /* RPKI validation state */
9081 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9083 if (rpki_state
== RPKI_VALID
)
9085 else if (rpki_state
== RPKI_INVALID
)
9087 else if (rpki_state
== RPKI_NOTFOUND
)
9092 /* Route status display. */
9093 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9095 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9097 else if (bgp_path_suppressed(path
))
9099 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9100 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9106 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9108 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9110 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9112 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9117 /* Internal route. */
9118 if (path
->peer
&& (path
->peer
->as
)
9119 && (path
->peer
->as
== path
->peer
->local_as
))
9125 static char *bgp_nexthop_hostname(struct peer
*peer
,
9126 struct bgp_nexthop_cache
*bnc
)
9129 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9130 return peer
->hostname
;
9134 /* called from terminal list command */
9135 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9136 struct bgp_path_info
*path
, int display
, safi_t safi
,
9137 json_object
*json_paths
, bool wide
)
9140 struct attr
*attr
= path
->attr
;
9141 json_object
*json_path
= NULL
;
9142 json_object
*json_nexthops
= NULL
;
9143 json_object
*json_nexthop_global
= NULL
;
9144 json_object
*json_nexthop_ll
= NULL
;
9145 json_object
*json_ext_community
= NULL
;
9146 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9148 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9149 bool nexthop_othervrf
= false;
9150 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9151 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9152 char *nexthop_hostname
=
9153 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9154 char esi_buf
[ESI_STR_LEN
];
9157 json_path
= json_object_new_object();
9159 /* short status lead text */
9160 route_vty_short_status_out(vty
, path
, p
, json_path
);
9163 /* print prefix and mask */
9165 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9167 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9169 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9173 * If vrf id of nexthop is different from that of prefix,
9174 * set up printable string to append
9176 if (path
->extra
&& path
->extra
->bgp_orig
) {
9177 const char *self
= "";
9182 nexthop_othervrf
= true;
9183 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9185 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9186 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9187 "@%s%s", VRFID_NONE_STR
, self
);
9189 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9190 path
->extra
->bgp_orig
->vrf_id
, self
);
9192 if (path
->extra
->bgp_orig
->inst_type
9193 != BGP_INSTANCE_TYPE_DEFAULT
)
9195 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9197 const char *self
= "";
9202 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9206 * For ENCAP and EVPN routes, nexthop address family is not
9207 * neccessarily the same as the prefix address family.
9208 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9209 * EVPN routes are also exchanged with a MP nexthop. Currently,
9211 * is only IPv4, the value will be present in either
9213 * attr->mp_nexthop_global_in
9215 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9217 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9221 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9222 &attr
->mp_nexthop_global_in
);
9225 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9226 &attr
->mp_nexthop_global
);
9229 snprintf(nexthop
, sizeof(nexthop
), "?");
9234 json_nexthop_global
= json_object_new_object();
9236 json_object_string_add(json_nexthop_global
, "ip",
9239 if (path
->peer
->hostname
)
9240 json_object_string_add(json_nexthop_global
,
9242 path
->peer
->hostname
);
9244 json_object_string_add(json_nexthop_global
, "afi",
9245 (af
== AF_INET
) ? "ipv4"
9247 json_object_boolean_true_add(json_nexthop_global
,
9250 if (nexthop_hostname
)
9251 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9252 nexthop_hostname
, vrf_id_str
);
9254 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9256 len
= wide
? (41 - len
) : (16 - len
);
9258 vty_out(vty
, "\n%*s", 36, " ");
9260 vty_out(vty
, "%*s", len
, " ");
9262 } else if (safi
== SAFI_EVPN
) {
9264 json_nexthop_global
= json_object_new_object();
9266 json_object_string_addf(json_nexthop_global
, "ip",
9268 &attr
->mp_nexthop_global_in
);
9270 if (path
->peer
->hostname
)
9271 json_object_string_add(json_nexthop_global
,
9273 path
->peer
->hostname
);
9275 json_object_string_add(json_nexthop_global
, "afi",
9277 json_object_boolean_true_add(json_nexthop_global
,
9280 if (nexthop_hostname
)
9281 len
= vty_out(vty
, "%pI4(%s)%s",
9282 &attr
->mp_nexthop_global_in
,
9283 nexthop_hostname
, vrf_id_str
);
9285 len
= vty_out(vty
, "%pI4%s",
9286 &attr
->mp_nexthop_global_in
,
9289 len
= wide
? (41 - len
) : (16 - len
);
9291 vty_out(vty
, "\n%*s", 36, " ");
9293 vty_out(vty
, "%*s", len
, " ");
9295 } else if (safi
== SAFI_FLOWSPEC
) {
9296 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9298 json_nexthop_global
= json_object_new_object();
9300 json_object_string_add(json_nexthop_global
,
9302 json_object_string_addf(json_nexthop_global
,
9306 if (path
->peer
->hostname
)
9307 json_object_string_add(
9308 json_nexthop_global
, "hostname",
9309 path
->peer
->hostname
);
9311 json_object_boolean_true_add(
9312 json_nexthop_global
,
9315 if (nexthop_hostname
)
9316 len
= vty_out(vty
, "%pI4(%s)%s",
9321 len
= vty_out(vty
, "%pI4%s",
9325 len
= wide
? (41 - len
) : (16 - len
);
9327 vty_out(vty
, "\n%*s", 36, " ");
9329 vty_out(vty
, "%*s", len
, " ");
9332 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9334 json_nexthop_global
= json_object_new_object();
9336 json_object_string_addf(json_nexthop_global
, "ip",
9337 "%pI4", &attr
->nexthop
);
9339 if (path
->peer
->hostname
)
9340 json_object_string_add(json_nexthop_global
,
9342 path
->peer
->hostname
);
9344 json_object_string_add(json_nexthop_global
, "afi",
9346 json_object_boolean_true_add(json_nexthop_global
,
9349 if (nexthop_hostname
)
9350 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9351 nexthop_hostname
, vrf_id_str
);
9353 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9356 len
= wide
? (41 - len
) : (16 - len
);
9358 vty_out(vty
, "\n%*s", 36, " ");
9360 vty_out(vty
, "%*s", len
, " ");
9365 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9367 json_nexthop_global
= json_object_new_object();
9368 json_object_string_addf(json_nexthop_global
, "ip",
9370 &attr
->mp_nexthop_global
);
9372 if (path
->peer
->hostname
)
9373 json_object_string_add(json_nexthop_global
,
9375 path
->peer
->hostname
);
9377 json_object_string_add(json_nexthop_global
, "afi",
9379 json_object_string_add(json_nexthop_global
, "scope",
9382 /* We display both LL & GL if both have been
9384 if ((attr
->mp_nexthop_len
9385 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9386 || (path
->peer
->conf_if
)) {
9387 json_nexthop_ll
= json_object_new_object();
9388 json_object_string_addf(
9389 json_nexthop_ll
, "ip", "%pI6",
9390 &attr
->mp_nexthop_local
);
9392 if (path
->peer
->hostname
)
9393 json_object_string_add(
9394 json_nexthop_ll
, "hostname",
9395 path
->peer
->hostname
);
9397 json_object_string_add(json_nexthop_ll
, "afi",
9399 json_object_string_add(json_nexthop_ll
, "scope",
9402 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9403 &attr
->mp_nexthop_local
)
9405 && !attr
->mp_nexthop_prefer_global
)
9406 json_object_boolean_true_add(
9407 json_nexthop_ll
, "used");
9409 json_object_boolean_true_add(
9410 json_nexthop_global
, "used");
9412 json_object_boolean_true_add(
9413 json_nexthop_global
, "used");
9415 /* Display LL if LL/Global both in table unless
9416 * prefer-global is set */
9417 if (((attr
->mp_nexthop_len
9418 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9419 && !attr
->mp_nexthop_prefer_global
)
9420 || (path
->peer
->conf_if
)) {
9421 if (path
->peer
->conf_if
) {
9422 len
= vty_out(vty
, "%s",
9423 path
->peer
->conf_if
);
9424 /* len of IPv6 addr + max len of def
9426 len
= wide
? (41 - len
) : (16 - len
);
9429 vty_out(vty
, "\n%*s", 36, " ");
9431 vty_out(vty
, "%*s", len
, " ");
9433 if (nexthop_hostname
)
9436 &attr
->mp_nexthop_local
,
9442 &attr
->mp_nexthop_local
,
9445 len
= wide
? (41 - len
) : (16 - len
);
9448 vty_out(vty
, "\n%*s", 36, " ");
9450 vty_out(vty
, "%*s", len
, " ");
9453 if (nexthop_hostname
)
9454 len
= vty_out(vty
, "%pI6(%s)%s",
9455 &attr
->mp_nexthop_global
,
9459 len
= vty_out(vty
, "%pI6%s",
9460 &attr
->mp_nexthop_global
,
9463 len
= wide
? (41 - len
) : (16 - len
);
9466 vty_out(vty
, "\n%*s", 36, " ");
9468 vty_out(vty
, "%*s", len
, " ");
9474 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9476 json_object_int_add(json_path
, "metric", attr
->med
);
9478 vty_out(vty
, "%7u", attr
->med
);
9480 vty_out(vty
, "%10u", attr
->med
);
9481 else if (!json_paths
) {
9483 vty_out(vty
, "%*s", 7, " ");
9485 vty_out(vty
, "%*s", 10, " ");
9489 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9491 json_object_int_add(json_path
, "locPrf",
9494 vty_out(vty
, "%7u", attr
->local_pref
);
9495 else if (!json_paths
)
9499 json_object_int_add(json_path
, "weight", attr
->weight
);
9501 vty_out(vty
, "%7u ", attr
->weight
);
9504 json_object_string_addf(json_path
, "peerId", "%pSU",
9510 json_object_string_add(json_path
, "path",
9513 aspath_print_vty(vty
, attr
->aspath
);
9518 json_object_string_add(json_path
, "origin",
9519 bgp_origin_long_str
[attr
->origin
]);
9521 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9524 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9525 json_object_string_add(json_path
, "esi",
9526 esi_to_str(&attr
->esi
,
9527 esi_buf
, sizeof(esi_buf
)));
9529 if (safi
== SAFI_EVPN
&&
9530 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9531 json_ext_community
= json_object_new_object();
9532 json_object_string_add(
9533 json_ext_community
, "string",
9534 bgp_attr_get_ecommunity(attr
)->str
);
9535 json_object_object_add(json_path
,
9536 "extendedCommunity",
9537 json_ext_community
);
9541 json_object_boolean_true_add(json_path
,
9542 "announceNexthopSelf");
9543 if (nexthop_othervrf
) {
9544 json_object_string_add(json_path
, "nhVrfName",
9547 json_object_int_add(json_path
, "nhVrfId",
9548 ((nexthop_vrfid
== VRF_UNKNOWN
)
9550 : (int)nexthop_vrfid
));
9555 if (json_nexthop_global
|| json_nexthop_ll
) {
9556 json_nexthops
= json_object_new_array();
9558 if (json_nexthop_global
)
9559 json_object_array_add(json_nexthops
,
9560 json_nexthop_global
);
9562 if (json_nexthop_ll
)
9563 json_object_array_add(json_nexthops
,
9566 json_object_object_add(json_path
, "nexthops",
9570 json_object_array_add(json_paths
, json_path
);
9574 if (safi
== SAFI_EVPN
) {
9575 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9576 /* XXX - add these params to the json out */
9577 vty_out(vty
, "%*s", 20, " ");
9578 vty_out(vty
, "ESI:%s",
9579 esi_to_str(&attr
->esi
, esi_buf
,
9585 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9586 vty_out(vty
, "%*s", 20, " ");
9587 vty_out(vty
, "%s\n",
9588 bgp_attr_get_ecommunity(attr
)->str
);
9592 #ifdef ENABLE_BGP_VNC
9593 /* prints an additional line, indented, with VNC info, if
9595 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9596 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9601 /* called from terminal list command */
9602 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9603 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9604 bool use_json
, json_object
*json_ar
, bool wide
)
9606 json_object
*json_status
= NULL
;
9607 json_object
*json_net
= NULL
;
9611 /* Route status display. */
9613 json_status
= json_object_new_object();
9614 json_net
= json_object_new_object();
9621 /* print prefix and mask */
9623 if (safi
== SAFI_EVPN
)
9624 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9625 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9626 json_object_string_add(
9627 json_net
, "addrPrefix",
9628 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9630 json_object_int_add(json_net
, "prefixLen",
9632 json_object_string_addf(json_net
, "network", "%pFX", p
);
9635 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9637 /* Print attribute */
9640 if (p
->family
== AF_INET
&&
9641 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9642 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9643 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9644 json_object_string_addf(
9645 json_net
, "nextHop", "%pI4",
9646 &attr
->mp_nexthop_global_in
);
9648 json_object_string_addf(
9649 json_net
, "nextHop", "%pI4",
9651 } else if (p
->family
== AF_INET6
||
9652 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9653 json_object_string_addf(
9654 json_net
, "nextHopGlobal", "%pI6",
9655 &attr
->mp_nexthop_global
);
9656 } else if (p
->family
== AF_EVPN
&&
9657 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9658 json_object_string_addf(
9659 json_net
, "nextHop", "%pI4",
9660 &attr
->mp_nexthop_global_in
);
9664 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9665 json_object_int_add(json_net
, "metric",
9668 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9669 json_object_int_add(json_net
, "locPrf",
9672 json_object_int_add(json_net
, "weight", attr
->weight
);
9676 json_object_string_add(json_net
, "path",
9680 #if CONFDATE > 20231208
9681 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9683 json_object_string_add(json_net
, "bgpOriginCode",
9684 bgp_origin_str
[attr
->origin
]);
9685 json_object_string_add(
9687 bgp_origin_long_str
[attr
->origin
]);
9689 if (p
->family
== AF_INET
&&
9690 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9691 safi
== SAFI_EVPN
||
9692 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9693 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9694 || safi
== SAFI_EVPN
)
9695 vty_out(vty
, "%-16pI4",
9696 &attr
->mp_nexthop_global_in
);
9698 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9700 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9701 } else if (p
->family
== AF_INET6
||
9702 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9703 len
= vty_out(vty
, "%pI6",
9704 &attr
->mp_nexthop_global
);
9705 len
= wide
? (41 - len
) : (16 - len
);
9707 vty_out(vty
, "\n%*s", 36, " ");
9709 vty_out(vty
, "%*s", len
, " ");
9712 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9714 vty_out(vty
, "%7u", attr
->med
);
9716 vty_out(vty
, "%10u", attr
->med
);
9722 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9723 vty_out(vty
, "%7u", attr
->local_pref
);
9727 vty_out(vty
, "%7u ", attr
->weight
);
9731 aspath_print_vty(vty
, attr
->aspath
);
9734 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9738 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9740 #if CONFDATE > 20231208
9741 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9743 json_object_boolean_true_add(json_status
, "*");
9744 json_object_boolean_true_add(json_status
, ">");
9745 json_object_boolean_true_add(json_net
, "valid");
9746 json_object_boolean_true_add(json_net
, "best");
9748 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9749 json_object_boolean_true_add(json_status
, "=");
9750 json_object_boolean_true_add(json_net
, "multipath");
9752 json_object_object_add(json_net
, "appliedStatusSymbols",
9754 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9759 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9760 struct bgp_path_info
*path
, int display
, safi_t safi
,
9763 json_object
*json_out
= NULL
;
9765 mpls_label_t label
= MPLS_INVALID_LABEL
;
9771 json_out
= json_object_new_object();
9773 /* short status lead text */
9774 route_vty_short_status_out(vty
, path
, p
, json_out
);
9776 /* print prefix and mask */
9779 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9781 vty_out(vty
, "%*s", 17, " ");
9784 /* Print attribute */
9786 if (((p
->family
== AF_INET
) &&
9787 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9788 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9789 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9790 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9791 || safi
== SAFI_EVPN
) {
9793 json_object_string_addf(
9794 json_out
, "mpNexthopGlobalIn", "%pI4",
9795 &attr
->mp_nexthop_global_in
);
9797 vty_out(vty
, "%-16pI4",
9798 &attr
->mp_nexthop_global_in
);
9801 json_object_string_addf(json_out
, "nexthop",
9802 "%pI4", &attr
->nexthop
);
9804 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9806 } else if (((p
->family
== AF_INET6
) &&
9807 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9808 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9809 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9812 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9814 json_object_string_addf(
9815 json_out
, "mpNexthopGlobalIn", "%pI6",
9816 &attr
->mp_nexthop_global
);
9820 &attr
->mp_nexthop_global
,
9821 buf_a
, sizeof(buf_a
)));
9822 } else if (attr
->mp_nexthop_len
9823 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9824 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9825 &attr
->mp_nexthop_global
,
9826 &attr
->mp_nexthop_local
);
9828 json_object_string_add(json_out
,
9829 "mpNexthopGlobalLocal",
9832 vty_out(vty
, "%s", buf_a
);
9836 label
= decode_label(&path
->extra
->label
[0]);
9838 if (bgp_is_valid_label(&label
)) {
9840 json_object_int_add(json_out
, "notag", label
);
9841 json_object_array_add(json
, json_out
);
9843 vty_out(vty
, "notag/%d", label
);
9850 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9851 struct bgp_path_info
*path
, int display
,
9852 json_object
*json_paths
)
9855 json_object
*json_path
= NULL
;
9856 json_object
*json_nexthop
= NULL
;
9857 json_object
*json_overlay
= NULL
;
9863 json_path
= json_object_new_object();
9864 json_overlay
= json_object_new_object();
9865 json_nexthop
= json_object_new_object();
9868 /* short status lead text */
9869 route_vty_short_status_out(vty
, path
, p
, json_path
);
9871 /* print prefix and mask */
9873 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9875 vty_out(vty
, "%*s", 17, " ");
9877 /* Print attribute */
9879 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9884 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9886 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9887 &attr
->mp_nexthop_global_in
);
9889 json_object_string_add(json_nexthop
, "afi", "ipv4");
9891 json_object_object_add(json_path
, "nexthop",
9897 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9898 &attr
->mp_nexthop_local
);
9900 json_object_string_addf(json_nexthop
, "ipv6Global",
9902 &attr
->mp_nexthop_global
);
9904 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9906 &attr
->mp_nexthop_local
);
9908 json_object_string_add(json_nexthop
, "afi", "ipv6");
9910 json_object_object_add(json_path
, "nexthop",
9918 json_object_string_add(json_nexthop
, "error",
9919 "Unsupported address-family");
9923 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9926 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9928 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9930 if (bgp_attr_get_ecommunity(attr
)) {
9932 struct ecommunity_val
*routermac
= ecommunity_lookup(
9933 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9934 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9937 mac
= ecom_mac2str((char *)routermac
->val
);
9940 vty_out(vty
, "/%s", mac
);
9942 json_object_string_add(json_overlay
, "rmac",
9945 XFREE(MTYPE_TMP
, mac
);
9952 json_object_object_add(json_path
, "overlay", json_overlay
);
9954 json_object_array_add(json_paths
, json_path
);
9958 /* dampening route */
9959 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9960 struct bgp_path_info
*path
, int display
,
9961 afi_t afi
, safi_t safi
, bool use_json
,
9962 json_object
*json_paths
)
9964 struct attr
*attr
= path
->attr
;
9966 char timebuf
[BGP_UPTIME_LEN
];
9967 json_object
*json_path
= NULL
;
9970 json_path
= json_object_new_object();
9972 /* short status lead text */
9973 route_vty_short_status_out(vty
, path
, p
, json_path
);
9975 /* print prefix and mask */
9978 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9980 vty_out(vty
, "%*s", 17, " ");
9982 len
= vty_out(vty
, "%s", path
->peer
->host
);
9986 vty_out(vty
, "\n%*s", 34, " ");
9988 vty_out(vty
, "%*s", len
, " ");
9991 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9992 BGP_UPTIME_LEN
, afi
, safi
,
9996 aspath_print_vty(vty
, attr
->aspath
);
9998 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10000 vty_out(vty
, "\n");
10002 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
10003 safi
, use_json
, json_path
);
10006 json_object_string_add(json_path
, "asPath",
10007 attr
->aspath
->str
);
10009 json_object_string_add(json_path
, "origin",
10010 bgp_origin_str
[attr
->origin
]);
10011 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10013 json_object_array_add(json_paths
, json_path
);
10018 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
10019 struct bgp_path_info
*path
, int display
,
10020 afi_t afi
, safi_t safi
, bool use_json
,
10021 json_object
*json_paths
)
10023 struct attr
*attr
= path
->attr
;
10024 struct bgp_damp_info
*bdi
;
10025 char timebuf
[BGP_UPTIME_LEN
];
10027 json_object
*json_path
= NULL
;
10033 json_path
= json_object_new_object();
10035 bdi
= path
->extra
->damp_info
;
10037 /* short status lead text */
10038 route_vty_short_status_out(vty
, path
, p
, json_path
);
10042 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10044 vty_out(vty
, "%*s", 17, " ");
10046 len
= vty_out(vty
, "%s", path
->peer
->host
);
10049 vty_out(vty
, "\n%*s", 33, " ");
10051 vty_out(vty
, "%*s", len
, " ");
10053 len
= vty_out(vty
, "%d", bdi
->flap
);
10058 vty_out(vty
, "%*s", len
, " ");
10060 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10061 BGP_UPTIME_LEN
, 0, NULL
));
10063 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10064 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10065 vty_out(vty
, "%s ",
10066 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10067 BGP_UPTIME_LEN
, afi
,
10068 safi
, use_json
, NULL
));
10070 vty_out(vty
, "%*s ", 8, " ");
10073 aspath_print_vty(vty
, attr
->aspath
);
10075 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10077 vty_out(vty
, "\n");
10079 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10080 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10082 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10085 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10086 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10087 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10088 BGP_UPTIME_LEN
, afi
, safi
,
10089 use_json
, json_path
);
10092 json_object_string_add(json_path
, "asPath",
10093 attr
->aspath
->str
);
10095 json_object_string_add(json_path
, "origin",
10096 bgp_origin_str
[attr
->origin
]);
10098 json_object_array_add(json_paths
, json_path
);
10102 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10103 int *first
, const char *header
,
10104 json_object
*json_adv_to
)
10106 json_object
*json_peer
= NULL
;
10109 /* 'advertised-to' is a dictionary of peers we have advertised
10111 * prefix too. The key is the peer's IP or swpX, the value is
10113 * hostname if we know it and "" if not.
10115 json_peer
= json_object_new_object();
10117 if (peer
->hostname
)
10118 json_object_string_add(json_peer
, "hostname",
10122 json_object_object_add(json_adv_to
, peer
->conf_if
,
10125 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10129 vty_out(vty
, "%s", header
);
10134 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10136 vty_out(vty
, " %s(%s)", peer
->hostname
,
10139 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10143 vty_out(vty
, " %s", peer
->conf_if
);
10145 vty_out(vty
, " %pSU", &peer
->su
);
10150 static void route_vty_out_tx_ids(struct vty
*vty
,
10151 struct bgp_addpath_info_data
*d
)
10155 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10156 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10157 d
->addpath_tx_id
[i
],
10158 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10162 static void route_vty_out_detail_es_info(struct vty
*vty
,
10163 struct bgp_path_info
*pi
,
10165 json_object
*json_path
)
10167 char esi_buf
[ESI_STR_LEN
];
10168 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10169 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10170 ATTR_ES_PEER_ROUTER
);
10171 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10172 ATTR_ES_PEER_ACTIVE
);
10173 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10174 ATTR_ES_PEER_PROXY
);
10175 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10177 json_object
*json_es_info
= NULL
;
10179 json_object_string_add(
10182 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10183 json_es_info
= json_object_new_object();
10185 json_object_boolean_true_add(
10186 json_es_info
, "localEs");
10188 json_object_boolean_true_add(
10189 json_es_info
, "peerActive");
10191 json_object_boolean_true_add(
10192 json_es_info
, "peerProxy");
10194 json_object_boolean_true_add(
10195 json_es_info
, "peerRouter");
10196 if (attr
->mm_sync_seqnum
)
10197 json_object_int_add(
10198 json_es_info
, "peerSeq",
10199 attr
->mm_sync_seqnum
);
10200 json_object_object_add(
10201 json_path
, "es_info",
10205 if (bgp_evpn_attr_is_sync(attr
))
10207 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10209 es_local
? "local-es":"",
10210 peer_proxy
? "proxy " : "",
10211 peer_active
? "active ":"",
10212 peer_router
? "router ":"",
10213 attr
->mm_sync_seqnum
);
10215 vty_out(vty
, " ESI %s %s\n",
10217 es_local
? "local-es":"");
10221 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10222 const struct prefix
*p
, struct bgp_path_info
*path
,
10223 afi_t afi
, safi_t safi
,
10224 enum rpki_states rpki_curr_state
,
10225 json_object
*json_paths
)
10227 char buf
[INET6_ADDRSTRLEN
];
10229 struct attr
*attr
= path
->attr
;
10231 json_object
*json_bestpath
= NULL
;
10232 json_object
*json_cluster_list
= NULL
;
10233 json_object
*json_cluster_list_list
= NULL
;
10234 json_object
*json_ext_community
= NULL
;
10235 json_object
*json_last_update
= NULL
;
10236 json_object
*json_pmsi
= NULL
;
10237 json_object
*json_nexthop_global
= NULL
;
10238 json_object
*json_nexthop_ll
= NULL
;
10239 json_object
*json_nexthops
= NULL
;
10240 json_object
*json_path
= NULL
;
10241 json_object
*json_peer
= NULL
;
10242 json_object
*json_string
= NULL
;
10243 json_object
*json_adv_to
= NULL
;
10245 struct listnode
*node
, *nnode
;
10247 bool addpath_capable
;
10249 unsigned int first_as
;
10250 bool nexthop_self
=
10251 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10253 char *nexthop_hostname
=
10254 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10258 mpls_label_t label
= MPLS_INVALID_LABEL
;
10260 struct bgp_path_info
*bpi_ultimate
=
10261 bgp_get_imported_bpi_ultimate(path
);
10264 json_path
= json_object_new_object();
10265 json_peer
= json_object_new_object();
10266 json_nexthop_global
= json_object_new_object();
10269 if (safi
== SAFI_EVPN
) {
10271 vty_out(vty
, " Route %pFX", p
);
10275 if (path
->extra
&& path
->extra
->num_labels
) {
10276 bgp_evpn_label2str(path
->extra
->label
,
10277 path
->extra
->num_labels
, tag_buf
,
10280 if (safi
== SAFI_EVPN
) {
10282 if (tag_buf
[0] != '\0')
10283 vty_out(vty
, " VNI %s", tag_buf
);
10286 json_object_string_add(json_path
, "vni",
10292 if (safi
== SAFI_EVPN
10293 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10294 char gwip_buf
[INET6_ADDRSTRLEN
];
10296 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10300 json_object_string_add(json_path
, "gatewayIP",
10303 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10306 if (safi
== SAFI_EVPN
&& !json_path
)
10307 vty_out(vty
, "\n");
10310 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10311 struct bgp_path_info
*parent_ri
;
10312 struct bgp_dest
*dest
, *pdest
;
10314 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10315 dest
= parent_ri
->net
;
10316 if (dest
&& dest
->pdest
) {
10317 pdest
= dest
->pdest
;
10318 if (is_pi_family_evpn(parent_ri
)) {
10319 vty_out(vty
, " Imported from ");
10320 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10321 (struct prefix_rd
*)bgp_dest_get_prefix(
10323 vty_out(vty
, ":%pFX, VNI %s",
10324 (struct prefix_evpn
*)
10325 bgp_dest_get_prefix(dest
),
10327 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10328 vty_out(vty
, ", L3NHG %s",
10331 ATTR_ES_L3_NHG_ACTIVE
)
10334 vty_out(vty
, "\n");
10337 vty_out(vty
, " Imported from ");
10338 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10339 (struct prefix_rd
*)bgp_dest_get_prefix(
10341 vty_out(vty
, ":%pFX\n",
10342 (struct prefix_evpn
*)
10343 bgp_dest_get_prefix(dest
));
10348 /* Line1 display AS-path, Aggregator */
10349 if (attr
->aspath
) {
10351 if (!attr
->aspath
->json
)
10352 aspath_str_update(attr
->aspath
, true);
10353 json_object_lock(attr
->aspath
->json
);
10354 json_object_object_add(json_path
, "aspath",
10355 attr
->aspath
->json
);
10357 if (attr
->aspath
->segments
)
10358 vty_out(vty
, " %s", attr
->aspath
->str
);
10360 vty_out(vty
, " Local");
10364 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10366 json_object_boolean_true_add(json_path
, "removed");
10368 vty_out(vty
, ", (removed)");
10371 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10373 json_object_boolean_true_add(json_path
, "stale");
10375 vty_out(vty
, ", (stale)");
10378 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10380 json_object_int_add(json_path
, "aggregatorAs",
10381 attr
->aggregator_as
);
10382 json_object_string_addf(json_path
, "aggregatorId",
10383 "%pI4", &attr
->aggregator_addr
);
10385 vty_out(vty
, ", (aggregated by %u %pI4)",
10386 attr
->aggregator_as
, &attr
->aggregator_addr
);
10390 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10391 PEER_FLAG_REFLECTOR_CLIENT
)) {
10393 json_object_boolean_true_add(json_path
,
10394 "rxedFromRrClient");
10396 vty_out(vty
, ", (Received from a RR-client)");
10399 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10400 PEER_FLAG_RSERVER_CLIENT
)) {
10402 json_object_boolean_true_add(json_path
,
10403 "rxedFromRsClient");
10405 vty_out(vty
, ", (Received from a RS-client)");
10408 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10410 json_object_boolean_true_add(json_path
,
10411 "dampeningHistoryEntry");
10413 vty_out(vty
, ", (history entry)");
10414 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10416 json_object_boolean_true_add(json_path
,
10417 "dampeningSuppressed");
10419 vty_out(vty
, ", (suppressed due to dampening)");
10423 vty_out(vty
, "\n");
10425 /* Line2 display Next-hop, Neighbor, Router-id */
10426 /* Display the nexthop */
10428 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10429 p
->family
== AF_EVPN
) &&
10430 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10431 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10432 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10433 || safi
== SAFI_EVPN
) {
10435 json_object_string_addf(
10436 json_nexthop_global
, "ip", "%pI4",
10437 &attr
->mp_nexthop_global_in
);
10439 if (path
->peer
->hostname
)
10440 json_object_string_add(
10441 json_nexthop_global
, "hostname",
10442 path
->peer
->hostname
);
10444 if (nexthop_hostname
)
10445 vty_out(vty
, " %pI4(%s)",
10446 &attr
->mp_nexthop_global_in
,
10449 vty_out(vty
, " %pI4",
10450 &attr
->mp_nexthop_global_in
);
10454 json_object_string_addf(json_nexthop_global
,
10458 if (path
->peer
->hostname
)
10459 json_object_string_add(
10460 json_nexthop_global
, "hostname",
10461 path
->peer
->hostname
);
10463 if (nexthop_hostname
)
10464 vty_out(vty
, " %pI4(%s)",
10468 vty_out(vty
, " %pI4",
10474 json_object_string_add(json_nexthop_global
, "afi",
10478 json_object_string_addf(json_nexthop_global
, "ip",
10480 &attr
->mp_nexthop_global
);
10482 if (path
->peer
->hostname
)
10483 json_object_string_add(json_nexthop_global
,
10485 path
->peer
->hostname
);
10487 json_object_string_add(json_nexthop_global
, "afi",
10489 json_object_string_add(json_nexthop_global
, "scope",
10492 if (nexthop_hostname
)
10493 vty_out(vty
, " %pI6(%s)",
10494 &attr
->mp_nexthop_global
,
10497 vty_out(vty
, " %pI6",
10498 &attr
->mp_nexthop_global
);
10502 /* Display the IGP cost or 'inaccessible' */
10503 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10504 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10507 json_object_boolean_false_add(json_nexthop_global
,
10509 json_object_boolean_add(json_nexthop_global
,
10510 "importCheckEnabled", import
);
10512 vty_out(vty
, " (inaccessible%s)",
10513 import
? ", import-check enabled" : "");
10516 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10518 json_object_int_add(
10519 json_nexthop_global
, "metric",
10520 bpi_ultimate
->extra
->igpmetric
);
10522 vty_out(vty
, " (metric %u)",
10523 bpi_ultimate
->extra
->igpmetric
);
10526 /* IGP cost is 0, display this only for json */
10529 json_object_int_add(json_nexthop_global
,
10534 json_object_boolean_true_add(json_nexthop_global
,
10538 /* Display peer "from" output */
10539 /* This path was originated locally */
10540 if (path
->peer
== bgp
->peer_self
) {
10542 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10543 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10545 json_object_string_add(json_peer
, "peerId",
10548 vty_out(vty
, " from 0.0.0.0 ");
10551 json_object_string_add(json_peer
, "peerId",
10554 vty_out(vty
, " from :: ");
10558 json_object_string_addf(json_peer
, "routerId", "%pI4",
10561 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10564 /* We RXed this path from one of our peers */
10568 json_object_string_addf(json_peer
, "peerId", "%pSU",
10570 json_object_string_addf(json_peer
, "routerId", "%pI4",
10571 &path
->peer
->remote_id
);
10573 if (path
->peer
->hostname
)
10574 json_object_string_add(json_peer
, "hostname",
10575 path
->peer
->hostname
);
10577 if (path
->peer
->domainname
)
10578 json_object_string_add(json_peer
, "domainname",
10579 path
->peer
->domainname
);
10581 if (path
->peer
->conf_if
)
10582 json_object_string_add(json_peer
, "interface",
10583 path
->peer
->conf_if
);
10585 if (path
->peer
->conf_if
) {
10586 if (path
->peer
->hostname
10587 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10588 BGP_FLAG_SHOW_HOSTNAME
))
10589 vty_out(vty
, " from %s(%s)",
10590 path
->peer
->hostname
,
10591 path
->peer
->conf_if
);
10593 vty_out(vty
, " from %s",
10594 path
->peer
->conf_if
);
10596 if (path
->peer
->hostname
10597 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10598 BGP_FLAG_SHOW_HOSTNAME
))
10599 vty_out(vty
, " from %s(%s)",
10600 path
->peer
->hostname
,
10603 vty_out(vty
, " from %pSU",
10607 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10608 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10610 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10615 * Note when vrfid of nexthop is different from that of prefix
10617 if (path
->extra
&& path
->extra
->bgp_orig
) {
10618 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10623 if (path
->extra
->bgp_orig
->inst_type
10624 == BGP_INSTANCE_TYPE_DEFAULT
)
10625 vn
= VRF_DEFAULT_NAME
;
10627 vn
= path
->extra
->bgp_orig
->name
;
10629 json_object_string_add(json_path
, "nhVrfName", vn
);
10631 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10632 json_object_int_add(json_path
, "nhVrfId", -1);
10634 json_object_int_add(json_path
, "nhVrfId",
10635 (int)nexthop_vrfid
);
10638 if (nexthop_vrfid
== VRF_UNKNOWN
)
10639 vty_out(vty
, " vrf ?");
10643 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10644 vty_out(vty
, " vrf %s(%u)",
10645 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10650 if (nexthop_self
) {
10652 json_object_boolean_true_add(json_path
,
10653 "announceNexthopSelf");
10655 vty_out(vty
, " announce-nh-self");
10660 vty_out(vty
, "\n");
10662 /* display the link-local nexthop */
10663 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10665 json_nexthop_ll
= json_object_new_object();
10666 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10667 &attr
->mp_nexthop_local
);
10669 if (path
->peer
->hostname
)
10670 json_object_string_add(json_nexthop_ll
,
10672 path
->peer
->hostname
);
10674 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10675 json_object_string_add(json_nexthop_ll
, "scope",
10678 json_object_boolean_true_add(json_nexthop_ll
,
10681 if (!attr
->mp_nexthop_prefer_global
)
10682 json_object_boolean_true_add(json_nexthop_ll
,
10685 json_object_boolean_true_add(
10686 json_nexthop_global
, "used");
10688 vty_out(vty
, " (%s) %s\n",
10689 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10690 buf
, INET6_ADDRSTRLEN
),
10691 attr
->mp_nexthop_prefer_global
10692 ? "(prefer-global)"
10696 /* If we do not have a link-local nexthop then we must flag the
10697 global as "used" */
10700 json_object_boolean_true_add(json_nexthop_global
,
10704 if (safi
== SAFI_EVPN
&&
10705 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10706 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10709 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10710 * Int/Ext/Local, Atomic, best */
10712 json_object_string_add(json_path
, "origin",
10713 bgp_origin_long_str
[attr
->origin
]);
10715 vty_out(vty
, " Origin %s",
10716 bgp_origin_long_str
[attr
->origin
]);
10718 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10720 json_object_int_add(json_path
, "metric", attr
->med
);
10722 vty_out(vty
, ", metric %u", attr
->med
);
10725 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10727 json_object_int_add(json_path
, "locPrf",
10730 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10733 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10735 json_object_int_add(json_path
, "aigpMetric",
10736 bgp_attr_get_aigp_metric(attr
));
10738 vty_out(vty
, ", aigp-metric %" PRIu64
,
10739 bgp_attr_get_aigp_metric(attr
));
10742 if (attr
->weight
!= 0) {
10744 json_object_int_add(json_path
, "weight", attr
->weight
);
10746 vty_out(vty
, ", weight %u", attr
->weight
);
10749 if (attr
->tag
!= 0) {
10751 json_object_int_add(json_path
, "tag", attr
->tag
);
10753 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10756 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10758 json_object_boolean_false_add(json_path
, "valid");
10760 vty_out(vty
, ", invalid");
10761 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10763 json_object_boolean_true_add(json_path
, "valid");
10765 vty_out(vty
, ", valid");
10769 json_object_int_add(json_path
, "version", bn
->version
);
10771 if (path
->peer
!= bgp
->peer_self
) {
10772 if (path
->peer
->as
== path
->peer
->local_as
) {
10773 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10775 json_object_string_add(
10777 "confed-internal");
10779 vty_out(vty
, ", confed-internal");
10782 json_object_string_add(
10783 json_peer
, "type", "internal");
10785 vty_out(vty
, ", internal");
10788 if (bgp_confederation_peers_check(bgp
,
10791 json_object_string_add(
10793 "confed-external");
10795 vty_out(vty
, ", confed-external");
10798 json_object_string_add(
10799 json_peer
, "type", "external");
10801 vty_out(vty
, ", external");
10804 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10806 json_object_boolean_true_add(json_path
, "aggregated");
10807 json_object_boolean_true_add(json_path
, "local");
10809 vty_out(vty
, ", aggregated, local");
10811 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10813 json_object_boolean_true_add(json_path
, "sourced");
10815 vty_out(vty
, ", sourced");
10818 json_object_boolean_true_add(json_path
, "sourced");
10819 json_object_boolean_true_add(json_path
, "local");
10821 vty_out(vty
, ", sourced, local");
10825 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10827 json_object_boolean_true_add(json_path
,
10828 "atomicAggregate");
10830 vty_out(vty
, ", atomic-aggregate");
10833 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10835 json_object_int_add(json_path
, "otc", attr
->otc
);
10837 vty_out(vty
, ", otc %u", attr
->otc
);
10840 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10841 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10842 && bgp_path_info_mpath_count(path
))) {
10844 json_object_boolean_true_add(json_path
, "multipath");
10846 vty_out(vty
, ", multipath");
10849 // Mark the bestpath(s)
10850 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10851 first_as
= aspath_get_first_as(attr
->aspath
);
10854 if (!json_bestpath
)
10855 json_bestpath
= json_object_new_object();
10856 json_object_int_add(json_bestpath
, "bestpathFromAs",
10860 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10862 vty_out(vty
, ", bestpath-from-AS Local");
10866 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10868 if (!json_bestpath
)
10869 json_bestpath
= json_object_new_object();
10870 json_object_boolean_true_add(json_bestpath
, "overall");
10871 json_object_string_add(
10872 json_bestpath
, "selectionReason",
10873 bgp_path_selection_reason2str(bn
->reason
));
10875 vty_out(vty
, ", best");
10876 vty_out(vty
, " (%s)",
10877 bgp_path_selection_reason2str(bn
->reason
));
10881 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10883 json_object_string_add(
10884 json_path
, "rpkiValidationState",
10885 bgp_rpki_validation2str(rpki_curr_state
));
10887 vty_out(vty
, ", rpki validation-state: %s",
10888 bgp_rpki_validation2str(rpki_curr_state
));
10892 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10895 vty_out(vty
, "\n");
10897 /* Line 4 display Community */
10898 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10900 if (!bgp_attr_get_community(attr
)->json
)
10901 community_str(bgp_attr_get_community(attr
),
10903 json_object_lock(bgp_attr_get_community(attr
)->json
);
10904 json_object_object_add(
10905 json_path
, "community",
10906 bgp_attr_get_community(attr
)->json
);
10908 vty_out(vty
, " Community: %s\n",
10909 bgp_attr_get_community(attr
)->str
);
10913 /* Line 5 display Extended-community */
10914 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10916 json_ext_community
= json_object_new_object();
10917 json_object_string_add(
10918 json_ext_community
, "string",
10919 bgp_attr_get_ecommunity(attr
)->str
);
10920 json_object_object_add(json_path
, "extendedCommunity",
10921 json_ext_community
);
10923 vty_out(vty
, " Extended Community: %s\n",
10924 bgp_attr_get_ecommunity(attr
)->str
);
10928 /* Line 6 display Large community */
10929 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10931 if (!bgp_attr_get_lcommunity(attr
)->json
)
10932 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10934 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10935 json_object_object_add(
10936 json_path
, "largeCommunity",
10937 bgp_attr_get_lcommunity(attr
)->json
);
10939 vty_out(vty
, " Large Community: %s\n",
10940 bgp_attr_get_lcommunity(attr
)->str
);
10944 /* Line 7 display Originator, Cluster-id */
10945 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10946 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10947 char buf
[BUFSIZ
] = {0};
10949 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10951 json_object_string_addf(json_path
,
10952 "originatorId", "%pI4",
10953 &attr
->originator_id
);
10955 vty_out(vty
, " Originator: %pI4",
10956 &attr
->originator_id
);
10959 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10960 struct cluster_list
*cluster
=
10961 bgp_attr_get_cluster(attr
);
10965 json_cluster_list
= json_object_new_object();
10966 json_cluster_list_list
=
10967 json_object_new_array();
10969 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10970 json_string
= json_object_new_string(
10973 buf
, sizeof(buf
)));
10974 json_object_array_add(
10975 json_cluster_list_list
,
10980 * struct cluster_list does not have
10981 * "str" variable like aspath and community
10982 * do. Add this someday if someone asks
10984 * json_object_string_add(json_cluster_list,
10985 * "string", cluster->str);
10987 json_object_object_add(json_cluster_list
,
10989 json_cluster_list_list
);
10990 json_object_object_add(json_path
, "clusterList",
10991 json_cluster_list
);
10993 vty_out(vty
, ", Cluster list: ");
10995 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10996 vty_out(vty
, "%pI4 ",
10997 &cluster
->list
[i
]);
11003 vty_out(vty
, "\n");
11006 if (path
->extra
&& path
->extra
->damp_info
)
11007 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
11010 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
11011 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
11012 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
11016 json_object_int_add(json_path
, "remoteLabel", label
);
11018 vty_out(vty
, " Remote label: %d\n", label
);
11022 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
11024 json_object_string_addf(json_path
, "remoteSid", "%pI6",
11025 &path
->extra
->sid
[0].sid
);
11027 vty_out(vty
, " Remote SID: %pI6\n",
11028 &path
->extra
->sid
[0].sid
);
11032 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
11034 json_object_int_add(json_path
, "labelIndex",
11035 attr
->label_index
);
11037 vty_out(vty
, " Label Index: %d\n",
11038 attr
->label_index
);
11041 /* Line 8 display Addpath IDs */
11042 if (path
->addpath_rx_id
11043 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11045 json_object_int_add(json_path
, "addpathRxId",
11046 path
->addpath_rx_id
);
11048 /* Keep backwards compatibility with the old API
11049 * by putting TX All's ID in the old field
11051 json_object_int_add(
11052 json_path
, "addpathTxId",
11054 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11056 /* ... but create a specific field for each
11059 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11060 json_object_int_add(
11062 bgp_addpath_names(i
)->id_json_name
,
11063 path
->tx_addpath
.addpath_tx_id
[i
]);
11066 vty_out(vty
, " AddPath ID: RX %u, ",
11067 path
->addpath_rx_id
);
11069 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11073 /* If we used addpath to TX a non-bestpath we need to display
11074 * "Advertised to" on a path-by-path basis
11076 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11079 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11081 bgp_addpath_encode_tx(peer
, afi
, safi
);
11082 has_adj
= bgp_adj_out_lookup(
11084 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11085 &path
->tx_addpath
));
11087 if ((addpath_capable
&& has_adj
)
11088 || (!addpath_capable
&& has_adj
11089 && CHECK_FLAG(path
->flags
,
11090 BGP_PATH_SELECTED
))) {
11091 if (json_path
&& !json_adv_to
)
11092 json_adv_to
= json_object_new_object();
11094 route_vty_out_advertised_to(
11096 " Advertised to:", json_adv_to
);
11102 json_object_object_add(
11103 json_path
, "advertisedTo", json_adv_to
);
11107 vty_out(vty
, "\n");
11112 /* Line 9 display Uptime */
11113 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11115 json_last_update
= json_object_new_object();
11116 json_object_int_add(json_last_update
, "epoch", tbuf
);
11117 json_object_string_add(json_last_update
, "string",
11119 json_object_object_add(json_path
, "lastUpdate",
11122 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11124 /* Line 10 display PMSI tunnel attribute, if present */
11125 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11126 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11127 bgp_attr_get_pmsi_tnl_type(attr
),
11128 PMSI_TNLTYPE_STR_DEFAULT
);
11131 json_pmsi
= json_object_new_object();
11132 json_object_string_add(json_pmsi
, "tunnelType", str
);
11133 json_object_int_add(json_pmsi
, "label",
11134 label2vni(&attr
->label
));
11135 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11137 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11138 str
, label2vni(&attr
->label
));
11141 if (path
->peer
->t_gr_restart
&&
11142 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11143 unsigned long gr_remaining
=
11144 event_timer_remain_second(path
->peer
->t_gr_restart
);
11147 json_object_int_add(json_path
,
11148 "gracefulRestartSecondsRemaining",
11152 " Time until Graceful Restart stale route deleted: %lu\n",
11156 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11157 bgp_attr_get_community(attr
) &&
11158 community_include(bgp_attr_get_community(attr
),
11159 COMMUNITY_LLGR_STALE
)) {
11160 unsigned long llgr_remaining
= event_timer_remain_second(
11161 path
->peer
->t_llgr_stale
[afi
][safi
]);
11164 json_object_int_add(json_path
, "llgrSecondsRemaining",
11168 " Time until Long-lived stale route deleted: %lu\n",
11172 /* Output some debug about internal state of the dest flags */
11174 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11175 json_object_boolean_true_add(json_path
, "processScheduled");
11176 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11177 json_object_boolean_true_add(json_path
, "userCleared");
11178 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11179 json_object_boolean_true_add(json_path
, "labelChanged");
11180 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11181 json_object_boolean_true_add(json_path
, "registeredForLabel");
11182 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11183 json_object_boolean_true_add(json_path
, "selectDefered");
11184 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11185 json_object_boolean_true_add(json_path
, "fibInstalled");
11186 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11187 json_object_boolean_true_add(json_path
, "fibPending");
11189 if (json_nexthop_global
|| json_nexthop_ll
) {
11190 json_nexthops
= json_object_new_array();
11192 if (json_nexthop_global
)
11193 json_object_array_add(json_nexthops
,
11194 json_nexthop_global
);
11196 if (json_nexthop_ll
)
11197 json_object_array_add(json_nexthops
,
11200 json_object_object_add(json_path
, "nexthops",
11204 json_object_object_add(json_path
, "peer", json_peer
);
11205 json_object_array_add(json_paths
, json_path
);
11209 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11210 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11211 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11213 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11214 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11216 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11217 const char *comstr
, int exact
, afi_t afi
,
11218 safi_t safi
, uint16_t show_flags
);
11220 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11221 struct bgp_table
*table
, enum bgp_show_type type
,
11222 void *output_arg
, const char *rd
, int is_last
,
11223 unsigned long *output_cum
, unsigned long *total_cum
,
11224 unsigned long *json_header_depth
, uint16_t show_flags
,
11225 enum rpki_states rpki_target_state
)
11227 struct bgp_path_info
*pi
;
11228 struct bgp_dest
*dest
;
11229 bool header
= true;
11230 bool json_detail_header
= false;
11232 unsigned long output_count
= 0;
11233 unsigned long total_count
= 0;
11235 json_object
*json_paths
= NULL
;
11237 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11238 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11239 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11240 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11241 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11243 if (output_cum
&& *output_cum
!= 0)
11246 if (use_json
&& !*json_header_depth
) {
11248 *json_header_depth
= 1;
11250 vty_out(vty
, "{\n");
11251 *json_header_depth
= 2;
11254 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11255 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11257 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11258 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11261 table
->version
, &bgp
->router_id
,
11262 bgp
->default_local_pref
);
11263 if ((bgp
->asnotation
== ASNOTATION_PLAIN
) ||
11264 ((bgp
->asnotation
== ASNOTATION_DOT
) &&
11265 (bgp
->as
< UINT16_MAX
)))
11266 vty_out(vty
, "%u", bgp
->as
);
11268 vty_out(vty
, "\"");
11269 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
), &bgp
->as
);
11270 vty_out(vty
, "\"");
11272 vty_out(vty
, ",\n \"routes\": { ");
11274 vty_out(vty
, " \"routeDistinguishers\" : {");
11275 ++*json_header_depth
;
11279 if (use_json
&& rd
) {
11280 vty_out(vty
, " \"%s\" : { ", rd
);
11283 /* Check for 'json detail', where we need header output once per dest */
11284 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11285 type
!= bgp_show_type_damp_neighbor
&&
11286 type
!= bgp_show_type_flap_statistics
&&
11287 type
!= bgp_show_type_flap_neighbor
)
11288 json_detail_header
= true;
11290 /* Start processing of routes. */
11291 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11292 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11293 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11294 bool json_detail_header_used
= false;
11296 pi
= bgp_dest_get_bgp_path_info(dest
);
11302 json_paths
= json_object_new_array();
11306 for (; pi
; pi
= pi
->next
) {
11307 struct community
*picomm
= NULL
;
11309 picomm
= bgp_attr_get_community(pi
->attr
);
11313 if (type
== bgp_show_type_prefix_version
) {
11315 strtoul(output_arg
, NULL
, 10);
11316 if (dest
->version
< version
)
11320 if (type
== bgp_show_type_community_alias
) {
11321 char *alias
= output_arg
;
11322 char **communities
;
11324 bool found
= false;
11327 frrstr_split(picomm
->str
, " ",
11328 &communities
, &num
);
11329 for (int i
= 0; i
< num
; i
++) {
11330 const char *com2alias
=
11331 bgp_community2alias(
11334 && strcmp(alias
, com2alias
)
11340 XFREE(MTYPE_TMP
, communities
);
11344 bgp_attr_get_lcommunity(pi
->attr
)) {
11345 frrstr_split(bgp_attr_get_lcommunity(
11348 " ", &communities
, &num
);
11349 for (int i
= 0; i
< num
; i
++) {
11350 const char *com2alias
=
11351 bgp_community2alias(
11354 && strcmp(alias
, com2alias
)
11360 XFREE(MTYPE_TMP
, communities
);
11367 if (type
== bgp_show_type_rpki
) {
11368 if (dest_p
->family
== AF_INET
11369 || dest_p
->family
== AF_INET6
)
11370 rpki_curr_state
= hook_call(
11371 bgp_rpki_prefix_status
,
11372 pi
->peer
, pi
->attr
, dest_p
);
11373 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11374 && rpki_curr_state
!= rpki_target_state
)
11378 if (type
== bgp_show_type_flap_statistics
11379 || type
== bgp_show_type_flap_neighbor
11380 || type
== bgp_show_type_dampend_paths
11381 || type
== bgp_show_type_damp_neighbor
) {
11382 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11385 if (type
== bgp_show_type_regexp
) {
11386 regex_t
*regex
= output_arg
;
11388 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11392 if (type
== bgp_show_type_prefix_list
) {
11393 struct prefix_list
*plist
= output_arg
;
11395 if (prefix_list_apply(plist
, dest_p
)
11399 if (type
== bgp_show_type_access_list
) {
11400 struct access_list
*alist
= output_arg
;
11402 if (access_list_apply(alist
, dest_p
) !=
11406 if (type
== bgp_show_type_filter_list
) {
11407 struct as_list
*as_list
= output_arg
;
11409 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11410 != AS_FILTER_PERMIT
)
11413 if (type
== bgp_show_type_route_map
) {
11414 struct route_map
*rmap
= output_arg
;
11415 struct bgp_path_info path
;
11416 struct bgp_path_info_extra extra
;
11417 struct attr dummy_attr
= {};
11418 route_map_result_t ret
;
11420 dummy_attr
= *pi
->attr
;
11422 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11423 pi
->peer
, &dummy_attr
);
11425 ret
= route_map_apply(rmap
, dest_p
, &path
);
11426 bgp_attr_flush(&dummy_attr
);
11427 if (ret
== RMAP_DENYMATCH
)
11430 if (type
== bgp_show_type_neighbor
11431 || type
== bgp_show_type_flap_neighbor
11432 || type
== bgp_show_type_damp_neighbor
) {
11433 union sockunion
*su
= output_arg
;
11435 if (pi
->peer
== NULL
11436 || pi
->peer
->su_remote
== NULL
11437 || !sockunion_same(pi
->peer
->su_remote
, su
))
11440 if (type
== bgp_show_type_cidr_only
) {
11441 uint32_t destination
;
11443 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11444 if (IN_CLASSC(destination
)
11445 && dest_p
->prefixlen
== 24)
11447 if (IN_CLASSB(destination
)
11448 && dest_p
->prefixlen
== 16)
11450 if (IN_CLASSA(destination
)
11451 && dest_p
->prefixlen
== 8)
11454 if (type
== bgp_show_type_prefix_longer
) {
11456 if (!prefix_match(p
, dest_p
))
11459 if (type
== bgp_show_type_community_all
) {
11463 if (type
== bgp_show_type_community
) {
11464 struct community
*com
= output_arg
;
11466 if (!picomm
|| !community_match(picomm
, com
))
11469 if (type
== bgp_show_type_community_exact
) {
11470 struct community
*com
= output_arg
;
11472 if (!picomm
|| !community_cmp(picomm
, com
))
11475 if (type
== bgp_show_type_community_list
) {
11476 struct community_list
*list
= output_arg
;
11478 if (!community_list_match(picomm
, list
))
11481 if (type
== bgp_show_type_community_list_exact
) {
11482 struct community_list
*list
= output_arg
;
11484 if (!community_list_exact_match(picomm
, list
))
11487 if (type
== bgp_show_type_lcommunity
) {
11488 struct lcommunity
*lcom
= output_arg
;
11490 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11492 bgp_attr_get_lcommunity(pi
->attr
),
11497 if (type
== bgp_show_type_lcommunity_exact
) {
11498 struct lcommunity
*lcom
= output_arg
;
11500 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11502 bgp_attr_get_lcommunity(pi
->attr
),
11506 if (type
== bgp_show_type_lcommunity_list
) {
11507 struct community_list
*list
= output_arg
;
11509 if (!lcommunity_list_match(
11510 bgp_attr_get_lcommunity(pi
->attr
),
11515 == bgp_show_type_lcommunity_list_exact
) {
11516 struct community_list
*list
= output_arg
;
11518 if (!lcommunity_list_exact_match(
11519 bgp_attr_get_lcommunity(pi
->attr
),
11523 if (type
== bgp_show_type_lcommunity_all
) {
11524 if (!bgp_attr_get_lcommunity(pi
->attr
))
11527 if (type
== bgp_show_type_dampend_paths
11528 || type
== bgp_show_type_damp_neighbor
) {
11529 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11530 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11533 if (type
== bgp_show_type_self_originated
) {
11534 if (pi
->peer
!= bgp
->peer_self
)
11538 if (!use_json
&& header
) {
11540 "BGP table version is %" PRIu64
11541 ", local router ID is %pI4, vrf id ",
11542 table
->version
, &bgp
->router_id
);
11543 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11544 vty_out(vty
, "%s", VRFID_NONE_STR
);
11546 vty_out(vty
, "%u", bgp
->vrf_id
);
11547 vty_out(vty
, "\n");
11548 vty_out(vty
, "Default local pref %u, ",
11549 bgp
->default_local_pref
);
11550 vty_out(vty
, "local AS ");
11551 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
),
11553 vty_out(vty
, "\n");
11554 if (!detail_routes
) {
11555 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11556 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11557 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11558 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11560 if (type
== bgp_show_type_dampend_paths
11561 || type
== bgp_show_type_damp_neighbor
)
11562 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11563 else if (type
== bgp_show_type_flap_statistics
11564 || type
== bgp_show_type_flap_neighbor
)
11565 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11566 else if (!detail_routes
)
11567 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11568 : BGP_SHOW_HEADER
));
11572 if (rd
!= NULL
&& !display
&& !output_count
) {
11575 "Route Distinguisher: %s\n",
11578 if (type
== bgp_show_type_dampend_paths
11579 || type
== bgp_show_type_damp_neighbor
)
11580 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11581 AFI_IP
, safi
, use_json
,
11583 else if (type
== bgp_show_type_flap_statistics
11584 || type
== bgp_show_type_flap_neighbor
)
11585 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11586 AFI_IP
, safi
, use_json
,
11589 if (detail_routes
|| detail_json
) {
11590 const struct prefix_rd
*prd
= NULL
;
11593 prd
= bgp_rd_from_dest(
11594 dest
->pdest
, safi
);
11597 route_vty_out_detail_header(
11599 bgp_dest_get_prefix(
11601 prd
, table
->afi
, safi
,
11604 route_vty_out_detail(
11605 vty
, bgp
, dest
, dest_p
, pi
,
11606 family2afi(dest_p
->family
),
11607 safi
, RPKI_NOT_BEING_USED
,
11610 route_vty_out(vty
, dest_p
, pi
, display
,
11611 safi
, json_paths
, wide
);
11622 /* encode prefix */
11623 if (dest_p
->family
== AF_FLOWSPEC
) {
11624 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11627 bgp_fs_nlri_get_string(
11629 dest_p
->u
.prefix_flowspec
.ptr
,
11630 dest_p
->u
.prefix_flowspec
.prefixlen
,
11631 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11632 family2afi(dest_p
->u
11633 .prefix_flowspec
.family
));
11635 vty_out(vty
, "\"%s/%d\": ", retstr
,
11636 dest_p
->u
.prefix_flowspec
11639 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11640 dest_p
->u
.prefix_flowspec
11644 vty_out(vty
, "\"%pFX\": ", dest_p
);
11646 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11649 /* This is used for 'json detail' vty keywords.
11651 * In plain 'json' the per-prefix header is encoded
11652 * as a standalone dictionary in the first json_paths
11654 * "<prefix>": [{header}, {path-1}, {path-N}]
11655 * (which is confusing and borderline broken)
11657 * For 'json detail' this changes the value
11658 * of each prefix-key to be a dictionary where each
11659 * header item has its own key, and json_paths is
11660 * tucked under the "paths" key:
11662 * "<header-key-1>": <header-val-1>,
11663 * "<header-key-N>": <header-val-N>,
11664 * "paths": [{path-1}, {path-N}]
11667 if (json_detail_header
&& json_paths
!= NULL
) {
11668 const struct prefix_rd
*prd
;
11670 /* Start per-prefix dictionary */
11671 vty_out(vty
, "{\n");
11673 prd
= bgp_rd_from_dest(dest
, safi
);
11675 route_vty_out_detail_header(
11677 bgp_dest_get_prefix(dest
), prd
,
11678 table
->afi
, safi
, json_paths
, true);
11680 vty_out(vty
, "\"paths\": ");
11681 json_detail_header_used
= true;
11685 * We are using no_pretty here because under
11686 * extremely high settings( say lots and lots of
11687 * routes with lots and lots of ways to reach
11688 * that route via different paths ) this can
11689 * save several minutes of output when FRR
11690 * is run on older cpu's or more underperforming
11691 * routers out there
11693 vty_json_no_pretty(vty
, json_paths
);
11695 /* End per-prefix dictionary */
11696 if (json_detail_header_used
)
11697 vty_out(vty
, "} ");
11702 json_object_free(json_paths
);
11706 output_count
+= *output_cum
;
11707 *output_cum
= output_count
;
11710 total_count
+= *total_cum
;
11711 *total_cum
= total_count
;
11715 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11719 for (i
= 0; i
< *json_header_depth
; ++i
)
11720 vty_out(vty
, " } ");
11722 vty_out(vty
, "\n");
11726 /* No route is displayed */
11727 if (output_count
== 0) {
11728 if (type
== bgp_show_type_normal
)
11730 "No BGP prefixes displayed, %ld exist\n",
11734 "\nDisplayed %ld routes and %ld total paths\n",
11735 output_count
, total_count
);
11739 return CMD_SUCCESS
;
11742 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11743 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11744 enum bgp_show_type type
, void *output_arg
,
11745 uint16_t show_flags
)
11747 struct bgp_dest
*dest
, *next
;
11748 unsigned long output_cum
= 0;
11749 unsigned long total_cum
= 0;
11750 unsigned long json_header_depth
= 0;
11751 struct bgp_table
*itable
;
11753 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11755 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11757 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11758 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11760 next
= bgp_route_next(dest
);
11761 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11764 itable
= bgp_dest_get_bgp_table_info(dest
);
11765 if (itable
!= NULL
) {
11766 struct prefix_rd prd
;
11767 char rd
[RD_ADDRSTRLEN
];
11769 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11770 prefix_rd2str(&prd
, rd
, sizeof(rd
), bgp
->asnotation
);
11771 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11772 rd
, next
== NULL
, &output_cum
,
11773 &total_cum
, &json_header_depth
,
11774 show_flags
, RPKI_NOT_BEING_USED
);
11780 if (output_cum
== 0)
11781 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11785 "\nDisplayed %ld routes and %ld total paths\n",
11786 output_cum
, total_cum
);
11788 if (use_json
&& output_cum
== 0)
11789 vty_out(vty
, "{}\n");
11791 return CMD_SUCCESS
;
11794 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11795 enum bgp_show_type type
, void *output_arg
,
11796 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11798 struct bgp_table
*table
;
11799 unsigned long json_header_depth
= 0;
11800 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11803 bgp
= bgp_get_default();
11808 vty_out(vty
, "No BGP process is configured\n");
11810 vty_out(vty
, "{}\n");
11811 return CMD_WARNING
;
11814 /* Labeled-unicast routes live in the unicast table. */
11815 if (safi
== SAFI_LABELED_UNICAST
)
11816 safi
= SAFI_UNICAST
;
11818 table
= bgp
->rib
[afi
][safi
];
11819 /* use MPLS and ENCAP specific shows until they are merged */
11820 if (safi
== SAFI_MPLS_VPN
) {
11821 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11822 output_arg
, show_flags
);
11825 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11826 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11827 output_arg
, use_json
,
11831 if (safi
== SAFI_EVPN
)
11832 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11834 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11835 NULL
, NULL
, &json_header_depth
, show_flags
,
11836 rpki_target_state
);
11839 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11840 safi_t safi
, uint16_t show_flags
)
11842 struct listnode
*node
, *nnode
;
11845 bool route_output
= false;
11846 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11849 vty_out(vty
, "{\n");
11851 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11852 route_output
= true;
11855 vty_out(vty
, ",\n");
11859 vty_out(vty
, "\"%s\":",
11860 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11864 vty_out(vty
, "\nInstance %s:\n",
11865 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11869 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11870 show_flags
, RPKI_NOT_BEING_USED
);
11874 vty_out(vty
, "}\n");
11875 else if (!route_output
)
11876 vty_out(vty
, "%% BGP instance not found\n");
11879 /* Header of detailed BGP route information */
11880 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11881 struct bgp_dest
*dest
, const struct prefix
*p
,
11882 const struct prefix_rd
*prd
, afi_t afi
,
11883 safi_t safi
, json_object
*json
,
11884 bool incremental_print
)
11886 struct bgp_path_info
*pi
;
11888 struct listnode
*node
, *nnode
;
11889 char buf1
[RD_ADDRSTRLEN
];
11893 int accept_own
= 0;
11894 int route_filter_translated_v4
= 0;
11895 int route_filter_v4
= 0;
11896 int route_filter_translated_v6
= 0;
11897 int route_filter_v6
= 0;
11898 int llgr_stale
= 0;
11900 int accept_own_nexthop
= 0;
11903 int no_advertise
= 0;
11907 int has_valid_label
= 0;
11908 mpls_label_t label
= 0;
11909 json_object
*json_adv_to
= NULL
;
11914 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11916 has_valid_label
= bgp_is_valid_label(&label
);
11918 if (safi
== SAFI_EVPN
) {
11920 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11921 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11924 prd
? ":" : "", (struct prefix_evpn
*)p
);
11926 json_object_string_add(
11928 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11931 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11936 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11938 (((safi
== SAFI_MPLS_VPN
||
11939 safi
== SAFI_ENCAP
) &&
11941 ? prefix_rd2str(prd
, buf1
,
11945 safi
== SAFI_MPLS_VPN
&& prd
? ":" : "", p
,
11949 if (incremental_print
) {
11950 vty_out(vty
, "\"prefix\": \"%pFX\",\n", p
);
11951 vty_out(vty
, "\"version\": \"%" PRIu64
"\",\n",
11954 json_object_string_addf(json
, "prefix", "%pFX",
11956 json_object_int_add(json
, "version",
11962 if (has_valid_label
) {
11964 if (incremental_print
)
11965 vty_out(vty
, "\"localLabel\": \"%u\",\n",
11968 json_object_int_add(json
, "localLabel", label
);
11970 vty_out(vty
, "Local label: %d\n", label
);
11974 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11975 vty_out(vty
, "not allocated\n");
11977 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11978 struct community
*picomm
= NULL
;
11980 picomm
= bgp_attr_get_community(pi
->attr
);
11983 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11985 if (bgp_path_suppressed(pi
))
11991 no_advertise
+= community_include(
11992 picomm
, COMMUNITY_NO_ADVERTISE
);
11994 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11996 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11998 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11999 route_filter_translated_v4
+= community_include(
12000 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
12001 route_filter_translated_v6
+= community_include(
12002 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
12003 route_filter_v4
+= community_include(
12004 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
12005 route_filter_v6
+= community_include(
12006 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
12008 community_include(picomm
, COMMUNITY_LLGR_STALE
);
12009 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
12010 accept_own_nexthop
+= community_include(
12011 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
12013 community_include(picomm
, COMMUNITY_BLACKHOLE
);
12014 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
12019 vty_out(vty
, "Paths: (%d available", count
);
12021 vty_out(vty
, ", best #%d", best
);
12022 if (safi
== SAFI_UNICAST
) {
12023 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
12024 vty_out(vty
, ", table %s",
12027 vty_out(vty
, ", vrf %s",
12031 vty_out(vty
, ", no best path");
12035 ", accept own local route exported and imported in different VRF");
12036 else if (route_filter_translated_v4
)
12038 ", mark translated RTs for VPNv4 route filtering");
12039 else if (route_filter_v4
)
12041 ", attach RT as-is for VPNv4 route filtering");
12042 else if (route_filter_translated_v6
)
12044 ", mark translated RTs for VPNv6 route filtering");
12045 else if (route_filter_v6
)
12047 ", attach RT as-is for VPNv6 route filtering");
12048 else if (llgr_stale
)
12050 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
12053 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
12054 else if (accept_own_nexthop
)
12056 ", accept local nexthop");
12057 else if (blackhole
)
12058 vty_out(vty
, ", inform peer to blackhole prefix");
12059 else if (no_export
)
12060 vty_out(vty
, ", not advertised to EBGP peer");
12061 else if (no_advertise
)
12062 vty_out(vty
, ", not advertised to any peer");
12064 vty_out(vty
, ", not advertised outside local AS");
12067 ", inform EBGP peer not to advertise to their EBGP peers");
12071 ", Advertisements suppressed by an aggregate.");
12072 vty_out(vty
, ")\n");
12075 /* If we are not using addpath then we can display Advertised to and
12077 * show what peers we advertised the bestpath to. If we are using
12079 * though then we must display Advertised to on a path-by-path basis. */
12080 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12081 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12082 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12083 if (json
&& !json_adv_to
)
12084 json_adv_to
= json_object_new_object();
12086 route_vty_out_advertised_to(
12088 " Advertised to non peer-group peers:\n ",
12093 if (json
&& json_adv_to
) {
12094 if (incremental_print
) {
12095 vty_out(vty
, "\"advertisedTo\": ");
12096 vty_json(vty
, json_adv_to
);
12099 json_object_object_add(json
, "advertisedTo",
12102 if (!json
&& first
)
12103 vty_out(vty
, " Not advertised to any peer");
12104 vty_out(vty
, "\n");
12109 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12110 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12111 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12112 json_object
*json
, enum bgp_path_type pathtype
,
12113 int *display
, enum rpki_states rpki_target_state
)
12115 struct bgp_path_info
*pi
;
12117 json_object
*json_header
= NULL
;
12118 json_object
*json_paths
= NULL
;
12119 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12121 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12122 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12124 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12125 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12126 pi
->peer
, pi
->attr
, p
);
12128 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12129 && rpki_curr_state
!= rpki_target_state
)
12132 if (json
&& !json_paths
) {
12133 /* Instantiate json_paths only if path is valid */
12134 json_paths
= json_object_new_array();
12136 json_header
= json_object_new_object();
12138 json_header
= json
;
12142 route_vty_out_detail_header(
12143 vty
, bgp
, bgp_node
,
12144 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12145 safi
, json_header
, false);
12150 if (pathtype
== BGP_PATH_SHOW_ALL
12151 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12152 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12153 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12154 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12155 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12156 route_vty_out_detail(vty
, bgp
, bgp_node
,
12157 bgp_dest_get_prefix(bgp_node
), pi
,
12158 AFI_IP
, safi
, rpki_curr_state
,
12162 if (json
&& json_paths
) {
12163 json_object_object_add(json_header
, "paths", json_paths
);
12166 json_object_object_addf(
12168 BGP_RD_AS_FORMAT(bgp
->asnotation
), pfx_rd
);
12173 * Return rd based on safi
12175 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12179 case SAFI_MPLS_VPN
:
12182 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12185 case SAFI_MULTICAST
:
12186 case SAFI_LABELED_UNICAST
:
12187 case SAFI_FLOWSPEC
:
12192 assert(!"Reached end of function when we were not expecting it");
12195 /* Display specified route of BGP table. */
12196 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12197 struct bgp_table
*rib
, const char *ip_str
,
12198 afi_t afi
, safi_t safi
,
12199 enum rpki_states rpki_target_state
,
12200 struct prefix_rd
*prd
, int prefix_check
,
12201 enum bgp_path_type pathtype
, bool use_json
)
12205 struct prefix match
;
12206 struct bgp_dest
*dest
;
12207 struct bgp_dest
*rm
;
12208 struct bgp_table
*table
;
12209 json_object
*json
= NULL
;
12210 json_object
*json_paths
= NULL
;
12212 /* Check IP address argument. */
12213 ret
= str2prefix(ip_str
, &match
);
12215 vty_out(vty
, "address is malformed\n");
12216 return CMD_WARNING
;
12219 match
.family
= afi2family(afi
);
12222 json
= json_object_new_object();
12224 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12225 for (dest
= bgp_table_top(rib
); dest
;
12226 dest
= bgp_route_next(dest
)) {
12227 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12229 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12231 table
= bgp_dest_get_bgp_table_info(dest
);
12235 rm
= bgp_node_match(table
, &match
);
12239 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12241 && rm_p
->prefixlen
!= match
.prefixlen
) {
12242 bgp_dest_unlock_node(rm
);
12246 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12247 bgp
, afi
, safi
, json
, pathtype
,
12248 &display
, rpki_target_state
);
12250 bgp_dest_unlock_node(rm
);
12252 } else if (safi
== SAFI_EVPN
) {
12253 struct bgp_dest
*longest_pfx
;
12254 bool is_exact_pfxlen_match
= false;
12256 for (dest
= bgp_table_top(rib
); dest
;
12257 dest
= bgp_route_next(dest
)) {
12258 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12260 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12262 table
= bgp_dest_get_bgp_table_info(dest
);
12266 longest_pfx
= NULL
;
12267 is_exact_pfxlen_match
= false;
12269 * Search through all the prefixes for a match. The
12270 * pfx's are enumerated in ascending order of pfxlens.
12271 * So, the last pfx match is the longest match. Set
12272 * is_exact_pfxlen_match when we get exact pfxlen match
12274 for (rm
= bgp_table_top(table
); rm
;
12275 rm
= bgp_route_next(rm
)) {
12276 const struct prefix
*rm_p
=
12277 bgp_dest_get_prefix(rm
);
12279 * Get prefixlen of the ip-prefix within type5
12282 if (evpn_type5_prefix_match(rm_p
, &match
)
12286 bgp_evpn_get_type5_prefixlen(
12288 if (type5_pfxlen
== match
.prefixlen
) {
12289 is_exact_pfxlen_match
= true;
12290 bgp_dest_unlock_node(rm
);
12299 if (prefix_check
&& !is_exact_pfxlen_match
)
12303 bgp_dest_lock_node(rm
);
12305 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12306 bgp
, afi
, safi
, json
, pathtype
,
12307 &display
, rpki_target_state
);
12309 bgp_dest_unlock_node(rm
);
12311 } else if (safi
== SAFI_FLOWSPEC
) {
12313 json_paths
= json_object_new_array();
12315 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12316 &match
, prefix_check
,
12322 json_object_object_add(json
, "paths",
12325 json_object_free(json_paths
);
12328 dest
= bgp_node_match(rib
, &match
);
12329 if (dest
!= NULL
) {
12330 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12332 || dest_p
->prefixlen
== match
.prefixlen
) {
12333 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12334 safi
, json
, pathtype
,
12335 &display
, rpki_target_state
);
12338 bgp_dest_unlock_node(dest
);
12343 vty_json(vty
, json
);
12346 vty_out(vty
, "%% Network not in table\n");
12347 return CMD_WARNING
;
12351 return CMD_SUCCESS
;
12354 /* Display specified route of Main RIB */
12355 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12356 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12357 int prefix_check
, enum bgp_path_type pathtype
,
12358 enum rpki_states rpki_target_state
, bool use_json
)
12361 bgp
= bgp_get_default();
12364 vty_out(vty
, "No BGP process is configured\n");
12366 vty_out(vty
, "{}\n");
12367 return CMD_WARNING
;
12371 /* labeled-unicast routes live in the unicast table */
12372 if (safi
== SAFI_LABELED_UNICAST
)
12373 safi
= SAFI_UNICAST
;
12375 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12376 afi
, safi
, rpki_target_state
, prd
,
12377 prefix_check
, pathtype
, use_json
);
12380 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12381 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12382 safi_t safi
, bool uj
)
12384 struct lcommunity
*lcom
;
12389 uint16_t show_flags
= 0;
12393 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12395 b
= buffer_new(1024);
12396 for (i
= 0; i
< argc
; i
++) {
12398 buffer_putc(b
, ' ');
12400 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12402 buffer_putstr(b
, argv
[i
]->arg
);
12406 buffer_putc(b
, '\0');
12408 str
= buffer_getstr(b
);
12411 lcom
= lcommunity_str2com(str
);
12412 XFREE(MTYPE_TMP
, str
);
12414 vty_out(vty
, "%% Large-community malformed\n");
12415 return CMD_WARNING
;
12418 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12419 (exact
? bgp_show_type_lcommunity_exact
12420 : bgp_show_type_lcommunity
),
12421 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12423 lcommunity_free(&lcom
);
12427 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12428 const char *lcom
, bool exact
, afi_t afi
,
12429 safi_t safi
, bool uj
)
12431 struct community_list
*list
;
12432 uint16_t show_flags
= 0;
12435 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12438 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12439 LARGE_COMMUNITY_LIST_MASTER
);
12440 if (list
== NULL
) {
12441 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12443 return CMD_WARNING
;
12446 return bgp_show(vty
, bgp
, afi
, safi
,
12447 (exact
? bgp_show_type_lcommunity_list_exact
12448 : bgp_show_type_lcommunity_list
),
12449 list
, show_flags
, RPKI_NOT_BEING_USED
);
12452 DEFUN (show_ip_bgp_large_community_list
,
12453 show_ip_bgp_large_community_list_cmd
,
12454 "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]",
12458 BGP_INSTANCE_HELP_STR
12460 BGP_SAFI_WITH_LABEL_HELP_STR
12461 "Display routes matching the large-community-list\n"
12462 "large-community-list number\n"
12463 "large-community-list name\n"
12464 "Exact match of the large-communities\n"
12467 afi_t afi
= AFI_IP6
;
12468 safi_t safi
= SAFI_UNICAST
;
12470 bool exact_match
= 0;
12471 struct bgp
*bgp
= NULL
;
12472 bool uj
= use_json(argc
, argv
);
12477 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12480 return CMD_WARNING
;
12482 argv_find(argv
, argc
, "large-community-list", &idx
);
12484 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12486 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12489 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12490 exact_match
, afi
, safi
, uj
);
12492 DEFUN (show_ip_bgp_large_community
,
12493 show_ip_bgp_large_community_cmd
,
12494 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12498 BGP_INSTANCE_HELP_STR
12500 BGP_SAFI_WITH_LABEL_HELP_STR
12501 "Display routes matching the large-communities\n"
12502 "List of large-community numbers\n"
12503 "Exact match of the large-communities\n"
12506 afi_t afi
= AFI_IP6
;
12507 safi_t safi
= SAFI_UNICAST
;
12509 bool exact_match
= 0;
12510 struct bgp
*bgp
= NULL
;
12511 bool uj
= use_json(argc
, argv
);
12512 uint16_t show_flags
= 0;
12516 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12519 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12522 return CMD_WARNING
;
12524 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12525 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12529 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12530 exact_match
, afi
, safi
, uj
);
12532 return bgp_show(vty
, bgp
, afi
, safi
,
12533 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12534 RPKI_NOT_BEING_USED
);
12537 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12538 safi_t safi
, struct json_object
*json_array
);
12539 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12540 safi_t safi
, struct json_object
*json
);
12543 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12544 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12545 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12546 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12548 bool uj
= use_json(argc
, argv
);
12549 struct bgp
*bgp
= NULL
;
12550 safi_t safi
= SAFI_UNICAST
;
12551 afi_t afi
= AFI_IP6
;
12553 struct json_object
*json_all
= NULL
;
12554 struct json_object
*json_afi_safi
= NULL
;
12556 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12559 return CMD_WARNING
;
12562 json_all
= json_object_new_object();
12564 FOREACH_AFI_SAFI (afi
, safi
) {
12566 * So limit output to those afi/safi pairs that
12567 * actually have something interesting in them
12569 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12574 json_afi_safi
= json_object_new_array();
12575 json_object_object_add(
12577 get_afi_safi_str(afi
, safi
, true),
12580 json_afi_safi
= NULL
;
12583 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12587 vty_json(vty
, json_all
);
12589 return CMD_SUCCESS
;
12592 /* BGP route print out function without JSON */
12593 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12594 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12595 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12599 BGP_INSTANCE_HELP_STR
12602 "BGP RIB advertisement statistics\n"
12605 afi_t afi
= AFI_IP6
;
12606 safi_t safi
= SAFI_UNICAST
;
12607 struct bgp
*bgp
= NULL
;
12609 bool uj
= use_json(argc
, argv
);
12610 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12612 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12615 return CMD_WARNING
;
12618 json_afi_safi
= json_object_new_array();
12620 json_afi_safi
= NULL
;
12622 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12625 json
= json_object_new_object();
12626 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12628 vty_json(vty
, json
);
12633 /* BGP route print out function without JSON */
12634 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12635 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12636 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12638 statistics [json]",
12639 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12640 BGP_SAFI_WITH_LABEL_HELP_STR
12641 "BGP RIB advertisement statistics\n" JSON_STR
)
12643 afi_t afi
= AFI_IP6
;
12644 safi_t safi
= SAFI_UNICAST
;
12645 struct bgp
*bgp
= NULL
;
12647 bool uj
= use_json(argc
, argv
);
12648 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12650 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12653 return CMD_WARNING
;
12656 json_afi_safi
= json_object_new_array();
12658 json_afi_safi
= NULL
;
12660 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12663 json
= json_object_new_object();
12664 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12666 vty_json(vty
, json
);
12671 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12672 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12673 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12674 "]] [all$all] dampening parameters [json]",
12675 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12676 BGP_SAFI_WITH_LABEL_HELP_STR
12677 "Display the entries for all address families\n"
12678 "Display detailed information about dampening\n"
12679 "Display detail of configured dampening parameters\n"
12682 afi_t afi
= AFI_IP6
;
12683 safi_t safi
= SAFI_UNICAST
;
12684 struct bgp
*bgp
= NULL
;
12686 uint16_t show_flags
= 0;
12687 bool uj
= use_json(argc
, argv
);
12691 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12694 /* [<ipv4|ipv6> [all]] */
12696 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12697 if (argv_find(argv
, argc
, "ipv4", &idx
))
12698 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12700 if (argv_find(argv
, argc
, "ipv6", &idx
))
12701 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12704 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12707 return CMD_WARNING
;
12709 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12712 /* BGP route print out function */
12713 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12714 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12715 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12719 |dampening <flap-statistics|dampened-paths>\
12720 |community [AA:NN|local-AS|no-advertise|no-export\
12721 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12722 |accept-own|accept-own-nexthop|route-filter-v6\
12723 |route-filter-v4|route-filter-translated-v6\
12724 |route-filter-translated-v4] [exact-match]\
12725 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12726 |filter-list AS_PATH_FILTER_NAME\
12728 |access-list ACCESSLIST_NAME\
12729 |route-map RMAP_NAME\
12730 |rpki <invalid|valid|notfound>\
12731 |version (1-4294967295)\
12733 |A.B.C.D/M longer-prefixes\
12734 |X:X::X:X/M longer-prefixes\
12735 |"BGP_SELF_ORIG_CMD_STR
"\
12736 |detail-routes$detail_routes\
12737 ] [json$uj [detail$detail_json] | wide$wide]",
12738 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12739 BGP_SAFI_WITH_LABEL_HELP_STR
12740 "Display the entries for all address families\n"
12741 "Display only routes with non-natural netmasks\n"
12742 "Display detailed information about dampening\n"
12743 "Display flap statistics of routes\n"
12744 "Display paths suppressed due to dampening\n"
12745 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12746 "Do not send outside local AS (well-known community)\n"
12747 "Do not advertise to any peer (well-known community)\n"
12748 "Do not export to next AS (well-known community)\n"
12749 "Graceful shutdown (well-known community)\n"
12750 "Do not export to any peer (well-known community)\n"
12751 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12752 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12753 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12754 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12755 "Should accept VPN route with local nexthop (well-known community)\n"
12756 "RT VPNv6 route filtering (well-known community)\n"
12757 "RT VPNv4 route filtering (well-known community)\n"
12758 "RT translated VPNv6 route filtering (well-known community)\n"
12759 "RT translated VPNv4 route filtering (well-known community)\n"
12760 "Exact match of the communities\n"
12761 "Community-list number\n"
12762 "Community-list name\n"
12763 "Display routes matching the community-list\n"
12764 "Exact match of the communities\n"
12765 "Display routes conforming to the filter-list\n"
12766 "Regular expression access list name\n"
12767 "Display routes conforming to the prefix-list\n"
12768 "Prefix-list name\n"
12769 "Display routes conforming to the access-list\n"
12770 "Access-list name\n"
12771 "Display routes matching the route-map\n"
12772 "A route-map to match on\n"
12773 "RPKI route types\n"
12774 "A valid path as determined by rpki\n"
12775 "A invalid path as determined by rpki\n"
12776 "A path that has no rpki data\n"
12777 "Display prefixes with matching version numbers\n"
12778 "Version number and above\n"
12779 "Display prefixes with matching BGP community alias\n"
12780 "BGP community alias\n"
12782 "Display route and more specific routes\n"
12784 "Display route and more specific routes\n"
12785 BGP_SELF_ORIG_HELP_STR
12786 "Display detailed version of all routes\n"
12788 "Display detailed version of JSON output\n"
12789 "Increase table width for longer prefixes\n")
12791 afi_t afi
= AFI_IP6
;
12792 safi_t safi
= SAFI_UNICAST
;
12793 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12794 void *output_arg
= NULL
;
12795 struct bgp
*bgp
= NULL
;
12797 int exact_match
= 0;
12798 char *community
= NULL
;
12800 uint16_t show_flags
= 0;
12801 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12806 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12810 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12813 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12815 /* [<ipv4|ipv6> [all]] */
12817 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12819 if (argv_find(argv
, argc
, "ipv4", &idx
))
12820 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12822 if (argv_find(argv
, argc
, "ipv6", &idx
))
12823 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12827 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12829 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12832 return CMD_WARNING
;
12834 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12835 sh_type
= bgp_show_type_cidr_only
;
12837 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12838 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12839 sh_type
= bgp_show_type_dampend_paths
;
12840 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12841 sh_type
= bgp_show_type_flap_statistics
;
12844 if (argv_find(argv
, argc
, "community", &idx
)) {
12845 char *maybecomm
= NULL
;
12847 if (idx
+ 1 < argc
) {
12848 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12849 maybecomm
= argv
[idx
+ 1]->arg
;
12851 maybecomm
= argv
[idx
+ 1]->text
;
12854 if (maybecomm
&& !strmatch(maybecomm
, "json")
12855 && !strmatch(maybecomm
, "exact-match"))
12856 community
= maybecomm
;
12858 if (argv_find(argv
, argc
, "exact-match", &idx
))
12862 sh_type
= bgp_show_type_community_all
;
12865 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12866 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12867 struct community_list
*list
;
12869 if (argv_find(argv
, argc
, "exact-match", &idx
))
12872 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12873 COMMUNITY_LIST_MASTER
);
12874 if (list
== NULL
) {
12875 vty_out(vty
, "%% %s community-list not found\n",
12876 clist_number_or_name
);
12877 return CMD_WARNING
;
12881 sh_type
= bgp_show_type_community_list_exact
;
12883 sh_type
= bgp_show_type_community_list
;
12887 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12888 const char *filter
= argv
[++idx
]->arg
;
12889 struct as_list
*as_list
;
12891 as_list
= as_list_lookup(filter
);
12892 if (as_list
== NULL
) {
12893 vty_out(vty
, "%% %s AS-path access-list not found\n",
12895 return CMD_WARNING
;
12898 sh_type
= bgp_show_type_filter_list
;
12899 output_arg
= as_list
;
12902 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12903 const char *prefix_list_str
= argv
[++idx
]->arg
;
12904 struct prefix_list
*plist
;
12906 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12907 if (plist
== NULL
) {
12908 vty_out(vty
, "%% %s prefix-list not found\n",
12910 return CMD_WARNING
;
12913 sh_type
= bgp_show_type_prefix_list
;
12914 output_arg
= plist
;
12917 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12918 const char *access_list_str
= argv
[++idx
]->arg
;
12919 struct access_list
*alist
;
12921 alist
= access_list_lookup(afi
, access_list_str
);
12923 vty_out(vty
, "%% %s access-list not found\n",
12925 return CMD_WARNING
;
12928 sh_type
= bgp_show_type_access_list
;
12929 output_arg
= alist
;
12932 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12933 const char *rmap_str
= argv
[++idx
]->arg
;
12934 struct route_map
*rmap
;
12936 rmap
= route_map_lookup_by_name(rmap_str
);
12938 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12939 return CMD_WARNING
;
12942 sh_type
= bgp_show_type_route_map
;
12946 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12947 sh_type
= bgp_show_type_rpki
;
12948 if (argv_find(argv
, argc
, "valid", &idx
))
12949 rpki_target_state
= RPKI_VALID
;
12950 else if (argv_find(argv
, argc
, "invalid", &idx
))
12951 rpki_target_state
= RPKI_INVALID
;
12954 /* Display prefixes with matching version numbers */
12955 if (argv_find(argv
, argc
, "version", &idx
)) {
12956 sh_type
= bgp_show_type_prefix_version
;
12957 output_arg
= argv
[idx
+ 1]->arg
;
12960 /* Display prefixes with matching BGP community alias */
12961 if (argv_find(argv
, argc
, "alias", &idx
)) {
12962 sh_type
= bgp_show_type_community_alias
;
12963 output_arg
= argv
[idx
+ 1]->arg
;
12966 /* prefix-longer */
12967 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12968 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12969 const char *prefix_str
= argv
[idx
]->arg
;
12971 if (!str2prefix(prefix_str
, &p
)) {
12972 vty_out(vty
, "%% Malformed Prefix\n");
12973 return CMD_WARNING
;
12976 sh_type
= bgp_show_type_prefix_longer
;
12980 /* self originated only */
12981 if (argv_find(argv
, argc
, BGP_SELF_ORIG_CMD_STR
, &idx
))
12982 sh_type
= bgp_show_type_self_originated
;
12985 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12987 return bgp_show_community(vty
, bgp
, community
,
12988 exact_match
, afi
, safi
,
12991 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12992 output_arg
, show_flags
,
12993 rpki_target_state
);
12995 struct listnode
*node
;
12997 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
13001 vty_out(vty
, "{\n");
13003 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13004 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
13005 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13008 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
13009 FOREACH_SAFI (safi
) {
13010 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
13018 vty_out(vty
, ",\n");
13019 vty_out(vty
, "\"%s\":{\n",
13020 get_afi_safi_str(afi
,
13025 "\nFor address family: %s\n",
13031 bgp_show_community(
13032 vty
, abgp
, community
,
13033 exact_match
, afi
, safi
,
13036 bgp_show(vty
, abgp
, afi
, safi
,
13037 sh_type
, output_arg
,
13039 rpki_target_state
);
13041 vty_out(vty
, "}\n");
13045 /* show <ip> bgp all: for each AFI and SAFI*/
13046 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
13047 FOREACH_AFI_SAFI (afi
, safi
) {
13048 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
13056 vty_out(vty
, ",\n");
13058 vty_out(vty
, "\"%s\":{\n",
13059 get_afi_safi_str(afi
,
13064 "\nFor address family: %s\n",
13070 bgp_show_community(
13071 vty
, abgp
, community
,
13072 exact_match
, afi
, safi
,
13075 bgp_show(vty
, abgp
, afi
, safi
,
13076 sh_type
, output_arg
,
13078 rpki_target_state
);
13080 vty_out(vty
, "}\n");
13085 vty_out(vty
, "}\n");
13087 return CMD_SUCCESS
;
13090 DEFUN (show_ip_bgp_route
,
13091 show_ip_bgp_route_cmd
,
13092 "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]",
13096 BGP_INSTANCE_HELP_STR
13098 BGP_SAFI_WITH_LABEL_HELP_STR
13099 "Network in the BGP routing table to display\n"
13101 "Network in the BGP routing table to display\n"
13103 "Display only the bestpath\n"
13104 "Display only multipaths\n"
13105 "Display only paths that match the specified rpki state\n"
13106 "A valid path as determined by rpki\n"
13107 "A invalid path as determined by rpki\n"
13108 "A path that has no rpki data\n"
13111 int prefix_check
= 0;
13113 afi_t afi
= AFI_IP6
;
13114 safi_t safi
= SAFI_UNICAST
;
13115 char *prefix
= NULL
;
13116 struct bgp
*bgp
= NULL
;
13117 enum bgp_path_type path_type
;
13118 bool uj
= use_json(argc
, argv
);
13122 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13125 return CMD_WARNING
;
13129 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13130 return CMD_WARNING
;
13133 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13134 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13135 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13137 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13138 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13141 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13142 && afi
!= AFI_IP6
) {
13144 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13145 return CMD_WARNING
;
13147 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13148 && afi
!= AFI_IP
) {
13150 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13151 return CMD_WARNING
;
13154 prefix
= argv
[idx
]->arg
;
13156 /* [<bestpath|multipath>] */
13157 if (argv_find(argv
, argc
, "bestpath", &idx
))
13158 path_type
= BGP_PATH_SHOW_BESTPATH
;
13159 else if (argv_find(argv
, argc
, "multipath", &idx
))
13160 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13162 path_type
= BGP_PATH_SHOW_ALL
;
13164 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13165 path_type
, RPKI_NOT_BEING_USED
, uj
);
13168 DEFUN (show_ip_bgp_regexp
,
13169 show_ip_bgp_regexp_cmd
,
13170 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13174 BGP_INSTANCE_HELP_STR
13176 BGP_SAFI_WITH_LABEL_HELP_STR
13177 "Display routes matching the AS path regular expression\n"
13178 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13181 afi_t afi
= AFI_IP6
;
13182 safi_t safi
= SAFI_UNICAST
;
13183 struct bgp
*bgp
= NULL
;
13184 bool uj
= use_json(argc
, argv
);
13185 char *regstr
= NULL
;
13188 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13191 return CMD_WARNING
;
13193 // get index of regex
13194 if (argv_find(argv
, argc
, "REGEX", &idx
))
13195 regstr
= argv
[idx
]->arg
;
13198 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13199 bgp_show_type_regexp
, uj
);
13202 DEFPY (show_ip_bgp_instance_all
,
13203 show_ip_bgp_instance_all_cmd
,
13204 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13208 BGP_INSTANCE_ALL_HELP_STR
13210 BGP_SAFI_WITH_LABEL_HELP_STR
13212 "Increase table width for longer prefixes\n")
13214 afi_t afi
= AFI_IP6
;
13215 safi_t safi
= SAFI_UNICAST
;
13216 struct bgp
*bgp
= NULL
;
13218 uint16_t show_flags
= 0;
13222 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13226 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13228 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13231 return CMD_WARNING
;
13233 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13234 return CMD_SUCCESS
;
13237 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13238 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13243 uint16_t show_flags
= 0;
13246 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13248 if (!config_bgp_aspath_validate(regstr
)) {
13249 vty_out(vty
, "Invalid character in REGEX %s\n",
13251 return CMD_WARNING_CONFIG_FAILED
;
13254 regex
= bgp_regcomp(regstr
);
13256 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13257 return CMD_WARNING
;
13260 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13261 RPKI_NOT_BEING_USED
);
13262 bgp_regex_free(regex
);
13266 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13267 const char *comstr
, int exact
, afi_t afi
,
13268 safi_t safi
, uint16_t show_flags
)
13270 struct community
*com
;
13273 com
= community_str2com(comstr
);
13275 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13276 return CMD_WARNING
;
13279 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13280 (exact
? bgp_show_type_community_exact
13281 : bgp_show_type_community
),
13282 com
, show_flags
, RPKI_NOT_BEING_USED
);
13283 community_free(&com
);
13289 BGP_STATS_MAXBITLEN
= 0,
13291 BGP_STATS_PREFIXES
,
13293 BGP_STATS_UNAGGREGATEABLE
,
13294 BGP_STATS_MAX_AGGREGATEABLE
,
13295 BGP_STATS_AGGREGATES
,
13297 BGP_STATS_ASPATH_COUNT
,
13298 BGP_STATS_ASPATH_MAXHOPS
,
13299 BGP_STATS_ASPATH_TOTHOPS
,
13300 BGP_STATS_ASPATH_MAXSIZE
,
13301 BGP_STATS_ASPATH_TOTSIZE
,
13302 BGP_STATS_ASN_HIGHEST
,
13306 #define TABLE_STATS_IDX_VTY 0
13307 #define TABLE_STATS_IDX_JSON 1
13309 static const char *table_stats_strs
[][2] = {
13310 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13311 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13312 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13313 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13314 "unaggregateablePrefixes"},
13315 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13316 "maximumAggregateablePrefixes"},
13317 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13318 "bgpAggregateAdvertisements"},
13319 [BGP_STATS_SPACE
] = {"Address space advertised",
13320 "addressSpaceAdvertised"},
13321 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13322 "advertisementsWithPaths"},
13323 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13325 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13327 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13328 "averageAsPathLengthHops"},
13329 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13330 "averageAsPathSizeBytes"},
13331 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13332 [BGP_STATS_MAX
] = {NULL
, NULL
}
13335 struct bgp_table_stats
{
13336 struct bgp_table
*table
;
13337 unsigned long long counts
[BGP_STATS_MAX
];
13340 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13343 double total_space
;
13346 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13347 struct bgp_table_stats
*ts
, unsigned int space
)
13349 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13350 struct bgp_path_info
*pi
;
13351 const struct prefix
*rn_p
;
13353 if (!bgp_dest_has_bgp_path_info_data(dest
))
13356 rn_p
= bgp_dest_get_prefix(dest
);
13357 ts
->counts
[BGP_STATS_PREFIXES
]++;
13358 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13360 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13361 /* check if the prefix is included by any other announcements */
13362 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13363 pdest
= bgp_dest_parent_nolock(pdest
);
13365 if (pdest
== NULL
|| pdest
== top
) {
13366 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13367 /* announced address space */
13369 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13370 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13371 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13374 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13375 ts
->counts
[BGP_STATS_RIB
]++;
13377 if (CHECK_FLAG(pi
->attr
->flag
,
13378 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13379 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13381 /* as-path stats */
13382 if (pi
->attr
->aspath
) {
13383 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13384 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13385 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13387 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13389 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13390 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13392 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13393 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13395 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13396 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13397 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13398 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13403 static void bgp_table_stats_walker(struct event
*t
)
13405 struct bgp_dest
*dest
, *ndest
;
13406 struct bgp_dest
*top
;
13407 struct bgp_table_stats
*ts
= EVENT_ARG(t
);
13408 unsigned int space
= 0;
13410 if (!(top
= bgp_table_top(ts
->table
)))
13413 switch (ts
->table
->afi
) {
13415 space
= IPV4_MAX_BITLEN
;
13418 space
= IPV6_MAX_BITLEN
;
13421 space
= EVPN_ROUTE_PREFIXLEN
;
13428 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13430 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13431 if (ts
->table
->safi
== SAFI_MPLS_VPN
13432 || ts
->table
->safi
== SAFI_ENCAP
13433 || ts
->table
->safi
== SAFI_EVPN
) {
13434 struct bgp_table
*table
;
13436 table
= bgp_dest_get_bgp_table_info(dest
);
13440 top
= bgp_table_top(table
);
13441 for (ndest
= bgp_table_top(table
); ndest
;
13442 ndest
= bgp_route_next(ndest
))
13443 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13445 bgp_table_stats_rn(dest
, top
, ts
, space
);
13450 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13451 struct json_object
*json_array
)
13453 struct listnode
*node
, *nnode
;
13456 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13457 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13460 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13461 safi_t safi
, struct json_object
*json_array
)
13463 struct bgp_table_stats ts
;
13465 int ret
= CMD_SUCCESS
;
13467 struct json_object
*json
= NULL
;
13468 uint32_t bitlen
= 0;
13469 struct json_object
*json_bitlen
;
13472 json
= json_object_new_object();
13474 if (!bgp
->rib
[afi
][safi
]) {
13475 char warning_msg
[50];
13477 snprintf(warning_msg
, sizeof(warning_msg
),
13478 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13482 vty_out(vty
, "%s\n", warning_msg
);
13484 json_object_string_add(json
, "warning", warning_msg
);
13487 goto end_table_stats
;
13491 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13492 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13494 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13496 /* labeled-unicast routes live in the unicast table */
13497 if (safi
== SAFI_LABELED_UNICAST
)
13498 safi
= SAFI_UNICAST
;
13500 memset(&ts
, 0, sizeof(ts
));
13501 ts
.table
= bgp
->rib
[afi
][safi
];
13502 event_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13504 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13505 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13506 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13510 case BGP_STATS_ASPATH_TOTHOPS
:
13511 case BGP_STATS_ASPATH_TOTSIZE
:
13514 temp_buf
, sizeof(temp_buf
), "%12.2f",
13516 ? (float)ts
.counts
[i
]
13518 [BGP_STATS_ASPATH_COUNT
]
13520 vty_out(vty
, "%-30s: %s",
13521 table_stats_strs
[i
]
13522 [TABLE_STATS_IDX_VTY
],
13525 json_object_double_add(
13527 table_stats_strs
[i
]
13528 [TABLE_STATS_IDX_JSON
],
13530 ? (double)ts
.counts
[i
]
13531 / (double)ts
.counts
13532 [BGP_STATS_ASPATH_COUNT
]
13536 case BGP_STATS_TOTPLEN
:
13539 temp_buf
, sizeof(temp_buf
), "%12.2f",
13541 ? (float)ts
.counts
[i
]
13543 [BGP_STATS_PREFIXES
]
13545 vty_out(vty
, "%-30s: %s",
13546 table_stats_strs
[i
]
13547 [TABLE_STATS_IDX_VTY
],
13550 json_object_double_add(
13552 table_stats_strs
[i
]
13553 [TABLE_STATS_IDX_JSON
],
13555 ? (double)ts
.counts
[i
]
13556 / (double)ts
.counts
13557 [BGP_STATS_PREFIXES
]
13561 case BGP_STATS_SPACE
:
13563 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13565 vty_out(vty
, "%-30s: %s\n",
13566 table_stats_strs
[i
]
13567 [TABLE_STATS_IDX_VTY
],
13570 json_object_double_add(
13572 table_stats_strs
[i
]
13573 [TABLE_STATS_IDX_JSON
],
13574 (double)ts
.total_space
);
13576 if (afi
== AFI_IP6
) {
13578 snprintf(temp_buf
, sizeof(temp_buf
),
13581 * pow(2.0, -128 + 32));
13582 vty_out(vty
, "%30s: %s\n",
13583 "/32 equivalent %s\n",
13586 json_object_double_add(
13587 json
, "/32equivalent",
13588 (double)(ts
.total_space
13593 snprintf(temp_buf
, sizeof(temp_buf
),
13596 * pow(2.0, -128 + 48));
13597 vty_out(vty
, "%30s: %s\n",
13598 "/48 equivalent %s\n",
13601 json_object_double_add(
13602 json
, "/48equivalent",
13603 (double)(ts
.total_space
13609 snprintf(temp_buf
, sizeof(temp_buf
),
13611 ts
.total_space
* 100.
13613 vty_out(vty
, "%30s: %s\n",
13614 "% announced ", temp_buf
);
13616 json_object_double_add(
13617 json
, "%announced",
13618 (double)(ts
.total_space
* 100.
13622 snprintf(temp_buf
, sizeof(temp_buf
),
13625 * pow(2.0, -32 + 8));
13626 vty_out(vty
, "%30s: %s\n",
13627 "/8 equivalent ", temp_buf
);
13629 json_object_double_add(
13630 json
, "/8equivalent",
13631 (double)(ts
.total_space
13632 * pow(2.0, -32 + 8)));
13635 snprintf(temp_buf
, sizeof(temp_buf
),
13638 * pow(2.0, -32 + 24));
13639 vty_out(vty
, "%30s: %s\n",
13640 "/24 equivalent ", temp_buf
);
13642 json_object_double_add(
13643 json
, "/24equivalent",
13644 (double)(ts
.total_space
13645 * pow(2.0, -32 + 24)));
13651 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13653 vty_out(vty
, "%-30s: %s",
13654 table_stats_strs
[i
]
13655 [TABLE_STATS_IDX_VTY
],
13658 json_object_int_add(
13660 table_stats_strs
[i
]
13661 [TABLE_STATS_IDX_JSON
],
13666 vty_out(vty
, "\n");
13671 bitlen
= IPV4_MAX_BITLEN
;
13674 bitlen
= IPV6_MAX_BITLEN
;
13677 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13685 json_bitlen
= json_object_new_array();
13687 for (i
= 0; i
<= bitlen
; i
++) {
13688 struct json_object
*ind_bit
= json_object_new_object();
13690 if (!ts
.prefix_len_count
[i
])
13693 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13694 json_object_int_add(ind_bit
, temp_buf
,
13695 ts
.prefix_len_count
[i
]);
13696 json_object_array_add(json_bitlen
, ind_bit
);
13698 json_object_object_add(json
, "prefixLength", json_bitlen
);
13703 json_object_array_add(json_array
, json
);
13707 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13708 safi_t safi
, struct json_object
*json_array
)
13711 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13712 return CMD_SUCCESS
;
13715 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13727 PCOUNT_BPATH_SELECTED
,
13728 PCOUNT_PFCNT
, /* the figure we display to users */
13732 static const char *const pcount_strs
[] = {
13733 [PCOUNT_ADJ_IN
] = "Adj-in",
13734 [PCOUNT_DAMPED
] = "Damped",
13735 [PCOUNT_REMOVED
] = "Removed",
13736 [PCOUNT_HISTORY
] = "History",
13737 [PCOUNT_STALE
] = "Stale",
13738 [PCOUNT_VALID
] = "Valid",
13739 [PCOUNT_ALL
] = "All RIB",
13740 [PCOUNT_COUNTED
] = "PfxCt counted",
13741 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13742 [PCOUNT_PFCNT
] = "Useable",
13743 [PCOUNT_MAX
] = NULL
,
13746 struct peer_pcounts
{
13747 unsigned int count
[PCOUNT_MAX
];
13748 const struct peer
*peer
;
13749 const struct bgp_table
*table
;
13753 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13755 const struct bgp_adj_in
*ain
;
13756 const struct bgp_path_info
*pi
;
13757 const struct peer
*peer
= pc
->peer
;
13759 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13760 if (ain
->peer
== peer
)
13761 pc
->count
[PCOUNT_ADJ_IN
]++;
13763 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13765 if (pi
->peer
!= peer
)
13768 pc
->count
[PCOUNT_ALL
]++;
13770 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13771 pc
->count
[PCOUNT_DAMPED
]++;
13772 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13773 pc
->count
[PCOUNT_HISTORY
]++;
13774 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13775 pc
->count
[PCOUNT_REMOVED
]++;
13776 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13777 pc
->count
[PCOUNT_STALE
]++;
13778 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13779 pc
->count
[PCOUNT_VALID
]++;
13780 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13781 pc
->count
[PCOUNT_PFCNT
]++;
13782 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13783 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13785 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13786 pc
->count
[PCOUNT_COUNTED
]++;
13787 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13789 EC_LIB_DEVELOPMENT
,
13790 "Attempting to count but flags say it is unusable");
13792 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13794 EC_LIB_DEVELOPMENT
,
13795 "Not counted but flags say we should");
13800 static void bgp_peer_count_walker(struct event
*t
)
13802 struct bgp_dest
*rn
, *rm
;
13803 const struct bgp_table
*table
;
13804 struct peer_pcounts
*pc
= EVENT_ARG(t
);
13806 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13807 || pc
->safi
== SAFI_EVPN
) {
13808 /* Special handling for 2-level routing tables. */
13809 for (rn
= bgp_table_top(pc
->table
); rn
;
13810 rn
= bgp_route_next(rn
)) {
13811 table
= bgp_dest_get_bgp_table_info(rn
);
13813 for (rm
= bgp_table_top(table
); rm
;
13814 rm
= bgp_route_next(rm
))
13815 bgp_peer_count_proc(rm
, pc
);
13818 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13819 bgp_peer_count_proc(rn
, pc
);
13822 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13823 safi_t safi
, bool use_json
)
13825 struct peer_pcounts pcounts
= {.peer
= peer
};
13827 json_object
*json
= NULL
;
13828 json_object
*json_loop
= NULL
;
13831 json
= json_object_new_object();
13832 json_loop
= json_object_new_object();
13835 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13836 || !peer
->bgp
->rib
[afi
][safi
]) {
13838 json_object_string_add(
13840 "No such neighbor or address family");
13841 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13842 json_object_free(json
);
13843 json_object_free(json_loop
);
13845 vty_out(vty
, "%% No such neighbor or address family\n");
13847 return CMD_WARNING
;
13850 memset(&pcounts
, 0, sizeof(pcounts
));
13851 pcounts
.peer
= peer
;
13852 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13853 pcounts
.safi
= safi
;
13855 /* in-place call via thread subsystem so as to record execution time
13856 * stats for the thread-walk (i.e. ensure this can't be blamed on
13857 * on just vty_read()).
13859 event_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13862 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13863 json_object_string_add(json
, "multiProtocol",
13864 get_afi_safi_str(afi
, safi
, true));
13865 json_object_int_add(json
, "pfxCounter",
13866 peer
->pcount
[afi
][safi
]);
13868 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13869 json_object_int_add(json_loop
, pcount_strs
[i
],
13872 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13874 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13875 json_object_string_add(json
, "pfxctDriftFor",
13877 json_object_string_add(
13878 json
, "recommended",
13879 "Please report this bug, with the above command output");
13881 vty_json(vty
, json
);
13885 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13886 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13887 peer
->hostname
, peer
->host
,
13888 get_afi_safi_str(afi
, safi
, false));
13890 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13891 get_afi_safi_str(afi
, safi
, false));
13894 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13895 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13897 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13898 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13901 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13902 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13904 "Please report this bug, with the above command output\n");
13908 return CMD_SUCCESS
;
13911 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13912 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13913 "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]",
13917 BGP_INSTANCE_HELP_STR
13920 "Detailed information on TCP and BGP neighbor connections\n"
13921 "Neighbor to display information about\n"
13922 "Neighbor to display information about\n"
13923 "Neighbor on BGP configured interface\n"
13924 "Display detailed prefix count information\n"
13927 afi_t afi
= AFI_IP6
;
13928 safi_t safi
= SAFI_UNICAST
;
13931 struct bgp
*bgp
= NULL
;
13932 bool uj
= use_json(argc
, argv
);
13937 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13940 return CMD_WARNING
;
13942 argv_find(argv
, argc
, "neighbors", &idx
);
13943 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13945 return CMD_WARNING
;
13947 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13950 #ifdef KEEP_OLD_VPN_COMMANDS
13951 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13952 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13953 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13958 "Display information about all VPNv4 NLRIs\n"
13959 "Detailed information on TCP and BGP neighbor connections\n"
13960 "Neighbor to display information about\n"
13961 "Neighbor to display information about\n"
13962 "Neighbor on BGP configured interface\n"
13963 "Display detailed prefix count information\n"
13968 bool uj
= use_json(argc
, argv
);
13970 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13972 return CMD_WARNING
;
13974 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13977 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13978 show_ip_bgp_vpn_all_route_prefix_cmd
,
13979 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13984 "Display information about all VPNv4 NLRIs\n"
13985 "Network in the BGP routing table to display\n"
13986 "Network in the BGP routing table to display\n"
13990 char *network
= NULL
;
13991 struct bgp
*bgp
= bgp_get_default();
13993 vty_out(vty
, "Can't find default instance\n");
13994 return CMD_WARNING
;
13997 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13998 network
= argv
[idx
]->arg
;
13999 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
14000 network
= argv
[idx
]->arg
;
14002 vty_out(vty
, "Unable to figure out Network\n");
14003 return CMD_WARNING
;
14006 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
14007 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14008 use_json(argc
, argv
));
14010 #endif /* KEEP_OLD_VPN_COMMANDS */
14012 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
14013 show_bgp_l2vpn_evpn_route_prefix_cmd
,
14014 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
14019 "Network in the BGP routing table to display\n"
14020 "Network in the BGP routing table to display\n"
14021 "Network in the BGP routing table to display\n"
14022 "Network in the BGP routing table to display\n"
14026 char *network
= NULL
;
14027 int prefix_check
= 0;
14029 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
14030 argv_find(argv
, argc
, "X:X::X:X", &idx
))
14031 network
= argv
[idx
]->arg
;
14032 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
14033 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
14034 network
= argv
[idx
]->arg
;
14037 vty_out(vty
, "Unable to figure out Network\n");
14038 return CMD_WARNING
;
14040 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
14041 prefix_check
, BGP_PATH_SHOW_ALL
,
14042 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
14045 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
14046 struct bgp_table
*table
, int *header1
,
14047 int *header2
, json_object
*json
,
14048 json_object
*json_scode
,
14049 json_object
*json_ocode
, bool wide
,
14052 uint64_t version
= table
? table
->version
: 0;
14056 json_object_int_add(json
, "bgpTableVersion", version
);
14057 json_object_string_addf(json
, "bgpLocalRouterId",
14058 "%pI4", &peer
->bgp
->router_id
);
14059 json_object_int_add(json
, "defaultLocPrf",
14060 peer
->bgp
->default_local_pref
);
14061 json_object_int_add(json
, "localAS",
14062 peer
->change_local_as
14063 ? peer
->change_local_as
14065 json_object_object_add(json
, "bgpStatusCodes",
14067 json_object_object_add(json
, "bgpOriginCodes",
14071 "BGP table version is %" PRIu64
14072 ", local router ID is %pI4, vrf id ",
14073 version
, &peer
->bgp
->router_id
);
14074 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
14075 vty_out(vty
, "%s", VRFID_NONE_STR
);
14077 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
14078 vty_out(vty
, "\n");
14079 vty_out(vty
, "Default local pref %u, ",
14080 peer
->bgp
->default_local_pref
);
14081 vty_out(vty
, "local AS %u\n",
14082 peer
->change_local_as
? peer
->change_local_as
14085 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14086 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14087 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14088 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14094 if (!json
&& !detail
)
14095 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14096 : BGP_SHOW_HEADER
));
14102 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14103 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14104 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14105 json_object
*json_scode
, json_object
*json_ocode
,
14106 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14107 const struct prefix
*match
, unsigned long *output_count
,
14108 unsigned long *filtered_count
)
14110 struct bgp_adj_in
*ain
= NULL
;
14111 struct bgp_adj_out
*adj
= NULL
;
14112 struct bgp_dest
*dest
;
14116 struct update_subgroup
*subgrp
;
14117 struct peer_af
*paf
= NULL
;
14118 bool route_filtered
;
14119 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14120 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14121 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14122 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14123 || (safi
== SAFI_EVPN
))
14127 json_object
*json_net
= NULL
;
14131 /* If the user supplied a prefix, look for a matching route instead
14132 * of walking the whole table.
14135 dest
= bgp_node_match(table
, match
);
14138 vty_out(vty
, "Network not in table\n");
14142 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14144 if (rn_p
->prefixlen
!= match
->prefixlen
) {
14146 vty_out(vty
, "Network not in table\n");
14147 bgp_dest_unlock_node(dest
);
14151 if (type
== bgp_show_adj_route_received
||
14152 type
== bgp_show_adj_route_filtered
) {
14153 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14154 if (ain
->peer
== peer
) {
14159 /* bail out if if adj_out is empty, or
14160 * if the prefix isn't in this peer's
14163 if (!ain
|| ain
->peer
!= peer
) {
14165 vty_out(vty
, "Network not in table\n");
14166 bgp_dest_unlock_node(dest
);
14169 } else if (type
== bgp_show_adj_route_advertised
) {
14170 bool peer_found
= false;
14172 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
) {
14173 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14174 if (paf
->peer
== peer
&& adj
->attr
) {
14183 /* bail out if if adj_out is empty, or
14184 * if the prefix isn't in this peer's
14187 if (!paf
|| !peer_found
) {
14189 vty_out(vty
, "Network not in table\n");
14190 bgp_dest_unlock_node(dest
);
14195 ret
= bgp_output_modifier(peer
, rn_p
, &attr
, afi
, safi
,
14198 if (ret
!= RMAP_DENY
) {
14199 show_adj_route_header(vty
, peer
, table
, header1
,
14200 header2
, json
, json_scode
,
14201 json_ocode
, wide
, detail
);
14204 json_net
= json_object_new_object();
14206 bgp_show_path_info(NULL
/* prefix_rd */, dest
, vty
, bgp
,
14207 afi
, safi
, json_net
,
14208 BGP_PATH_SHOW_ALL
, &display
,
14209 RPKI_NOT_BEING_USED
);
14211 json_object_object_addf(json_ar
, json_net
,
14215 (*filtered_count
)++;
14217 bgp_attr_flush(&attr
);
14218 bgp_dest_unlock_node(dest
);
14223 subgrp
= peer_subgroup(peer
, afi
, safi
);
14225 if (type
== bgp_show_adj_route_advertised
&& subgrp
14226 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14228 json_object_int_add(json
, "bgpTableVersion",
14230 json_object_string_addf(json
, "bgpLocalRouterId",
14231 "%pI4", &bgp
->router_id
);
14232 json_object_int_add(json
, "defaultLocPrf",
14233 bgp
->default_local_pref
);
14234 json_object_int_add(json
, "localAS",
14235 peer
->change_local_as
14236 ? peer
->change_local_as
14238 json_object_object_add(json
, "bgpStatusCodes",
14240 json_object_object_add(json
, "bgpOriginCodes",
14242 json_object_string_add(
14243 json
, "bgpOriginatingDefaultNetwork",
14244 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14247 "BGP table version is %" PRIu64
14248 ", local router ID is %pI4, vrf id ",
14249 table
->version
, &bgp
->router_id
);
14250 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14251 vty_out(vty
, "%s", VRFID_NONE_STR
);
14253 vty_out(vty
, "%u", bgp
->vrf_id
);
14254 vty_out(vty
, "\n");
14255 vty_out(vty
, "Default local pref %u, ",
14256 bgp
->default_local_pref
);
14257 vty_out(vty
, "local AS %u\n",
14258 peer
->change_local_as
? peer
->change_local_as
14261 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14262 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14263 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14264 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14267 vty_out(vty
, "Originating default network %s\n\n",
14268 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14274 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14275 if (type
== bgp_show_adj_route_received
14276 || type
== bgp_show_adj_route_filtered
) {
14277 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14278 if (ain
->peer
!= peer
)
14281 show_adj_route_header(vty
, peer
, table
, header1
,
14282 header2
, json
, json_scode
,
14283 json_ocode
, wide
, detail
);
14285 if ((safi
== SAFI_MPLS_VPN
)
14286 || (safi
== SAFI_ENCAP
)
14287 || (safi
== SAFI_EVPN
)) {
14289 json_object_string_add(
14290 json_ar
, "rd", rd_str
);
14291 else if (show_rd
&& rd_str
) {
14293 "Route Distinguisher: %s\n",
14300 route_filtered
= false;
14302 /* Filter prefix using distribute list,
14303 * filter list or prefix list
14305 const struct prefix
*rn_p
=
14306 bgp_dest_get_prefix(dest
);
14307 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14310 route_filtered
= true;
14312 /* Filter prefix using route-map */
14313 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14314 safi
, rmap_name
, NULL
,
14317 if (type
== bgp_show_adj_route_filtered
&&
14318 !route_filtered
&& ret
!= RMAP_DENY
) {
14319 bgp_attr_flush(&attr
);
14323 if (type
== bgp_show_adj_route_received
14324 && (route_filtered
|| ret
== RMAP_DENY
))
14325 (*filtered_count
)++;
14330 json_object_new_object();
14331 bgp_show_path_info(
14332 NULL
/* prefix_rd */, dest
, vty
,
14333 bgp
, afi
, safi
, json_net
,
14334 BGP_PATH_SHOW_ALL
, &display
,
14335 RPKI_NOT_BEING_USED
);
14337 json_object_object_addf(
14341 route_vty_out_tmp(vty
, dest
, rn_p
,
14342 &attr
, safi
, use_json
,
14344 bgp_attr_flush(&attr
);
14347 } else if (type
== bgp_show_adj_route_advertised
) {
14348 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14349 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14350 if (paf
->peer
!= peer
|| !adj
->attr
)
14353 show_adj_route_header(
14354 vty
, peer
, table
, header1
,
14355 header2
, json
, json_scode
,
14356 json_ocode
, wide
, detail
);
14358 const struct prefix
*rn_p
=
14359 bgp_dest_get_prefix(dest
);
14362 ret
= bgp_output_modifier(
14363 peer
, rn_p
, &attr
, afi
, safi
,
14366 if (ret
!= RMAP_DENY
) {
14367 if ((safi
== SAFI_MPLS_VPN
)
14368 || (safi
== SAFI_ENCAP
)
14369 || (safi
== SAFI_EVPN
)) {
14371 json_object_string_add(
14378 "Route Distinguisher: %s\n",
14386 json_object_new_object();
14387 bgp_show_path_info(
14396 RPKI_NOT_BEING_USED
);
14398 json_object_object_addf(
14411 (*filtered_count
)++;
14414 bgp_attr_flush(&attr
);
14416 } else if (type
== bgp_show_adj_route_bestpath
) {
14417 struct bgp_path_info
*pi
;
14419 show_adj_route_header(vty
, peer
, table
, header1
,
14420 header2
, json
, json_scode
,
14421 json_ocode
, wide
, detail
);
14423 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14425 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14427 if (pi
->peer
!= peer
)
14430 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14436 json_object_new_object();
14437 bgp_show_path_info(
14438 NULL
/* prefix_rd */, dest
, vty
,
14439 bgp
, afi
, safi
, json_net
,
14440 BGP_PATH_SHOW_BESTPATH
,
14441 &display
, RPKI_NOT_BEING_USED
);
14443 json_object_object_addf(
14448 vty
, dest
, rn_p
, pi
->attr
, safi
,
14449 use_json
, json_ar
, wide
);
14456 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14457 safi_t safi
, enum bgp_show_adj_route_type type
,
14458 const char *rmap_name
, const struct prefix
*match
,
14459 uint16_t show_flags
)
14462 struct bgp_table
*table
;
14463 json_object
*json
= NULL
;
14464 json_object
*json_scode
= NULL
;
14465 json_object
*json_ocode
= NULL
;
14466 json_object
*json_ar
= NULL
;
14467 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14469 /* Init BGP headers here so they're only displayed once
14470 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14476 * Initialize variables for each RD
14477 * All prefixes under an RD is aggregated within "json_routes"
14479 char rd_str
[BUFSIZ
] = {0};
14480 json_object
*json_routes
= NULL
;
14483 /* For 2-tier tables, prefix counts need to be
14484 * maintained across multiple runs of show_adj_route()
14486 unsigned long output_count_per_rd
;
14487 unsigned long filtered_count_per_rd
;
14488 unsigned long output_count
= 0;
14489 unsigned long filtered_count
= 0;
14492 json
= json_object_new_object();
14493 json_ar
= json_object_new_object();
14494 json_scode
= json_object_new_object();
14495 json_ocode
= json_object_new_object();
14496 #if CONFDATE > 20231208
14497 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14499 json_object_string_add(json_scode
, "suppressed", "s");
14500 json_object_string_add(json_scode
, "damped", "d");
14501 json_object_string_add(json_scode
, "history", "h");
14502 json_object_string_add(json_scode
, "valid", "*");
14503 json_object_string_add(json_scode
, "best", ">");
14504 json_object_string_add(json_scode
, "multipath", "=");
14505 json_object_string_add(json_scode
, "internal", "i");
14506 json_object_string_add(json_scode
, "ribFailure", "r");
14507 json_object_string_add(json_scode
, "stale", "S");
14508 json_object_string_add(json_scode
, "removed", "R");
14510 #if CONFDATE > 20231208
14511 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14513 json_object_string_add(json_ocode
, "igp", "i");
14514 json_object_string_add(json_ocode
, "egp", "e");
14515 json_object_string_add(json_ocode
, "incomplete", "?");
14518 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14520 json_object_string_add(
14522 "No such neighbor or address family");
14523 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14524 json_object_free(json
);
14525 json_object_free(json_ar
);
14526 json_object_free(json_scode
);
14527 json_object_free(json_ocode
);
14529 vty_out(vty
, "%% No such neighbor or address family\n");
14531 return CMD_WARNING
;
14534 if ((type
== bgp_show_adj_route_received
14535 || type
== bgp_show_adj_route_filtered
)
14536 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14537 PEER_FLAG_SOFT_RECONFIG
)) {
14539 json_object_string_add(
14541 "Inbound soft reconfiguration not enabled");
14542 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14543 json_object_free(json
);
14544 json_object_free(json_ar
);
14545 json_object_free(json_scode
);
14546 json_object_free(json_ocode
);
14549 "%% Inbound soft reconfiguration not enabled\n");
14551 return CMD_WARNING
;
14556 /* labeled-unicast routes live in the unicast table */
14557 if (safi
== SAFI_LABELED_UNICAST
)
14558 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14560 table
= bgp
->rib
[afi
][safi
];
14562 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14563 || (safi
== SAFI_EVPN
)) {
14565 struct bgp_dest
*dest
;
14567 for (dest
= bgp_table_top(table
); dest
;
14568 dest
= bgp_route_next(dest
)) {
14569 table
= bgp_dest_get_bgp_table_info(dest
);
14573 output_count_per_rd
= 0;
14574 filtered_count_per_rd
= 0;
14577 json_routes
= json_object_new_object();
14579 const struct prefix_rd
*prd
;
14580 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14583 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
),
14587 vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14588 json
, json_routes
, json_scode
, json_ocode
,
14589 show_flags
, &header1
, &header2
, rd_str
, match
,
14590 &output_count_per_rd
, &filtered_count_per_rd
);
14592 /* Don't include an empty RD in the output! */
14593 if (json_routes
&& (output_count_per_rd
> 0))
14594 json_object_object_add(json_ar
, rd_str
,
14597 output_count
+= output_count_per_rd
;
14598 filtered_count
+= filtered_count_per_rd
;
14601 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14602 json
, json_ar
, json_scode
, json_ocode
,
14603 show_flags
, &header1
, &header2
, rd_str
, match
,
14604 &output_count
, &filtered_count
);
14607 if (type
== bgp_show_adj_route_advertised
)
14608 json_object_object_add(json
, "advertisedRoutes",
14611 json_object_object_add(json
, "receivedRoutes", json_ar
);
14612 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14613 json_object_int_add(json
, "filteredPrefixCounter",
14617 * These fields only give up ownership to `json` when `header1`
14618 * is used (set to zero). See code in `show_adj_route` and
14619 * `show_adj_route_header`.
14621 if (header1
== 1) {
14622 json_object_free(json_scode
);
14623 json_object_free(json_ocode
);
14626 vty_json(vty
, json
);
14627 } else if (output_count
> 0) {
14628 if (!match
&& filtered_count
> 0)
14630 "\nTotal number of prefixes %ld (%ld filtered)\n",
14631 output_count
, filtered_count
);
14633 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14637 return CMD_SUCCESS
;
14640 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14641 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14642 "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]",
14646 BGP_INSTANCE_HELP_STR
14648 BGP_SAFI_WITH_LABEL_HELP_STR
14649 "Detailed information on TCP and BGP neighbor connections\n"
14650 "Neighbor to display information about\n"
14651 "Neighbor to display information about\n"
14652 "Neighbor on BGP configured interface\n"
14653 "Display the routes selected by best path\n"
14654 "Display detailed version of routes\n"
14656 "Increase table width for longer prefixes\n")
14658 afi_t afi
= AFI_IP6
;
14659 safi_t safi
= SAFI_UNICAST
;
14660 char *rmap_name
= NULL
;
14661 char *peerstr
= NULL
;
14662 struct bgp
*bgp
= NULL
;
14664 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14666 uint16_t show_flags
= 0;
14669 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14672 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14675 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14677 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14681 return CMD_WARNING
;
14683 argv_find(argv
, argc
, "neighbors", &idx
);
14684 peerstr
= argv
[++idx
]->arg
;
14686 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14688 return CMD_WARNING
;
14690 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, NULL
,
14694 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14695 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14696 "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]",
14700 BGP_INSTANCE_HELP_STR
14702 BGP_SAFI_WITH_LABEL_HELP_STR
14703 "Display the entries for all address families\n"
14704 "Detailed information on TCP and BGP neighbor connections\n"
14705 "Neighbor to display information about\n"
14706 "Neighbor to display information about\n"
14707 "Neighbor on BGP configured interface\n"
14708 "Display the routes advertised to a BGP neighbor\n"
14709 "Display the received routes from neighbor\n"
14710 "Display the filtered routes received from neighbor\n"
14711 "Route-map to modify the attributes\n"
14712 "Name of the route map\n"
14715 "Display detailed version of routes\n"
14717 "Increase table width for longer prefixes\n")
14719 afi_t afi
= AFI_IP6
;
14720 safi_t safi
= SAFI_UNICAST
;
14721 char *peerstr
= NULL
;
14722 struct bgp
*bgp
= NULL
;
14724 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14727 uint16_t show_flags
= 0;
14728 struct listnode
*node
;
14731 if (detail
|| prefix_str
)
14732 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14736 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14740 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14741 if (argv_find(argv
, argc
, "ipv4", &idx
))
14742 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14744 if (argv_find(argv
, argc
, "ipv6", &idx
))
14745 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14749 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14751 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14754 return CMD_WARNING
;
14756 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14757 argv_find(argv
, argc
, "neighbors", &idx
);
14758 peerstr
= argv
[++idx
]->arg
;
14760 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14762 return CMD_WARNING
;
14764 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14765 type
= bgp_show_adj_route_advertised
;
14766 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14767 type
= bgp_show_adj_route_received
;
14768 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14769 type
= bgp_show_adj_route_filtered
;
14772 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14773 prefix_str
? prefix
: NULL
, show_flags
);
14775 vty_out(vty
, "{\n");
14777 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14778 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14779 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14781 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14782 FOREACH_SAFI (safi
) {
14783 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14790 vty_out(vty
, ",\n");
14791 vty_out(vty
, "\"%s\":",
14792 get_afi_safi_str(afi
, safi
,
14796 "\nFor address family: %s\n",
14797 get_afi_safi_str(afi
, safi
,
14800 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14801 route_map
, prefix
, show_flags
);
14805 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14806 FOREACH_AFI_SAFI (afi
, safi
) {
14807 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14814 vty_out(vty
, ",\n");
14815 vty_out(vty
, "\"%s\":",
14816 get_afi_safi_str(afi
, safi
,
14820 "\nFor address family: %s\n",
14821 get_afi_safi_str(afi
, safi
,
14824 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14825 route_map
, prefix
, show_flags
);
14830 vty_out(vty
, "}\n");
14832 return CMD_SUCCESS
;
14835 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14836 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14837 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14841 BGP_INSTANCE_HELP_STR
14844 BGP_AF_MODIFIER_STR
14845 "Detailed information on TCP and BGP neighbor connections\n"
14846 "Neighbor to display information about\n"
14847 "Neighbor to display information about\n"
14848 "Neighbor on BGP configured interface\n"
14849 "Display information received from a BGP neighbor\n"
14850 "Display the prefixlist filter\n"
14853 afi_t afi
= AFI_IP6
;
14854 safi_t safi
= SAFI_UNICAST
;
14855 char *peerstr
= NULL
;
14860 struct bgp
*bgp
= NULL
;
14861 bool uj
= use_json(argc
, argv
);
14866 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14869 return CMD_WARNING
;
14871 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14872 argv_find(argv
, argc
, "neighbors", &idx
);
14873 peerstr
= argv
[++idx
]->arg
;
14875 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14877 return CMD_WARNING
;
14879 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14880 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14883 vty_out(vty
, "Address Family: %s\n",
14884 get_afi_safi_str(afi
, safi
, false));
14885 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14888 vty_out(vty
, "{}\n");
14890 vty_out(vty
, "No functional output\n");
14893 return CMD_SUCCESS
;
14896 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14897 afi_t afi
, safi_t safi
,
14898 enum bgp_show_type type
, bool use_json
)
14900 uint16_t show_flags
= 0;
14903 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14905 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14907 json_object
*json_no
= NULL
;
14908 json_no
= json_object_new_object();
14909 json_object_string_add(
14910 json_no
, "warning",
14911 "No such neighbor or address family");
14912 vty_out(vty
, "%s\n",
14913 json_object_to_json_string(json_no
));
14914 json_object_free(json_no
);
14916 vty_out(vty
, "%% No such neighbor or address family\n");
14917 return CMD_WARNING
;
14920 /* labeled-unicast routes live in the unicast table */
14921 if (safi
== SAFI_LABELED_UNICAST
)
14922 safi
= SAFI_UNICAST
;
14924 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14925 RPKI_NOT_BEING_USED
);
14928 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14929 show_ip_bgp_flowspec_routes_detailed_cmd
,
14930 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14934 BGP_INSTANCE_HELP_STR
14937 "Detailed information on flowspec entries\n"
14940 afi_t afi
= AFI_IP6
;
14941 safi_t safi
= SAFI_UNICAST
;
14942 struct bgp
*bgp
= NULL
;
14944 bool uj
= use_json(argc
, argv
);
14945 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14949 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14952 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14955 return CMD_WARNING
;
14957 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14958 show_flags
, RPKI_NOT_BEING_USED
);
14961 DEFUN (show_ip_bgp_neighbor_routes
,
14962 show_ip_bgp_neighbor_routes_cmd
,
14963 "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]",
14967 BGP_INSTANCE_HELP_STR
14969 BGP_SAFI_WITH_LABEL_HELP_STR
14970 "Detailed information on TCP and BGP neighbor connections\n"
14971 "Neighbor to display information about\n"
14972 "Neighbor to display information about\n"
14973 "Neighbor on BGP configured interface\n"
14974 "Display flap statistics of the routes learned from neighbor\n"
14975 "Display the dampened routes received from neighbor\n"
14976 "Display routes learned from neighbor\n"
14979 char *peerstr
= NULL
;
14980 struct bgp
*bgp
= NULL
;
14981 afi_t afi
= AFI_IP6
;
14982 safi_t safi
= SAFI_UNICAST
;
14984 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14986 bool uj
= use_json(argc
, argv
);
14991 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14994 return CMD_WARNING
;
14996 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14997 argv_find(argv
, argc
, "neighbors", &idx
);
14998 peerstr
= argv
[++idx
]->arg
;
15000 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
15002 return CMD_WARNING
;
15004 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
15005 sh_type
= bgp_show_type_flap_neighbor
;
15006 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
15007 sh_type
= bgp_show_type_damp_neighbor
;
15008 else if (argv_find(argv
, argc
, "routes", &idx
))
15009 sh_type
= bgp_show_type_neighbor
;
15011 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
15014 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
15016 struct bgp_distance
{
15017 /* Distance value for the IP source prefix. */
15020 /* Name of the access-list to be matched. */
15024 DEFUN (show_bgp_afi_vpn_rd_route
,
15025 show_bgp_afi_vpn_rd_route_cmd
,
15026 "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]",
15030 BGP_AF_MODIFIER_STR
15031 "Display information for a route distinguisher\n"
15032 "Route Distinguisher\n"
15033 "All Route Distinguishers\n"
15034 "Network in the BGP routing table to display\n"
15035 "Network in the BGP routing table to display\n"
15039 struct prefix_rd prd
;
15040 afi_t afi
= AFI_MAX
;
15043 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
15044 vty_out(vty
, "%% Malformed Address Family\n");
15045 return CMD_WARNING
;
15048 if (!strcmp(argv
[5]->arg
, "all"))
15049 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
15050 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
15051 RPKI_NOT_BEING_USED
,
15052 use_json(argc
, argv
));
15054 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
15056 vty_out(vty
, "%% Malformed Route Distinguisher\n");
15057 return CMD_WARNING
;
15060 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
15061 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
15062 use_json(argc
, argv
));
15065 static struct bgp_distance
*bgp_distance_new(void)
15067 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
15070 static void bgp_distance_free(struct bgp_distance
*bdistance
)
15072 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
15075 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
15076 const char *ip_str
, const char *access_list_str
)
15083 struct bgp_dest
*dest
;
15084 struct bgp_distance
*bdistance
;
15086 afi
= bgp_node_afi(vty
);
15087 safi
= bgp_node_safi(vty
);
15089 ret
= str2prefix(ip_str
, &p
);
15091 vty_out(vty
, "Malformed prefix\n");
15092 return CMD_WARNING_CONFIG_FAILED
;
15095 distance
= atoi(distance_str
);
15097 /* Get BGP distance node. */
15098 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
15099 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15101 bgp_dest_unlock_node(dest
);
15103 bdistance
= bgp_distance_new();
15104 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
15107 /* Set distance value. */
15108 bdistance
->distance
= distance
;
15110 /* Reset access-list configuration. */
15111 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15112 if (access_list_str
)
15113 bdistance
->access_list
=
15114 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
15116 return CMD_SUCCESS
;
15119 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
15120 const char *ip_str
, const char *access_list_str
)
15127 struct bgp_dest
*dest
;
15128 struct bgp_distance
*bdistance
;
15130 afi
= bgp_node_afi(vty
);
15131 safi
= bgp_node_safi(vty
);
15133 ret
= str2prefix(ip_str
, &p
);
15135 vty_out(vty
, "Malformed prefix\n");
15136 return CMD_WARNING_CONFIG_FAILED
;
15139 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
15141 vty_out(vty
, "Can't find specified prefix\n");
15142 return CMD_WARNING_CONFIG_FAILED
;
15145 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15146 distance
= atoi(distance_str
);
15148 if (bdistance
->distance
!= distance
) {
15149 vty_out(vty
, "Distance does not match configured\n");
15150 bgp_dest_unlock_node(dest
);
15151 return CMD_WARNING_CONFIG_FAILED
;
15154 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15155 bgp_distance_free(bdistance
);
15157 bgp_dest_set_bgp_path_info(dest
, NULL
);
15158 bgp_dest_unlock_node(dest
);
15159 bgp_dest_unlock_node(dest
);
15161 return CMD_SUCCESS
;
15164 /* Apply BGP information to distance method. */
15165 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
15166 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
15168 struct bgp_dest
*dest
;
15169 struct prefix q
= {0};
15171 struct bgp_distance
*bdistance
;
15172 struct access_list
*alist
;
15173 struct bgp_static
*bgp_static
;
15174 struct bgp_path_info
*bpi_ultimate
;
15179 peer
= pinfo
->peer
;
15181 if (pinfo
->attr
->distance
)
15182 return pinfo
->attr
->distance
;
15184 /* get peer origin to calculate appropriate distance */
15185 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
15186 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
15187 peer
= bpi_ultimate
->peer
;
15190 /* Check source address.
15191 * Note: for aggregate route, peer can have unspec af type.
15193 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
15194 && !sockunion2hostprefix(&peer
->su
, &q
))
15197 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
15199 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15200 bgp_dest_unlock_node(dest
);
15202 if (bdistance
->access_list
) {
15203 alist
= access_list_lookup(afi
, bdistance
->access_list
);
15205 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
15206 return bdistance
->distance
;
15208 return bdistance
->distance
;
15211 /* Backdoor check. */
15212 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
15214 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15215 bgp_dest_unlock_node(dest
);
15217 if (bgp_static
->backdoor
) {
15218 if (bgp
->distance_local
[afi
][safi
])
15219 return bgp
->distance_local
[afi
][safi
];
15221 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15225 if (peer
->sort
== BGP_PEER_EBGP
) {
15226 if (bgp
->distance_ebgp
[afi
][safi
])
15227 return bgp
->distance_ebgp
[afi
][safi
];
15228 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15229 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15230 if (bgp
->distance_ibgp
[afi
][safi
])
15231 return bgp
->distance_ibgp
[afi
][safi
];
15232 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15234 if (bgp
->distance_local
[afi
][safi
])
15235 return bgp
->distance_local
[afi
][safi
];
15236 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15240 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15241 * we should tell ZEBRA update the routes for a specific
15242 * AFI/SAFI to reflect changes in RIB.
15244 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15246 safi_t update_safi
)
15251 FOREACH_AFI_SAFI (afi
, safi
) {
15252 if (!bgp_fibupd_safi(safi
))
15255 if (afi
!= update_afi
&& safi
!= update_safi
)
15258 if (BGP_DEBUG(zebra
, ZEBRA
))
15260 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15261 __func__
, afi
, safi
);
15262 bgp_zebra_announce_table(bgp
, afi
, safi
);
15266 DEFUN (bgp_distance
,
15268 "distance bgp (1-255) (1-255) (1-255)",
15269 "Define an administrative distance\n"
15271 "Distance for routes external to the AS\n"
15272 "Distance for routes internal to the AS\n"
15273 "Distance for local routes\n")
15275 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15276 int idx_number
= 2;
15277 int idx_number_2
= 3;
15278 int idx_number_3
= 4;
15279 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15280 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15281 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15285 afi
= bgp_node_afi(vty
);
15286 safi
= bgp_node_safi(vty
);
15288 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15289 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15290 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15291 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15292 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15293 bgp
->distance_local
[afi
][safi
] = distance_local
;
15294 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15296 return CMD_SUCCESS
;
15299 DEFUN (no_bgp_distance
,
15300 no_bgp_distance_cmd
,
15301 "no distance bgp [(1-255) (1-255) (1-255)]",
15303 "Define an administrative distance\n"
15305 "Distance for routes external to the AS\n"
15306 "Distance for routes internal to the AS\n"
15307 "Distance for local routes\n")
15309 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15313 afi
= bgp_node_afi(vty
);
15314 safi
= bgp_node_safi(vty
);
15316 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15317 || bgp
->distance_ibgp
[afi
][safi
] != 0
15318 || bgp
->distance_local
[afi
][safi
] != 0) {
15319 bgp
->distance_ebgp
[afi
][safi
] = 0;
15320 bgp
->distance_ibgp
[afi
][safi
] = 0;
15321 bgp
->distance_local
[afi
][safi
] = 0;
15322 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15324 return CMD_SUCCESS
;
15328 DEFUN (bgp_distance_source
,
15329 bgp_distance_source_cmd
,
15330 "distance (1-255) A.B.C.D/M",
15331 "Define an administrative distance\n"
15332 "Administrative distance\n"
15333 "IP source prefix\n")
15335 int idx_number
= 1;
15336 int idx_ipv4_prefixlen
= 2;
15337 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15338 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15339 return CMD_SUCCESS
;
15342 DEFUN (no_bgp_distance_source
,
15343 no_bgp_distance_source_cmd
,
15344 "no distance (1-255) A.B.C.D/M",
15346 "Define an administrative distance\n"
15347 "Administrative distance\n"
15348 "IP source prefix\n")
15350 int idx_number
= 2;
15351 int idx_ipv4_prefixlen
= 3;
15352 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15353 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15354 return CMD_SUCCESS
;
15357 DEFUN (bgp_distance_source_access_list
,
15358 bgp_distance_source_access_list_cmd
,
15359 "distance (1-255) A.B.C.D/M WORD",
15360 "Define an administrative distance\n"
15361 "Administrative distance\n"
15362 "IP source prefix\n"
15363 "Access list name\n")
15365 int idx_number
= 1;
15366 int idx_ipv4_prefixlen
= 2;
15368 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15369 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15370 return CMD_SUCCESS
;
15373 DEFUN (no_bgp_distance_source_access_list
,
15374 no_bgp_distance_source_access_list_cmd
,
15375 "no distance (1-255) A.B.C.D/M WORD",
15377 "Define an administrative distance\n"
15378 "Administrative distance\n"
15379 "IP source prefix\n"
15380 "Access list name\n")
15382 int idx_number
= 2;
15383 int idx_ipv4_prefixlen
= 3;
15385 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15386 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15387 return CMD_SUCCESS
;
15390 DEFUN (ipv6_bgp_distance_source
,
15391 ipv6_bgp_distance_source_cmd
,
15392 "distance (1-255) X:X::X:X/M",
15393 "Define an administrative distance\n"
15394 "Administrative distance\n"
15395 "IP source prefix\n")
15397 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15398 return CMD_SUCCESS
;
15401 DEFUN (no_ipv6_bgp_distance_source
,
15402 no_ipv6_bgp_distance_source_cmd
,
15403 "no distance (1-255) X:X::X:X/M",
15405 "Define an administrative distance\n"
15406 "Administrative distance\n"
15407 "IP source prefix\n")
15409 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15410 return CMD_SUCCESS
;
15413 DEFUN (ipv6_bgp_distance_source_access_list
,
15414 ipv6_bgp_distance_source_access_list_cmd
,
15415 "distance (1-255) X:X::X:X/M WORD",
15416 "Define an administrative distance\n"
15417 "Administrative distance\n"
15418 "IP source prefix\n"
15419 "Access list name\n")
15421 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15422 return CMD_SUCCESS
;
15425 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15426 no_ipv6_bgp_distance_source_access_list_cmd
,
15427 "no distance (1-255) X:X::X:X/M WORD",
15429 "Define an administrative distance\n"
15430 "Administrative distance\n"
15431 "IP source prefix\n"
15432 "Access list name\n")
15434 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15435 return CMD_SUCCESS
;
15438 DEFUN (bgp_damp_set
,
15440 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15441 "BGP Specific commands\n"
15442 "Enable route-flap dampening\n"
15443 "Half-life time for the penalty\n"
15444 "Value to start reusing a route\n"
15445 "Value to start suppressing a route\n"
15446 "Maximum duration to suppress a stable route\n")
15448 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15449 int idx_half_life
= 2;
15451 int idx_suppress
= 4;
15452 int idx_max_suppress
= 5;
15453 int half
= DEFAULT_HALF_LIFE
* 60;
15454 int reuse
= DEFAULT_REUSE
;
15455 int suppress
= DEFAULT_SUPPRESS
;
15456 int max
= 4 * half
;
15459 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15460 reuse
= atoi(argv
[idx_reuse
]->arg
);
15461 suppress
= atoi(argv
[idx_suppress
]->arg
);
15462 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15463 } else if (argc
== 3) {
15464 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15469 * These can't be 0 but our SA doesn't understand the
15470 * way our cli is constructed
15474 if (suppress
< reuse
) {
15476 "Suppress value cannot be less than reuse value \n");
15480 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15481 reuse
, suppress
, max
);
15484 DEFUN (bgp_damp_unset
,
15485 bgp_damp_unset_cmd
,
15486 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15488 "BGP Specific commands\n"
15489 "Enable route-flap dampening\n"
15490 "Half-life time for the penalty\n"
15491 "Value to start reusing a route\n"
15492 "Value to start suppressing a route\n"
15493 "Maximum duration to suppress a stable route\n")
15495 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15496 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15499 /* Display specified route of BGP table. */
15500 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15501 const char *ip_str
, afi_t afi
, safi_t safi
,
15502 struct prefix_rd
*prd
, int prefix_check
)
15505 struct prefix match
;
15506 struct bgp_dest
*dest
;
15507 struct bgp_dest
*rm
;
15508 struct bgp_path_info
*pi
;
15509 struct bgp_path_info
*pi_temp
;
15511 struct bgp_table
*table
;
15513 /* BGP structure lookup. */
15515 bgp
= bgp_lookup_by_name(view_name
);
15517 vty_out(vty
, "%% Can't find BGP instance %s\n",
15519 return CMD_WARNING
;
15522 bgp
= bgp_get_default();
15524 vty_out(vty
, "%% No BGP process is configured\n");
15525 return CMD_WARNING
;
15529 /* Check IP address argument. */
15530 ret
= str2prefix(ip_str
, &match
);
15532 vty_out(vty
, "%% address is malformed\n");
15533 return CMD_WARNING
;
15536 match
.family
= afi2family(afi
);
15538 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15539 || (safi
== SAFI_EVPN
)) {
15540 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15541 dest
= bgp_route_next(dest
)) {
15542 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15544 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15546 table
= bgp_dest_get_bgp_table_info(dest
);
15549 rm
= bgp_node_match(table
, &match
);
15553 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15556 || rm_p
->prefixlen
== match
.prefixlen
) {
15557 pi
= bgp_dest_get_bgp_path_info(rm
);
15559 if (pi
->extra
&& pi
->extra
->damp_info
) {
15560 pi_temp
= pi
->next
;
15561 bgp_damp_info_free(
15562 pi
->extra
->damp_info
,
15570 bgp_dest_unlock_node(rm
);
15573 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15574 if (dest
!= NULL
) {
15575 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15578 || dest_p
->prefixlen
== match
.prefixlen
) {
15579 pi
= bgp_dest_get_bgp_path_info(dest
);
15581 if (pi
->extra
&& pi
->extra
->damp_info
) {
15582 pi_temp
= pi
->next
;
15583 bgp_damp_info_free(
15584 pi
->extra
->damp_info
,
15592 bgp_dest_unlock_node(dest
);
15596 return CMD_SUCCESS
;
15599 DEFUN (clear_ip_bgp_dampening
,
15600 clear_ip_bgp_dampening_cmd
,
15601 "clear ip bgp dampening",
15605 "Clear route flap dampening information\n")
15607 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15608 return CMD_SUCCESS
;
15611 DEFUN (clear_ip_bgp_dampening_prefix
,
15612 clear_ip_bgp_dampening_prefix_cmd
,
15613 "clear ip bgp dampening A.B.C.D/M",
15617 "Clear route flap dampening information\n"
15620 int idx_ipv4_prefixlen
= 4;
15621 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15622 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15625 DEFUN (clear_ip_bgp_dampening_address
,
15626 clear_ip_bgp_dampening_address_cmd
,
15627 "clear ip bgp dampening A.B.C.D",
15631 "Clear route flap dampening information\n"
15632 "Network to clear damping information\n")
15635 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15636 SAFI_UNICAST
, NULL
, 0);
15639 DEFUN (clear_ip_bgp_dampening_address_mask
,
15640 clear_ip_bgp_dampening_address_mask_cmd
,
15641 "clear ip bgp dampening A.B.C.D A.B.C.D",
15645 "Clear route flap dampening information\n"
15646 "Network to clear damping information\n"
15650 int idx_ipv4_2
= 5;
15652 char prefix_str
[BUFSIZ
];
15654 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15655 prefix_str
, sizeof(prefix_str
));
15657 vty_out(vty
, "%% Inconsistent address and mask\n");
15658 return CMD_WARNING
;
15661 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15665 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15667 struct vty
*vty
= arg
;
15668 struct peer
*peer
= bucket
->data
;
15670 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15673 DEFUN (show_bgp_listeners
,
15674 show_bgp_listeners_cmd
,
15675 "show bgp listeners",
15678 "Display Listen Sockets and who created them\n")
15680 bgp_dump_listener_info(vty
);
15682 return CMD_SUCCESS
;
15685 DEFUN (show_bgp_peerhash
,
15686 show_bgp_peerhash_cmd
,
15687 "show bgp peerhash",
15690 "Display information about the BGP peerhash\n")
15692 struct list
*instances
= bm
->bgp
;
15693 struct listnode
*node
;
15696 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15697 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15698 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15702 return CMD_SUCCESS
;
15705 /* also used for encap safi */
15706 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15707 afi_t afi
, safi_t safi
)
15709 struct bgp_dest
*pdest
;
15710 struct bgp_dest
*dest
;
15711 struct bgp_table
*table
;
15712 const struct prefix
*p
;
15713 struct bgp_static
*bgp_static
;
15714 mpls_label_t label
;
15716 /* Network configuration. */
15717 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15718 pdest
= bgp_route_next(pdest
)) {
15719 table
= bgp_dest_get_bgp_table_info(pdest
);
15723 for (dest
= bgp_table_top(table
); dest
;
15724 dest
= bgp_route_next(dest
)) {
15725 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15726 if (bgp_static
== NULL
)
15729 p
= bgp_dest_get_prefix(dest
);
15731 /* "network" configuration display. */
15732 label
= decode_label(&bgp_static
->label
);
15734 vty_out(vty
, " network %pFX rd %s", p
,
15735 bgp_static
->prd_pretty
);
15736 if (safi
== SAFI_MPLS_VPN
)
15737 vty_out(vty
, " label %u", label
);
15739 if (bgp_static
->rmap
.name
)
15740 vty_out(vty
, " route-map %s",
15741 bgp_static
->rmap
.name
);
15743 if (bgp_static
->backdoor
)
15744 vty_out(vty
, " backdoor");
15746 vty_out(vty
, "\n");
15751 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15752 afi_t afi
, safi_t safi
)
15754 struct bgp_dest
*pdest
;
15755 struct bgp_dest
*dest
;
15756 struct bgp_table
*table
;
15757 const struct prefix
*p
;
15758 struct bgp_static
*bgp_static
;
15759 char buf
[PREFIX_STRLEN
* 2];
15760 char buf2
[SU_ADDRSTRLEN
];
15761 char esi_buf
[ESI_STR_LEN
];
15763 /* Network configuration. */
15764 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15765 pdest
= bgp_route_next(pdest
)) {
15766 table
= bgp_dest_get_bgp_table_info(pdest
);
15770 for (dest
= bgp_table_top(table
); dest
;
15771 dest
= bgp_route_next(dest
)) {
15772 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15773 if (bgp_static
== NULL
)
15776 char *macrouter
= NULL
;
15778 if (bgp_static
->router_mac
)
15779 macrouter
= prefix_mac2str(
15780 bgp_static
->router_mac
, NULL
, 0);
15781 if (bgp_static
->eth_s_id
)
15782 esi_to_str(bgp_static
->eth_s_id
,
15783 esi_buf
, sizeof(esi_buf
));
15784 p
= bgp_dest_get_prefix(dest
);
15786 /* "network" configuration display. */
15787 if (p
->u
.prefix_evpn
.route_type
== 5) {
15788 char local_buf
[PREFIX_STRLEN
];
15790 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15791 struct prefix_evpn
*)p
)
15795 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15797 local_buf
, sizeof(local_buf
));
15798 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15799 p
->u
.prefix_evpn
.prefix_addr
15800 .ip_prefix_length
);
15802 prefix2str(p
, buf
, sizeof(buf
));
15805 if (bgp_static
->gatewayIp
.family
== AF_INET
15806 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15807 inet_ntop(bgp_static
->gatewayIp
.family
,
15808 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15811 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15812 buf
, bgp_static
->prd_pretty
,
15813 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15814 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15817 XFREE(MTYPE_TMP
, macrouter
);
15822 /* Configuration of static route announcement and aggregate
15824 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15827 struct bgp_dest
*dest
;
15828 const struct prefix
*p
;
15829 struct bgp_static
*bgp_static
;
15830 struct bgp_aggregate
*bgp_aggregate
;
15832 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15833 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15837 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15838 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15842 /* Network configuration. */
15843 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15844 dest
= bgp_route_next(dest
)) {
15845 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15846 if (bgp_static
== NULL
)
15849 p
= bgp_dest_get_prefix(dest
);
15851 vty_out(vty
, " network %pFX", p
);
15853 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15854 vty_out(vty
, " label-index %u",
15855 bgp_static
->label_index
);
15857 if (bgp_static
->rmap
.name
)
15858 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15860 if (bgp_static
->backdoor
)
15861 vty_out(vty
, " backdoor");
15863 vty_out(vty
, "\n");
15866 /* Aggregate-address configuration. */
15867 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15868 dest
= bgp_route_next(dest
)) {
15869 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15870 if (bgp_aggregate
== NULL
)
15873 p
= bgp_dest_get_prefix(dest
);
15875 vty_out(vty
, " aggregate-address %pFX", p
);
15877 if (bgp_aggregate
->as_set
)
15878 vty_out(vty
, " as-set");
15880 if (bgp_aggregate
->summary_only
)
15881 vty_out(vty
, " summary-only");
15883 if (bgp_aggregate
->rmap
.name
)
15884 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15886 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15887 vty_out(vty
, " origin %s",
15888 bgp_origin2str(bgp_aggregate
->origin
));
15890 if (bgp_aggregate
->match_med
)
15891 vty_out(vty
, " matching-MED-only");
15893 if (bgp_aggregate
->suppress_map_name
)
15894 vty_out(vty
, " suppress-map %s",
15895 bgp_aggregate
->suppress_map_name
);
15897 vty_out(vty
, "\n");
15901 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15904 struct bgp_dest
*dest
;
15905 struct bgp_distance
*bdistance
;
15907 /* Distance configuration. */
15908 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15909 && bgp
->distance_local
[afi
][safi
]
15910 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15911 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15912 || bgp
->distance_local
[afi
][safi
]
15913 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15914 vty_out(vty
, " distance bgp %d %d %d\n",
15915 bgp
->distance_ebgp
[afi
][safi
],
15916 bgp
->distance_ibgp
[afi
][safi
],
15917 bgp
->distance_local
[afi
][safi
]);
15920 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15921 dest
= bgp_route_next(dest
)) {
15922 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15923 if (bdistance
!= NULL
)
15924 vty_out(vty
, " distance %d %pBD %s\n",
15925 bdistance
->distance
, dest
,
15926 bdistance
->access_list
? bdistance
->access_list
15931 /* Allocate routing table structure and install commands. */
15932 void bgp_route_init(void)
15937 /* Init BGP distance table. */
15938 FOREACH_AFI_SAFI (afi
, safi
)
15939 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15941 /* IPv4 BGP commands. */
15942 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15943 install_element(BGP_NODE
, &bgp_network_cmd
);
15944 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15946 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15948 /* IPv4 unicast configuration. */
15949 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15950 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15951 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15953 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15955 /* IPv4 multicast configuration. */
15956 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15957 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15958 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15959 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15961 /* IPv4 labeled-unicast configuration. */
15962 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15963 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15965 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15966 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15967 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15968 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15969 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15970 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15971 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15972 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15974 install_element(VIEW_NODE
,
15975 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15976 install_element(VIEW_NODE
,
15977 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15978 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15979 install_element(VIEW_NODE
,
15980 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15981 #ifdef KEEP_OLD_VPN_COMMANDS
15982 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15983 #endif /* KEEP_OLD_VPN_COMMANDS */
15984 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15985 install_element(VIEW_NODE
,
15986 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15988 /* BGP dampening clear commands */
15989 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15990 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15992 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15993 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15996 install_element(ENABLE_NODE
,
15997 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15998 #ifdef KEEP_OLD_VPN_COMMANDS
15999 install_element(ENABLE_NODE
,
16000 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
16001 #endif /* KEEP_OLD_VPN_COMMANDS */
16003 /* New config IPv6 BGP commands. */
16004 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
16005 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
16006 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
16008 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
16010 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
16012 /* IPv6 labeled unicast address family. */
16013 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
16014 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
16016 install_element(BGP_NODE
, &bgp_distance_cmd
);
16017 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
16018 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
16019 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
16020 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
16021 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
16022 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
16023 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
16024 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
16025 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
16026 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
16027 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
16028 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
16029 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
16030 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
16031 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
16032 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
16033 install_element(BGP_IPV4M_NODE
,
16034 &no_bgp_distance_source_access_list_cmd
);
16035 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
16036 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
16037 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
16038 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
16039 install_element(BGP_IPV6_NODE
,
16040 &ipv6_bgp_distance_source_access_list_cmd
);
16041 install_element(BGP_IPV6_NODE
,
16042 &no_ipv6_bgp_distance_source_access_list_cmd
);
16043 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
16044 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
16045 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
16046 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
16047 install_element(BGP_IPV6M_NODE
,
16048 &ipv6_bgp_distance_source_access_list_cmd
);
16049 install_element(BGP_IPV6M_NODE
,
16050 &no_ipv6_bgp_distance_source_access_list_cmd
);
16052 /* BGP dampening */
16053 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
16054 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
16055 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
16056 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
16057 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
16058 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
16059 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
16060 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
16061 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
16062 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
16063 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
16064 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
16065 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
16066 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
16068 /* Large Communities */
16069 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
16070 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
16072 /* show bgp ipv4 flowspec detailed */
16073 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
16075 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
16076 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
16079 void bgp_route_finish(void)
16084 FOREACH_AFI_SAFI (afi
, safi
) {
16085 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
16086 bgp_distance_table
[afi
][safi
] = NULL
;