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 /* Disable PHP : explicit-null */
3091 if (!!CHECK_FLAG(bgp
->flags
, BGP_FLAG_LU_IPV4_EXPLICIT_NULL
) &&
3093 *label
= MPLS_LABEL_IPV4_EXPLICIT_NULL
;
3094 else if (!!CHECK_FLAG(bgp
->flags
, BGP_FLAG_LU_IPV6_EXPLICIT_NULL
) &&
3096 *label
= MPLS_LABEL_IPV6_EXPLICIT_NULL
;
3098 /* Enforced PHP popping: implicit-null */
3099 *label
= MPLS_LABEL_IMPLICIT_NULL
;
3105 * old_select = The old best path
3106 * new_select = the new best path
3108 * if (!old_select && new_select)
3109 * We are sending new information on.
3111 * if (old_select && new_select) {
3112 * if (new_select != old_select)
3113 * We have a new best path send a change
3115 * We've received a update with new attributes that needs
3119 * if (old_select && !new_select)
3120 * We have no eligible route that we can announce or the rn
3123 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3124 afi_t afi
, safi_t safi
)
3126 struct bgp_path_info
*new_select
;
3127 struct bgp_path_info
*old_select
;
3128 struct bgp_path_info_pair old_and_new
;
3130 mpls_label_t mpls_label_null
;
3132 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3134 debug
= bgp_debug_bestpath(dest
);
3137 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3138 __func__
, dest
, bgp
->name_pretty
);
3141 /* Is it end of initial update? (after startup) */
3143 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3144 sizeof(bgp
->update_delay_zebra_resume_time
));
3146 bgp
->main_zebra_update_hold
= 0;
3147 FOREACH_AFI_SAFI (afi
, safi
) {
3148 if (bgp_fibupd_safi(safi
))
3149 bgp_zebra_announce_table(bgp
, afi
, safi
);
3151 bgp
->main_peers_update_hold
= 0;
3153 bgp_start_routeadv(bgp
);
3157 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3159 debug
= bgp_debug_bestpath(dest
);
3161 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__
,
3162 dest
, bgp
->name_pretty
, afi2str(afi
),
3165 /* The best path calculation for the route is deferred if
3166 * BGP_NODE_SELECT_DEFER is set
3168 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3169 if (BGP_DEBUG(update
, UPDATE_OUT
))
3170 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3171 dest
, bgp
->name_pretty
);
3175 /* Best path selection. */
3176 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3178 old_select
= old_and_new
.old
;
3179 new_select
= old_and_new
.new;
3181 /* Do we need to allocate or free labels?
3182 * Right now, since we only deal with per-prefix labels, it is not
3183 * necessary to do this upon changes to best path. Exceptions:
3184 * - label index has changed -> recalculate resulting label
3185 * - path_info sub_type changed -> switch to/from null label value
3186 * - no valid label (due to removed static label binding) -> get new one
3188 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3191 || bgp_label_index_differs(new_select
, old_select
)
3192 || new_select
->sub_type
!= old_select
->sub_type
3193 || !bgp_is_valid_label(&dest
->local_label
)) {
3194 /* control label imposition for local routes,
3195 * aggregate and redistributed routes
3197 mpls_label_null
= MPLS_LABEL_IMPLICIT_NULL
;
3198 if (bgp_lu_need_null_label(bgp
, new_select
, afi
,
3199 &mpls_label_null
)) {
3202 BGP_NODE_REGISTERED_FOR_LABEL
)
3205 BGP_NODE_LABEL_REQUESTED
))
3206 bgp_unregister_for_label(dest
);
3207 dest
->local_label
= mpls_lse_encode(
3208 mpls_label_null
, 0, 0, 1);
3209 bgp_set_valid_label(&dest
->local_label
);
3211 bgp_register_for_label(dest
,
3214 } else if (CHECK_FLAG(dest
->flags
,
3215 BGP_NODE_REGISTERED_FOR_LABEL
)
3216 || CHECK_FLAG(dest
->flags
,
3217 BGP_NODE_LABEL_REQUESTED
)) {
3218 bgp_unregister_for_label(dest
);
3220 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3221 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3222 bgp_unregister_for_label(dest
);
3227 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3228 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3229 safi2str(safi
), old_select
, new_select
);
3231 /* If best route remains the same and this is not due to user-initiated
3232 * clear, see exactly what needs to be done.
3234 if (old_select
&& old_select
== new_select
3235 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3236 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3237 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3238 if (bgp_zebra_has_route_changed(old_select
)) {
3239 #ifdef ENABLE_BGP_VNC
3240 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3241 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3243 if (bgp_fibupd_safi(safi
)
3244 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3246 if (new_select
->type
== ZEBRA_ROUTE_BGP
3247 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3248 || new_select
->sub_type
3249 == BGP_ROUTE_IMPORTED
))
3251 bgp_zebra_announce(dest
, p
, old_select
,
3256 /* If there is a change of interest to peers, reannounce the
3258 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3259 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3260 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3261 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3263 /* unicast routes must also be annouced to
3264 * labeled-unicast update-groups */
3265 if (safi
== SAFI_UNICAST
)
3266 group_announce_route(bgp
, afi
,
3267 SAFI_LABELED_UNICAST
, dest
,
3270 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3271 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3274 /* advertise/withdraw type-5 routes */
3275 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3276 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3277 bgp_process_evpn_route_injection(
3278 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3280 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3281 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3282 bgp_zebra_clear_route_change_flags(dest
);
3283 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3287 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3289 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3291 /* bestpath has changed; bump version */
3292 if (old_select
|| new_select
) {
3293 bgp_bump_version(dest
);
3295 if (!bgp
->t_rmap_def_originate_eval
) {
3299 update_group_refresh_default_originate_route_map
,
3300 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3301 &bgp
->t_rmap_def_originate_eval
);
3306 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3309 zlog_debug("%s: setting SELECTED flag", __func__
);
3310 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3311 bgp_path_info_unset_flag(dest
, new_select
,
3312 BGP_PATH_ATTR_CHANGED
);
3313 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3314 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3317 #ifdef ENABLE_BGP_VNC
3318 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3319 if (old_select
!= new_select
) {
3321 vnc_import_bgp_exterior_del_route(bgp
, p
,
3323 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3326 vnc_import_bgp_exterior_add_route(bgp
, p
,
3328 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3334 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3336 /* unicast routes must also be annouced to labeled-unicast update-groups
3338 if (safi
== SAFI_UNICAST
)
3339 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3343 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3344 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3346 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3347 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3348 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3349 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3351 /* if this is an evpn imported type-5 prefix,
3352 * we need to withdraw the route first to clear
3353 * the nh neigh and the RMAC entry.
3356 is_route_parent_evpn(old_select
))
3357 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3359 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3361 /* Withdraw the route from the kernel. */
3362 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3363 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3364 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3365 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3367 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3371 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3374 /* Clear any route change flags. */
3375 bgp_zebra_clear_route_change_flags(dest
);
3377 /* Reap old select bgp_path_info, if it has been removed */
3378 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3379 bgp_path_info_reap(dest
, old_select
);
3381 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3385 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3386 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3388 struct bgp_dest
*dest
;
3390 struct afi_safi_info
*thread_info
;
3392 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3393 struct event
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3395 thread_info
= EVENT_ARG(t
);
3396 XFREE(MTYPE_TMP
, thread_info
);
3397 EVENT_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3400 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3401 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3402 get_afi_safi_str(afi
, safi
, false),
3403 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3406 /* Process the route list */
3407 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3408 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3409 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3410 dest
= bgp_route_next(dest
)) {
3411 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3414 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3415 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3416 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3419 /* If iteration stopped before the entire table was traversed then the
3420 * node needs to be unlocked.
3423 bgp_dest_unlock_node(dest
);
3427 /* Send EOR message when all routes are processed */
3428 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3429 bgp_send_delayed_eor(bgp
);
3430 /* Send route processing complete message to RIB */
3431 bgp_zebra_update(bgp
, afi
, safi
,
3432 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3436 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3438 thread_info
->afi
= afi
;
3439 thread_info
->safi
= safi
;
3440 thread_info
->bgp
= bgp
;
3442 /* If there are more routes to be processed, start the
3445 event_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3446 BGP_ROUTE_SELECT_DELAY
,
3447 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3450 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3452 struct bgp_process_queue
*pqnode
= data
;
3453 struct bgp
*bgp
= pqnode
->bgp
;
3454 struct bgp_table
*table
;
3455 struct bgp_dest
*dest
;
3458 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3459 bgp_process_main_one(bgp
, NULL
, 0, 0);
3460 /* should always have dedicated wq call */
3461 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3465 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3466 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3467 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3468 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3469 table
= bgp_dest_table(dest
);
3470 /* note, new DESTs may be added as part of processing */
3471 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3473 bgp_dest_unlock_node(dest
);
3474 bgp_table_unlock(table
);
3480 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3482 struct bgp_process_queue
*pqnode
= data
;
3484 bgp_unlock(pqnode
->bgp
);
3486 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3489 void bgp_process_queue_init(struct bgp
*bgp
)
3491 if (!bgp
->process_queue
) {
3494 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3495 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3498 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3499 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3500 bgp
->process_queue
->spec
.max_retries
= 0;
3501 bgp
->process_queue
->spec
.hold
= 50;
3502 /* Use a higher yield value of 50ms for main queue processing */
3503 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3506 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3508 struct bgp_process_queue
*pqnode
;
3510 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3511 sizeof(struct bgp_process_queue
));
3513 /* unlocked in bgp_processq_del */
3514 pqnode
->bgp
= bgp_lock(bgp
);
3515 STAILQ_INIT(&pqnode
->pqueue
);
3520 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3522 #define ARBITRARY_PROCESS_QLEN 10000
3523 struct work_queue
*wq
= bgp
->process_queue
;
3524 struct bgp_process_queue
*pqnode
;
3525 int pqnode_reuse
= 0;
3527 /* already scheduled for processing? */
3528 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3531 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3534 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3535 if (BGP_DEBUG(update
, UPDATE_OUT
))
3536 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3541 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3542 if (BGP_DEBUG(update
, UPDATE_OUT
))
3544 "Soft reconfigure table in progress for route %p",
3552 /* Add route nodes to an existing work queue item until reaching the
3553 limit only if is from the same BGP view and it's not an EOIU marker
3555 if (work_queue_item_count(wq
)) {
3556 struct work_queue_item
*item
= work_queue_last_item(wq
);
3557 pqnode
= item
->data
;
3559 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3560 || pqnode
->bgp
!= bgp
3561 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3562 pqnode
= bgp_processq_alloc(bgp
);
3566 pqnode
= bgp_processq_alloc(bgp
);
3567 /* all unlocked in bgp_process_wq */
3568 bgp_table_lock(bgp_dest_table(dest
));
3570 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3571 bgp_dest_lock_node(dest
);
3573 /* can't be enqueued twice */
3574 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3575 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3579 work_queue_add(wq
, pqnode
);
3584 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3586 struct bgp_process_queue
*pqnode
;
3588 if (bgp
->process_queue
== NULL
)
3591 pqnode
= bgp_processq_alloc(bgp
);
3593 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3594 work_queue_add(bgp
->process_queue
, pqnode
);
3597 static void bgp_maximum_prefix_restart_timer(struct event
*thread
)
3601 peer
= EVENT_ARG(thread
);
3602 peer
->t_pmax_restart
= NULL
;
3604 if (bgp_debug_neighbor_events(peer
))
3606 "%s Maximum-prefix restart timer expired, restore peering",
3609 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3610 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3613 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3617 bool filtered
= false;
3618 struct bgp_dest
*dest
;
3619 struct bgp_adj_in
*ain
;
3620 struct attr attr
= {};
3621 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3623 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3624 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3625 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3629 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3633 if (bgp_input_modifier(
3634 peer
, rn_p
, &attr
, afi
, safi
,
3635 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3643 bgp_attr_flush(&attr
);
3650 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3654 iana_safi_t pkt_safi
;
3655 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3656 PEER_FLAG_MAX_PREFIX_FORCE
))
3657 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3658 + peer
->pcount
[afi
][safi
]
3659 : peer
->pcount
[afi
][safi
];
3661 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3664 if (pcount
> peer
->pmax
[afi
][safi
]) {
3665 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3666 PEER_STATUS_PREFIX_LIMIT
)
3671 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3672 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3673 peer
->pmax
[afi
][safi
]);
3674 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3676 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3677 PEER_FLAG_MAX_PREFIX_WARNING
))
3680 /* Convert AFI, SAFI to values for packet. */
3681 pkt_afi
= afi_int2iana(afi
);
3682 pkt_safi
= safi_int2iana(safi
);
3686 ndata
[0] = (pkt_afi
>> 8);
3688 ndata
[2] = pkt_safi
;
3689 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3690 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3691 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3692 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3694 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3695 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3696 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3700 /* Dynamic peers will just close their connection. */
3701 if (peer_dynamic_neighbor(peer
))
3704 /* restart timer start */
3705 if (peer
->pmax_restart
[afi
][safi
]) {
3706 peer
->v_pmax_restart
=
3707 peer
->pmax_restart
[afi
][safi
] * 60;
3709 if (bgp_debug_neighbor_events(peer
))
3711 "%pBP Maximum-prefix restart timer started for %d secs",
3712 peer
, peer
->v_pmax_restart
);
3714 BGP_TIMER_ON(peer
->t_pmax_restart
,
3715 bgp_maximum_prefix_restart_timer
,
3716 peer
->v_pmax_restart
);
3721 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3722 PEER_STATUS_PREFIX_LIMIT
);
3725 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3726 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3727 PEER_STATUS_PREFIX_THRESHOLD
)
3732 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3733 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3734 peer
->pmax
[afi
][safi
]);
3735 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3736 PEER_STATUS_PREFIX_THRESHOLD
);
3738 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3739 PEER_STATUS_PREFIX_THRESHOLD
);
3743 /* Unconditionally remove the route from the RIB, without taking
3744 * damping into consideration (eg, because the session went down)
3746 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3747 struct peer
*peer
, afi_t afi
, safi_t safi
)
3750 struct bgp
*bgp
= NULL
;
3751 bool delete_route
= false;
3753 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3756 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3757 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3759 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3762 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3763 delete_route
= true;
3764 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3765 delete_route
= true;
3767 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3768 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3769 bgp
= pi
->peer
->bgp
;
3770 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3775 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3776 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3779 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3780 struct peer
*peer
, afi_t afi
, safi_t safi
,
3781 struct prefix_rd
*prd
)
3783 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3785 /* apply dampening, if result is suppressed, we'll be retaining
3786 * the bgp_path_info in the RIB for historical reference.
3788 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3789 && peer
->sort
== BGP_PEER_EBGP
)
3790 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3791 == BGP_DAMP_SUPPRESSED
) {
3792 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3797 #ifdef ENABLE_BGP_VNC
3798 if (safi
== SAFI_MPLS_VPN
) {
3799 struct bgp_dest
*pdest
= NULL
;
3800 struct bgp_table
*table
= NULL
;
3802 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3803 (struct prefix
*)prd
);
3804 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3805 table
= bgp_dest_get_bgp_table_info(pdest
);
3807 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3808 peer
->bgp
, prd
, table
, p
, pi
);
3810 bgp_dest_unlock_node(pdest
);
3812 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3813 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3815 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3816 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3821 /* If this is an EVPN route, process for un-import. */
3822 if (safi
== SAFI_EVPN
)
3823 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3825 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3828 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3829 struct peer
*peer
, struct attr
*attr
,
3830 struct bgp_dest
*dest
)
3832 struct bgp_path_info
*new;
3834 /* Make new BGP info. */
3835 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3837 new->instance
= instance
;
3838 new->sub_type
= sub_type
;
3841 new->uptime
= monotime(NULL
);
3846 /* Check if received nexthop is valid or not. */
3847 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3848 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3849 struct bgp_dest
*dest
)
3852 bool is_bgp_static_route
=
3853 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3856 /* If `bgp allow-martian-nexthop` is turned on, return next-hop
3859 if (bgp
->allow_martian
)
3863 * Only validated for unicast and multicast currently.
3864 * Also valid for EVPN where the nexthop is an IP address.
3865 * If we are a bgp static route being checked then there is
3866 * no need to check to see if the nexthop is martian as
3867 * that it should be ok.
3869 if (is_bgp_static_route
||
3870 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3873 /* If NEXT_HOP is present, validate it. */
3874 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3875 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3876 !ipv4_unicast_valid(&attr
->nexthop
) ||
3877 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3881 /* If MP_NEXTHOP is present, validate it. */
3882 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3883 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3884 * it is not an IPv6 link-local address.
3886 * If we receive an UPDATE with nexthop length set to 32 bytes
3887 * we shouldn't discard an UPDATE if it's set to (::).
3888 * The link-local (2st) is validated along the code path later.
3890 if (attr
->mp_nexthop_len
) {
3891 switch (attr
->mp_nexthop_len
) {
3892 case BGP_ATTR_NHLEN_IPV4
:
3893 case BGP_ATTR_NHLEN_VPNV4
:
3894 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3896 !ipv4_unicast_valid(
3897 &attr
->mp_nexthop_global_in
) ||
3898 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3902 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3903 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3904 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3905 &attr
->mp_nexthop_global
)
3906 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3907 || IN6_IS_ADDR_MULTICAST(
3908 &attr
->mp_nexthop_global
)
3909 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3912 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3913 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3914 || IN6_IS_ADDR_MULTICAST(
3915 &attr
->mp_nexthop_global
)
3916 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3929 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3931 struct community
*old
;
3932 struct community
*new;
3933 struct community
*merge
;
3934 struct community
*no_export
;
3936 old
= bgp_attr_get_community(attr
);
3937 no_export
= community_str2com("no-export");
3942 merge
= community_merge(community_dup(old
), no_export
);
3945 community_free(&old
);
3947 new = community_uniq_sort(merge
);
3948 community_free(&merge
);
3950 new = community_dup(no_export
);
3953 community_free(&no_export
);
3955 bgp_attr_set_community(attr
, new);
3958 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3959 struct attr
*attr
, const struct prefix
*prefix
,
3962 struct listnode
*node
, *nnode
;
3964 bool accept_own_found
= false;
3966 if (safi
!= SAFI_MPLS_VPN
)
3969 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3970 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3973 /* The route in question carries the ACCEPT_OWN community */
3974 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3975 struct community
*comm
= bgp_attr_get_community(attr
);
3977 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3978 accept_own_found
= true;
3981 /* The route in question is targeted to one or more destination VRFs
3982 * on the router (as determined by inspecting the Route Target(s)).
3984 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3985 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3988 if (accept_own_found
&&
3990 bgp
->vpn_policy
[afi
]
3991 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3992 bgp_attr_get_ecommunity(attr
))) {
3993 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3995 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3998 /* Treat this route as imported, because it's leaked
3999 * already from another VRF, and we got an updated
4000 * version from route-reflector with ACCEPT_OWN
4003 *sub_type
= BGP_ROUTE_IMPORTED
;
4012 void bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4013 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4014 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4015 uint32_t num_labels
, int soft_reconfig
,
4016 struct bgp_route_evpn
*evpn
)
4019 int aspath_loop_count
= 0;
4020 struct bgp_dest
*dest
;
4022 struct attr new_attr
;
4023 struct attr
*attr_new
;
4024 struct bgp_path_info
*pi
;
4025 struct bgp_path_info
*new = NULL
;
4026 struct bgp_path_info_extra
*extra
;
4028 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4030 int do_loop_check
= 1;
4031 int has_valid_label
= 0;
4033 bool force_evpn_import
= false;
4034 safi_t orig_safi
= safi
;
4035 bool leak_success
= true;
4038 if (frrtrace_enabled(frr_bgp
, process_update
)) {
4039 char pfxprint
[PREFIX2STR_BUFFER
];
4041 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
4042 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
4046 #ifdef ENABLE_BGP_VNC
4047 int vnc_implicit_withdraw
= 0;
4050 const struct prefix
*bgp_nht_param_prefix
;
4052 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4053 if (orig_safi
== SAFI_LABELED_UNICAST
)
4054 safi
= SAFI_UNICAST
;
4056 memset(&new_attr
, 0, sizeof(new_attr
));
4057 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4058 new_attr
.label
= MPLS_INVALID_LABEL
;
4061 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4062 /* TODO: Check to see if we can get rid of "is_valid_label" */
4063 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4064 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4066 has_valid_label
= bgp_is_valid_label(label
);
4068 if (has_valid_label
)
4069 assert(label
!= NULL
);
4072 /* When peer's soft reconfiguration enabled. Record input packet in
4074 if (!soft_reconfig
&&
4075 CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
) &&
4076 peer
!= bgp
->peer_self
) {
4078 * If the trigger is not from soft_reconfig and if
4079 * PEER_FLAG_SOFT_RECONFIG is enabled for the peer, then attr
4080 * will not be interned. In which case, it is ok to update the
4081 * attr->evpn_overlay, so that, this can be stored in adj_in.
4083 if ((afi
== AFI_L2VPN
) && evpn
) {
4084 memcpy(&attr
->evpn_overlay
, evpn
,
4085 sizeof(struct bgp_route_evpn
));
4087 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4090 /* Update permitted loop count */
4091 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4092 allowas_in
= peer
->allowas_in
[afi
][safi
];
4094 /* Check previously received route. */
4095 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4096 if (pi
->peer
== peer
&& pi
->type
== type
4097 && pi
->sub_type
== sub_type
4098 && pi
->addpath_rx_id
== addpath_id
)
4101 /* AS path local-as loop check. */
4102 if (peer
->change_local_as
) {
4104 aspath_loop_count
= allowas_in
;
4105 else if (!CHECK_FLAG(peer
->flags
,
4106 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4107 aspath_loop_count
= 1;
4109 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4110 > aspath_loop_count
) {
4111 peer
->stat_pfx_aspath_loop
++;
4112 reason
= "as-path contains our own AS;";
4117 /* If the peer is configured for "allowas-in origin" and the last ASN in
4119 * as-path is our ASN then we do not need to call aspath_loop_check
4121 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4122 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4125 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4126 bgp_nht_param_prefix
= NULL
;
4128 bgp_nht_param_prefix
= p
;
4130 /* AS path loop check. */
4131 if (do_loop_check
) {
4132 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4133 peer
->allowas_in
[afi
][safi
]) {
4134 peer
->stat_pfx_aspath_loop
++;
4135 reason
= "as-path contains our own AS;";
4140 /* If we're a CONFED we need to loop check the CONFED ID too */
4141 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4142 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4143 peer
->allowas_in
[afi
][safi
]) {
4144 peer
->stat_pfx_aspath_loop
++;
4145 reason
= "as-path contains our own confed AS;";
4149 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4150 * enabled, then take care of that too.
4152 bool accept_own
= false;
4154 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4155 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4157 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4159 peer
->stat_pfx_originator_loop
++;
4160 reason
= "originator is us;";
4165 /* Route reflector cluster ID check. */
4166 if (bgp_cluster_filter(peer
, attr
)) {
4167 peer
->stat_pfx_cluster_loop
++;
4168 reason
= "reflected from the same cluster;";
4172 /* Apply incoming filter. */
4173 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4174 peer
->stat_pfx_filter
++;
4179 /* If the route has Node Target Extended Communities, check
4180 * if it's allowed to be installed locally.
4182 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4183 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4185 if (ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
4186 ECOMMUNITY_NODE_TARGET
) &&
4187 !ecommunity_node_target_match(ecomm
, &peer
->local_id
)) {
4189 "Node-Target Extended Communities do not contain own BGP Identifier;";
4194 /* RFC 8212 to prevent route leaks.
4195 * This specification intends to improve this situation by requiring the
4196 * explicit configuration of both BGP Import and Export Policies for any
4197 * External BGP (EBGP) session such as customers, peers, or
4198 * confederation boundaries for all enabled address families. Through
4199 * codification of the aforementioned requirement, operators will
4200 * benefit from consistent behavior across different BGP
4203 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4204 if (!bgp_inbound_policy_exists(peer
,
4205 &peer
->filter
[afi
][safi
])) {
4206 reason
= "inbound policy missing";
4207 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4208 NULL
) > FIFTEENMINUTE2USEC
||
4209 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4211 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4212 monotime(&bgp
->ebgprequirespolicywarning
);
4217 /* draft-ietf-idr-deprecate-as-set-confed-set
4218 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4219 * Eventually, This document (if approved) updates RFC 4271
4220 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4221 * and obsoletes RFC 6472.
4223 if (peer
->bgp
->reject_as_sets
)
4224 if (aspath_check_as_sets(attr
->aspath
)) {
4226 "as-path contains AS_SET or AS_CONFED_SET type;";
4232 * If bgp_update is called with soft_reconfig set then
4233 * attr is interned. In this case, do not overwrite the
4234 * attr->evpn_overlay with evpn directly. Instead memcpy
4235 * evpn to new_atr.evpn_overlay before it is interned.
4237 if (soft_reconfig
&& (afi
== AFI_L2VPN
) && evpn
)
4238 memcpy(&new_attr
.evpn_overlay
, evpn
,
4239 sizeof(struct bgp_route_evpn
));
4241 /* Apply incoming route-map.
4242 * NB: new_attr may now contain newly allocated values from route-map
4244 * commands, so we need bgp_attr_flush in the error paths, until we
4246 * the attr (which takes over the memory references) */
4247 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4250 peer
->stat_pfx_filter
++;
4251 reason
= "route-map;";
4252 bgp_attr_flush(&new_attr
);
4256 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4257 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4258 /* remove from RIB previous entry */
4259 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4262 if (peer
->sort
== BGP_PEER_EBGP
) {
4265 * A BGP speaker receiving an announcement tagged with the
4266 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4267 * NO_EXPORT community as defined in RFC1997, or a
4268 * similar community, to prevent propagation of the
4269 * prefix outside the local AS. The community to prevent
4270 * propagation SHOULD be chosen according to the operator's
4273 if (bgp_attr_get_community(&new_attr
) &&
4274 community_include(bgp_attr_get_community(&new_attr
),
4275 COMMUNITY_BLACKHOLE
))
4276 bgp_attr_add_no_export_community(&new_attr
);
4278 /* If we receive the graceful-shutdown community from an eBGP
4279 * peer we must lower local-preference */
4280 if (bgp_attr_get_community(&new_attr
) &&
4281 community_include(bgp_attr_get_community(&new_attr
),
4283 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4284 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4286 /* If graceful-shutdown is configured globally or
4287 * per neighbor, then add the GSHUT community to
4288 * all paths received from eBGP peers. */
4289 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4290 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4291 bgp_attr_add_gshut_community(&new_attr
);
4294 /* next hop check. */
4295 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4296 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4298 peer
->stat_pfx_nh_invalid
++;
4299 reason
= "martian or self next-hop;";
4300 bgp_attr_flush(&new_attr
);
4304 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4305 peer
->stat_pfx_nh_invalid
++;
4306 reason
= "self mac;";
4307 bgp_attr_flush(&new_attr
);
4311 if (bgp_check_role_applicability(afi
, safi
) &&
4312 bgp_otc_filter(peer
, &new_attr
)) {
4313 reason
= "failing otc validation";
4314 bgp_attr_flush(&new_attr
);
4318 /* If neighbor soo is configured, tag all incoming routes with
4319 * this SoO tag and then filter out advertisements in
4320 * subgroup_announce_check() if it matches the configured SoO
4321 * on the other peer.
4323 if (peer
->soo
[afi
][safi
]) {
4324 struct ecommunity
*old_ecomm
=
4325 bgp_attr_get_ecommunity(&new_attr
);
4326 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4327 struct ecommunity
*new_ecomm
;
4330 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4333 if (!old_ecomm
->refcnt
)
4334 ecommunity_free(&old_ecomm
);
4336 new_ecomm
= ecommunity_dup(ecomm_soo
);
4339 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4342 attr_new
= bgp_attr_intern(&new_attr
);
4344 /* If the update is implicit withdraw. */
4346 pi
->uptime
= monotime(NULL
);
4347 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4349 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4351 /* Same attribute comes in. */
4352 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4354 && (!has_valid_label
4355 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4356 num_labels
* sizeof(mpls_label_t
))
4358 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4359 BGP_CONFIG_DAMPENING
)
4360 && peer
->sort
== BGP_PEER_EBGP
4361 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4362 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4363 bgp_debug_rdpfxpath2str(
4364 afi
, safi
, prd
, p
, label
,
4365 num_labels
, addpath_id
? 1 : 0,
4366 addpath_id
, evpn
, pfx_buf
,
4368 zlog_debug("%pBP rcvd %s", peer
,
4372 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4373 != BGP_DAMP_SUPPRESSED
) {
4374 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4376 bgp_process(bgp
, dest
, afi
, safi
);
4378 } else /* Duplicate - odd */
4380 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4381 if (!peer
->rcvd_attr_printed
) {
4383 "%pBP rcvd UPDATE w/ attr: %s",
4385 peer
->rcvd_attr_str
);
4386 peer
->rcvd_attr_printed
= 1;
4389 bgp_debug_rdpfxpath2str(
4390 afi
, safi
, prd
, p
, label
,
4391 num_labels
, addpath_id
? 1 : 0,
4392 addpath_id
, evpn
, pfx_buf
,
4395 "%pBP rcvd %s...duplicate ignored",
4399 /* graceful restart STALE flag unset. */
4400 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4401 bgp_path_info_unset_flag(
4402 dest
, pi
, BGP_PATH_STALE
);
4403 bgp_dest_set_defer_flag(dest
, false);
4404 bgp_process(bgp
, dest
, afi
, safi
);
4408 bgp_dest_unlock_node(dest
);
4409 bgp_attr_unintern(&attr_new
);
4414 /* Withdraw/Announce before we fully processed the withdraw */
4415 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4416 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4417 bgp_debug_rdpfxpath2str(
4418 afi
, safi
, prd
, p
, label
, num_labels
,
4419 addpath_id
? 1 : 0, addpath_id
, evpn
,
4420 pfx_buf
, sizeof(pfx_buf
));
4422 "%pBP rcvd %s, flapped quicker than processing",
4426 bgp_path_info_restore(dest
, pi
);
4429 * If the BGP_PATH_REMOVED flag is set, then EVPN
4430 * routes would have been unimported already when a
4431 * prior BGP withdraw processing happened. Such routes
4432 * need to be imported again, so flag accordingly.
4434 force_evpn_import
= true;
4436 /* implicit withdraw, decrement aggregate and pcount
4437 * here. only if update is accepted, they'll increment
4440 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4443 /* Received Logging. */
4444 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4445 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4446 num_labels
, addpath_id
? 1 : 0,
4447 addpath_id
, evpn
, pfx_buf
,
4449 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4452 /* graceful restart STALE flag unset. */
4453 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4454 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4455 bgp_dest_set_defer_flag(dest
, false);
4458 /* The attribute is changed. */
4459 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4461 /* Update bgp route dampening information. */
4462 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4463 && peer
->sort
== BGP_PEER_EBGP
) {
4464 /* This is implicit withdraw so we should update
4467 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4468 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4470 #ifdef ENABLE_BGP_VNC
4471 if (safi
== SAFI_MPLS_VPN
) {
4472 struct bgp_dest
*pdest
= NULL
;
4473 struct bgp_table
*table
= NULL
;
4475 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4476 (struct prefix
*)prd
);
4477 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4478 table
= bgp_dest_get_bgp_table_info(pdest
);
4480 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4481 bgp
, prd
, table
, p
, pi
);
4483 bgp_dest_unlock_node(pdest
);
4485 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4486 && (safi
== SAFI_UNICAST
)) {
4487 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4489 * Implicit withdraw case.
4491 ++vnc_implicit_withdraw
;
4492 vnc_import_bgp_del_route(bgp
, p
, pi
);
4493 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4498 /* Special handling for EVPN update of an existing route. If the
4499 * extended community attribute has changed, we need to
4501 * the route using its existing extended community. It will be
4502 * subsequently processed for import with the new extended
4505 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4508 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4510 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4513 cmp
= ecommunity_cmp(
4514 bgp_attr_get_ecommunity(pi
->attr
),
4515 bgp_attr_get_ecommunity(attr_new
));
4517 if (bgp_debug_update(peer
, p
, NULL
, 1))
4519 "Change in EXT-COMM, existing %s new %s",
4521 bgp_attr_get_ecommunity(
4524 bgp_attr_get_ecommunity(
4526 if (safi
== SAFI_EVPN
)
4527 bgp_evpn_unimport_route(
4528 bgp
, afi
, safi
, p
, pi
);
4529 else /* SAFI_MPLS_VPN */
4530 vpn_leak_to_vrf_withdraw(pi
);
4535 /* Update to new attribute. */
4536 bgp_attr_unintern(&pi
->attr
);
4537 pi
->attr
= attr_new
;
4539 /* Update MPLS label */
4540 if (has_valid_label
) {
4541 extra
= bgp_path_info_extra_get(pi
);
4542 if (extra
->label
!= label
) {
4543 memcpy(&extra
->label
, label
,
4544 num_labels
* sizeof(mpls_label_t
));
4545 extra
->num_labels
= num_labels
;
4547 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4548 bgp_set_valid_label(&extra
->label
[0]);
4551 /* Update SRv6 SID */
4552 if (attr
->srv6_l3vpn
) {
4553 extra
= bgp_path_info_extra_get(pi
);
4554 if (sid_diff(&extra
->sid
[0].sid
,
4555 &attr
->srv6_l3vpn
->sid
)) {
4556 sid_copy(&extra
->sid
[0].sid
,
4557 &attr
->srv6_l3vpn
->sid
);
4558 extra
->num_sids
= 1;
4560 extra
->sid
[0].loc_block_len
= 0;
4561 extra
->sid
[0].loc_node_len
= 0;
4562 extra
->sid
[0].func_len
= 0;
4563 extra
->sid
[0].arg_len
= 0;
4564 extra
->sid
[0].transposition_len
= 0;
4565 extra
->sid
[0].transposition_offset
= 0;
4567 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4568 extra
->sid
[0].loc_block_len
=
4569 attr
->srv6_l3vpn
->loc_block_len
;
4570 extra
->sid
[0].loc_node_len
=
4571 attr
->srv6_l3vpn
->loc_node_len
;
4572 extra
->sid
[0].func_len
=
4573 attr
->srv6_l3vpn
->func_len
;
4574 extra
->sid
[0].arg_len
=
4575 attr
->srv6_l3vpn
->arg_len
;
4576 extra
->sid
[0].transposition_len
=
4578 ->transposition_len
;
4579 extra
->sid
[0].transposition_offset
=
4581 ->transposition_offset
;
4584 } else if (attr
->srv6_vpn
) {
4585 extra
= bgp_path_info_extra_get(pi
);
4586 if (sid_diff(&extra
->sid
[0].sid
,
4587 &attr
->srv6_vpn
->sid
)) {
4588 sid_copy(&extra
->sid
[0].sid
,
4589 &attr
->srv6_vpn
->sid
);
4590 extra
->num_sids
= 1;
4594 #ifdef ENABLE_BGP_VNC
4595 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4596 && (safi
== SAFI_UNICAST
)) {
4597 if (vnc_implicit_withdraw
) {
4599 * Add back the route with its new attributes
4601 * The route is still selected, until the route
4603 * queued by bgp_process actually runs. We have
4605 * update to the VNC side immediately to avoid
4607 * configuration changes (e.g., route-map
4609 * trigger re-importation of the entire RIB.
4611 vnc_import_bgp_add_route(bgp
, p
, pi
);
4612 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4617 /* Update bgp route dampening information. */
4618 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4619 && peer
->sort
== BGP_PEER_EBGP
) {
4620 /* Now we do normal update dampening. */
4621 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4622 if (ret
== BGP_DAMP_SUPPRESSED
) {
4623 bgp_dest_unlock_node(dest
);
4628 /* Nexthop reachability check - for unicast and
4629 * labeled-unicast.. */
4630 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4631 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4632 || (safi
== SAFI_EVPN
&&
4633 bgp_evpn_is_prefix_nht_supported(p
))) {
4634 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4635 && peer
->ttl
== BGP_DEFAULT_TTL
4636 && !CHECK_FLAG(peer
->flags
,
4637 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4638 && !CHECK_FLAG(bgp
->flags
,
4639 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4644 struct bgp
*bgp_nexthop
= bgp
;
4646 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4647 bgp_nexthop
= pi
->extra
->bgp_orig
;
4649 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4651 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4652 safi
, pi
, NULL
, connected
,
4653 bgp_nht_param_prefix
) ||
4654 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4655 bgp_path_info_set_flag(dest
, pi
,
4658 if (BGP_DEBUG(nht
, NHT
)) {
4659 zlog_debug("%s(%pI4): NH unresolved",
4661 (in_addr_t
*)&attr_new
->nexthop
);
4663 bgp_path_info_unset_flag(dest
, pi
,
4668 bgp_path_info_set_flag(dest
, pi
,
4669 BGP_PATH_ACCEPT_OWN
);
4671 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4674 #ifdef ENABLE_BGP_VNC
4675 if (safi
== SAFI_MPLS_VPN
) {
4676 struct bgp_dest
*pdest
= NULL
;
4677 struct bgp_table
*table
= NULL
;
4679 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4680 (struct prefix
*)prd
);
4681 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4682 table
= bgp_dest_get_bgp_table_info(pdest
);
4684 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4685 bgp
, prd
, table
, p
, pi
);
4687 bgp_dest_unlock_node(pdest
);
4691 /* If this is an EVPN route and some attribute has changed,
4692 * or we are explicitly told to perform a route import, process
4693 * route for import. If the extended community has changed, we
4695 * have done the un-import earlier and the import would result
4697 * route getting injected into appropriate L2 VNIs. If it is
4699 * some other attribute change, the import will result in
4701 * the attributes for the route in the VNI(s).
4703 if (safi
== SAFI_EVPN
&&
4704 (!same_attr
|| force_evpn_import
) &&
4705 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4706 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4708 /* Process change. */
4709 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4711 bgp_process(bgp
, dest
, afi
, safi
);
4712 bgp_dest_unlock_node(dest
);
4714 if (SAFI_UNICAST
== safi
4715 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4716 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4718 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4720 if ((SAFI_MPLS_VPN
== safi
)
4721 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4722 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4725 #ifdef ENABLE_BGP_VNC
4726 if (SAFI_MPLS_VPN
== safi
) {
4727 mpls_label_t label_decoded
= decode_label(label
);
4729 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4730 type
, sub_type
, &label_decoded
);
4732 if (SAFI_ENCAP
== safi
) {
4733 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4734 type
, sub_type
, NULL
);
4737 if ((safi
== SAFI_MPLS_VPN
) &&
4738 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4739 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4741 bgp_unlink_nexthop(pi
);
4742 bgp_path_info_delete(dest
, pi
);
4745 } // End of implicit withdraw
4747 /* Received Logging. */
4748 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4749 if (!peer
->rcvd_attr_printed
) {
4750 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4751 peer
->rcvd_attr_str
);
4752 peer
->rcvd_attr_printed
= 1;
4755 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4756 addpath_id
? 1 : 0, addpath_id
, evpn
,
4757 pfx_buf
, sizeof(pfx_buf
));
4758 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4761 /* Make new BGP info. */
4762 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4764 /* Update MPLS label */
4765 if (has_valid_label
) {
4766 extra
= bgp_path_info_extra_get(new);
4767 if (extra
->label
!= label
) {
4768 memcpy(&extra
->label
, label
,
4769 num_labels
* sizeof(mpls_label_t
));
4770 extra
->num_labels
= num_labels
;
4772 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4773 bgp_set_valid_label(&extra
->label
[0]);
4776 /* Update SRv6 SID */
4777 if (safi
== SAFI_MPLS_VPN
) {
4778 extra
= bgp_path_info_extra_get(new);
4779 if (attr
->srv6_l3vpn
) {
4780 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4781 extra
->num_sids
= 1;
4783 extra
->sid
[0].loc_block_len
=
4784 attr
->srv6_l3vpn
->loc_block_len
;
4785 extra
->sid
[0].loc_node_len
=
4786 attr
->srv6_l3vpn
->loc_node_len
;
4787 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4788 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4789 extra
->sid
[0].transposition_len
=
4790 attr
->srv6_l3vpn
->transposition_len
;
4791 extra
->sid
[0].transposition_offset
=
4792 attr
->srv6_l3vpn
->transposition_offset
;
4793 } else if (attr
->srv6_vpn
) {
4794 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4795 extra
->num_sids
= 1;
4799 /* Nexthop reachability check. */
4800 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4801 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4802 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4803 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4804 && peer
->ttl
== BGP_DEFAULT_TTL
4805 && !CHECK_FLAG(peer
->flags
,
4806 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4807 && !CHECK_FLAG(bgp
->flags
,
4808 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4813 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4815 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4816 connected
, bgp_nht_param_prefix
) ||
4817 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4818 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4820 if (BGP_DEBUG(nht
, NHT
))
4821 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4822 &attr_new
->nexthop
);
4823 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4827 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4829 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4832 /* If maximum prefix count is configured and current prefix
4835 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4836 reason
= "maximum-prefix overflow";
4837 bgp_attr_flush(&new_attr
);
4842 new->addpath_rx_id
= addpath_id
;
4844 /* Increment prefix */
4845 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4847 /* Register new BGP information. */
4848 bgp_path_info_add(dest
, new);
4850 /* route_node_get lock */
4851 bgp_dest_unlock_node(dest
);
4853 #ifdef ENABLE_BGP_VNC
4854 if (safi
== SAFI_MPLS_VPN
) {
4855 struct bgp_dest
*pdest
= NULL
;
4856 struct bgp_table
*table
= NULL
;
4858 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4859 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4860 table
= bgp_dest_get_bgp_table_info(pdest
);
4862 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4863 bgp
, prd
, table
, p
, new);
4865 bgp_dest_unlock_node(pdest
);
4869 /* If this is an EVPN route, process for import. */
4870 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4871 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4873 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4875 /* Process change. */
4876 bgp_process(bgp
, dest
, afi
, safi
);
4878 if (SAFI_UNICAST
== safi
4879 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4880 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4881 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4883 if ((SAFI_MPLS_VPN
== safi
)
4884 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4885 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4887 #ifdef ENABLE_BGP_VNC
4888 if (SAFI_MPLS_VPN
== safi
) {
4889 mpls_label_t label_decoded
= decode_label(label
);
4891 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4892 sub_type
, &label_decoded
);
4894 if (SAFI_ENCAP
== safi
) {
4895 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4899 if ((safi
== SAFI_MPLS_VPN
) &&
4900 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4901 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4903 bgp_unlink_nexthop(new);
4904 bgp_path_info_delete(dest
, new);
4909 /* This BGP update is filtered. Log the reason then update BGP
4913 bgp_unlink_nexthop(new);
4914 bgp_path_info_delete(dest
, new);
4915 bgp_path_info_extra_free(&new->extra
);
4916 XFREE(MTYPE_BGP_ROUTE
, new);
4919 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4921 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4922 if (!peer
->rcvd_attr_printed
) {
4923 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4924 peer
->rcvd_attr_str
);
4925 peer
->rcvd_attr_printed
= 1;
4928 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4929 addpath_id
? 1 : 0, addpath_id
, evpn
,
4930 pfx_buf
, sizeof(pfx_buf
));
4931 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4932 peer
, pfx_buf
, reason
);
4936 /* If this is an EVPN route, un-import it as it is now filtered.
4938 if (safi
== SAFI_EVPN
)
4939 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4941 if (SAFI_UNICAST
== safi
4942 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4943 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4945 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4947 if ((SAFI_MPLS_VPN
== safi
)
4948 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4950 vpn_leak_to_vrf_withdraw(pi
);
4953 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4956 bgp_dest_unlock_node(dest
);
4958 #ifdef ENABLE_BGP_VNC
4960 * Filtered update is treated as an implicit withdrawal (see
4962 * a few lines above)
4964 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4965 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4973 void bgp_withdraw(struct peer
*peer
, const struct prefix
*p
,
4974 uint32_t addpath_id
, afi_t afi
, safi_t safi
, int type
,
4975 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4976 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4979 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4980 struct bgp_dest
*dest
;
4981 struct bgp_path_info
*pi
;
4983 #ifdef ENABLE_BGP_VNC
4984 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4985 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4993 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4995 /* If peer is soft reconfiguration enabled. Record input packet for
4996 * further calculation.
4998 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4999 * routes that are filtered. This tanks out Quagga RS pretty badly due
5001 * the iteration over all RS clients.
5002 * Since we need to remove the entry from adj_in anyway, do that first
5004 * if there was no entry, we don't need to do anything more.
5006 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
5007 && peer
!= bgp
->peer_self
)
5008 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
5009 peer
->stat_pfx_dup_withdraw
++;
5011 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5012 bgp_debug_rdpfxpath2str(
5013 afi
, safi
, prd
, p
, label
, num_labels
,
5014 addpath_id
? 1 : 0, addpath_id
, NULL
,
5015 pfx_buf
, sizeof(pfx_buf
));
5017 "%s withdrawing route %s not in adj-in",
5018 peer
->host
, pfx_buf
);
5020 bgp_dest_unlock_node(dest
);
5024 /* Lookup withdrawn route. */
5025 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5026 if (pi
->peer
== peer
&& pi
->type
== type
5027 && pi
->sub_type
== sub_type
5028 && pi
->addpath_rx_id
== addpath_id
)
5032 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5033 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5034 addpath_id
? 1 : 0, addpath_id
, NULL
,
5035 pfx_buf
, sizeof(pfx_buf
));
5036 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
5040 /* Withdraw specified route from routing table. */
5041 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
5042 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
5043 if (SAFI_UNICAST
== safi
5044 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5045 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5046 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5048 if ((SAFI_MPLS_VPN
== safi
)
5049 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5051 vpn_leak_to_vrf_withdraw(pi
);
5053 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5054 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5055 addpath_id
? 1 : 0, addpath_id
, NULL
,
5056 pfx_buf
, sizeof(pfx_buf
));
5057 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
5060 /* Unlock bgp_node_get() lock. */
5061 bgp_dest_unlock_node(dest
);
5066 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
5069 struct update_subgroup
*subgrp
;
5070 subgrp
= peer_subgroup(peer
, afi
, safi
);
5071 subgroup_default_originate(subgrp
, withdraw
);
5076 * bgp_stop_announce_route_timer
5078 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5080 if (!paf
->t_announce_route
)
5083 EVENT_OFF(paf
->t_announce_route
);
5087 * bgp_announce_route_timer_expired
5089 * Callback that is invoked when the route announcement timer for a
5092 static void bgp_announce_route_timer_expired(struct event
*t
)
5094 struct peer_af
*paf
;
5100 if (!peer_established(peer
))
5103 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5106 peer_af_announce_route(paf
, 1);
5108 /* Notify BGP conditional advertisement scanner percess */
5109 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5113 * bgp_announce_route
5115 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5117 * if force is true we will force an update even if the update
5118 * limiting code is attempted to kick in.
5120 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5122 struct peer_af
*paf
;
5123 struct update_subgroup
*subgrp
;
5125 paf
= peer_af_find(peer
, afi
, safi
);
5128 subgrp
= PAF_SUBGRP(paf
);
5131 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5132 * or a refresh has already been triggered.
5134 if (!subgrp
|| paf
->t_announce_route
)
5138 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5141 * Start a timer to stagger/delay the announce. This serves
5142 * two purposes - announcement can potentially be combined for
5143 * multiple peers and the announcement doesn't happen in the
5146 event_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5147 (subgrp
->peer_count
== 1)
5148 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5149 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5150 &paf
->t_announce_route
);
5154 * Announce routes from all AF tables to a peer.
5156 * This should ONLY be called when there is a need to refresh the
5157 * routes to the peer based on a policy change for this peer alone
5158 * or a route refresh request received from the peer.
5159 * The operation will result in splitting the peer from its existing
5160 * subgroups and putting it in new subgroups.
5162 void bgp_announce_route_all(struct peer
*peer
)
5167 FOREACH_AFI_SAFI (afi
, safi
)
5168 bgp_announce_route(peer
, afi
, safi
, false);
5171 /* Flag or unflag bgp_dest to determine whether it should be treated by
5172 * bgp_soft_reconfig_table_task.
5173 * Flag if flag is true. Unflag if flag is false.
5175 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5177 struct bgp_dest
*dest
;
5178 struct bgp_adj_in
*ain
;
5183 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5184 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5185 if (ain
->peer
!= NULL
)
5188 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5189 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5191 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5195 static void bgp_soft_reconfig_table_update(struct peer
*peer
,
5196 struct bgp_dest
*dest
,
5197 struct bgp_adj_in
*ain
, afi_t afi
,
5198 safi_t safi
, struct prefix_rd
*prd
)
5200 struct bgp_path_info
*pi
;
5201 uint32_t num_labels
= 0;
5202 mpls_label_t
*label_pnt
= NULL
;
5203 struct bgp_route_evpn evpn
;
5205 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5206 if (pi
->peer
== peer
)
5209 if (pi
&& pi
->extra
)
5210 num_labels
= pi
->extra
->num_labels
;
5212 label_pnt
= &pi
->extra
->label
[0];
5214 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5217 memset(&evpn
, 0, sizeof(evpn
));
5219 bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5220 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, prd
,
5221 label_pnt
, num_labels
, 1, &evpn
);
5224 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5225 struct bgp_table
*table
,
5226 struct prefix_rd
*prd
)
5228 struct bgp_dest
*dest
;
5229 struct bgp_adj_in
*ain
;
5232 table
= peer
->bgp
->rib
[afi
][safi
];
5234 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5235 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5236 if (ain
->peer
!= peer
)
5239 bgp_soft_reconfig_table_update(peer
, dest
, ain
, afi
,
5244 /* Do soft reconfig table per bgp table.
5245 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5246 * when BGP_NODE_SOFT_RECONFIG is set,
5247 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5248 * Schedule a new thread to continue the job.
5249 * Without splitting the full job into several part,
5250 * vtysh waits for the job to finish before responding to a BGP command
5252 static void bgp_soft_reconfig_table_task(struct event
*thread
)
5254 uint32_t iter
, max_iter
;
5255 struct bgp_dest
*dest
;
5256 struct bgp_adj_in
*ain
;
5258 struct bgp_table
*table
;
5259 struct prefix_rd
*prd
;
5260 struct listnode
*node
, *nnode
;
5262 table
= EVENT_ARG(thread
);
5265 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5266 if (table
->soft_reconfig_init
) {
5267 /* first call of the function with a new srta structure.
5268 * Don't do any treatment this time on nodes
5269 * in order vtysh to respond quickly
5274 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5275 dest
= bgp_route_next(dest
)) {
5276 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5279 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5281 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5282 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5284 if (ain
->peer
!= peer
)
5287 bgp_soft_reconfig_table_update(
5288 peer
, dest
, ain
, table
->afi
,
5295 /* we're either starting the initial iteration,
5296 * or we're going to continue an ongoing iteration
5298 if (dest
|| table
->soft_reconfig_init
) {
5299 table
->soft_reconfig_init
= false;
5300 event_add_event(bm
->master
, bgp_soft_reconfig_table_task
, table
,
5301 0, &table
->soft_reconfig_thread
);
5304 /* we're done, clean up the background iteration context info and
5305 schedule route annoucement
5307 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5308 listnode_delete(table
->soft_reconfig_peers
, peer
);
5309 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5312 list_delete(&table
->soft_reconfig_peers
);
5316 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5318 * - bgp cannot be NULL
5319 * - if table and peer are NULL, cancel all threads within the bgp instance
5320 * - if table is NULL and peer is not,
5321 * remove peer in all threads within the bgp instance
5322 * - if peer is NULL, cancel all threads matching table within the bgp instance
5324 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5325 const struct bgp_table
*table
,
5326 const struct peer
*peer
)
5329 struct listnode
*node
, *nnode
;
5331 struct bgp_table
*ntable
;
5336 FOREACH_AFI_SAFI (afi
, safi
) {
5337 ntable
= bgp
->rib
[afi
][safi
];
5340 if (table
&& table
!= ntable
)
5343 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5345 if (peer
&& peer
!= npeer
)
5347 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5350 if (!ntable
->soft_reconfig_peers
5351 || !list_isempty(ntable
->soft_reconfig_peers
))
5354 list_delete(&ntable
->soft_reconfig_peers
);
5355 bgp_soft_reconfig_table_flag(ntable
, false);
5356 EVENT_OFF(ntable
->soft_reconfig_thread
);
5361 * Returns false if the peer is not configured for soft reconfig in
5363 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5365 struct bgp_dest
*dest
;
5366 struct bgp_table
*table
;
5367 struct listnode
*node
, *nnode
;
5369 struct peer_af
*paf
;
5371 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5374 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5375 && (safi
!= SAFI_EVPN
)) {
5376 table
= peer
->bgp
->rib
[afi
][safi
];
5380 table
->soft_reconfig_init
= true;
5382 if (!table
->soft_reconfig_peers
)
5383 table
->soft_reconfig_peers
= list_new();
5385 /* add peer to the table soft_reconfig_peers if not already
5388 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5394 listnode_add(table
->soft_reconfig_peers
, peer
);
5396 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5397 * on table would start back at the beginning.
5399 bgp_soft_reconfig_table_flag(table
, true);
5401 if (!table
->soft_reconfig_thread
)
5402 event_add_event(bm
->master
,
5403 bgp_soft_reconfig_table_task
, table
, 0,
5404 &table
->soft_reconfig_thread
);
5405 /* Cancel bgp_announce_route_timer_expired threads.
5406 * bgp_announce_route_timer_expired threads have been scheduled
5407 * to announce routes as soon as the soft_reconfigure process
5409 * In this case, soft_reconfigure is also scheduled by using
5410 * a thread but is planned after the
5411 * bgp_announce_route_timer_expired threads. It means that,
5412 * without cancelling the threads, the route announcement task
5413 * would run before the soft reconfiguration one. That would
5414 * useless and would block vtysh during several seconds. Route
5415 * announcements are rescheduled as soon as the soft_reconfigure
5418 paf
= peer_af_find(peer
, afi
, safi
);
5420 bgp_stop_announce_route_timer(paf
);
5422 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5423 dest
= bgp_route_next(dest
)) {
5424 table
= bgp_dest_get_bgp_table_info(dest
);
5429 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5430 struct prefix_rd prd
;
5432 prd
.family
= AF_UNSPEC
;
5434 memcpy(&prd
.val
, p
->u
.val
, 8);
5436 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5443 struct bgp_clear_node_queue
{
5444 struct bgp_dest
*dest
;
5447 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5449 struct bgp_clear_node_queue
*cnq
= data
;
5450 struct bgp_dest
*dest
= cnq
->dest
;
5451 struct peer
*peer
= wq
->spec
.data
;
5452 struct bgp_path_info
*pi
;
5454 afi_t afi
= bgp_dest_table(dest
)->afi
;
5455 safi_t safi
= bgp_dest_table(dest
)->safi
;
5457 assert(dest
&& peer
);
5460 /* It is possible that we have multiple paths for a prefix from a peer
5461 * if that peer is using AddPath.
5463 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5464 if (pi
->peer
!= peer
)
5467 /* graceful restart STALE flag set. */
5468 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5469 && peer
->nsf
[afi
][safi
])
5470 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5471 PEER_STATUS_ENHANCED_REFRESH
))
5472 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5473 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5474 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5476 /* If this is an EVPN route, process for
5478 if (safi
== SAFI_EVPN
)
5479 bgp_evpn_unimport_route(
5481 bgp_dest_get_prefix(dest
), pi
);
5482 /* Handle withdraw for VRF route-leaking and L3VPN */
5483 if (SAFI_UNICAST
== safi
5484 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5485 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5486 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5489 if (SAFI_MPLS_VPN
== safi
&&
5490 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5491 vpn_leak_to_vrf_withdraw(pi
);
5494 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5500 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5502 struct bgp_clear_node_queue
*cnq
= data
;
5503 struct bgp_dest
*dest
= cnq
->dest
;
5504 struct bgp_table
*table
= bgp_dest_table(dest
);
5506 bgp_dest_unlock_node(dest
);
5507 bgp_table_unlock(table
);
5508 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5511 static void bgp_clear_node_complete(struct work_queue
*wq
)
5513 struct peer
*peer
= wq
->spec
.data
;
5515 /* Tickle FSM to start moving again */
5516 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5518 peer_unlock(peer
); /* bgp_clear_route */
5521 static void bgp_clear_node_queue_init(struct peer
*peer
)
5523 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5525 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5526 #undef CLEAR_QUEUE_NAME_LEN
5528 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5529 peer
->clear_node_queue
->spec
.hold
= 10;
5530 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5531 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5532 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5533 peer
->clear_node_queue
->spec
.max_retries
= 0;
5535 /* we only 'lock' this peer reference when the queue is actually active
5537 peer
->clear_node_queue
->spec
.data
= peer
;
5540 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5541 struct bgp_table
*table
)
5543 struct bgp_dest
*dest
;
5544 int force
= peer
->bgp
->process_queue
? 0 : 1;
5547 table
= peer
->bgp
->rib
[afi
][safi
];
5549 /* If still no table => afi/safi isn't configured at all or smth. */
5553 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5554 struct bgp_path_info
*pi
, *next
;
5555 struct bgp_adj_in
*ain
;
5556 struct bgp_adj_in
*ain_next
;
5558 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5559 * queued for every clearing peer, regardless of whether it is
5560 * relevant to the peer at hand.
5562 * Overview: There are 3 different indices which need to be
5563 * scrubbed, potentially, when a peer is removed:
5565 * 1 peer's routes visible via the RIB (ie accepted routes)
5566 * 2 peer's routes visible by the (optional) peer's adj-in index
5567 * 3 other routes visible by the peer's adj-out index
5569 * 3 there is no hurry in scrubbing, once the struct peer is
5570 * removed from bgp->peer, we could just GC such deleted peer's
5571 * adj-outs at our leisure.
5573 * 1 and 2 must be 'scrubbed' in some way, at least made
5574 * invisible via RIB index before peer session is allowed to be
5575 * brought back up. So one needs to know when such a 'search' is
5580 * - there'd be a single global queue or a single RIB walker
5581 * - rather than tracking which route_nodes still need to be
5582 * examined on a peer basis, we'd track which peers still
5585 * Given that our per-peer prefix-counts now should be reliable,
5586 * this may actually be achievable. It doesn't seem to be a huge
5587 * problem at this time,
5589 * It is possible that we have multiple paths for a prefix from
5591 * if that peer is using AddPath.
5595 ain_next
= ain
->next
;
5597 if (ain
->peer
== peer
)
5598 bgp_adj_in_remove(dest
, ain
);
5603 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5605 if (pi
->peer
!= peer
)
5609 bgp_path_info_reap(dest
, pi
);
5611 struct bgp_clear_node_queue
*cnq
;
5613 /* both unlocked in bgp_clear_node_queue_del */
5614 bgp_table_lock(bgp_dest_table(dest
));
5615 bgp_dest_lock_node(dest
);
5617 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5618 sizeof(struct bgp_clear_node_queue
));
5620 work_queue_add(peer
->clear_node_queue
, cnq
);
5628 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5630 struct bgp_dest
*dest
;
5631 struct bgp_table
*table
;
5633 if (peer
->clear_node_queue
== NULL
)
5634 bgp_clear_node_queue_init(peer
);
5636 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5637 * Idle until it receives a Clearing_Completed event. This protects
5638 * against peers which flap faster than we can we clear, which could
5641 * a) race with routes from the new session being installed before
5642 * clear_route_node visits the node (to delete the route of that
5644 * b) resource exhaustion, clear_route_node likely leads to an entry
5645 * on the process_main queue. Fast-flapping could cause that queue
5649 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5650 * the unlock will happen upon work-queue completion; other wise, the
5651 * unlock happens at the end of this function.
5653 if (!peer
->clear_node_queue
->thread
)
5656 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5657 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5659 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5660 dest
= bgp_route_next(dest
)) {
5661 table
= bgp_dest_get_bgp_table_info(dest
);
5665 bgp_clear_route_table(peer
, afi
, safi
, table
);
5668 /* unlock if no nodes got added to the clear-node-queue. */
5669 if (!peer
->clear_node_queue
->thread
)
5673 void bgp_clear_route_all(struct peer
*peer
)
5678 FOREACH_AFI_SAFI (afi
, safi
)
5679 bgp_clear_route(peer
, afi
, safi
);
5681 #ifdef ENABLE_BGP_VNC
5682 rfapiProcessPeerDown(peer
);
5686 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5688 struct bgp_table
*table
;
5689 struct bgp_dest
*dest
;
5690 struct bgp_adj_in
*ain
;
5691 struct bgp_adj_in
*ain_next
;
5693 table
= peer
->bgp
->rib
[afi
][safi
];
5695 /* It is possible that we have multiple paths for a prefix from a peer
5696 * if that peer is using AddPath.
5698 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5702 ain_next
= ain
->next
;
5704 if (ain
->peer
== peer
)
5705 bgp_adj_in_remove(dest
, ain
);
5712 /* If any of the routes from the peer have been marked with the NO_LLGR
5713 * community, either as sent by the peer, or as the result of a configured
5714 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5715 * operation of [RFC4271].
5717 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5719 struct bgp_dest
*dest
;
5720 struct bgp_path_info
*pi
;
5721 struct bgp_table
*table
;
5723 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5724 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5725 dest
= bgp_route_next(dest
)) {
5726 struct bgp_dest
*rm
;
5728 /* look for neighbor in tables */
5729 table
= bgp_dest_get_bgp_table_info(dest
);
5733 for (rm
= bgp_table_top(table
); rm
;
5734 rm
= bgp_route_next(rm
))
5735 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5737 if (pi
->peer
!= peer
)
5740 peer
->af_sflags
[afi
][safi
],
5741 PEER_STATUS_LLGR_WAIT
) &&
5742 bgp_attr_get_community(pi
->attr
) &&
5744 bgp_attr_get_community(
5748 if (!CHECK_FLAG(pi
->flags
,
5753 * If this is VRF leaked route
5754 * process for withdraw.
5757 BGP_ROUTE_IMPORTED
&&
5758 peer
->bgp
->inst_type
==
5759 BGP_INSTANCE_TYPE_DEFAULT
)
5760 vpn_leak_to_vrf_withdraw(pi
);
5762 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5767 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5768 dest
= bgp_route_next(dest
))
5769 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5771 if (pi
->peer
!= peer
)
5773 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5774 PEER_STATUS_LLGR_WAIT
) &&
5775 bgp_attr_get_community(pi
->attr
) &&
5777 bgp_attr_get_community(pi
->attr
),
5780 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5782 if (safi
== SAFI_UNICAST
&&
5783 (peer
->bgp
->inst_type
==
5784 BGP_INSTANCE_TYPE_VRF
||
5785 peer
->bgp
->inst_type
==
5786 BGP_INSTANCE_TYPE_DEFAULT
))
5787 vpn_leak_from_vrf_withdraw(
5788 bgp_get_default(), peer
->bgp
,
5791 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5797 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5799 struct bgp_dest
*dest
, *ndest
;
5800 struct bgp_path_info
*pi
;
5801 struct bgp_table
*table
;
5803 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5804 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5805 dest
= bgp_route_next(dest
)) {
5806 table
= bgp_dest_get_bgp_table_info(dest
);
5810 for (ndest
= bgp_table_top(table
); ndest
;
5811 ndest
= bgp_route_next(ndest
)) {
5812 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5814 if (pi
->peer
!= peer
)
5818 peer
->af_sflags
[afi
][safi
],
5819 PEER_STATUS_ENHANCED_REFRESH
))
5820 && !CHECK_FLAG(pi
->flags
,
5824 BGP_PATH_UNUSEABLE
)) {
5825 if (bgp_debug_neighbor_events(
5828 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5832 bgp_dest_get_prefix(
5835 bgp_path_info_set_flag(
5843 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5844 dest
= bgp_route_next(dest
)) {
5845 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5847 if (pi
->peer
!= peer
)
5850 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5851 PEER_STATUS_ENHANCED_REFRESH
))
5852 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5853 && !CHECK_FLAG(pi
->flags
,
5854 BGP_PATH_UNUSEABLE
)) {
5855 if (bgp_debug_neighbor_events(peer
))
5857 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5860 bgp_dest_get_prefix(
5863 bgp_path_info_set_flag(dest
, pi
,
5871 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5873 if (peer
->sort
== BGP_PEER_IBGP
)
5876 if (peer
->sort
== BGP_PEER_EBGP
5877 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5878 || FILTER_LIST_OUT_NAME(filter
)
5879 || DISTRIBUTE_OUT_NAME(filter
)))
5884 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5886 if (peer
->sort
== BGP_PEER_IBGP
)
5889 if (peer
->sort
== BGP_PEER_EBGP
5890 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5891 || FILTER_LIST_IN_NAME(filter
)
5892 || DISTRIBUTE_IN_NAME(filter
)))
5897 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5900 struct bgp_dest
*dest
;
5901 struct bgp_path_info
*pi
;
5902 struct bgp_path_info
*next
;
5904 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5905 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5906 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5910 /* Unimport EVPN routes from VRFs */
5911 if (safi
== SAFI_EVPN
)
5912 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5915 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5916 && pi
->type
== ZEBRA_ROUTE_BGP
5917 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5918 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5919 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5921 if (bgp_fibupd_safi(safi
))
5922 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5925 bgp_path_info_reap(dest
, pi
);
5929 /* Delete all kernel routes. */
5930 void bgp_cleanup_routes(struct bgp
*bgp
)
5933 struct bgp_dest
*dest
;
5934 struct bgp_table
*table
;
5936 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5937 if (afi
== AFI_L2VPN
)
5939 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5942 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5944 if (afi
!= AFI_L2VPN
) {
5946 safi
= SAFI_MPLS_VPN
;
5947 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5948 dest
= bgp_route_next(dest
)) {
5949 table
= bgp_dest_get_bgp_table_info(dest
);
5950 if (table
!= NULL
) {
5951 bgp_cleanup_table(bgp
, table
, safi
);
5952 bgp_table_finish(&table
);
5953 bgp_dest_set_bgp_table_info(dest
, NULL
);
5954 bgp_dest_unlock_node(dest
);
5958 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5959 dest
= bgp_route_next(dest
)) {
5960 table
= bgp_dest_get_bgp_table_info(dest
);
5961 if (table
!= NULL
) {
5962 bgp_cleanup_table(bgp
, table
, safi
);
5963 bgp_table_finish(&table
);
5964 bgp_dest_set_bgp_table_info(dest
, NULL
);
5965 bgp_dest_unlock_node(dest
);
5970 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5971 dest
= bgp_route_next(dest
)) {
5972 table
= bgp_dest_get_bgp_table_info(dest
);
5973 if (table
!= NULL
) {
5974 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5975 bgp_table_finish(&table
);
5976 bgp_dest_set_bgp_table_info(dest
, NULL
);
5977 bgp_dest_unlock_node(dest
);
5982 void bgp_reset(void)
5985 bgp_zclient_reset();
5986 access_list_reset();
5987 prefix_list_reset();
5990 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5992 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5993 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5994 PEER_CAP_ADDPATH_AF_TX_RCV
));
5997 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5999 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
6000 struct bgp_nlri
*packet
)
6008 bool addpath_capable
;
6009 uint32_t addpath_id
;
6012 lim
= pnt
+ packet
->length
;
6014 safi
= packet
->safi
;
6016 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
6018 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6019 syntactic validity. If the field is syntactically incorrect,
6020 then the Error Subcode is set to Invalid Network Field. */
6021 for (; pnt
< lim
; pnt
+= psize
) {
6022 /* Clear prefix structure. */
6023 memset(&p
, 0, sizeof(p
));
6025 if (addpath_capable
) {
6027 /* When packet overflow occurs return immediately. */
6028 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
6029 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6031 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
6032 addpath_id
= ntohl(addpath_id
);
6033 pnt
+= BGP_ADDPATH_ID_LEN
;
6036 /* Fetch prefix length. */
6037 p
.prefixlen
= *pnt
++;
6038 /* afi/safi validity already verified by caller,
6039 * bgp_update_receive */
6040 p
.family
= afi2family(afi
);
6042 /* Prefix length check. */
6043 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
6046 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
6047 peer
->host
, p
.prefixlen
, packet
->afi
);
6048 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
6051 /* Packet size overflow check. */
6052 psize
= PSIZE(p
.prefixlen
);
6054 /* When packet overflow occur return immediately. */
6055 if (pnt
+ psize
> lim
) {
6058 "%s [Error] Update packet error (prefix length %d overflows packet)",
6059 peer
->host
, p
.prefixlen
);
6060 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6063 /* Defensive coding, double-check the psize fits in a struct
6064 * prefix for the v4 and v6 afi's and unicast/multicast */
6065 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6068 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6069 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6070 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6073 /* Fetch prefix from NLRI packet. */
6074 memcpy(p
.u
.val
, pnt
, psize
);
6076 /* Check address. */
6077 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6078 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6079 /* From RFC4271 Section 6.3:
6081 * If a prefix in the NLRI field is semantically
6083 * (e.g., an unexpected multicast IP address),
6085 * be logged locally, and the prefix SHOULD be
6090 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6091 peer
->host
, &p
.u
.prefix4
);
6096 /* Check address. */
6097 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6098 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6101 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6102 peer
->host
, &p
.u
.prefix6
);
6106 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6109 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6110 peer
->host
, &p
.u
.prefix6
);
6116 /* Normal process. */
6118 bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6119 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6122 bgp_withdraw(peer
, &p
, addpath_id
, afi
, safi
,
6123 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6126 /* Do not send BGP notification twice when maximum-prefix count
6128 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6129 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6132 /* Packet length consistency check. */
6136 "%s [Error] Update packet error (prefix length mismatch with total length)",
6138 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6141 return BGP_NLRI_PARSE_OK
;
6144 static struct bgp_static
*bgp_static_new(void)
6146 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6149 static void bgp_static_free(struct bgp_static
*bgp_static
)
6151 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6152 route_map_counter_decrement(bgp_static
->rmap
.map
);
6154 if (bgp_static
->prd_pretty
)
6155 XFREE(MTYPE_BGP
, bgp_static
->prd_pretty
);
6156 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6157 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6160 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6161 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6163 struct bgp_dest
*dest
;
6164 struct bgp_path_info
*pi
;
6165 struct bgp_path_info
*new;
6166 struct bgp_path_info rmap_path
;
6168 struct attr
*attr_new
;
6169 route_map_result_t ret
;
6170 #ifdef ENABLE_BGP_VNC
6171 int vnc_implicit_withdraw
= 0;
6176 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6178 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6180 attr
.nexthop
= bgp_static
->igpnexthop
;
6181 attr
.med
= bgp_static
->igpmetric
;
6182 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6185 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6187 if (bgp_static
->igpmetric
)
6188 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6190 if (bgp_static
->atomic
)
6191 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6193 /* Store label index, if required. */
6194 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6195 attr
.label_index
= bgp_static
->label_index
;
6196 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6199 /* Apply route-map. */
6200 if (bgp_static
->rmap
.name
) {
6201 struct attr attr_tmp
= attr
;
6203 memset(&rmap_path
, 0, sizeof(rmap_path
));
6204 rmap_path
.peer
= bgp
->peer_self
;
6205 rmap_path
.attr
= &attr_tmp
;
6207 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6209 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6211 bgp
->peer_self
->rmap_type
= 0;
6213 if (ret
== RMAP_DENYMATCH
) {
6214 /* Free uninterned attribute. */
6215 bgp_attr_flush(&attr_tmp
);
6217 /* Unintern original. */
6218 aspath_unintern(&attr
.aspath
);
6219 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6220 bgp_dest_unlock_node(dest
);
6224 if (bgp_in_graceful_shutdown(bgp
))
6225 bgp_attr_add_gshut_community(&attr_tmp
);
6227 attr_new
= bgp_attr_intern(&attr_tmp
);
6230 if (bgp_in_graceful_shutdown(bgp
))
6231 bgp_attr_add_gshut_community(&attr
);
6233 attr_new
= bgp_attr_intern(&attr
);
6236 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6237 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6238 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6242 if (attrhash_cmp(pi
->attr
, attr_new
)
6243 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6244 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6245 bgp_dest_unlock_node(dest
);
6246 bgp_attr_unintern(&attr_new
);
6247 aspath_unintern(&attr
.aspath
);
6250 /* The attribute is changed. */
6251 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6253 /* Rewrite BGP route information. */
6254 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6255 bgp_path_info_restore(dest
, pi
);
6257 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6258 #ifdef ENABLE_BGP_VNC
6259 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6260 && (safi
== SAFI_UNICAST
)) {
6261 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6263 * Implicit withdraw case.
6264 * We have to do this before pi is
6267 ++vnc_implicit_withdraw
;
6268 vnc_import_bgp_del_route(bgp
, p
, pi
);
6269 vnc_import_bgp_exterior_del_route(
6274 bgp_attr_unintern(&pi
->attr
);
6275 pi
->attr
= attr_new
;
6276 pi
->uptime
= monotime(NULL
);
6277 #ifdef ENABLE_BGP_VNC
6278 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6279 && (safi
== SAFI_UNICAST
)) {
6280 if (vnc_implicit_withdraw
) {
6281 vnc_import_bgp_add_route(bgp
, p
, pi
);
6282 vnc_import_bgp_exterior_add_route(
6288 /* Nexthop reachability check. */
6289 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6290 && (safi
== SAFI_UNICAST
6291 || safi
== SAFI_LABELED_UNICAST
)) {
6293 struct bgp
*bgp_nexthop
= bgp
;
6295 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6296 bgp_nexthop
= pi
->extra
->bgp_orig
;
6298 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6299 afi
, safi
, pi
, NULL
,
6301 bgp_path_info_set_flag(dest
, pi
,
6304 if (BGP_DEBUG(nht
, NHT
)) {
6305 char buf1
[INET6_ADDRSTRLEN
];
6306 inet_ntop(p
->family
,
6310 "%s(%s): Route not in table, not advertising",
6313 bgp_path_info_unset_flag(
6314 dest
, pi
, BGP_PATH_VALID
);
6317 /* Delete the NHT structure if any, if we're
6319 * enabling/disabling import check. We
6320 * deregister the route
6321 * from NHT to avoid overloading NHT and the
6322 * process interaction
6324 bgp_unlink_nexthop(pi
);
6325 bgp_path_info_set_flag(dest
, pi
,
6328 /* Process change. */
6329 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6330 bgp_process(bgp
, dest
, afi
, safi
);
6332 if (SAFI_UNICAST
== safi
6333 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6335 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6336 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6340 bgp_dest_unlock_node(dest
);
6341 aspath_unintern(&attr
.aspath
);
6346 /* Make new BGP info. */
6347 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6349 /* Nexthop reachability check. */
6350 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6351 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6352 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6354 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6356 if (BGP_DEBUG(nht
, NHT
)) {
6357 char buf1
[INET6_ADDRSTRLEN
];
6359 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6362 "%s(%s): Route not in table, not advertising",
6365 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6368 /* Delete the NHT structure if any, if we're toggling between
6369 * enabling/disabling import check. We deregister the route
6370 * from NHT to avoid overloading NHT and the process interaction
6372 bgp_unlink_nexthop(new);
6374 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6377 /* Aggregate address increment. */
6378 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6380 /* Register new BGP information. */
6381 bgp_path_info_add(dest
, new);
6383 /* route_node_get lock */
6384 bgp_dest_unlock_node(dest
);
6386 /* Process change. */
6387 bgp_process(bgp
, dest
, afi
, safi
);
6389 if (SAFI_UNICAST
== safi
6390 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6391 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6392 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6395 /* Unintern original. */
6396 aspath_unintern(&attr
.aspath
);
6399 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6402 struct bgp_dest
*dest
;
6403 struct bgp_path_info
*pi
;
6405 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6407 /* Check selected route and self inserted route. */
6408 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6409 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6410 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6413 /* Withdraw static BGP route from routing table. */
6415 if (SAFI_UNICAST
== safi
6416 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6417 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6418 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6420 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6421 bgp_unlink_nexthop(pi
);
6422 bgp_path_info_delete(dest
, pi
);
6423 bgp_process(bgp
, dest
, afi
, safi
);
6426 /* Unlock bgp_node_lookup. */
6427 bgp_dest_unlock_node(dest
);
6431 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6433 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6434 afi_t afi
, safi_t safi
,
6435 struct prefix_rd
*prd
)
6437 struct bgp_dest
*dest
;
6438 struct bgp_path_info
*pi
;
6440 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6442 /* Check selected route and self inserted route. */
6443 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6444 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6445 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6448 /* Withdraw static BGP route from routing table. */
6450 #ifdef ENABLE_BGP_VNC
6451 rfapiProcessWithdraw(
6452 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6453 1); /* Kill, since it is an administrative change */
6455 if (SAFI_MPLS_VPN
== safi
6456 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6457 vpn_leak_to_vrf_withdraw(pi
);
6459 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6460 bgp_path_info_delete(dest
, pi
);
6461 bgp_process(bgp
, dest
, afi
, safi
);
6464 /* Unlock bgp_node_lookup. */
6465 bgp_dest_unlock_node(dest
);
6468 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6469 struct bgp_static
*bgp_static
, afi_t afi
,
6472 struct bgp_dest
*dest
;
6473 struct bgp_path_info
*new;
6474 struct attr
*attr_new
;
6475 struct attr attr
= {0};
6476 struct bgp_path_info
*pi
;
6477 #ifdef ENABLE_BGP_VNC
6478 mpls_label_t label
= 0;
6480 uint32_t num_labels
= 0;
6484 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6486 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6489 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6491 attr
.nexthop
= bgp_static
->igpnexthop
;
6492 attr
.med
= bgp_static
->igpmetric
;
6493 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6495 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6496 || (safi
== SAFI_ENCAP
)) {
6497 if (afi
== AFI_IP
) {
6498 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6499 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6502 if (afi
== AFI_L2VPN
) {
6503 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6504 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6505 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6506 &bgp_static
->gatewayIp
.u
.prefix4
,
6508 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6509 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6510 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6511 &bgp_static
->gatewayIp
.u
.prefix6
,
6514 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6515 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6516 struct bgp_encap_type_vxlan bet
;
6517 memset(&bet
, 0, sizeof(bet
));
6518 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6519 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6521 if (bgp_static
->router_mac
) {
6522 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6525 /* Apply route-map. */
6526 if (bgp_static
->rmap
.name
) {
6527 struct attr attr_tmp
= attr
;
6528 struct bgp_path_info rmap_path
;
6529 route_map_result_t ret
;
6531 rmap_path
.peer
= bgp
->peer_self
;
6532 rmap_path
.attr
= &attr_tmp
;
6534 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6536 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6538 bgp
->peer_self
->rmap_type
= 0;
6540 if (ret
== RMAP_DENYMATCH
) {
6541 /* Free uninterned attribute. */
6542 bgp_attr_flush(&attr_tmp
);
6544 /* Unintern original. */
6545 aspath_unintern(&attr
.aspath
);
6546 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6548 bgp_dest_unlock_node(dest
);
6552 attr_new
= bgp_attr_intern(&attr_tmp
);
6554 attr_new
= bgp_attr_intern(&attr
);
6557 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6558 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6559 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6563 if (attrhash_cmp(pi
->attr
, attr_new
)
6564 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6565 bgp_dest_unlock_node(dest
);
6566 bgp_attr_unintern(&attr_new
);
6567 aspath_unintern(&attr
.aspath
);
6570 /* The attribute is changed. */
6571 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6573 /* Rewrite BGP route information. */
6574 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6575 bgp_path_info_restore(dest
, pi
);
6577 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6578 bgp_attr_unintern(&pi
->attr
);
6579 pi
->attr
= attr_new
;
6580 pi
->uptime
= monotime(NULL
);
6581 #ifdef ENABLE_BGP_VNC
6583 label
= decode_label(&pi
->extra
->label
[0]);
6586 /* Process change. */
6587 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6588 bgp_process(bgp
, dest
, afi
, safi
);
6590 if (SAFI_MPLS_VPN
== safi
6591 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6592 vpn_leak_to_vrf_update(bgp
, pi
,
6595 #ifdef ENABLE_BGP_VNC
6596 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6597 pi
->attr
, afi
, safi
, pi
->type
,
6598 pi
->sub_type
, &label
);
6600 bgp_dest_unlock_node(dest
);
6601 aspath_unintern(&attr
.aspath
);
6607 /* Make new BGP info. */
6608 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6610 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6611 bgp_path_info_extra_get(new);
6613 new->extra
->label
[0] = bgp_static
->label
;
6614 new->extra
->num_labels
= num_labels
;
6616 #ifdef ENABLE_BGP_VNC
6617 label
= decode_label(&bgp_static
->label
);
6620 /* Aggregate address increment. */
6621 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6623 /* Register new BGP information. */
6624 bgp_path_info_add(dest
, new);
6625 /* route_node_get lock */
6626 bgp_dest_unlock_node(dest
);
6628 /* Process change. */
6629 bgp_process(bgp
, dest
, afi
, safi
);
6631 if (SAFI_MPLS_VPN
== safi
6632 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6633 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6635 #ifdef ENABLE_BGP_VNC
6636 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6637 safi
, new->type
, new->sub_type
, &label
);
6640 /* Unintern original. */
6641 aspath_unintern(&attr
.aspath
);
6644 /* Configure static BGP network. When user don't run zebra, static
6645 route should be installed as valid. */
6646 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6647 const char *ip_str
, afi_t afi
, safi_t safi
,
6648 const char *rmap
, int backdoor
, uint32_t label_index
)
6650 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6653 struct bgp_static
*bgp_static
;
6654 struct bgp_dest
*dest
;
6655 uint8_t need_update
= 0;
6657 /* Convert IP prefix string to struct prefix. */
6658 ret
= str2prefix(ip_str
, &p
);
6660 vty_out(vty
, "%% Malformed prefix\n");
6661 return CMD_WARNING_CONFIG_FAILED
;
6663 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6664 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6665 return CMD_WARNING_CONFIG_FAILED
;
6672 /* Set BGP static route configuration. */
6673 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6676 vty_out(vty
, "%% Can't find static route specified\n");
6677 return CMD_WARNING_CONFIG_FAILED
;
6680 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6682 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6683 && (label_index
!= bgp_static
->label_index
)) {
6685 "%% label-index doesn't match static route\n");
6686 bgp_dest_unlock_node(dest
);
6687 return CMD_WARNING_CONFIG_FAILED
;
6690 if ((rmap
&& bgp_static
->rmap
.name
)
6691 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6693 "%% route-map name doesn't match static route\n");
6694 bgp_dest_unlock_node(dest
);
6695 return CMD_WARNING_CONFIG_FAILED
;
6698 /* Update BGP RIB. */
6699 if (!bgp_static
->backdoor
)
6700 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6702 /* Clear configuration. */
6703 bgp_static_free(bgp_static
);
6704 bgp_dest_set_bgp_static_info(dest
, NULL
);
6705 bgp_dest_unlock_node(dest
);
6706 bgp_dest_unlock_node(dest
);
6709 /* Set BGP static route configuration. */
6710 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6711 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6713 /* Configuration change. */
6714 /* Label index cannot be changed. */
6715 if (bgp_static
->label_index
!= label_index
) {
6716 vty_out(vty
, "%% cannot change label-index\n");
6717 bgp_dest_unlock_node(dest
);
6718 return CMD_WARNING_CONFIG_FAILED
;
6721 /* Check previous routes are installed into BGP. */
6722 if (bgp_static
->valid
6723 && bgp_static
->backdoor
!= backdoor
)
6726 bgp_static
->backdoor
= backdoor
;
6729 XFREE(MTYPE_ROUTE_MAP_NAME
,
6730 bgp_static
->rmap
.name
);
6731 route_map_counter_decrement(
6732 bgp_static
->rmap
.map
);
6733 bgp_static
->rmap
.name
=
6734 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6735 bgp_static
->rmap
.map
=
6736 route_map_lookup_by_name(rmap
);
6737 route_map_counter_increment(
6738 bgp_static
->rmap
.map
);
6740 XFREE(MTYPE_ROUTE_MAP_NAME
,
6741 bgp_static
->rmap
.name
);
6742 route_map_counter_decrement(
6743 bgp_static
->rmap
.map
);
6744 bgp_static
->rmap
.map
= NULL
;
6745 bgp_static
->valid
= 0;
6747 bgp_dest_unlock_node(dest
);
6749 /* New configuration. */
6750 bgp_static
= bgp_static_new();
6751 bgp_static
->backdoor
= backdoor
;
6752 bgp_static
->valid
= 0;
6753 bgp_static
->igpmetric
= 0;
6754 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6755 bgp_static
->label_index
= label_index
;
6758 XFREE(MTYPE_ROUTE_MAP_NAME
,
6759 bgp_static
->rmap
.name
);
6760 route_map_counter_decrement(
6761 bgp_static
->rmap
.map
);
6762 bgp_static
->rmap
.name
=
6763 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6764 bgp_static
->rmap
.map
=
6765 route_map_lookup_by_name(rmap
);
6766 route_map_counter_increment(
6767 bgp_static
->rmap
.map
);
6769 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6772 bgp_static
->valid
= 1;
6774 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6776 if (!bgp_static
->backdoor
)
6777 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6783 void bgp_static_add(struct bgp
*bgp
)
6787 struct bgp_dest
*dest
;
6788 struct bgp_dest
*rm
;
6789 struct bgp_table
*table
;
6790 struct bgp_static
*bgp_static
;
6792 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6793 FOREACH_AFI_SAFI (afi
, safi
)
6794 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6795 dest
= bgp_route_next(dest
)) {
6796 if (!bgp_dest_has_bgp_path_info_data(dest
))
6799 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6800 || (safi
== SAFI_EVPN
)) {
6801 table
= bgp_dest_get_bgp_table_info(dest
);
6803 for (rm
= bgp_table_top(table
); rm
;
6804 rm
= bgp_route_next(rm
)) {
6806 bgp_dest_get_bgp_static_info(
6808 bgp_static_update_safi(
6809 bgp
, bgp_dest_get_prefix(rm
),
6810 bgp_static
, afi
, safi
);
6814 bgp
, bgp_dest_get_prefix(dest
),
6815 bgp_dest_get_bgp_static_info(dest
), afi
,
6819 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6822 /* Called from bgp_delete(). Delete all static routes from the BGP
6824 void bgp_static_delete(struct bgp
*bgp
)
6828 struct bgp_dest
*dest
;
6829 struct bgp_dest
*rm
;
6830 struct bgp_table
*table
;
6831 struct bgp_static
*bgp_static
;
6833 FOREACH_AFI_SAFI (afi
, safi
)
6834 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6835 dest
= bgp_route_next(dest
)) {
6836 if (!bgp_dest_has_bgp_path_info_data(dest
))
6839 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6840 || (safi
== SAFI_EVPN
)) {
6841 table
= bgp_dest_get_bgp_table_info(dest
);
6843 for (rm
= bgp_table_top(table
); rm
;
6844 rm
= bgp_route_next(rm
)) {
6846 bgp_dest_get_bgp_static_info(
6851 bgp_static_withdraw_safi(
6852 bgp
, bgp_dest_get_prefix(rm
),
6854 (struct prefix_rd
*)
6855 bgp_dest_get_prefix(
6857 bgp_static_free(bgp_static
);
6858 bgp_dest_set_bgp_static_info(rm
,
6860 bgp_dest_unlock_node(rm
);
6863 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6864 bgp_static_withdraw(bgp
,
6865 bgp_dest_get_prefix(dest
),
6867 bgp_static_free(bgp_static
);
6868 bgp_dest_set_bgp_static_info(dest
, NULL
);
6869 bgp_dest_unlock_node(dest
);
6874 void bgp_static_redo_import_check(struct bgp
*bgp
)
6878 struct bgp_dest
*dest
;
6879 struct bgp_dest
*rm
;
6880 struct bgp_table
*table
;
6881 struct bgp_static
*bgp_static
;
6883 /* Use this flag to force reprocessing of the route */
6884 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6885 FOREACH_AFI_SAFI (afi
, safi
) {
6886 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6887 dest
= bgp_route_next(dest
)) {
6888 if (!bgp_dest_has_bgp_path_info_data(dest
))
6891 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6892 || (safi
== SAFI_EVPN
)) {
6893 table
= bgp_dest_get_bgp_table_info(dest
);
6895 for (rm
= bgp_table_top(table
); rm
;
6896 rm
= bgp_route_next(rm
)) {
6898 bgp_dest_get_bgp_static_info(
6900 bgp_static_update_safi(
6901 bgp
, bgp_dest_get_prefix(rm
),
6902 bgp_static
, afi
, safi
);
6905 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6906 bgp_static_update(bgp
,
6907 bgp_dest_get_prefix(dest
),
6908 bgp_static
, afi
, safi
);
6912 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6915 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6918 struct bgp_table
*table
;
6919 struct bgp_dest
*dest
;
6920 struct bgp_path_info
*pi
;
6922 /* Do not install the aggregate route if BGP is in the
6923 * process of termination.
6925 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6926 || (bgp
->peer_self
== NULL
))
6929 table
= bgp
->rib
[afi
][safi
];
6930 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6931 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6932 if (pi
->peer
== bgp
->peer_self
6933 && ((pi
->type
== ZEBRA_ROUTE_BGP
6934 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6935 || (pi
->type
!= ZEBRA_ROUTE_BGP
6937 == BGP_ROUTE_REDISTRIBUTE
))) {
6938 bgp_aggregate_decrement(
6939 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6941 bgp_unlink_nexthop(pi
);
6942 bgp_path_info_delete(dest
, pi
);
6943 bgp_process(bgp
, dest
, afi
, safi
);
6950 * Purge all networks and redistributed routes from routing table.
6951 * Invoked upon the instance going down.
6953 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6958 FOREACH_AFI_SAFI (afi
, safi
)
6959 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6964 * Currently this is used to set static routes for VPN and ENCAP.
6965 * I think it can probably be factored with bgp_static_set.
6967 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6968 const char *ip_str
, const char *rd_str
,
6969 const char *label_str
, const char *rmap_str
,
6970 int evpn_type
, const char *esi
, const char *gwip
,
6971 const char *ethtag
, const char *routermac
)
6973 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6976 struct prefix_rd prd
;
6977 struct bgp_dest
*pdest
;
6978 struct bgp_dest
*dest
;
6979 struct bgp_table
*table
;
6980 struct bgp_static
*bgp_static
;
6981 mpls_label_t label
= MPLS_INVALID_LABEL
;
6982 struct prefix gw_ip
;
6984 /* validate ip prefix */
6985 ret
= str2prefix(ip_str
, &p
);
6987 vty_out(vty
, "%% Malformed prefix\n");
6988 return CMD_WARNING_CONFIG_FAILED
;
6991 if ((afi
== AFI_L2VPN
)
6992 && (bgp_build_evpn_prefix(evpn_type
,
6993 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6994 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6995 return CMD_WARNING_CONFIG_FAILED
;
6998 ret
= str2prefix_rd(rd_str
, &prd
);
7000 vty_out(vty
, "%% Malformed rd\n");
7001 return CMD_WARNING_CONFIG_FAILED
;
7005 unsigned long label_val
;
7006 label_val
= strtoul(label_str
, NULL
, 10);
7007 encode_label(label_val
, &label
);
7010 if (safi
== SAFI_EVPN
) {
7011 if (esi
&& str2esi(esi
, NULL
) == 0) {
7012 vty_out(vty
, "%% Malformed ESI\n");
7013 return CMD_WARNING_CONFIG_FAILED
;
7015 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
7016 vty_out(vty
, "%% Malformed Router MAC\n");
7017 return CMD_WARNING_CONFIG_FAILED
;
7020 memset(&gw_ip
, 0, sizeof(gw_ip
));
7021 ret
= str2prefix(gwip
, &gw_ip
);
7023 vty_out(vty
, "%% Malformed GatewayIp\n");
7024 return CMD_WARNING_CONFIG_FAILED
;
7026 if ((gw_ip
.family
== AF_INET
7027 && is_evpn_prefix_ipaddr_v6(
7028 (struct prefix_evpn
*)&p
))
7029 || (gw_ip
.family
== AF_INET6
7030 && is_evpn_prefix_ipaddr_v4(
7031 (struct prefix_evpn
*)&p
))) {
7033 "%% GatewayIp family differs with IP prefix\n");
7034 return CMD_WARNING_CONFIG_FAILED
;
7038 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7039 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7040 bgp_dest_set_bgp_table_info(pdest
,
7041 bgp_table_init(bgp
, afi
, safi
));
7042 table
= bgp_dest_get_bgp_table_info(pdest
);
7044 dest
= bgp_node_get(table
, &p
);
7046 if (bgp_dest_has_bgp_path_info_data(dest
)) {
7047 vty_out(vty
, "%% Same network configuration exists\n");
7048 bgp_dest_unlock_node(dest
);
7050 /* New configuration. */
7051 bgp_static
= bgp_static_new();
7052 bgp_static
->backdoor
= 0;
7053 bgp_static
->valid
= 0;
7054 bgp_static
->igpmetric
= 0;
7055 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7056 bgp_static
->label
= label
;
7057 bgp_static
->prd
= prd
;
7059 bgp_static
->prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_str
);
7062 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7063 route_map_counter_decrement(bgp_static
->rmap
.map
);
7064 bgp_static
->rmap
.name
=
7065 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7066 bgp_static
->rmap
.map
=
7067 route_map_lookup_by_name(rmap_str
);
7068 route_map_counter_increment(bgp_static
->rmap
.map
);
7071 if (safi
== SAFI_EVPN
) {
7073 bgp_static
->eth_s_id
=
7076 str2esi(esi
, bgp_static
->eth_s_id
);
7079 bgp_static
->router_mac
=
7080 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7081 (void)prefix_str2mac(routermac
,
7082 bgp_static
->router_mac
);
7085 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7087 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7089 bgp_static
->valid
= 1;
7090 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7096 /* Configure static BGP network. */
7097 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7098 const char *ip_str
, const char *rd_str
,
7099 const char *label_str
, int evpn_type
, const char *esi
,
7100 const char *gwip
, const char *ethtag
)
7102 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7105 struct prefix_rd prd
;
7106 struct bgp_dest
*pdest
;
7107 struct bgp_dest
*dest
;
7108 struct bgp_table
*table
;
7109 struct bgp_static
*bgp_static
;
7110 mpls_label_t label
= MPLS_INVALID_LABEL
;
7112 /* Convert IP prefix string to struct prefix. */
7113 ret
= str2prefix(ip_str
, &p
);
7115 vty_out(vty
, "%% Malformed prefix\n");
7116 return CMD_WARNING_CONFIG_FAILED
;
7119 if ((afi
== AFI_L2VPN
)
7120 && (bgp_build_evpn_prefix(evpn_type
,
7121 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7122 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7123 return CMD_WARNING_CONFIG_FAILED
;
7125 ret
= str2prefix_rd(rd_str
, &prd
);
7127 vty_out(vty
, "%% Malformed rd\n");
7128 return CMD_WARNING_CONFIG_FAILED
;
7132 unsigned long label_val
;
7133 label_val
= strtoul(label_str
, NULL
, 10);
7134 encode_label(label_val
, &label
);
7137 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7138 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7139 bgp_dest_set_bgp_table_info(pdest
,
7140 bgp_table_init(bgp
, afi
, safi
));
7142 bgp_dest_unlock_node(pdest
);
7143 table
= bgp_dest_get_bgp_table_info(pdest
);
7145 dest
= bgp_node_lookup(table
, &p
);
7148 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7150 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7151 bgp_static_free(bgp_static
);
7152 bgp_dest_set_bgp_static_info(dest
, NULL
);
7153 bgp_dest_unlock_node(dest
);
7154 bgp_dest_unlock_node(dest
);
7156 vty_out(vty
, "%% Can't find the route\n");
7161 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7162 const char *rmap_name
)
7164 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7165 struct bgp_rmap
*rmap
;
7167 rmap
= &bgp
->table_map
[afi
][safi
];
7169 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7170 route_map_counter_decrement(rmap
->map
);
7171 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7172 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7173 route_map_counter_increment(rmap
->map
);
7175 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7176 route_map_counter_decrement(rmap
->map
);
7180 if (bgp_fibupd_safi(safi
))
7181 bgp_zebra_announce_table(bgp
, afi
, safi
);
7186 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7187 const char *rmap_name
)
7189 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7190 struct bgp_rmap
*rmap
;
7192 rmap
= &bgp
->table_map
[afi
][safi
];
7193 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7194 route_map_counter_decrement(rmap
->map
);
7197 if (bgp_fibupd_safi(safi
))
7198 bgp_zebra_announce_table(bgp
, afi
, safi
);
7203 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7206 if (bgp
->table_map
[afi
][safi
].name
) {
7207 vty_out(vty
, " table-map %s\n",
7208 bgp
->table_map
[afi
][safi
].name
);
7212 DEFUN (bgp_table_map
,
7215 "BGP table to RIB route download filter\n"
7216 "Name of the route map\n")
7219 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7220 argv
[idx_word
]->arg
);
7222 DEFUN (no_bgp_table_map
,
7223 no_bgp_table_map_cmd
,
7224 "no table-map WORD",
7226 "BGP table to RIB route download filter\n"
7227 "Name of the route map\n")
7230 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7231 argv
[idx_word
]->arg
);
7237 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7238 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7239 backdoor$backdoor}]",
7241 "Specify a network to announce via BGP\n"
7246 "Route-map to modify the attributes\n"
7247 "Name of the route map\n"
7248 "Label index to associate with the prefix\n"
7249 "Label index value\n"
7250 "Specify a BGP backdoor route\n")
7252 char addr_prefix_str
[BUFSIZ
];
7257 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7259 sizeof(addr_prefix_str
));
7261 vty_out(vty
, "%% Inconsistent address and mask\n");
7262 return CMD_WARNING_CONFIG_FAILED
;
7266 return bgp_static_set(
7267 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7268 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7269 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7272 DEFPY(ipv6_bgp_network
,
7273 ipv6_bgp_network_cmd
,
7274 "[no] network X:X::X:X/M$prefix \
7275 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7277 "Specify a network to announce via BGP\n"
7279 "Route-map to modify the attributes\n"
7280 "Name of the route map\n"
7281 "Label index to associate with the prefix\n"
7282 "Label index value\n")
7284 return bgp_static_set(
7285 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7286 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7289 static struct bgp_aggregate
*bgp_aggregate_new(void)
7291 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7294 void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7296 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7297 route_map_counter_decrement(aggregate
->suppress_map
);
7298 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7299 route_map_counter_decrement(aggregate
->rmap
.map
);
7300 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7304 * Helper function to avoid repeated code: prepare variables for a
7305 * `route_map_apply` call.
7307 * \returns `true` on route map match, otherwise `false`.
7309 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7310 struct bgp_aggregate
*aggregate
,
7311 struct bgp_path_info
*pi
)
7313 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7314 route_map_result_t rmr
= RMAP_DENYMATCH
;
7315 struct bgp_path_info rmap_path
= {};
7316 struct attr attr
= {};
7318 /* No route map entries created, just don't match. */
7319 if (aggregate
->suppress_map
== NULL
)
7322 /* Call route map matching and return result. */
7323 attr
.aspath
= aspath_empty(bgp
->asnotation
);
7324 rmap_path
.peer
= bgp
->peer_self
;
7325 rmap_path
.attr
= &attr
;
7327 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7328 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7329 bgp
->peer_self
->rmap_type
= 0;
7331 bgp_attr_flush(&attr
);
7332 aspath_unintern(&attr
.aspath
);
7334 return rmr
== RMAP_PERMITMATCH
;
7337 /** Test whether the aggregation has suppressed this path or not. */
7338 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7339 struct bgp_path_info
*pi
)
7341 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7344 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7348 * Suppress this path and keep the reference.
7350 * \returns `true` if needs processing otherwise `false`.
7352 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7353 struct bgp_path_info
*pi
)
7355 struct bgp_path_info_extra
*pie
;
7357 /* Path is already suppressed by this aggregation. */
7358 if (aggr_suppress_exists(aggregate
, pi
))
7361 pie
= bgp_path_info_extra_get(pi
);
7363 /* This is the first suppression, allocate memory and list it. */
7364 if (pie
->aggr_suppressors
== NULL
)
7365 pie
->aggr_suppressors
= list_new();
7367 listnode_add(pie
->aggr_suppressors
, aggregate
);
7369 /* Only mark for processing if suppressed. */
7370 if (listcount(pie
->aggr_suppressors
) == 1) {
7371 if (BGP_DEBUG(update
, UPDATE_OUT
))
7372 zlog_debug("aggregate-address suppressing: %pFX",
7373 bgp_dest_get_prefix(pi
->net
));
7375 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7383 * Unsuppress this path and remove the reference.
7385 * \returns `true` if needs processing otherwise `false`.
7387 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7388 struct bgp_path_info
*pi
)
7390 /* Path wasn't suppressed. */
7391 if (!aggr_suppress_exists(aggregate
, pi
))
7394 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7396 /* Unsuppress and free extra memory if last item. */
7397 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7398 if (BGP_DEBUG(update
, UPDATE_OUT
))
7399 zlog_debug("aggregate-address unsuppressing: %pFX",
7400 bgp_dest_get_prefix(pi
->net
));
7402 list_delete(&pi
->extra
->aggr_suppressors
);
7403 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7410 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7411 struct aspath
*aspath
,
7412 struct community
*comm
,
7413 struct ecommunity
*ecomm
,
7414 struct lcommunity
*lcomm
)
7416 static struct aspath
*ae
= NULL
;
7417 enum asnotation_mode asnotation
;
7419 asnotation
= bgp_get_asnotation(NULL
);
7422 ae
= aspath_empty(asnotation
);
7427 if (origin
!= pi
->attr
->origin
)
7430 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7433 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7436 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7439 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7442 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7448 static void bgp_aggregate_install(
7449 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7450 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7451 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7452 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7454 struct bgp_dest
*dest
;
7455 struct bgp_table
*table
;
7456 struct bgp_path_info
*pi
, *orig
, *new;
7459 table
= bgp
->rib
[afi
][safi
];
7461 dest
= bgp_node_get(table
, p
);
7463 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7464 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7465 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7469 * If we have paths with different MEDs, then don't install
7470 * (or uninstall) the aggregate route.
7472 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7473 goto uninstall_aggregate_route
;
7475 if (aggregate
->count
> 0) {
7477 * If the aggregate information has not changed
7478 * no need to re-install it again.
7480 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7481 ecommunity
, lcommunity
)) {
7482 bgp_dest_unlock_node(dest
);
7485 aspath_free(aspath
);
7487 community_free(&community
);
7489 ecommunity_free(&ecommunity
);
7491 lcommunity_free(&lcommunity
);
7497 * Mark the old as unusable
7500 bgp_path_info_delete(dest
, pi
);
7502 attr
= bgp_attr_aggregate_intern(
7503 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7504 aggregate
, atomic_aggregate
, p
);
7507 aspath_free(aspath
);
7508 community_free(&community
);
7509 ecommunity_free(&ecommunity
);
7510 lcommunity_free(&lcommunity
);
7511 bgp_dest_unlock_node(dest
);
7512 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7513 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7514 zlog_debug("%s: %pFX null attribute", __func__
,
7519 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7520 bgp
->peer_self
, attr
, dest
);
7522 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7524 bgp_path_info_add(dest
, new);
7525 bgp_process(bgp
, dest
, afi
, safi
);
7527 uninstall_aggregate_route
:
7528 for (pi
= orig
; pi
; pi
= pi
->next
)
7529 if (pi
->peer
== bgp
->peer_self
7530 && pi
->type
== ZEBRA_ROUTE_BGP
7531 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7534 /* Withdraw static BGP route from routing table. */
7536 bgp_path_info_delete(dest
, pi
);
7537 bgp_process(bgp
, dest
, afi
, safi
);
7541 bgp_dest_unlock_node(dest
);
7545 * Check if the current path has different MED than other known paths.
7547 * \returns `true` if the MED matched the others else `false`.
7549 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7550 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7552 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7554 /* This is the first route being analyzed. */
7555 if (!aggregate
->med_initialized
) {
7556 aggregate
->med_initialized
= true;
7557 aggregate
->med_mismatched
= false;
7558 aggregate
->med_matched_value
= cur_med
;
7560 /* Check if routes with different MED showed up. */
7561 if (cur_med
!= aggregate
->med_matched_value
)
7562 aggregate
->med_mismatched
= true;
7565 return !aggregate
->med_mismatched
;
7569 * Initializes and tests all routes in the aggregate address path for MED
7572 * \returns `true` if all MEDs are the same otherwise `false`.
7574 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7575 struct bgp
*bgp
, const struct prefix
*p
,
7576 afi_t afi
, safi_t safi
)
7578 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7579 const struct prefix
*dest_p
;
7580 struct bgp_dest
*dest
, *top
;
7581 struct bgp_path_info
*pi
;
7582 bool med_matched
= true;
7584 aggregate
->med_initialized
= false;
7586 top
= bgp_node_get(table
, p
);
7587 for (dest
= bgp_node_get(table
, p
); dest
;
7588 dest
= bgp_route_next_until(dest
, top
)) {
7589 dest_p
= bgp_dest_get_prefix(dest
);
7590 if (dest_p
->prefixlen
<= p
->prefixlen
)
7593 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7594 if (BGP_PATH_HOLDDOWN(pi
))
7596 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7598 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7599 med_matched
= false;
7606 bgp_dest_unlock_node(top
);
7612 * Toggles the route suppression status for this aggregate address
7615 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7616 struct bgp
*bgp
, const struct prefix
*p
,
7617 afi_t afi
, safi_t safi
, bool suppress
)
7619 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7620 const struct prefix
*dest_p
;
7621 struct bgp_dest
*dest
, *top
;
7622 struct bgp_path_info
*pi
;
7623 bool toggle_suppression
;
7625 /* We've found a different MED we must revert any suppressed routes. */
7626 top
= bgp_node_get(table
, p
);
7627 for (dest
= bgp_node_get(table
, p
); dest
;
7628 dest
= bgp_route_next_until(dest
, top
)) {
7629 dest_p
= bgp_dest_get_prefix(dest
);
7630 if (dest_p
->prefixlen
<= p
->prefixlen
)
7633 toggle_suppression
= false;
7634 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7635 if (BGP_PATH_HOLDDOWN(pi
))
7637 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7640 /* We are toggling suppression back. */
7642 /* Suppress route if not suppressed already. */
7643 if (aggr_suppress_path(aggregate
, pi
))
7644 toggle_suppression
= true;
7648 /* Install route if there is no more suppression. */
7649 if (aggr_unsuppress_path(aggregate
, pi
))
7650 toggle_suppression
= true;
7653 if (toggle_suppression
)
7654 bgp_process(bgp
, dest
, afi
, safi
);
7656 bgp_dest_unlock_node(top
);
7660 * Aggregate address MED matching incremental test: this function is called
7661 * when the initial aggregation occurred and we are only testing a single
7664 * In addition to testing and setting the MED validity it also installs back
7665 * suppressed routes (if summary is configured).
7667 * Must not be called in `bgp_aggregate_route`.
7669 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7670 struct bgp
*bgp
, const struct prefix
*p
,
7671 afi_t afi
, safi_t safi
,
7672 struct bgp_path_info
*pi
)
7674 /* MED matching disabled. */
7675 if (!aggregate
->match_med
)
7678 /* Aggregation with different MED, recheck if we have got equal MEDs
7681 if (aggregate
->med_mismatched
&&
7682 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7683 aggregate
->summary_only
)
7684 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7687 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7689 /* No mismatches, just quit. */
7690 if (!aggregate
->med_mismatched
)
7693 /* Route summarization is disabled. */
7694 if (!aggregate
->summary_only
)
7697 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7700 /* Update an aggregate as routes are added/removed from the BGP table */
7701 bool bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7702 safi_t safi
, struct bgp_aggregate
*aggregate
)
7704 struct bgp_table
*table
;
7705 struct bgp_dest
*top
;
7706 struct bgp_dest
*dest
;
7708 struct aspath
*aspath
= NULL
;
7709 struct community
*community
= NULL
;
7710 struct ecommunity
*ecommunity
= NULL
;
7711 struct lcommunity
*lcommunity
= NULL
;
7712 struct bgp_path_info
*pi
;
7713 unsigned long match
= 0;
7714 uint8_t atomic_aggregate
= 0;
7716 /* If the bgp instance is being deleted or self peer is deleted
7717 * then do not create aggregate route
7719 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
7720 bgp
->peer_self
== NULL
)
7723 /* Initialize and test routes for MED difference. */
7724 if (aggregate
->match_med
)
7725 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7728 * Reset aggregate count: we might've been called from route map
7729 * update so in that case we must retest all more specific routes.
7731 * \see `bgp_route_map_process_update`.
7733 aggregate
->count
= 0;
7734 aggregate
->incomplete_origin_count
= 0;
7735 aggregate
->incomplete_origin_count
= 0;
7736 aggregate
->egp_origin_count
= 0;
7738 /* ORIGIN attribute: If at least one route among routes that are
7739 aggregated has ORIGIN with the value INCOMPLETE, then the
7740 aggregated route must have the ORIGIN attribute with the value
7741 INCOMPLETE. Otherwise, if at least one route among routes that
7742 are aggregated has ORIGIN with the value EGP, then the aggregated
7743 route must have the origin attribute with the value EGP. In all
7744 other case the value of the ORIGIN attribute of the aggregated
7745 route is INTERNAL. */
7746 origin
= BGP_ORIGIN_IGP
;
7748 table
= bgp
->rib
[afi
][safi
];
7750 top
= bgp_node_get(table
, p
);
7751 for (dest
= bgp_node_get(table
, p
); dest
;
7752 dest
= bgp_route_next_until(dest
, top
)) {
7753 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7755 if (dest_p
->prefixlen
<= p
->prefixlen
)
7758 /* If suppress fib is enabled and route not installed
7759 * in FIB, skip the route
7761 if (!bgp_check_advertise(bgp
, dest
))
7766 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7767 if (BGP_PATH_HOLDDOWN(pi
))
7771 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7772 atomic_aggregate
= 1;
7774 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7778 * summary-only aggregate route suppress
7779 * aggregated route announcements.
7782 * Don't create summaries if MED didn't match
7783 * otherwise neither the specific routes and the
7784 * aggregation will be announced.
7786 if (aggregate
->summary_only
7787 && AGGREGATE_MED_VALID(aggregate
)) {
7788 if (aggr_suppress_path(aggregate
, pi
))
7793 * Suppress more specific routes that match the route
7797 * Don't suppress routes if MED matching is enabled and
7798 * it mismatched otherwise we might end up with no
7799 * routes for this path.
7801 if (aggregate
->suppress_map_name
7802 && AGGREGATE_MED_VALID(aggregate
)
7803 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7804 if (aggr_suppress_path(aggregate
, pi
))
7811 * If at least one route among routes that are
7812 * aggregated has ORIGIN with the value INCOMPLETE,
7813 * then the aggregated route MUST have the ORIGIN
7814 * attribute with the value INCOMPLETE. Otherwise, if
7815 * at least one route among routes that are aggregated
7816 * has ORIGIN with the value EGP, then the aggregated
7817 * route MUST have the ORIGIN attribute with the value
7820 switch (pi
->attr
->origin
) {
7821 case BGP_ORIGIN_INCOMPLETE
:
7822 aggregate
->incomplete_origin_count
++;
7824 case BGP_ORIGIN_EGP
:
7825 aggregate
->egp_origin_count
++;
7833 if (!aggregate
->as_set
)
7837 * as-set aggregate route generate origin, as path,
7838 * and community aggregation.
7840 /* Compute aggregate route's as-path.
7842 bgp_compute_aggregate_aspath_hash(aggregate
,
7845 /* Compute aggregate route's community.
7847 if (bgp_attr_get_community(pi
->attr
))
7848 bgp_compute_aggregate_community_hash(
7850 bgp_attr_get_community(pi
->attr
));
7852 /* Compute aggregate route's extended community.
7854 if (bgp_attr_get_ecommunity(pi
->attr
))
7855 bgp_compute_aggregate_ecommunity_hash(
7857 bgp_attr_get_ecommunity(pi
->attr
));
7859 /* Compute aggregate route's large community.
7861 if (bgp_attr_get_lcommunity(pi
->attr
))
7862 bgp_compute_aggregate_lcommunity_hash(
7864 bgp_attr_get_lcommunity(pi
->attr
));
7867 bgp_process(bgp
, dest
, afi
, safi
);
7869 if (aggregate
->as_set
) {
7870 bgp_compute_aggregate_aspath_val(aggregate
);
7871 bgp_compute_aggregate_community_val(aggregate
);
7872 bgp_compute_aggregate_ecommunity_val(aggregate
);
7873 bgp_compute_aggregate_lcommunity_val(aggregate
);
7877 bgp_dest_unlock_node(top
);
7880 if (aggregate
->incomplete_origin_count
> 0)
7881 origin
= BGP_ORIGIN_INCOMPLETE
;
7882 else if (aggregate
->egp_origin_count
> 0)
7883 origin
= BGP_ORIGIN_EGP
;
7885 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7886 origin
= aggregate
->origin
;
7888 if (aggregate
->as_set
) {
7889 if (aggregate
->aspath
)
7890 /* Retrieve aggregate route's as-path.
7892 aspath
= aspath_dup(aggregate
->aspath
);
7894 if (aggregate
->community
)
7895 /* Retrieve aggregate route's community.
7897 community
= community_dup(aggregate
->community
);
7899 if (aggregate
->ecommunity
)
7900 /* Retrieve aggregate route's ecommunity.
7902 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7904 if (aggregate
->lcommunity
)
7905 /* Retrieve aggregate route's lcommunity.
7907 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7910 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7911 ecommunity
, lcommunity
, atomic_aggregate
,
7917 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7918 safi_t safi
, struct bgp_aggregate
*aggregate
)
7920 struct bgp_table
*table
;
7921 struct bgp_dest
*top
;
7922 struct bgp_dest
*dest
;
7923 struct bgp_path_info
*pi
;
7924 unsigned long match
;
7926 table
= bgp
->rib
[afi
][safi
];
7928 /* If routes exists below this node, generate aggregate routes. */
7929 top
= bgp_node_get(table
, p
);
7930 for (dest
= bgp_node_get(table
, p
); dest
;
7931 dest
= bgp_route_next_until(dest
, top
)) {
7932 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7934 if (dest_p
->prefixlen
<= p
->prefixlen
)
7938 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7939 if (BGP_PATH_HOLDDOWN(pi
))
7942 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7946 * This route is suppressed: attempt to unsuppress it.
7948 * `aggr_unsuppress_path` will fail if this particular
7949 * aggregate route was not the suppressor.
7951 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7952 listcount(pi
->extra
->aggr_suppressors
)) {
7953 if (aggr_unsuppress_path(aggregate
, pi
))
7959 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7960 aggregate
->incomplete_origin_count
--;
7961 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7962 aggregate
->egp_origin_count
--;
7964 if (aggregate
->as_set
) {
7965 /* Remove as-path from aggregate.
7967 bgp_remove_aspath_from_aggregate_hash(
7971 if (bgp_attr_get_community(pi
->attr
))
7972 /* Remove community from aggregate.
7974 bgp_remove_comm_from_aggregate_hash(
7976 bgp_attr_get_community(
7979 if (bgp_attr_get_ecommunity(pi
->attr
))
7980 /* Remove ecommunity from aggregate.
7982 bgp_remove_ecomm_from_aggregate_hash(
7984 bgp_attr_get_ecommunity(
7987 if (bgp_attr_get_lcommunity(pi
->attr
))
7988 /* Remove lcommunity from aggregate.
7990 bgp_remove_lcomm_from_aggregate_hash(
7992 bgp_attr_get_lcommunity(
7997 /* If this node was suppressed, process the change. */
7999 bgp_process(bgp
, dest
, afi
, safi
);
8001 if (aggregate
->as_set
) {
8002 aspath_free(aggregate
->aspath
);
8003 aggregate
->aspath
= NULL
;
8004 if (aggregate
->community
)
8005 community_free(&aggregate
->community
);
8006 if (aggregate
->ecommunity
)
8007 ecommunity_free(&aggregate
->ecommunity
);
8008 if (aggregate
->lcommunity
)
8009 lcommunity_free(&aggregate
->lcommunity
);
8012 bgp_dest_unlock_node(top
);
8015 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
8016 const struct prefix
*aggr_p
,
8017 struct bgp_path_info
*pinew
, afi_t afi
,
8019 struct bgp_aggregate
*aggregate
)
8022 struct aspath
*aspath
= NULL
;
8023 uint8_t atomic_aggregate
= 0;
8024 struct community
*community
= NULL
;
8025 struct ecommunity
*ecommunity
= NULL
;
8026 struct lcommunity
*lcommunity
= NULL
;
8028 /* If the bgp instance is being deleted or self peer is deleted
8029 * then do not create aggregate route
8031 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8032 || (bgp
->peer_self
== NULL
))
8035 /* ORIGIN attribute: If at least one route among routes that are
8036 * aggregated has ORIGIN with the value INCOMPLETE, then the
8037 * aggregated route must have the ORIGIN attribute with the value
8038 * INCOMPLETE. Otherwise, if at least one route among routes that
8039 * are aggregated has ORIGIN with the value EGP, then the aggregated
8040 * route must have the origin attribute with the value EGP. In all
8041 * other case the value of the ORIGIN attribute of the aggregated
8042 * route is INTERNAL.
8044 origin
= BGP_ORIGIN_IGP
;
8049 * This must be called before `summary` check to avoid
8050 * "suppressing" twice.
8052 if (aggregate
->match_med
)
8053 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8056 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8057 aggr_suppress_path(aggregate
, pinew
);
8059 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8060 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8061 aggr_suppress_path(aggregate
, pinew
);
8063 switch (pinew
->attr
->origin
) {
8064 case BGP_ORIGIN_INCOMPLETE
:
8065 aggregate
->incomplete_origin_count
++;
8067 case BGP_ORIGIN_EGP
:
8068 aggregate
->egp_origin_count
++;
8076 if (aggregate
->incomplete_origin_count
> 0)
8077 origin
= BGP_ORIGIN_INCOMPLETE
;
8078 else if (aggregate
->egp_origin_count
> 0)
8079 origin
= BGP_ORIGIN_EGP
;
8081 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8082 origin
= aggregate
->origin
;
8084 if (aggregate
->as_set
) {
8085 /* Compute aggregate route's as-path.
8087 bgp_compute_aggregate_aspath(aggregate
,
8088 pinew
->attr
->aspath
);
8090 /* Compute aggregate route's community.
8092 if (bgp_attr_get_community(pinew
->attr
))
8093 bgp_compute_aggregate_community(
8094 aggregate
, bgp_attr_get_community(pinew
->attr
));
8096 /* Compute aggregate route's extended community.
8098 if (bgp_attr_get_ecommunity(pinew
->attr
))
8099 bgp_compute_aggregate_ecommunity(
8101 bgp_attr_get_ecommunity(pinew
->attr
));
8103 /* Compute aggregate route's large community.
8105 if (bgp_attr_get_lcommunity(pinew
->attr
))
8106 bgp_compute_aggregate_lcommunity(
8108 bgp_attr_get_lcommunity(pinew
->attr
));
8110 /* Retrieve aggregate route's as-path.
8112 if (aggregate
->aspath
)
8113 aspath
= aspath_dup(aggregate
->aspath
);
8115 /* Retrieve aggregate route's community.
8117 if (aggregate
->community
)
8118 community
= community_dup(aggregate
->community
);
8120 /* Retrieve aggregate route's ecommunity.
8122 if (aggregate
->ecommunity
)
8123 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8125 /* Retrieve aggregate route's lcommunity.
8127 if (aggregate
->lcommunity
)
8128 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8131 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8132 aspath
, community
, ecommunity
,
8133 lcommunity
, atomic_aggregate
, aggregate
);
8136 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8138 struct bgp_path_info
*pi
,
8139 struct bgp_aggregate
*aggregate
,
8140 const struct prefix
*aggr_p
)
8143 struct aspath
*aspath
= NULL
;
8144 uint8_t atomic_aggregate
= 0;
8145 struct community
*community
= NULL
;
8146 struct ecommunity
*ecommunity
= NULL
;
8147 struct lcommunity
*lcommunity
= NULL
;
8148 unsigned long match
= 0;
8150 /* If the bgp instance is being deleted or self peer is deleted
8151 * then do not create aggregate route
8153 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8154 || (bgp
->peer_self
== NULL
))
8157 if (BGP_PATH_HOLDDOWN(pi
))
8160 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8163 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8164 if (aggr_unsuppress_path(aggregate
, pi
))
8167 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8168 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8169 if (aggr_unsuppress_path(aggregate
, pi
))
8173 * This must be called after `summary`, `suppress-map` check to avoid
8174 * "unsuppressing" twice.
8176 if (aggregate
->match_med
)
8177 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8179 if (aggregate
->count
> 0)
8182 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8183 aggregate
->incomplete_origin_count
--;
8184 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8185 aggregate
->egp_origin_count
--;
8187 if (aggregate
->as_set
) {
8188 /* Remove as-path from aggregate.
8190 bgp_remove_aspath_from_aggregate(aggregate
,
8193 if (bgp_attr_get_community(pi
->attr
))
8194 /* Remove community from aggregate.
8196 bgp_remove_community_from_aggregate(
8197 aggregate
, bgp_attr_get_community(pi
->attr
));
8199 if (bgp_attr_get_ecommunity(pi
->attr
))
8200 /* Remove ecommunity from aggregate.
8202 bgp_remove_ecommunity_from_aggregate(
8203 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8205 if (bgp_attr_get_lcommunity(pi
->attr
))
8206 /* Remove lcommunity from aggregate.
8208 bgp_remove_lcommunity_from_aggregate(
8209 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8212 /* If this node was suppressed, process the change. */
8214 bgp_process(bgp
, pi
->net
, afi
, safi
);
8216 origin
= BGP_ORIGIN_IGP
;
8217 if (aggregate
->incomplete_origin_count
> 0)
8218 origin
= BGP_ORIGIN_INCOMPLETE
;
8219 else if (aggregate
->egp_origin_count
> 0)
8220 origin
= BGP_ORIGIN_EGP
;
8222 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8223 origin
= aggregate
->origin
;
8225 if (aggregate
->as_set
) {
8226 /* Retrieve aggregate route's as-path.
8228 if (aggregate
->aspath
)
8229 aspath
= aspath_dup(aggregate
->aspath
);
8231 /* Retrieve aggregate route's community.
8233 if (aggregate
->community
)
8234 community
= community_dup(aggregate
->community
);
8236 /* Retrieve aggregate route's ecommunity.
8238 if (aggregate
->ecommunity
)
8239 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8241 /* Retrieve aggregate route's lcommunity.
8243 if (aggregate
->lcommunity
)
8244 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8247 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8248 aspath
, community
, ecommunity
,
8249 lcommunity
, atomic_aggregate
, aggregate
);
8252 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8253 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8255 struct bgp_dest
*child
;
8256 struct bgp_dest
*dest
;
8257 struct bgp_aggregate
*aggregate
;
8258 struct bgp_table
*table
;
8260 table
= bgp
->aggregate
[afi
][safi
];
8262 /* No aggregates configured. */
8263 if (bgp_table_top_nolock(table
) == NULL
)
8266 if (p
->prefixlen
== 0)
8269 if (BGP_PATH_HOLDDOWN(pi
))
8272 /* If suppress fib is enabled and route not installed
8273 * in FIB, do not update the aggregate route
8275 if (!bgp_check_advertise(bgp
, pi
->net
))
8278 child
= bgp_node_get(table
, p
);
8280 /* Aggregate address configuration check. */
8281 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8282 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8284 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8285 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8286 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8290 bgp_dest_unlock_node(child
);
8293 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8294 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8296 struct bgp_dest
*child
;
8297 struct bgp_dest
*dest
;
8298 struct bgp_aggregate
*aggregate
;
8299 struct bgp_table
*table
;
8301 table
= bgp
->aggregate
[afi
][safi
];
8303 /* No aggregates configured. */
8304 if (bgp_table_top_nolock(table
) == NULL
)
8307 if (p
->prefixlen
== 0)
8310 child
= bgp_node_get(table
, p
);
8312 /* Aggregate address configuration check. */
8313 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8314 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8316 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8317 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8318 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8322 bgp_dest_unlock_node(child
);
8325 /* Aggregate route attribute. */
8326 #define AGGREGATE_SUMMARY_ONLY 1
8327 #define AGGREGATE_AS_SET 1
8328 #define AGGREGATE_AS_UNSET 0
8330 static const char *bgp_origin2str(uint8_t origin
)
8333 case BGP_ORIGIN_IGP
:
8335 case BGP_ORIGIN_EGP
:
8337 case BGP_ORIGIN_INCOMPLETE
:
8338 return "incomplete";
8343 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8346 case RPKI_NOT_BEING_USED
:
8356 assert(!"We should never get here this is a dev escape");
8360 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8361 afi_t afi
, safi_t safi
)
8363 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8366 struct bgp_dest
*dest
;
8367 struct bgp_aggregate
*aggregate
;
8369 /* Convert string to prefix structure. */
8370 ret
= str2prefix(prefix_str
, &p
);
8372 vty_out(vty
, "Malformed prefix\n");
8373 return CMD_WARNING_CONFIG_FAILED
;
8377 /* Old configuration check. */
8378 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8381 "%% There is no aggregate-address configuration.\n");
8382 return CMD_WARNING_CONFIG_FAILED
;
8385 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8386 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8387 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8388 NULL
, NULL
, 0, aggregate
);
8390 /* Unlock aggregate address configuration. */
8391 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8393 bgp_free_aggregate_info(aggregate
);
8394 bgp_dest_unlock_node(dest
);
8395 bgp_dest_unlock_node(dest
);
8400 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8401 safi_t safi
, const char *rmap
,
8402 uint8_t summary_only
, uint8_t as_set
,
8403 uint8_t origin
, bool match_med
,
8404 const char *suppress_map
)
8406 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8409 struct bgp_dest
*dest
;
8410 struct bgp_aggregate
*aggregate
;
8411 uint8_t as_set_new
= as_set
;
8413 if (suppress_map
&& summary_only
) {
8415 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8416 return CMD_WARNING_CONFIG_FAILED
;
8419 /* Convert string to prefix structure. */
8420 ret
= str2prefix(prefix_str
, &p
);
8422 vty_out(vty
, "Malformed prefix\n");
8423 return CMD_WARNING_CONFIG_FAILED
;
8427 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8428 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8429 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8431 return CMD_WARNING_CONFIG_FAILED
;
8434 /* Old configuration check. */
8435 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8436 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8439 vty_out(vty
, "There is already same aggregate network.\n");
8440 /* try to remove the old entry */
8441 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8443 vty_out(vty
, "Error deleting aggregate.\n");
8444 bgp_dest_unlock_node(dest
);
8445 return CMD_WARNING_CONFIG_FAILED
;
8449 /* Make aggregate address structure. */
8450 aggregate
= bgp_aggregate_new();
8451 aggregate
->summary_only
= summary_only
;
8452 aggregate
->match_med
= match_med
;
8454 /* Network operators MUST NOT locally generate any new
8455 * announcements containing AS_SET or AS_CONFED_SET. If they have
8456 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8457 * SHOULD withdraw those routes and re-announce routes for the
8458 * aggregate or component prefixes (i.e., the more-specific routes
8459 * subsumed by the previously aggregated route) without AS_SET
8460 * or AS_CONFED_SET in the updates.
8462 if (bgp
->reject_as_sets
) {
8463 if (as_set
== AGGREGATE_AS_SET
) {
8464 as_set_new
= AGGREGATE_AS_UNSET
;
8466 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8469 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8473 aggregate
->as_set
= as_set_new
;
8474 aggregate
->safi
= safi
;
8475 /* Override ORIGIN attribute if defined.
8476 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8477 * to IGP which is not what rfc4271 says.
8478 * This enables the same behavior, optionally.
8480 aggregate
->origin
= origin
;
8483 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8484 route_map_counter_decrement(aggregate
->rmap
.map
);
8485 aggregate
->rmap
.name
=
8486 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8487 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8488 route_map_counter_increment(aggregate
->rmap
.map
);
8492 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8493 route_map_counter_decrement(aggregate
->suppress_map
);
8495 aggregate
->suppress_map_name
=
8496 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8497 aggregate
->suppress_map
=
8498 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8499 route_map_counter_increment(aggregate
->suppress_map
);
8502 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8504 /* Aggregate address insert into BGP routing table. */
8505 if (!bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
)) {
8506 bgp_aggregate_free(aggregate
);
8507 bgp_dest_unlock_node(dest
);
8513 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8514 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8516 "|summary-only$summary_only"
8517 "|route-map RMAP_NAME$rmap_name"
8518 "|origin <egp|igp|incomplete>$origin_s"
8519 "|matching-MED-only$match_med"
8520 "|suppress-map RMAP_NAME$suppress_map"
8523 "Configure BGP aggregate entries\n"
8524 "Aggregate prefix\n"
8525 "Aggregate address\n"
8527 "Generate AS set path information\n"
8528 "Filter more specific routes from updates\n"
8529 "Apply route map to aggregate network\n"
8534 "Unknown heritage\n"
8535 "Only aggregate routes with matching MED\n"
8536 "Suppress the selected more specific routes\n"
8537 "Route map with the route selectors\n")
8539 const char *prefix_s
= NULL
;
8540 safi_t safi
= bgp_node_safi(vty
);
8541 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8542 int as_set
= AGGREGATE_AS_UNSET
;
8543 char prefix_buf
[PREFIX2STR_BUFFER
];
8546 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8549 vty_out(vty
, "%% Inconsistent address and mask\n");
8550 return CMD_WARNING_CONFIG_FAILED
;
8552 prefix_s
= prefix_buf
;
8554 prefix_s
= prefix_str
;
8557 if (strcmp(origin_s
, "egp") == 0)
8558 origin
= BGP_ORIGIN_EGP
;
8559 else if (strcmp(origin_s
, "igp") == 0)
8560 origin
= BGP_ORIGIN_IGP
;
8561 else if (strcmp(origin_s
, "incomplete") == 0)
8562 origin
= BGP_ORIGIN_INCOMPLETE
;
8566 as_set
= AGGREGATE_AS_SET
;
8568 /* Handle configuration removal, otherwise installation. */
8570 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8572 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8573 summary_only
!= NULL
, as_set
, origin
,
8574 match_med
!= NULL
, suppress_map
);
8577 void bgp_free_aggregate_info(struct bgp_aggregate
*aggregate
)
8579 if (aggregate
->community
)
8580 community_free(&aggregate
->community
);
8582 hash_clean_and_free(&aggregate
->community_hash
,
8583 bgp_aggr_community_remove
);
8585 if (aggregate
->ecommunity
)
8586 ecommunity_free(&aggregate
->ecommunity
);
8588 hash_clean_and_free(&aggregate
->ecommunity_hash
,
8589 bgp_aggr_ecommunity_remove
);
8591 if (aggregate
->lcommunity
)
8592 lcommunity_free(&aggregate
->lcommunity
);
8594 hash_clean_and_free(&aggregate
->lcommunity_hash
,
8595 bgp_aggr_lcommunity_remove
);
8597 if (aggregate
->aspath
)
8598 aspath_free(aggregate
->aspath
);
8600 hash_clean_and_free(&aggregate
->aspath_hash
, bgp_aggr_aspath_remove
);
8602 bgp_aggregate_free(aggregate
);
8605 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8606 "[no] aggregate-address X:X::X:X/M$prefix [{"
8608 "|summary-only$summary_only"
8609 "|route-map RMAP_NAME$rmap_name"
8610 "|origin <egp|igp|incomplete>$origin_s"
8611 "|matching-MED-only$match_med"
8612 "|suppress-map RMAP_NAME$suppress_map"
8615 "Configure BGP aggregate entries\n"
8616 "Aggregate prefix\n"
8617 "Generate AS set path information\n"
8618 "Filter more specific routes from updates\n"
8619 "Apply route map to aggregate network\n"
8624 "Unknown heritage\n"
8625 "Only aggregate routes with matching MED\n"
8626 "Suppress the selected more specific routes\n"
8627 "Route map with the route selectors\n")
8629 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8630 int as_set
= AGGREGATE_AS_UNSET
;
8633 if (strcmp(origin_s
, "egp") == 0)
8634 origin
= BGP_ORIGIN_EGP
;
8635 else if (strcmp(origin_s
, "igp") == 0)
8636 origin
= BGP_ORIGIN_IGP
;
8637 else if (strcmp(origin_s
, "incomplete") == 0)
8638 origin
= BGP_ORIGIN_INCOMPLETE
;
8642 as_set
= AGGREGATE_AS_SET
;
8644 /* Handle configuration removal, otherwise installation. */
8646 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8649 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8650 rmap_name
, summary_only
!= NULL
, as_set
,
8651 origin
, match_med
!= NULL
, suppress_map
);
8654 /* Redistribute route treatment. */
8655 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8656 const union g_addr
*nexthop
, ifindex_t ifindex
,
8657 enum nexthop_types_t nhtype
, uint8_t distance
,
8658 enum blackhole_type bhtype
, uint32_t metric
,
8659 uint8_t type
, unsigned short instance
,
8662 struct bgp_path_info
*new;
8663 struct bgp_path_info
*bpi
;
8664 struct bgp_path_info rmap_path
;
8665 struct bgp_dest
*bn
;
8667 struct attr
*new_attr
;
8669 route_map_result_t ret
;
8670 struct bgp_redist
*red
;
8672 /* Make default attribute. */
8673 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8675 * This must not be NULL to satisfy Coverity SA
8677 assert(attr
.aspath
);
8680 case NEXTHOP_TYPE_IFINDEX
:
8681 switch (p
->family
) {
8683 attr
.nexthop
.s_addr
= INADDR_ANY
;
8684 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8687 memset(&attr
.mp_nexthop_global
, 0,
8688 sizeof(attr
.mp_nexthop_global
));
8689 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8693 case NEXTHOP_TYPE_IPV4
:
8694 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8695 attr
.nexthop
= nexthop
->ipv4
;
8696 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8698 case NEXTHOP_TYPE_IPV6
:
8699 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8700 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8701 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8703 case NEXTHOP_TYPE_BLACKHOLE
:
8704 switch (p
->family
) {
8706 attr
.nexthop
.s_addr
= INADDR_ANY
;
8707 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8710 memset(&attr
.mp_nexthop_global
, 0,
8711 sizeof(attr
.mp_nexthop_global
));
8712 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8715 attr
.bh_type
= bhtype
;
8718 attr
.nh_type
= nhtype
;
8719 attr
.nh_ifindex
= ifindex
;
8722 attr
.distance
= distance
;
8723 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8727 bgp_attr_set_aigp_metric(&attr
, metric
);
8729 afi
= family2afi(p
->family
);
8731 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8733 struct attr attr_new
;
8735 /* Copy attribute for modification. */
8738 if (red
->redist_metric_flag
) {
8739 attr_new
.med
= red
->redist_metric
;
8740 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8743 /* Apply route-map. */
8744 if (red
->rmap
.name
) {
8745 memset(&rmap_path
, 0, sizeof(rmap_path
));
8746 rmap_path
.peer
= bgp
->peer_self
;
8747 rmap_path
.attr
= &attr_new
;
8749 SET_FLAG(bgp
->peer_self
->rmap_type
,
8750 PEER_RMAP_TYPE_REDISTRIBUTE
);
8752 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8754 bgp
->peer_self
->rmap_type
= 0;
8756 if (ret
== RMAP_DENYMATCH
) {
8757 /* Free uninterned attribute. */
8758 bgp_attr_flush(&attr_new
);
8760 /* Unintern original. */
8761 aspath_unintern(&attr
.aspath
);
8762 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8767 if (bgp_in_graceful_shutdown(bgp
))
8768 bgp_attr_add_gshut_community(&attr_new
);
8770 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8771 SAFI_UNICAST
, p
, NULL
);
8773 new_attr
= bgp_attr_intern(&attr_new
);
8775 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8776 if (bpi
->peer
== bgp
->peer_self
8777 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8781 /* Ensure the (source route) type is updated. */
8783 if (attrhash_cmp(bpi
->attr
, new_attr
)
8784 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8785 bgp_attr_unintern(&new_attr
);
8786 aspath_unintern(&attr
.aspath
);
8787 bgp_dest_unlock_node(bn
);
8790 /* The attribute is changed. */
8791 bgp_path_info_set_flag(bn
, bpi
,
8792 BGP_PATH_ATTR_CHANGED
);
8794 /* Rewrite BGP route information. */
8795 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8796 bgp_path_info_restore(bn
, bpi
);
8798 bgp_aggregate_decrement(
8799 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8800 bgp_attr_unintern(&bpi
->attr
);
8801 bpi
->attr
= new_attr
;
8802 bpi
->uptime
= monotime(NULL
);
8804 /* Process change. */
8805 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8807 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8808 bgp_dest_unlock_node(bn
);
8809 aspath_unintern(&attr
.aspath
);
8811 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8813 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8815 vpn_leak_from_vrf_update(
8816 bgp_get_default(), bgp
, bpi
);
8822 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8823 bgp
->peer_self
, new_attr
, bn
);
8824 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8826 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8827 bgp_path_info_add(bn
, new);
8828 bgp_dest_unlock_node(bn
);
8829 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8830 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8832 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8833 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8835 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8839 /* Unintern original. */
8840 aspath_unintern(&attr
.aspath
);
8843 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8844 unsigned short instance
)
8847 struct bgp_dest
*dest
;
8848 struct bgp_path_info
*pi
;
8849 struct bgp_redist
*red
;
8851 afi
= family2afi(p
->family
);
8853 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8855 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8856 SAFI_UNICAST
, p
, NULL
);
8858 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8859 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8863 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8864 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8866 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8869 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8870 bgp_path_info_delete(dest
, pi
);
8871 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8873 bgp_dest_unlock_node(dest
);
8877 /* Withdraw specified route type's route. */
8878 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8879 unsigned short instance
)
8881 struct bgp_dest
*dest
;
8882 struct bgp_path_info
*pi
;
8883 struct bgp_table
*table
;
8885 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8887 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8888 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8889 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8890 && pi
->instance
== instance
)
8894 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8895 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8897 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8900 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8901 pi
, afi
, SAFI_UNICAST
);
8902 bgp_path_info_delete(dest
, pi
);
8903 if (!CHECK_FLAG(bgp
->flags
,
8904 BGP_FLAG_DELETE_IN_PROGRESS
))
8905 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8907 bgp_path_info_reap(dest
, pi
);
8912 /* Static function to display route. */
8913 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8914 struct vty
*vty
, json_object
*json
, bool wide
)
8917 char buf
[INET6_ADDRSTRLEN
];
8919 if (p
->family
== AF_INET
) {
8921 len
= vty_out(vty
, "%pFX", p
);
8923 json_object_string_add(json
, "prefix",
8924 inet_ntop(p
->family
,
8927 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8928 json_object_string_addf(json
, "network", "%pFX", p
);
8929 json_object_int_add(json
, "version", dest
->version
);
8931 } else if (p
->family
== AF_ETHERNET
) {
8932 len
= vty_out(vty
, "%pFX", p
);
8933 } else if (p
->family
== AF_EVPN
) {
8935 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8937 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8938 } else if (p
->family
== AF_FLOWSPEC
) {
8939 route_vty_out_flowspec(vty
, p
, NULL
,
8941 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8942 NLRI_STRING_FORMAT_MIN
, json
);
8945 len
= vty_out(vty
, "%pFX", p
);
8947 json_object_string_add(json
, "prefix",
8948 inet_ntop(p
->family
,
8951 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8952 json_object_string_addf(json
, "network", "%pFX", p
);
8953 json_object_int_add(json
, "version", dest
->version
);
8958 len
= wide
? (45 - len
) : (17 - len
);
8960 vty_out(vty
, "\n%*s", 20, " ");
8962 vty_out(vty
, "%*s", len
, " ");
8966 enum bgp_display_type
{
8970 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8973 case bgp_path_selection_none
:
8974 return "Nothing to Select";
8975 case bgp_path_selection_first
:
8976 return "First path received";
8977 case bgp_path_selection_evpn_sticky_mac
:
8978 return "EVPN Sticky Mac";
8979 case bgp_path_selection_evpn_seq
:
8980 return "EVPN sequence number";
8981 case bgp_path_selection_evpn_lower_ip
:
8982 return "EVPN lower IP";
8983 case bgp_path_selection_evpn_local_path
:
8984 return "EVPN local ES path";
8985 case bgp_path_selection_evpn_non_proxy
:
8986 return "EVPN non proxy";
8987 case bgp_path_selection_weight
:
8989 case bgp_path_selection_local_pref
:
8990 return "Local Pref";
8991 case bgp_path_selection_accept_own
:
8992 return "Accept Own";
8993 case bgp_path_selection_local_route
:
8994 return "Local Route";
8995 case bgp_path_selection_aigp
:
8997 case bgp_path_selection_confed_as_path
:
8998 return "Confederation based AS Path";
8999 case bgp_path_selection_as_path
:
9001 case bgp_path_selection_origin
:
9003 case bgp_path_selection_med
:
9005 case bgp_path_selection_peer
:
9007 case bgp_path_selection_confed
:
9008 return "Confed Peer Type";
9009 case bgp_path_selection_igp_metric
:
9010 return "IGP Metric";
9011 case bgp_path_selection_older
:
9012 return "Older Path";
9013 case bgp_path_selection_router_id
:
9015 case bgp_path_selection_cluster_length
:
9016 return "Cluster length";
9017 case bgp_path_selection_stale
:
9018 return "Path Staleness";
9019 case bgp_path_selection_local_configured
:
9020 return "Locally configured route";
9021 case bgp_path_selection_neighbor_ip
:
9022 return "Neighbor IP";
9023 case bgp_path_selection_default
:
9024 return "Nothing left to compare";
9026 return "Invalid (internal error)";
9029 /* Print the short form route status for a bgp_path_info */
9030 static void route_vty_short_status_out(struct vty
*vty
,
9031 struct bgp_path_info
*path
,
9032 const struct prefix
*p
,
9033 json_object
*json_path
)
9035 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
9039 /* Route status display. */
9040 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9041 json_object_boolean_true_add(json_path
, "removed");
9043 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9044 json_object_boolean_true_add(json_path
, "stale");
9046 if (path
->extra
&& bgp_path_suppressed(path
))
9047 json_object_boolean_true_add(json_path
, "suppressed");
9049 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9050 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9051 json_object_boolean_true_add(json_path
, "valid");
9054 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9055 json_object_boolean_true_add(json_path
, "history");
9057 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9058 json_object_boolean_true_add(json_path
, "damped");
9060 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9061 json_object_boolean_true_add(json_path
, "bestpath");
9062 json_object_string_add(json_path
, "selectionReason",
9063 bgp_path_selection_reason2str(
9064 path
->net
->reason
));
9067 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9068 json_object_boolean_true_add(json_path
, "multipath");
9070 /* Internal route. */
9071 if ((path
->peer
->as
)
9072 && (path
->peer
->as
== path
->peer
->local_as
))
9073 json_object_string_add(json_path
, "pathFrom",
9076 json_object_string_add(json_path
, "pathFrom",
9082 /* RPKI validation state */
9084 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9086 if (rpki_state
== RPKI_VALID
)
9088 else if (rpki_state
== RPKI_INVALID
)
9090 else if (rpki_state
== RPKI_NOTFOUND
)
9095 /* Route status display. */
9096 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9098 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9100 else if (bgp_path_suppressed(path
))
9102 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9103 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9109 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9111 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9113 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9115 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9120 /* Internal route. */
9121 if (path
->peer
&& (path
->peer
->as
)
9122 && (path
->peer
->as
== path
->peer
->local_as
))
9128 static char *bgp_nexthop_hostname(struct peer
*peer
,
9129 struct bgp_nexthop_cache
*bnc
)
9132 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9133 return peer
->hostname
;
9137 /* called from terminal list command */
9138 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9139 struct bgp_path_info
*path
, int display
, safi_t safi
,
9140 json_object
*json_paths
, bool wide
)
9143 struct attr
*attr
= path
->attr
;
9144 json_object
*json_path
= NULL
;
9145 json_object
*json_nexthops
= NULL
;
9146 json_object
*json_nexthop_global
= NULL
;
9147 json_object
*json_nexthop_ll
= NULL
;
9148 json_object
*json_ext_community
= NULL
;
9149 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9151 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9152 bool nexthop_othervrf
= false;
9153 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9154 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9155 char *nexthop_hostname
=
9156 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9157 char esi_buf
[ESI_STR_LEN
];
9160 json_path
= json_object_new_object();
9162 /* short status lead text */
9163 route_vty_short_status_out(vty
, path
, p
, json_path
);
9166 /* print prefix and mask */
9168 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9170 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9172 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9176 * If vrf id of nexthop is different from that of prefix,
9177 * set up printable string to append
9179 if (path
->extra
&& path
->extra
->bgp_orig
) {
9180 const char *self
= "";
9185 nexthop_othervrf
= true;
9186 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9188 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9189 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9190 "@%s%s", VRFID_NONE_STR
, self
);
9192 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9193 path
->extra
->bgp_orig
->vrf_id
, self
);
9195 if (path
->extra
->bgp_orig
->inst_type
9196 != BGP_INSTANCE_TYPE_DEFAULT
)
9198 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9200 const char *self
= "";
9205 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9209 * For ENCAP and EVPN routes, nexthop address family is not
9210 * neccessarily the same as the prefix address family.
9211 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9212 * EVPN routes are also exchanged with a MP nexthop. Currently,
9214 * is only IPv4, the value will be present in either
9216 * attr->mp_nexthop_global_in
9218 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9220 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9224 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9225 &attr
->mp_nexthop_global_in
);
9228 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9229 &attr
->mp_nexthop_global
);
9232 snprintf(nexthop
, sizeof(nexthop
), "?");
9237 json_nexthop_global
= json_object_new_object();
9239 json_object_string_add(json_nexthop_global
, "ip",
9242 if (path
->peer
->hostname
)
9243 json_object_string_add(json_nexthop_global
,
9245 path
->peer
->hostname
);
9247 json_object_string_add(json_nexthop_global
, "afi",
9248 (af
== AF_INET
) ? "ipv4"
9250 json_object_boolean_true_add(json_nexthop_global
,
9253 if (nexthop_hostname
)
9254 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9255 nexthop_hostname
, vrf_id_str
);
9257 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9259 len
= wide
? (41 - len
) : (16 - len
);
9261 vty_out(vty
, "\n%*s", 36, " ");
9263 vty_out(vty
, "%*s", len
, " ");
9265 } else if (safi
== SAFI_EVPN
) {
9267 json_nexthop_global
= json_object_new_object();
9269 json_object_string_addf(json_nexthop_global
, "ip",
9271 &attr
->mp_nexthop_global_in
);
9273 if (path
->peer
->hostname
)
9274 json_object_string_add(json_nexthop_global
,
9276 path
->peer
->hostname
);
9278 json_object_string_add(json_nexthop_global
, "afi",
9280 json_object_boolean_true_add(json_nexthop_global
,
9283 if (nexthop_hostname
)
9284 len
= vty_out(vty
, "%pI4(%s)%s",
9285 &attr
->mp_nexthop_global_in
,
9286 nexthop_hostname
, vrf_id_str
);
9288 len
= vty_out(vty
, "%pI4%s",
9289 &attr
->mp_nexthop_global_in
,
9292 len
= wide
? (41 - len
) : (16 - len
);
9294 vty_out(vty
, "\n%*s", 36, " ");
9296 vty_out(vty
, "%*s", len
, " ");
9298 } else if (safi
== SAFI_FLOWSPEC
) {
9299 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9301 json_nexthop_global
= json_object_new_object();
9303 json_object_string_add(json_nexthop_global
,
9305 json_object_string_addf(json_nexthop_global
,
9309 if (path
->peer
->hostname
)
9310 json_object_string_add(
9311 json_nexthop_global
, "hostname",
9312 path
->peer
->hostname
);
9314 json_object_boolean_true_add(
9315 json_nexthop_global
,
9318 if (nexthop_hostname
)
9319 len
= vty_out(vty
, "%pI4(%s)%s",
9324 len
= vty_out(vty
, "%pI4%s",
9328 len
= wide
? (41 - len
) : (16 - len
);
9330 vty_out(vty
, "\n%*s", 36, " ");
9332 vty_out(vty
, "%*s", len
, " ");
9335 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9337 json_nexthop_global
= json_object_new_object();
9339 json_object_string_addf(json_nexthop_global
, "ip",
9340 "%pI4", &attr
->nexthop
);
9342 if (path
->peer
->hostname
)
9343 json_object_string_add(json_nexthop_global
,
9345 path
->peer
->hostname
);
9347 json_object_string_add(json_nexthop_global
, "afi",
9349 json_object_boolean_true_add(json_nexthop_global
,
9352 if (nexthop_hostname
)
9353 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9354 nexthop_hostname
, vrf_id_str
);
9356 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9359 len
= wide
? (41 - len
) : (16 - len
);
9361 vty_out(vty
, "\n%*s", 36, " ");
9363 vty_out(vty
, "%*s", len
, " ");
9368 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9370 json_nexthop_global
= json_object_new_object();
9371 json_object_string_addf(json_nexthop_global
, "ip",
9373 &attr
->mp_nexthop_global
);
9375 if (path
->peer
->hostname
)
9376 json_object_string_add(json_nexthop_global
,
9378 path
->peer
->hostname
);
9380 json_object_string_add(json_nexthop_global
, "afi",
9382 json_object_string_add(json_nexthop_global
, "scope",
9385 /* We display both LL & GL if both have been
9387 if ((attr
->mp_nexthop_len
9388 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9389 || (path
->peer
->conf_if
)) {
9390 json_nexthop_ll
= json_object_new_object();
9391 json_object_string_addf(
9392 json_nexthop_ll
, "ip", "%pI6",
9393 &attr
->mp_nexthop_local
);
9395 if (path
->peer
->hostname
)
9396 json_object_string_add(
9397 json_nexthop_ll
, "hostname",
9398 path
->peer
->hostname
);
9400 json_object_string_add(json_nexthop_ll
, "afi",
9402 json_object_string_add(json_nexthop_ll
, "scope",
9405 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9406 &attr
->mp_nexthop_local
)
9408 && !attr
->mp_nexthop_prefer_global
)
9409 json_object_boolean_true_add(
9410 json_nexthop_ll
, "used");
9412 json_object_boolean_true_add(
9413 json_nexthop_global
, "used");
9415 json_object_boolean_true_add(
9416 json_nexthop_global
, "used");
9418 /* Display LL if LL/Global both in table unless
9419 * prefer-global is set */
9420 if (((attr
->mp_nexthop_len
9421 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9422 && !attr
->mp_nexthop_prefer_global
)
9423 || (path
->peer
->conf_if
)) {
9424 if (path
->peer
->conf_if
) {
9425 len
= vty_out(vty
, "%s",
9426 path
->peer
->conf_if
);
9427 /* len of IPv6 addr + max len of def
9429 len
= wide
? (41 - len
) : (16 - len
);
9432 vty_out(vty
, "\n%*s", 36, " ");
9434 vty_out(vty
, "%*s", len
, " ");
9436 if (nexthop_hostname
)
9439 &attr
->mp_nexthop_local
,
9445 &attr
->mp_nexthop_local
,
9448 len
= wide
? (41 - len
) : (16 - len
);
9451 vty_out(vty
, "\n%*s", 36, " ");
9453 vty_out(vty
, "%*s", len
, " ");
9456 if (nexthop_hostname
)
9457 len
= vty_out(vty
, "%pI6(%s)%s",
9458 &attr
->mp_nexthop_global
,
9462 len
= vty_out(vty
, "%pI6%s",
9463 &attr
->mp_nexthop_global
,
9466 len
= wide
? (41 - len
) : (16 - len
);
9469 vty_out(vty
, "\n%*s", 36, " ");
9471 vty_out(vty
, "%*s", len
, " ");
9477 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9479 json_object_int_add(json_path
, "metric", attr
->med
);
9481 vty_out(vty
, "%7u", attr
->med
);
9483 vty_out(vty
, "%10u", attr
->med
);
9484 else if (!json_paths
) {
9486 vty_out(vty
, "%*s", 7, " ");
9488 vty_out(vty
, "%*s", 10, " ");
9492 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9494 json_object_int_add(json_path
, "locPrf",
9497 vty_out(vty
, "%7u", attr
->local_pref
);
9498 else if (!json_paths
)
9502 json_object_int_add(json_path
, "weight", attr
->weight
);
9504 vty_out(vty
, "%7u ", attr
->weight
);
9507 json_object_string_addf(json_path
, "peerId", "%pSU",
9513 json_object_string_add(json_path
, "path",
9516 aspath_print_vty(vty
, attr
->aspath
);
9521 json_object_string_add(json_path
, "origin",
9522 bgp_origin_long_str
[attr
->origin
]);
9524 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9527 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9528 json_object_string_add(json_path
, "esi",
9529 esi_to_str(&attr
->esi
,
9530 esi_buf
, sizeof(esi_buf
)));
9532 if (safi
== SAFI_EVPN
&&
9533 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9534 json_ext_community
= json_object_new_object();
9535 json_object_string_add(
9536 json_ext_community
, "string",
9537 bgp_attr_get_ecommunity(attr
)->str
);
9538 json_object_object_add(json_path
,
9539 "extendedCommunity",
9540 json_ext_community
);
9544 json_object_boolean_true_add(json_path
,
9545 "announceNexthopSelf");
9546 if (nexthop_othervrf
) {
9547 json_object_string_add(json_path
, "nhVrfName",
9550 json_object_int_add(json_path
, "nhVrfId",
9551 ((nexthop_vrfid
== VRF_UNKNOWN
)
9553 : (int)nexthop_vrfid
));
9558 if (json_nexthop_global
|| json_nexthop_ll
) {
9559 json_nexthops
= json_object_new_array();
9561 if (json_nexthop_global
)
9562 json_object_array_add(json_nexthops
,
9563 json_nexthop_global
);
9565 if (json_nexthop_ll
)
9566 json_object_array_add(json_nexthops
,
9569 json_object_object_add(json_path
, "nexthops",
9573 json_object_array_add(json_paths
, json_path
);
9577 if (safi
== SAFI_EVPN
) {
9578 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9579 /* XXX - add these params to the json out */
9580 vty_out(vty
, "%*s", 20, " ");
9581 vty_out(vty
, "ESI:%s",
9582 esi_to_str(&attr
->esi
, esi_buf
,
9588 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9589 vty_out(vty
, "%*s", 20, " ");
9590 vty_out(vty
, "%s\n",
9591 bgp_attr_get_ecommunity(attr
)->str
);
9595 #ifdef ENABLE_BGP_VNC
9596 /* prints an additional line, indented, with VNC info, if
9598 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9599 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9604 /* called from terminal list command */
9605 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9606 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9607 bool use_json
, json_object
*json_ar
, bool wide
)
9609 json_object
*json_status
= NULL
;
9610 json_object
*json_net
= NULL
;
9614 /* Route status display. */
9616 json_status
= json_object_new_object();
9617 json_net
= json_object_new_object();
9624 /* print prefix and mask */
9626 if (safi
== SAFI_EVPN
)
9627 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9628 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9629 json_object_string_add(
9630 json_net
, "addrPrefix",
9631 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9633 json_object_int_add(json_net
, "prefixLen",
9635 json_object_string_addf(json_net
, "network", "%pFX", p
);
9638 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9640 /* Print attribute */
9643 if (p
->family
== AF_INET
&&
9644 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9645 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9646 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9647 json_object_string_addf(
9648 json_net
, "nextHop", "%pI4",
9649 &attr
->mp_nexthop_global_in
);
9651 json_object_string_addf(
9652 json_net
, "nextHop", "%pI4",
9654 } else if (p
->family
== AF_INET6
||
9655 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9656 json_object_string_addf(
9657 json_net
, "nextHopGlobal", "%pI6",
9658 &attr
->mp_nexthop_global
);
9659 } else if (p
->family
== AF_EVPN
&&
9660 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9661 json_object_string_addf(
9662 json_net
, "nextHop", "%pI4",
9663 &attr
->mp_nexthop_global_in
);
9667 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9668 json_object_int_add(json_net
, "metric",
9671 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9672 json_object_int_add(json_net
, "locPrf",
9675 json_object_int_add(json_net
, "weight", attr
->weight
);
9679 json_object_string_add(json_net
, "path",
9683 #if CONFDATE > 20231208
9684 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9686 json_object_string_add(json_net
, "bgpOriginCode",
9687 bgp_origin_str
[attr
->origin
]);
9688 json_object_string_add(
9690 bgp_origin_long_str
[attr
->origin
]);
9692 if (p
->family
== AF_INET
&&
9693 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9694 safi
== SAFI_EVPN
||
9695 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9696 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9697 || safi
== SAFI_EVPN
)
9698 vty_out(vty
, "%-16pI4",
9699 &attr
->mp_nexthop_global_in
);
9701 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9703 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9704 } else if (p
->family
== AF_INET6
||
9705 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9706 len
= vty_out(vty
, "%pI6",
9707 &attr
->mp_nexthop_global
);
9708 len
= wide
? (41 - len
) : (16 - len
);
9710 vty_out(vty
, "\n%*s", 36, " ");
9712 vty_out(vty
, "%*s", len
, " ");
9715 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9717 vty_out(vty
, "%7u", attr
->med
);
9719 vty_out(vty
, "%10u", attr
->med
);
9725 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9726 vty_out(vty
, "%7u", attr
->local_pref
);
9730 vty_out(vty
, "%7u ", attr
->weight
);
9734 aspath_print_vty(vty
, attr
->aspath
);
9737 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9741 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9743 #if CONFDATE > 20231208
9744 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9746 json_object_boolean_true_add(json_status
, "*");
9747 json_object_boolean_true_add(json_status
, ">");
9748 json_object_boolean_true_add(json_net
, "valid");
9749 json_object_boolean_true_add(json_net
, "best");
9751 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9752 json_object_boolean_true_add(json_status
, "=");
9753 json_object_boolean_true_add(json_net
, "multipath");
9755 json_object_object_add(json_net
, "appliedStatusSymbols",
9757 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9762 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9763 struct bgp_path_info
*path
, int display
, safi_t safi
,
9766 json_object
*json_out
= NULL
;
9768 mpls_label_t label
= MPLS_INVALID_LABEL
;
9774 json_out
= json_object_new_object();
9776 /* short status lead text */
9777 route_vty_short_status_out(vty
, path
, p
, json_out
);
9779 /* print prefix and mask */
9782 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9784 vty_out(vty
, "%*s", 17, " ");
9787 /* Print attribute */
9789 if (((p
->family
== AF_INET
) &&
9790 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9791 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9792 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9793 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9794 || safi
== SAFI_EVPN
) {
9796 json_object_string_addf(
9797 json_out
, "mpNexthopGlobalIn", "%pI4",
9798 &attr
->mp_nexthop_global_in
);
9800 vty_out(vty
, "%-16pI4",
9801 &attr
->mp_nexthop_global_in
);
9804 json_object_string_addf(json_out
, "nexthop",
9805 "%pI4", &attr
->nexthop
);
9807 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9809 } else if (((p
->family
== AF_INET6
) &&
9810 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9811 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9812 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9815 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9817 json_object_string_addf(
9818 json_out
, "mpNexthopGlobalIn", "%pI6",
9819 &attr
->mp_nexthop_global
);
9823 &attr
->mp_nexthop_global
,
9824 buf_a
, sizeof(buf_a
)));
9825 } else if (attr
->mp_nexthop_len
9826 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9827 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9828 &attr
->mp_nexthop_global
,
9829 &attr
->mp_nexthop_local
);
9831 json_object_string_add(json_out
,
9832 "mpNexthopGlobalLocal",
9835 vty_out(vty
, "%s", buf_a
);
9839 label
= decode_label(&path
->extra
->label
[0]);
9841 if (bgp_is_valid_label(&label
)) {
9843 json_object_int_add(json_out
, "notag", label
);
9844 json_object_array_add(json
, json_out
);
9846 vty_out(vty
, "notag/%d", label
);
9853 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9854 struct bgp_path_info
*path
, int display
,
9855 json_object
*json_paths
)
9858 json_object
*json_path
= NULL
;
9859 json_object
*json_nexthop
= NULL
;
9860 json_object
*json_overlay
= NULL
;
9866 json_path
= json_object_new_object();
9867 json_overlay
= json_object_new_object();
9868 json_nexthop
= json_object_new_object();
9871 /* short status lead text */
9872 route_vty_short_status_out(vty
, path
, p
, json_path
);
9874 /* print prefix and mask */
9876 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9878 vty_out(vty
, "%*s", 17, " ");
9880 /* Print attribute */
9882 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9887 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9889 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9890 &attr
->mp_nexthop_global_in
);
9892 json_object_string_add(json_nexthop
, "afi", "ipv4");
9894 json_object_object_add(json_path
, "nexthop",
9900 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9901 &attr
->mp_nexthop_local
);
9903 json_object_string_addf(json_nexthop
, "ipv6Global",
9905 &attr
->mp_nexthop_global
);
9907 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9909 &attr
->mp_nexthop_local
);
9911 json_object_string_add(json_nexthop
, "afi", "ipv6");
9913 json_object_object_add(json_path
, "nexthop",
9921 json_object_string_add(json_nexthop
, "error",
9922 "Unsupported address-family");
9926 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9929 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9931 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9933 if (bgp_attr_get_ecommunity(attr
)) {
9935 struct ecommunity_val
*routermac
= ecommunity_lookup(
9936 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9937 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9940 mac
= ecom_mac2str((char *)routermac
->val
);
9943 vty_out(vty
, "/%s", mac
);
9945 json_object_string_add(json_overlay
, "rmac",
9948 XFREE(MTYPE_TMP
, mac
);
9955 json_object_object_add(json_path
, "overlay", json_overlay
);
9957 json_object_array_add(json_paths
, json_path
);
9961 /* dampening route */
9962 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9963 struct bgp_path_info
*path
, int display
,
9964 afi_t afi
, safi_t safi
, bool use_json
,
9965 json_object
*json_paths
)
9967 struct attr
*attr
= path
->attr
;
9969 char timebuf
[BGP_UPTIME_LEN
];
9970 json_object
*json_path
= NULL
;
9973 json_path
= json_object_new_object();
9975 /* short status lead text */
9976 route_vty_short_status_out(vty
, path
, p
, json_path
);
9978 /* print prefix and mask */
9981 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9983 vty_out(vty
, "%*s", 17, " ");
9985 len
= vty_out(vty
, "%s", path
->peer
->host
);
9989 vty_out(vty
, "\n%*s", 34, " ");
9991 vty_out(vty
, "%*s", len
, " ");
9994 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9995 BGP_UPTIME_LEN
, afi
, safi
,
9999 aspath_print_vty(vty
, attr
->aspath
);
10001 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10003 vty_out(vty
, "\n");
10005 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
10006 safi
, use_json
, json_path
);
10009 json_object_string_add(json_path
, "asPath",
10010 attr
->aspath
->str
);
10012 json_object_string_add(json_path
, "origin",
10013 bgp_origin_str
[attr
->origin
]);
10014 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10016 json_object_array_add(json_paths
, json_path
);
10021 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
10022 struct bgp_path_info
*path
, int display
,
10023 afi_t afi
, safi_t safi
, bool use_json
,
10024 json_object
*json_paths
)
10026 struct attr
*attr
= path
->attr
;
10027 struct bgp_damp_info
*bdi
;
10028 char timebuf
[BGP_UPTIME_LEN
];
10030 json_object
*json_path
= NULL
;
10036 json_path
= json_object_new_object();
10038 bdi
= path
->extra
->damp_info
;
10040 /* short status lead text */
10041 route_vty_short_status_out(vty
, path
, p
, json_path
);
10045 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10047 vty_out(vty
, "%*s", 17, " ");
10049 len
= vty_out(vty
, "%s", path
->peer
->host
);
10052 vty_out(vty
, "\n%*s", 33, " ");
10054 vty_out(vty
, "%*s", len
, " ");
10056 len
= vty_out(vty
, "%d", bdi
->flap
);
10061 vty_out(vty
, "%*s", len
, " ");
10063 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10064 BGP_UPTIME_LEN
, 0, NULL
));
10066 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10067 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10068 vty_out(vty
, "%s ",
10069 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10070 BGP_UPTIME_LEN
, afi
,
10071 safi
, use_json
, NULL
));
10073 vty_out(vty
, "%*s ", 8, " ");
10076 aspath_print_vty(vty
, attr
->aspath
);
10078 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10080 vty_out(vty
, "\n");
10082 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10083 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10085 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10088 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10089 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10090 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10091 BGP_UPTIME_LEN
, afi
, safi
,
10092 use_json
, json_path
);
10095 json_object_string_add(json_path
, "asPath",
10096 attr
->aspath
->str
);
10098 json_object_string_add(json_path
, "origin",
10099 bgp_origin_str
[attr
->origin
]);
10101 json_object_array_add(json_paths
, json_path
);
10105 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10106 int *first
, const char *header
,
10107 json_object
*json_adv_to
)
10109 json_object
*json_peer
= NULL
;
10112 /* 'advertised-to' is a dictionary of peers we have advertised
10114 * prefix too. The key is the peer's IP or swpX, the value is
10116 * hostname if we know it and "" if not.
10118 json_peer
= json_object_new_object();
10120 if (peer
->hostname
)
10121 json_object_string_add(json_peer
, "hostname",
10125 json_object_object_add(json_adv_to
, peer
->conf_if
,
10128 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10132 vty_out(vty
, "%s", header
);
10137 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10139 vty_out(vty
, " %s(%s)", peer
->hostname
,
10142 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10146 vty_out(vty
, " %s", peer
->conf_if
);
10148 vty_out(vty
, " %pSU", &peer
->su
);
10153 static void route_vty_out_tx_ids(struct vty
*vty
,
10154 struct bgp_addpath_info_data
*d
)
10158 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10159 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10160 d
->addpath_tx_id
[i
],
10161 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10165 static void route_vty_out_detail_es_info(struct vty
*vty
,
10166 struct bgp_path_info
*pi
,
10168 json_object
*json_path
)
10170 char esi_buf
[ESI_STR_LEN
];
10171 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10172 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10173 ATTR_ES_PEER_ROUTER
);
10174 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10175 ATTR_ES_PEER_ACTIVE
);
10176 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10177 ATTR_ES_PEER_PROXY
);
10178 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10180 json_object
*json_es_info
= NULL
;
10182 json_object_string_add(
10185 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10186 json_es_info
= json_object_new_object();
10188 json_object_boolean_true_add(
10189 json_es_info
, "localEs");
10191 json_object_boolean_true_add(
10192 json_es_info
, "peerActive");
10194 json_object_boolean_true_add(
10195 json_es_info
, "peerProxy");
10197 json_object_boolean_true_add(
10198 json_es_info
, "peerRouter");
10199 if (attr
->mm_sync_seqnum
)
10200 json_object_int_add(
10201 json_es_info
, "peerSeq",
10202 attr
->mm_sync_seqnum
);
10203 json_object_object_add(
10204 json_path
, "es_info",
10208 if (bgp_evpn_attr_is_sync(attr
))
10210 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10212 es_local
? "local-es":"",
10213 peer_proxy
? "proxy " : "",
10214 peer_active
? "active ":"",
10215 peer_router
? "router ":"",
10216 attr
->mm_sync_seqnum
);
10218 vty_out(vty
, " ESI %s %s\n",
10220 es_local
? "local-es":"");
10224 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10225 const struct prefix
*p
, struct bgp_path_info
*path
,
10226 afi_t afi
, safi_t safi
,
10227 enum rpki_states rpki_curr_state
,
10228 json_object
*json_paths
)
10230 char buf
[INET6_ADDRSTRLEN
];
10232 struct attr
*attr
= path
->attr
;
10234 json_object
*json_bestpath
= NULL
;
10235 json_object
*json_cluster_list
= NULL
;
10236 json_object
*json_cluster_list_list
= NULL
;
10237 json_object
*json_ext_community
= NULL
;
10238 json_object
*json_last_update
= NULL
;
10239 json_object
*json_pmsi
= NULL
;
10240 json_object
*json_nexthop_global
= NULL
;
10241 json_object
*json_nexthop_ll
= NULL
;
10242 json_object
*json_nexthops
= NULL
;
10243 json_object
*json_path
= NULL
;
10244 json_object
*json_peer
= NULL
;
10245 json_object
*json_string
= NULL
;
10246 json_object
*json_adv_to
= NULL
;
10248 struct listnode
*node
, *nnode
;
10250 bool addpath_capable
;
10252 unsigned int first_as
;
10253 bool nexthop_self
=
10254 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10256 char *nexthop_hostname
=
10257 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10261 mpls_label_t label
= MPLS_INVALID_LABEL
;
10263 struct bgp_path_info
*bpi_ultimate
=
10264 bgp_get_imported_bpi_ultimate(path
);
10267 json_path
= json_object_new_object();
10268 json_peer
= json_object_new_object();
10269 json_nexthop_global
= json_object_new_object();
10272 if (safi
== SAFI_EVPN
) {
10274 vty_out(vty
, " Route %pFX", p
);
10278 if (path
->extra
&& path
->extra
->num_labels
) {
10279 bgp_evpn_label2str(path
->extra
->label
,
10280 path
->extra
->num_labels
, tag_buf
,
10283 if (safi
== SAFI_EVPN
) {
10285 if (tag_buf
[0] != '\0')
10286 vty_out(vty
, " VNI %s", tag_buf
);
10289 json_object_string_add(json_path
, "vni",
10295 if (safi
== SAFI_EVPN
10296 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10297 char gwip_buf
[INET6_ADDRSTRLEN
];
10299 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10303 json_object_string_add(json_path
, "gatewayIP",
10306 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10309 if (safi
== SAFI_EVPN
&& !json_path
)
10310 vty_out(vty
, "\n");
10313 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10314 struct bgp_path_info
*parent_ri
;
10315 struct bgp_dest
*dest
, *pdest
;
10317 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10318 dest
= parent_ri
->net
;
10319 if (dest
&& dest
->pdest
) {
10320 pdest
= dest
->pdest
;
10321 if (is_pi_family_evpn(parent_ri
)) {
10322 vty_out(vty
, " Imported from ");
10323 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10324 (struct prefix_rd
*)bgp_dest_get_prefix(
10326 vty_out(vty
, ":%pFX, VNI %s",
10327 (struct prefix_evpn
*)
10328 bgp_dest_get_prefix(dest
),
10330 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10331 vty_out(vty
, ", L3NHG %s",
10334 ATTR_ES_L3_NHG_ACTIVE
)
10337 vty_out(vty
, "\n");
10340 vty_out(vty
, " Imported from ");
10341 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10342 (struct prefix_rd
*)bgp_dest_get_prefix(
10344 vty_out(vty
, ":%pFX\n",
10345 (struct prefix_evpn
*)
10346 bgp_dest_get_prefix(dest
));
10351 /* Line1 display AS-path, Aggregator */
10352 if (attr
->aspath
) {
10354 if (!attr
->aspath
->json
)
10355 aspath_str_update(attr
->aspath
, true);
10356 json_object_lock(attr
->aspath
->json
);
10357 json_object_object_add(json_path
, "aspath",
10358 attr
->aspath
->json
);
10360 if (attr
->aspath
->segments
)
10361 vty_out(vty
, " %s", attr
->aspath
->str
);
10363 vty_out(vty
, " Local");
10367 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10369 json_object_boolean_true_add(json_path
, "removed");
10371 vty_out(vty
, ", (removed)");
10374 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10376 json_object_boolean_true_add(json_path
, "stale");
10378 vty_out(vty
, ", (stale)");
10381 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10383 json_object_int_add(json_path
, "aggregatorAs",
10384 attr
->aggregator_as
);
10385 json_object_string_addf(json_path
, "aggregatorId",
10386 "%pI4", &attr
->aggregator_addr
);
10388 vty_out(vty
, ", (aggregated by %u %pI4)",
10389 attr
->aggregator_as
, &attr
->aggregator_addr
);
10393 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10394 PEER_FLAG_REFLECTOR_CLIENT
)) {
10396 json_object_boolean_true_add(json_path
,
10397 "rxedFromRrClient");
10399 vty_out(vty
, ", (Received from a RR-client)");
10402 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10403 PEER_FLAG_RSERVER_CLIENT
)) {
10405 json_object_boolean_true_add(json_path
,
10406 "rxedFromRsClient");
10408 vty_out(vty
, ", (Received from a RS-client)");
10411 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10413 json_object_boolean_true_add(json_path
,
10414 "dampeningHistoryEntry");
10416 vty_out(vty
, ", (history entry)");
10417 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10419 json_object_boolean_true_add(json_path
,
10420 "dampeningSuppressed");
10422 vty_out(vty
, ", (suppressed due to dampening)");
10426 vty_out(vty
, "\n");
10428 /* Line2 display Next-hop, Neighbor, Router-id */
10429 /* Display the nexthop */
10431 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10432 p
->family
== AF_EVPN
) &&
10433 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10434 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10435 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10436 || safi
== SAFI_EVPN
) {
10438 json_object_string_addf(
10439 json_nexthop_global
, "ip", "%pI4",
10440 &attr
->mp_nexthop_global_in
);
10442 if (path
->peer
->hostname
)
10443 json_object_string_add(
10444 json_nexthop_global
, "hostname",
10445 path
->peer
->hostname
);
10447 if (nexthop_hostname
)
10448 vty_out(vty
, " %pI4(%s)",
10449 &attr
->mp_nexthop_global_in
,
10452 vty_out(vty
, " %pI4",
10453 &attr
->mp_nexthop_global_in
);
10457 json_object_string_addf(json_nexthop_global
,
10461 if (path
->peer
->hostname
)
10462 json_object_string_add(
10463 json_nexthop_global
, "hostname",
10464 path
->peer
->hostname
);
10466 if (nexthop_hostname
)
10467 vty_out(vty
, " %pI4(%s)",
10471 vty_out(vty
, " %pI4",
10477 json_object_string_add(json_nexthop_global
, "afi",
10481 json_object_string_addf(json_nexthop_global
, "ip",
10483 &attr
->mp_nexthop_global
);
10485 if (path
->peer
->hostname
)
10486 json_object_string_add(json_nexthop_global
,
10488 path
->peer
->hostname
);
10490 json_object_string_add(json_nexthop_global
, "afi",
10492 json_object_string_add(json_nexthop_global
, "scope",
10495 if (nexthop_hostname
)
10496 vty_out(vty
, " %pI6(%s)",
10497 &attr
->mp_nexthop_global
,
10500 vty_out(vty
, " %pI6",
10501 &attr
->mp_nexthop_global
);
10505 /* Display the IGP cost or 'inaccessible' */
10506 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10507 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10510 json_object_boolean_false_add(json_nexthop_global
,
10512 json_object_boolean_add(json_nexthop_global
,
10513 "importCheckEnabled", import
);
10515 vty_out(vty
, " (inaccessible%s)",
10516 import
? ", import-check enabled" : "");
10519 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10521 json_object_int_add(
10522 json_nexthop_global
, "metric",
10523 bpi_ultimate
->extra
->igpmetric
);
10525 vty_out(vty
, " (metric %u)",
10526 bpi_ultimate
->extra
->igpmetric
);
10529 /* IGP cost is 0, display this only for json */
10532 json_object_int_add(json_nexthop_global
,
10537 json_object_boolean_true_add(json_nexthop_global
,
10541 /* Display peer "from" output */
10542 /* This path was originated locally */
10543 if (path
->peer
== bgp
->peer_self
) {
10545 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10546 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10548 json_object_string_add(json_peer
, "peerId",
10551 vty_out(vty
, " from 0.0.0.0 ");
10554 json_object_string_add(json_peer
, "peerId",
10557 vty_out(vty
, " from :: ");
10561 json_object_string_addf(json_peer
, "routerId", "%pI4",
10564 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10567 /* We RXed this path from one of our peers */
10571 json_object_string_addf(json_peer
, "peerId", "%pSU",
10573 json_object_string_addf(json_peer
, "routerId", "%pI4",
10574 &path
->peer
->remote_id
);
10576 if (path
->peer
->hostname
)
10577 json_object_string_add(json_peer
, "hostname",
10578 path
->peer
->hostname
);
10580 if (path
->peer
->domainname
)
10581 json_object_string_add(json_peer
, "domainname",
10582 path
->peer
->domainname
);
10584 if (path
->peer
->conf_if
)
10585 json_object_string_add(json_peer
, "interface",
10586 path
->peer
->conf_if
);
10588 if (path
->peer
->conf_if
) {
10589 if (path
->peer
->hostname
10590 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10591 BGP_FLAG_SHOW_HOSTNAME
))
10592 vty_out(vty
, " from %s(%s)",
10593 path
->peer
->hostname
,
10594 path
->peer
->conf_if
);
10596 vty_out(vty
, " from %s",
10597 path
->peer
->conf_if
);
10599 if (path
->peer
->hostname
10600 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10601 BGP_FLAG_SHOW_HOSTNAME
))
10602 vty_out(vty
, " from %s(%s)",
10603 path
->peer
->hostname
,
10606 vty_out(vty
, " from %pSU",
10610 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10611 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10613 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10618 * Note when vrfid of nexthop is different from that of prefix
10620 if (path
->extra
&& path
->extra
->bgp_orig
) {
10621 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10626 if (path
->extra
->bgp_orig
->inst_type
10627 == BGP_INSTANCE_TYPE_DEFAULT
)
10628 vn
= VRF_DEFAULT_NAME
;
10630 vn
= path
->extra
->bgp_orig
->name
;
10632 json_object_string_add(json_path
, "nhVrfName", vn
);
10634 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10635 json_object_int_add(json_path
, "nhVrfId", -1);
10637 json_object_int_add(json_path
, "nhVrfId",
10638 (int)nexthop_vrfid
);
10641 if (nexthop_vrfid
== VRF_UNKNOWN
)
10642 vty_out(vty
, " vrf ?");
10646 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10647 vty_out(vty
, " vrf %s(%u)",
10648 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10653 if (nexthop_self
) {
10655 json_object_boolean_true_add(json_path
,
10656 "announceNexthopSelf");
10658 vty_out(vty
, " announce-nh-self");
10663 vty_out(vty
, "\n");
10665 /* display the link-local nexthop */
10666 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10668 json_nexthop_ll
= json_object_new_object();
10669 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10670 &attr
->mp_nexthop_local
);
10672 if (path
->peer
->hostname
)
10673 json_object_string_add(json_nexthop_ll
,
10675 path
->peer
->hostname
);
10677 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10678 json_object_string_add(json_nexthop_ll
, "scope",
10681 json_object_boolean_true_add(json_nexthop_ll
,
10684 if (!attr
->mp_nexthop_prefer_global
)
10685 json_object_boolean_true_add(json_nexthop_ll
,
10688 json_object_boolean_true_add(
10689 json_nexthop_global
, "used");
10691 vty_out(vty
, " (%s) %s\n",
10692 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10693 buf
, INET6_ADDRSTRLEN
),
10694 attr
->mp_nexthop_prefer_global
10695 ? "(prefer-global)"
10699 /* If we do not have a link-local nexthop then we must flag the
10700 global as "used" */
10703 json_object_boolean_true_add(json_nexthop_global
,
10707 if (safi
== SAFI_EVPN
&&
10708 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10709 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10712 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10713 * Int/Ext/Local, Atomic, best */
10715 json_object_string_add(json_path
, "origin",
10716 bgp_origin_long_str
[attr
->origin
]);
10718 vty_out(vty
, " Origin %s",
10719 bgp_origin_long_str
[attr
->origin
]);
10721 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10723 json_object_int_add(json_path
, "metric", attr
->med
);
10725 vty_out(vty
, ", metric %u", attr
->med
);
10728 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10730 json_object_int_add(json_path
, "locPrf",
10733 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10736 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10738 json_object_int_add(json_path
, "aigpMetric",
10739 bgp_attr_get_aigp_metric(attr
));
10741 vty_out(vty
, ", aigp-metric %" PRIu64
,
10742 bgp_attr_get_aigp_metric(attr
));
10745 if (attr
->weight
!= 0) {
10747 json_object_int_add(json_path
, "weight", attr
->weight
);
10749 vty_out(vty
, ", weight %u", attr
->weight
);
10752 if (attr
->tag
!= 0) {
10754 json_object_int_add(json_path
, "tag", attr
->tag
);
10756 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10759 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10761 json_object_boolean_false_add(json_path
, "valid");
10763 vty_out(vty
, ", invalid");
10764 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10766 json_object_boolean_true_add(json_path
, "valid");
10768 vty_out(vty
, ", valid");
10772 json_object_int_add(json_path
, "version", bn
->version
);
10774 if (path
->peer
!= bgp
->peer_self
) {
10775 if (path
->peer
->as
== path
->peer
->local_as
) {
10776 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10778 json_object_string_add(
10780 "confed-internal");
10782 vty_out(vty
, ", confed-internal");
10785 json_object_string_add(
10786 json_peer
, "type", "internal");
10788 vty_out(vty
, ", internal");
10791 if (bgp_confederation_peers_check(bgp
,
10794 json_object_string_add(
10796 "confed-external");
10798 vty_out(vty
, ", confed-external");
10801 json_object_string_add(
10802 json_peer
, "type", "external");
10804 vty_out(vty
, ", external");
10807 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10809 json_object_boolean_true_add(json_path
, "aggregated");
10810 json_object_boolean_true_add(json_path
, "local");
10812 vty_out(vty
, ", aggregated, local");
10814 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10816 json_object_boolean_true_add(json_path
, "sourced");
10818 vty_out(vty
, ", sourced");
10821 json_object_boolean_true_add(json_path
, "sourced");
10822 json_object_boolean_true_add(json_path
, "local");
10824 vty_out(vty
, ", sourced, local");
10828 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10830 json_object_boolean_true_add(json_path
,
10831 "atomicAggregate");
10833 vty_out(vty
, ", atomic-aggregate");
10836 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10838 json_object_int_add(json_path
, "otc", attr
->otc
);
10840 vty_out(vty
, ", otc %u", attr
->otc
);
10843 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10844 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10845 && bgp_path_info_mpath_count(path
))) {
10847 json_object_boolean_true_add(json_path
, "multipath");
10849 vty_out(vty
, ", multipath");
10852 // Mark the bestpath(s)
10853 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10854 first_as
= aspath_get_first_as(attr
->aspath
);
10857 if (!json_bestpath
)
10858 json_bestpath
= json_object_new_object();
10859 json_object_int_add(json_bestpath
, "bestpathFromAs",
10863 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10865 vty_out(vty
, ", bestpath-from-AS Local");
10869 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10871 if (!json_bestpath
)
10872 json_bestpath
= json_object_new_object();
10873 json_object_boolean_true_add(json_bestpath
, "overall");
10874 json_object_string_add(
10875 json_bestpath
, "selectionReason",
10876 bgp_path_selection_reason2str(bn
->reason
));
10878 vty_out(vty
, ", best");
10879 vty_out(vty
, " (%s)",
10880 bgp_path_selection_reason2str(bn
->reason
));
10884 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10886 json_object_string_add(
10887 json_path
, "rpkiValidationState",
10888 bgp_rpki_validation2str(rpki_curr_state
));
10890 vty_out(vty
, ", rpki validation-state: %s",
10891 bgp_rpki_validation2str(rpki_curr_state
));
10895 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10898 vty_out(vty
, "\n");
10900 /* Line 4 display Community */
10901 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10903 if (!bgp_attr_get_community(attr
)->json
)
10904 community_str(bgp_attr_get_community(attr
),
10906 json_object_lock(bgp_attr_get_community(attr
)->json
);
10907 json_object_object_add(
10908 json_path
, "community",
10909 bgp_attr_get_community(attr
)->json
);
10911 vty_out(vty
, " Community: %s\n",
10912 bgp_attr_get_community(attr
)->str
);
10916 /* Line 5 display Extended-community */
10917 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10919 json_ext_community
= json_object_new_object();
10920 json_object_string_add(
10921 json_ext_community
, "string",
10922 bgp_attr_get_ecommunity(attr
)->str
);
10923 json_object_object_add(json_path
, "extendedCommunity",
10924 json_ext_community
);
10926 vty_out(vty
, " Extended Community: %s\n",
10927 bgp_attr_get_ecommunity(attr
)->str
);
10931 /* Line 6 display Large community */
10932 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10934 if (!bgp_attr_get_lcommunity(attr
)->json
)
10935 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10937 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10938 json_object_object_add(
10939 json_path
, "largeCommunity",
10940 bgp_attr_get_lcommunity(attr
)->json
);
10942 vty_out(vty
, " Large Community: %s\n",
10943 bgp_attr_get_lcommunity(attr
)->str
);
10947 /* Line 7 display Originator, Cluster-id */
10948 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10949 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10950 char buf
[BUFSIZ
] = {0};
10952 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10954 json_object_string_addf(json_path
,
10955 "originatorId", "%pI4",
10956 &attr
->originator_id
);
10958 vty_out(vty
, " Originator: %pI4",
10959 &attr
->originator_id
);
10962 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10963 struct cluster_list
*cluster
=
10964 bgp_attr_get_cluster(attr
);
10968 json_cluster_list
= json_object_new_object();
10969 json_cluster_list_list
=
10970 json_object_new_array();
10972 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10973 json_string
= json_object_new_string(
10976 buf
, sizeof(buf
)));
10977 json_object_array_add(
10978 json_cluster_list_list
,
10983 * struct cluster_list does not have
10984 * "str" variable like aspath and community
10985 * do. Add this someday if someone asks
10987 * json_object_string_add(json_cluster_list,
10988 * "string", cluster->str);
10990 json_object_object_add(json_cluster_list
,
10992 json_cluster_list_list
);
10993 json_object_object_add(json_path
, "clusterList",
10994 json_cluster_list
);
10996 vty_out(vty
, ", Cluster list: ");
10998 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10999 vty_out(vty
, "%pI4 ",
11000 &cluster
->list
[i
]);
11006 vty_out(vty
, "\n");
11009 if (path
->extra
&& path
->extra
->damp_info
)
11010 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
11013 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
11014 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
11015 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
11019 json_object_int_add(json_path
, "remoteLabel", label
);
11021 vty_out(vty
, " Remote label: %d\n", label
);
11025 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
11027 json_object_string_addf(json_path
, "remoteSid", "%pI6",
11028 &path
->extra
->sid
[0].sid
);
11030 vty_out(vty
, " Remote SID: %pI6\n",
11031 &path
->extra
->sid
[0].sid
);
11035 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
11037 json_object_int_add(json_path
, "labelIndex",
11038 attr
->label_index
);
11040 vty_out(vty
, " Label Index: %d\n",
11041 attr
->label_index
);
11044 /* Line 8 display Addpath IDs */
11045 if (path
->addpath_rx_id
11046 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11048 json_object_int_add(json_path
, "addpathRxId",
11049 path
->addpath_rx_id
);
11051 /* Keep backwards compatibility with the old API
11052 * by putting TX All's ID in the old field
11054 json_object_int_add(
11055 json_path
, "addpathTxId",
11057 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11059 /* ... but create a specific field for each
11062 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11063 json_object_int_add(
11065 bgp_addpath_names(i
)->id_json_name
,
11066 path
->tx_addpath
.addpath_tx_id
[i
]);
11069 vty_out(vty
, " AddPath ID: RX %u, ",
11070 path
->addpath_rx_id
);
11072 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11076 /* If we used addpath to TX a non-bestpath we need to display
11077 * "Advertised to" on a path-by-path basis
11079 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11082 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11084 bgp_addpath_encode_tx(peer
, afi
, safi
);
11085 has_adj
= bgp_adj_out_lookup(
11087 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11088 &path
->tx_addpath
));
11090 if ((addpath_capable
&& has_adj
)
11091 || (!addpath_capable
&& has_adj
11092 && CHECK_FLAG(path
->flags
,
11093 BGP_PATH_SELECTED
))) {
11094 if (json_path
&& !json_adv_to
)
11095 json_adv_to
= json_object_new_object();
11097 route_vty_out_advertised_to(
11099 " Advertised to:", json_adv_to
);
11105 json_object_object_add(
11106 json_path
, "advertisedTo", json_adv_to
);
11110 vty_out(vty
, "\n");
11115 /* Line 9 display Uptime */
11116 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11118 json_last_update
= json_object_new_object();
11119 json_object_int_add(json_last_update
, "epoch", tbuf
);
11120 json_object_string_add(json_last_update
, "string",
11122 json_object_object_add(json_path
, "lastUpdate",
11125 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11127 /* Line 10 display PMSI tunnel attribute, if present */
11128 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11129 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11130 bgp_attr_get_pmsi_tnl_type(attr
),
11131 PMSI_TNLTYPE_STR_DEFAULT
);
11134 json_pmsi
= json_object_new_object();
11135 json_object_string_add(json_pmsi
, "tunnelType", str
);
11136 json_object_int_add(json_pmsi
, "label",
11137 label2vni(&attr
->label
));
11138 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11140 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11141 str
, label2vni(&attr
->label
));
11144 if (path
->peer
->t_gr_restart
&&
11145 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11146 unsigned long gr_remaining
=
11147 event_timer_remain_second(path
->peer
->t_gr_restart
);
11150 json_object_int_add(json_path
,
11151 "gracefulRestartSecondsRemaining",
11155 " Time until Graceful Restart stale route deleted: %lu\n",
11159 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11160 bgp_attr_get_community(attr
) &&
11161 community_include(bgp_attr_get_community(attr
),
11162 COMMUNITY_LLGR_STALE
)) {
11163 unsigned long llgr_remaining
= event_timer_remain_second(
11164 path
->peer
->t_llgr_stale
[afi
][safi
]);
11167 json_object_int_add(json_path
, "llgrSecondsRemaining",
11171 " Time until Long-lived stale route deleted: %lu\n",
11175 /* Output some debug about internal state of the dest flags */
11177 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11178 json_object_boolean_true_add(json_path
, "processScheduled");
11179 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11180 json_object_boolean_true_add(json_path
, "userCleared");
11181 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11182 json_object_boolean_true_add(json_path
, "labelChanged");
11183 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11184 json_object_boolean_true_add(json_path
, "registeredForLabel");
11185 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11186 json_object_boolean_true_add(json_path
, "selectDefered");
11187 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11188 json_object_boolean_true_add(json_path
, "fibInstalled");
11189 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11190 json_object_boolean_true_add(json_path
, "fibPending");
11192 if (json_nexthop_global
|| json_nexthop_ll
) {
11193 json_nexthops
= json_object_new_array();
11195 if (json_nexthop_global
)
11196 json_object_array_add(json_nexthops
,
11197 json_nexthop_global
);
11199 if (json_nexthop_ll
)
11200 json_object_array_add(json_nexthops
,
11203 json_object_object_add(json_path
, "nexthops",
11207 json_object_object_add(json_path
, "peer", json_peer
);
11208 json_object_array_add(json_paths
, json_path
);
11212 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11213 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11214 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11216 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11217 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11219 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11220 const char *comstr
, int exact
, afi_t afi
,
11221 safi_t safi
, uint16_t show_flags
);
11223 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11224 struct bgp_table
*table
, enum bgp_show_type type
,
11225 void *output_arg
, const char *rd
, int is_last
,
11226 unsigned long *output_cum
, unsigned long *total_cum
,
11227 unsigned long *json_header_depth
, uint16_t show_flags
,
11228 enum rpki_states rpki_target_state
)
11230 struct bgp_path_info
*pi
;
11231 struct bgp_dest
*dest
;
11232 bool header
= true;
11233 bool json_detail_header
= false;
11235 unsigned long output_count
= 0;
11236 unsigned long total_count
= 0;
11238 json_object
*json_paths
= NULL
;
11240 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11241 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11242 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11243 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11244 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11246 if (output_cum
&& *output_cum
!= 0)
11249 if (use_json
&& !*json_header_depth
) {
11251 *json_header_depth
= 1;
11253 vty_out(vty
, "{\n");
11254 *json_header_depth
= 2;
11257 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11258 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11260 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11261 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11264 table
->version
, &bgp
->router_id
,
11265 bgp
->default_local_pref
);
11266 if ((bgp
->asnotation
== ASNOTATION_PLAIN
) ||
11267 ((bgp
->asnotation
== ASNOTATION_DOT
) &&
11268 (bgp
->as
< UINT16_MAX
)))
11269 vty_out(vty
, "%u", bgp
->as
);
11271 vty_out(vty
, "\"");
11272 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
), &bgp
->as
);
11273 vty_out(vty
, "\"");
11275 vty_out(vty
, ",\n \"routes\": { ");
11277 vty_out(vty
, " \"routeDistinguishers\" : {");
11278 ++*json_header_depth
;
11282 if (use_json
&& rd
) {
11283 vty_out(vty
, " \"%s\" : { ", rd
);
11286 /* Check for 'json detail', where we need header output once per dest */
11287 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11288 type
!= bgp_show_type_damp_neighbor
&&
11289 type
!= bgp_show_type_flap_statistics
&&
11290 type
!= bgp_show_type_flap_neighbor
)
11291 json_detail_header
= true;
11293 /* Start processing of routes. */
11294 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11295 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11296 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11297 bool json_detail_header_used
= false;
11299 pi
= bgp_dest_get_bgp_path_info(dest
);
11305 json_paths
= json_object_new_array();
11309 for (; pi
; pi
= pi
->next
) {
11310 struct community
*picomm
= NULL
;
11312 picomm
= bgp_attr_get_community(pi
->attr
);
11316 if (type
== bgp_show_type_prefix_version
) {
11318 strtoul(output_arg
, NULL
, 10);
11319 if (dest
->version
< version
)
11323 if (type
== bgp_show_type_community_alias
) {
11324 char *alias
= output_arg
;
11325 char **communities
;
11327 bool found
= false;
11330 frrstr_split(picomm
->str
, " ",
11331 &communities
, &num
);
11332 for (int i
= 0; i
< num
; i
++) {
11333 const char *com2alias
=
11334 bgp_community2alias(
11337 && strcmp(alias
, com2alias
)
11343 XFREE(MTYPE_TMP
, communities
);
11347 bgp_attr_get_lcommunity(pi
->attr
)) {
11348 frrstr_split(bgp_attr_get_lcommunity(
11351 " ", &communities
, &num
);
11352 for (int i
= 0; i
< num
; i
++) {
11353 const char *com2alias
=
11354 bgp_community2alias(
11357 && strcmp(alias
, com2alias
)
11363 XFREE(MTYPE_TMP
, communities
);
11370 if (type
== bgp_show_type_rpki
) {
11371 if (dest_p
->family
== AF_INET
11372 || dest_p
->family
== AF_INET6
)
11373 rpki_curr_state
= hook_call(
11374 bgp_rpki_prefix_status
,
11375 pi
->peer
, pi
->attr
, dest_p
);
11376 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11377 && rpki_curr_state
!= rpki_target_state
)
11381 if (type
== bgp_show_type_flap_statistics
11382 || type
== bgp_show_type_flap_neighbor
11383 || type
== bgp_show_type_dampend_paths
11384 || type
== bgp_show_type_damp_neighbor
) {
11385 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11388 if (type
== bgp_show_type_regexp
) {
11389 regex_t
*regex
= output_arg
;
11391 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11395 if (type
== bgp_show_type_prefix_list
) {
11396 struct prefix_list
*plist
= output_arg
;
11398 if (prefix_list_apply(plist
, dest_p
)
11402 if (type
== bgp_show_type_access_list
) {
11403 struct access_list
*alist
= output_arg
;
11405 if (access_list_apply(alist
, dest_p
) !=
11409 if (type
== bgp_show_type_filter_list
) {
11410 struct as_list
*as_list
= output_arg
;
11412 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11413 != AS_FILTER_PERMIT
)
11416 if (type
== bgp_show_type_route_map
) {
11417 struct route_map
*rmap
= output_arg
;
11418 struct bgp_path_info path
;
11419 struct bgp_path_info_extra extra
;
11420 struct attr dummy_attr
= {};
11421 route_map_result_t ret
;
11423 dummy_attr
= *pi
->attr
;
11425 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11426 pi
->peer
, &dummy_attr
);
11428 ret
= route_map_apply(rmap
, dest_p
, &path
);
11429 bgp_attr_flush(&dummy_attr
);
11430 if (ret
== RMAP_DENYMATCH
)
11433 if (type
== bgp_show_type_neighbor
11434 || type
== bgp_show_type_flap_neighbor
11435 || type
== bgp_show_type_damp_neighbor
) {
11436 union sockunion
*su
= output_arg
;
11438 if (pi
->peer
== NULL
11439 || pi
->peer
->su_remote
== NULL
11440 || !sockunion_same(pi
->peer
->su_remote
, su
))
11443 if (type
== bgp_show_type_cidr_only
) {
11444 uint32_t destination
;
11446 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11447 if (IN_CLASSC(destination
)
11448 && dest_p
->prefixlen
== 24)
11450 if (IN_CLASSB(destination
)
11451 && dest_p
->prefixlen
== 16)
11453 if (IN_CLASSA(destination
)
11454 && dest_p
->prefixlen
== 8)
11457 if (type
== bgp_show_type_prefix_longer
) {
11459 if (!prefix_match(p
, dest_p
))
11462 if (type
== bgp_show_type_community_all
) {
11466 if (type
== bgp_show_type_community
) {
11467 struct community
*com
= output_arg
;
11469 if (!picomm
|| !community_match(picomm
, com
))
11472 if (type
== bgp_show_type_community_exact
) {
11473 struct community
*com
= output_arg
;
11475 if (!picomm
|| !community_cmp(picomm
, com
))
11478 if (type
== bgp_show_type_community_list
) {
11479 struct community_list
*list
= output_arg
;
11481 if (!community_list_match(picomm
, list
))
11484 if (type
== bgp_show_type_community_list_exact
) {
11485 struct community_list
*list
= output_arg
;
11487 if (!community_list_exact_match(picomm
, list
))
11490 if (type
== bgp_show_type_lcommunity
) {
11491 struct lcommunity
*lcom
= output_arg
;
11493 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11495 bgp_attr_get_lcommunity(pi
->attr
),
11500 if (type
== bgp_show_type_lcommunity_exact
) {
11501 struct lcommunity
*lcom
= output_arg
;
11503 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11505 bgp_attr_get_lcommunity(pi
->attr
),
11509 if (type
== bgp_show_type_lcommunity_list
) {
11510 struct community_list
*list
= output_arg
;
11512 if (!lcommunity_list_match(
11513 bgp_attr_get_lcommunity(pi
->attr
),
11518 == bgp_show_type_lcommunity_list_exact
) {
11519 struct community_list
*list
= output_arg
;
11521 if (!lcommunity_list_exact_match(
11522 bgp_attr_get_lcommunity(pi
->attr
),
11526 if (type
== bgp_show_type_lcommunity_all
) {
11527 if (!bgp_attr_get_lcommunity(pi
->attr
))
11530 if (type
== bgp_show_type_dampend_paths
11531 || type
== bgp_show_type_damp_neighbor
) {
11532 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11533 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11536 if (type
== bgp_show_type_self_originated
) {
11537 if (pi
->peer
!= bgp
->peer_self
)
11541 if (!use_json
&& header
) {
11543 "BGP table version is %" PRIu64
11544 ", local router ID is %pI4, vrf id ",
11545 table
->version
, &bgp
->router_id
);
11546 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11547 vty_out(vty
, "%s", VRFID_NONE_STR
);
11549 vty_out(vty
, "%u", bgp
->vrf_id
);
11550 vty_out(vty
, "\n");
11551 vty_out(vty
, "Default local pref %u, ",
11552 bgp
->default_local_pref
);
11553 vty_out(vty
, "local AS ");
11554 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
),
11556 vty_out(vty
, "\n");
11557 if (!detail_routes
) {
11558 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11559 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11560 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11561 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11563 if (type
== bgp_show_type_dampend_paths
11564 || type
== bgp_show_type_damp_neighbor
)
11565 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11566 else if (type
== bgp_show_type_flap_statistics
11567 || type
== bgp_show_type_flap_neighbor
)
11568 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11569 else if (!detail_routes
)
11570 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11571 : BGP_SHOW_HEADER
));
11575 if (rd
!= NULL
&& !display
&& !output_count
) {
11578 "Route Distinguisher: %s\n",
11581 if (type
== bgp_show_type_dampend_paths
11582 || type
== bgp_show_type_damp_neighbor
)
11583 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11584 AFI_IP
, safi
, use_json
,
11586 else if (type
== bgp_show_type_flap_statistics
11587 || type
== bgp_show_type_flap_neighbor
)
11588 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11589 AFI_IP
, safi
, use_json
,
11592 if (detail_routes
|| detail_json
) {
11593 const struct prefix_rd
*prd
= NULL
;
11596 prd
= bgp_rd_from_dest(
11597 dest
->pdest
, safi
);
11600 route_vty_out_detail_header(
11602 bgp_dest_get_prefix(
11604 prd
, table
->afi
, safi
,
11607 route_vty_out_detail(
11608 vty
, bgp
, dest
, dest_p
, pi
,
11609 family2afi(dest_p
->family
),
11610 safi
, RPKI_NOT_BEING_USED
,
11613 route_vty_out(vty
, dest_p
, pi
, display
,
11614 safi
, json_paths
, wide
);
11625 /* encode prefix */
11626 if (dest_p
->family
== AF_FLOWSPEC
) {
11627 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11630 bgp_fs_nlri_get_string(
11632 dest_p
->u
.prefix_flowspec
.ptr
,
11633 dest_p
->u
.prefix_flowspec
.prefixlen
,
11634 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11635 family2afi(dest_p
->u
11636 .prefix_flowspec
.family
));
11638 vty_out(vty
, "\"%s/%d\": ", retstr
,
11639 dest_p
->u
.prefix_flowspec
11642 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11643 dest_p
->u
.prefix_flowspec
11647 vty_out(vty
, "\"%pFX\": ", dest_p
);
11649 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11652 /* This is used for 'json detail' vty keywords.
11654 * In plain 'json' the per-prefix header is encoded
11655 * as a standalone dictionary in the first json_paths
11657 * "<prefix>": [{header}, {path-1}, {path-N}]
11658 * (which is confusing and borderline broken)
11660 * For 'json detail' this changes the value
11661 * of each prefix-key to be a dictionary where each
11662 * header item has its own key, and json_paths is
11663 * tucked under the "paths" key:
11665 * "<header-key-1>": <header-val-1>,
11666 * "<header-key-N>": <header-val-N>,
11667 * "paths": [{path-1}, {path-N}]
11670 if (json_detail_header
&& json_paths
!= NULL
) {
11671 const struct prefix_rd
*prd
;
11673 /* Start per-prefix dictionary */
11674 vty_out(vty
, "{\n");
11676 prd
= bgp_rd_from_dest(dest
, safi
);
11678 route_vty_out_detail_header(
11680 bgp_dest_get_prefix(dest
), prd
,
11681 table
->afi
, safi
, json_paths
, true);
11683 vty_out(vty
, "\"paths\": ");
11684 json_detail_header_used
= true;
11688 * We are using no_pretty here because under
11689 * extremely high settings( say lots and lots of
11690 * routes with lots and lots of ways to reach
11691 * that route via different paths ) this can
11692 * save several minutes of output when FRR
11693 * is run on older cpu's or more underperforming
11694 * routers out there
11696 vty_json_no_pretty(vty
, json_paths
);
11698 /* End per-prefix dictionary */
11699 if (json_detail_header_used
)
11700 vty_out(vty
, "} ");
11705 json_object_free(json_paths
);
11709 output_count
+= *output_cum
;
11710 *output_cum
= output_count
;
11713 total_count
+= *total_cum
;
11714 *total_cum
= total_count
;
11718 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11722 for (i
= 0; i
< *json_header_depth
; ++i
)
11723 vty_out(vty
, " } ");
11725 vty_out(vty
, "\n");
11729 /* No route is displayed */
11730 if (output_count
== 0) {
11731 if (type
== bgp_show_type_normal
)
11733 "No BGP prefixes displayed, %ld exist\n",
11737 "\nDisplayed %ld routes and %ld total paths\n",
11738 output_count
, total_count
);
11742 return CMD_SUCCESS
;
11745 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11746 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11747 enum bgp_show_type type
, void *output_arg
,
11748 uint16_t show_flags
)
11750 struct bgp_dest
*dest
, *next
;
11751 unsigned long output_cum
= 0;
11752 unsigned long total_cum
= 0;
11753 unsigned long json_header_depth
= 0;
11754 struct bgp_table
*itable
;
11756 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11758 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11760 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11761 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11763 next
= bgp_route_next(dest
);
11764 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11767 itable
= bgp_dest_get_bgp_table_info(dest
);
11768 if (itable
!= NULL
) {
11769 struct prefix_rd prd
;
11770 char rd
[RD_ADDRSTRLEN
];
11772 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11773 prefix_rd2str(&prd
, rd
, sizeof(rd
), bgp
->asnotation
);
11774 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11775 rd
, next
== NULL
, &output_cum
,
11776 &total_cum
, &json_header_depth
,
11777 show_flags
, RPKI_NOT_BEING_USED
);
11783 if (output_cum
== 0)
11784 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11788 "\nDisplayed %ld routes and %ld total paths\n",
11789 output_cum
, total_cum
);
11791 if (use_json
&& output_cum
== 0)
11792 vty_out(vty
, "{}\n");
11794 return CMD_SUCCESS
;
11797 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11798 enum bgp_show_type type
, void *output_arg
,
11799 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11801 struct bgp_table
*table
;
11802 unsigned long json_header_depth
= 0;
11803 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11806 bgp
= bgp_get_default();
11811 vty_out(vty
, "No BGP process is configured\n");
11813 vty_out(vty
, "{}\n");
11814 return CMD_WARNING
;
11817 /* Labeled-unicast routes live in the unicast table. */
11818 if (safi
== SAFI_LABELED_UNICAST
)
11819 safi
= SAFI_UNICAST
;
11821 table
= bgp
->rib
[afi
][safi
];
11822 /* use MPLS and ENCAP specific shows until they are merged */
11823 if (safi
== SAFI_MPLS_VPN
) {
11824 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11825 output_arg
, show_flags
);
11828 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11829 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11830 output_arg
, use_json
,
11834 if (safi
== SAFI_EVPN
)
11835 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11837 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11838 NULL
, NULL
, &json_header_depth
, show_flags
,
11839 rpki_target_state
);
11842 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11843 safi_t safi
, uint16_t show_flags
)
11845 struct listnode
*node
, *nnode
;
11848 bool route_output
= false;
11849 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11852 vty_out(vty
, "{\n");
11854 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11855 route_output
= true;
11858 vty_out(vty
, ",\n");
11862 vty_out(vty
, "\"%s\":",
11863 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11867 vty_out(vty
, "\nInstance %s:\n",
11868 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11872 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11873 show_flags
, RPKI_NOT_BEING_USED
);
11877 vty_out(vty
, "}\n");
11878 else if (!route_output
)
11879 vty_out(vty
, "%% BGP instance not found\n");
11882 /* Header of detailed BGP route information */
11883 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11884 struct bgp_dest
*dest
, const struct prefix
*p
,
11885 const struct prefix_rd
*prd
, afi_t afi
,
11886 safi_t safi
, json_object
*json
,
11887 bool incremental_print
)
11889 struct bgp_path_info
*pi
;
11891 struct listnode
*node
, *nnode
;
11892 char buf1
[RD_ADDRSTRLEN
];
11896 int accept_own
= 0;
11897 int route_filter_translated_v4
= 0;
11898 int route_filter_v4
= 0;
11899 int route_filter_translated_v6
= 0;
11900 int route_filter_v6
= 0;
11901 int llgr_stale
= 0;
11903 int accept_own_nexthop
= 0;
11906 int no_advertise
= 0;
11910 int has_valid_label
= 0;
11911 mpls_label_t label
= 0;
11912 json_object
*json_adv_to
= NULL
;
11917 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11919 has_valid_label
= bgp_is_valid_label(&label
);
11921 if (safi
== SAFI_EVPN
) {
11923 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11924 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11927 prd
? ":" : "", (struct prefix_evpn
*)p
);
11929 json_object_string_add(
11931 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11934 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11939 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11941 (((safi
== SAFI_MPLS_VPN
||
11942 safi
== SAFI_ENCAP
) &&
11944 ? prefix_rd2str(prd
, buf1
,
11948 safi
== SAFI_MPLS_VPN
&& prd
? ":" : "", p
,
11952 if (incremental_print
) {
11953 vty_out(vty
, "\"prefix\": \"%pFX\",\n", p
);
11954 vty_out(vty
, "\"version\": \"%" PRIu64
"\",\n",
11957 json_object_string_addf(json
, "prefix", "%pFX",
11959 json_object_int_add(json
, "version",
11965 if (has_valid_label
) {
11967 if (incremental_print
)
11968 vty_out(vty
, "\"localLabel\": \"%u\",\n",
11971 json_object_int_add(json
, "localLabel", label
);
11973 vty_out(vty
, "Local label: %d\n", label
);
11977 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11978 vty_out(vty
, "not allocated\n");
11980 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11981 struct community
*picomm
= NULL
;
11983 picomm
= bgp_attr_get_community(pi
->attr
);
11986 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11988 if (bgp_path_suppressed(pi
))
11994 no_advertise
+= community_include(
11995 picomm
, COMMUNITY_NO_ADVERTISE
);
11997 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11999 community_include(picomm
, COMMUNITY_LOCAL_AS
);
12001 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
12002 route_filter_translated_v4
+= community_include(
12003 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
12004 route_filter_translated_v6
+= community_include(
12005 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
12006 route_filter_v4
+= community_include(
12007 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
12008 route_filter_v6
+= community_include(
12009 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
12011 community_include(picomm
, COMMUNITY_LLGR_STALE
);
12012 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
12013 accept_own_nexthop
+= community_include(
12014 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
12016 community_include(picomm
, COMMUNITY_BLACKHOLE
);
12017 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
12022 vty_out(vty
, "Paths: (%d available", count
);
12024 vty_out(vty
, ", best #%d", best
);
12025 if (safi
== SAFI_UNICAST
) {
12026 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
12027 vty_out(vty
, ", table %s",
12030 vty_out(vty
, ", vrf %s",
12034 vty_out(vty
, ", no best path");
12038 ", accept own local route exported and imported in different VRF");
12039 else if (route_filter_translated_v4
)
12041 ", mark translated RTs for VPNv4 route filtering");
12042 else if (route_filter_v4
)
12044 ", attach RT as-is for VPNv4 route filtering");
12045 else if (route_filter_translated_v6
)
12047 ", mark translated RTs for VPNv6 route filtering");
12048 else if (route_filter_v6
)
12050 ", attach RT as-is for VPNv6 route filtering");
12051 else if (llgr_stale
)
12053 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
12056 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
12057 else if (accept_own_nexthop
)
12059 ", accept local nexthop");
12060 else if (blackhole
)
12061 vty_out(vty
, ", inform peer to blackhole prefix");
12062 else if (no_export
)
12063 vty_out(vty
, ", not advertised to EBGP peer");
12064 else if (no_advertise
)
12065 vty_out(vty
, ", not advertised to any peer");
12067 vty_out(vty
, ", not advertised outside local AS");
12070 ", inform EBGP peer not to advertise to their EBGP peers");
12074 ", Advertisements suppressed by an aggregate.");
12075 vty_out(vty
, ")\n");
12078 /* If we are not using addpath then we can display Advertised to and
12080 * show what peers we advertised the bestpath to. If we are using
12082 * though then we must display Advertised to on a path-by-path basis. */
12083 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12084 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12085 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12086 if (json
&& !json_adv_to
)
12087 json_adv_to
= json_object_new_object();
12089 route_vty_out_advertised_to(
12091 " Advertised to non peer-group peers:\n ",
12096 if (json
&& json_adv_to
) {
12097 if (incremental_print
) {
12098 vty_out(vty
, "\"advertisedTo\": ");
12099 vty_json(vty
, json_adv_to
);
12102 json_object_object_add(json
, "advertisedTo",
12105 if (!json
&& first
)
12106 vty_out(vty
, " Not advertised to any peer");
12107 vty_out(vty
, "\n");
12112 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12113 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12114 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12115 json_object
*json
, enum bgp_path_type pathtype
,
12116 int *display
, enum rpki_states rpki_target_state
)
12118 struct bgp_path_info
*pi
;
12120 json_object
*json_header
= NULL
;
12121 json_object
*json_paths
= NULL
;
12122 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12124 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12125 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12127 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12128 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12129 pi
->peer
, pi
->attr
, p
);
12131 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12132 && rpki_curr_state
!= rpki_target_state
)
12135 if (json
&& !json_paths
) {
12136 /* Instantiate json_paths only if path is valid */
12137 json_paths
= json_object_new_array();
12139 json_header
= json_object_new_object();
12141 json_header
= json
;
12145 route_vty_out_detail_header(
12146 vty
, bgp
, bgp_node
,
12147 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12148 safi
, json_header
, false);
12153 if (pathtype
== BGP_PATH_SHOW_ALL
12154 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12155 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12156 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12157 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12158 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12159 route_vty_out_detail(vty
, bgp
, bgp_node
,
12160 bgp_dest_get_prefix(bgp_node
), pi
,
12161 AFI_IP
, safi
, rpki_curr_state
,
12165 if (json
&& json_paths
) {
12166 json_object_object_add(json_header
, "paths", json_paths
);
12169 json_object_object_addf(
12171 BGP_RD_AS_FORMAT(bgp
->asnotation
), pfx_rd
);
12176 * Return rd based on safi
12178 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12182 case SAFI_MPLS_VPN
:
12185 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12188 case SAFI_MULTICAST
:
12189 case SAFI_LABELED_UNICAST
:
12190 case SAFI_FLOWSPEC
:
12195 assert(!"Reached end of function when we were not expecting it");
12198 /* Display specified route of BGP table. */
12199 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12200 struct bgp_table
*rib
, const char *ip_str
,
12201 afi_t afi
, safi_t safi
,
12202 enum rpki_states rpki_target_state
,
12203 struct prefix_rd
*prd
, int prefix_check
,
12204 enum bgp_path_type pathtype
, bool use_json
)
12208 struct prefix match
;
12209 struct bgp_dest
*dest
;
12210 struct bgp_dest
*rm
;
12211 struct bgp_table
*table
;
12212 json_object
*json
= NULL
;
12213 json_object
*json_paths
= NULL
;
12215 /* Check IP address argument. */
12216 ret
= str2prefix(ip_str
, &match
);
12218 vty_out(vty
, "address is malformed\n");
12219 return CMD_WARNING
;
12222 match
.family
= afi2family(afi
);
12225 json
= json_object_new_object();
12227 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12228 for (dest
= bgp_table_top(rib
); dest
;
12229 dest
= bgp_route_next(dest
)) {
12230 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12232 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12234 table
= bgp_dest_get_bgp_table_info(dest
);
12238 rm
= bgp_node_match(table
, &match
);
12242 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12244 && rm_p
->prefixlen
!= match
.prefixlen
) {
12245 bgp_dest_unlock_node(rm
);
12249 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12250 bgp
, afi
, safi
, json
, pathtype
,
12251 &display
, rpki_target_state
);
12253 bgp_dest_unlock_node(rm
);
12255 } else if (safi
== SAFI_EVPN
) {
12256 struct bgp_dest
*longest_pfx
;
12257 bool is_exact_pfxlen_match
= false;
12259 for (dest
= bgp_table_top(rib
); dest
;
12260 dest
= bgp_route_next(dest
)) {
12261 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12263 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12265 table
= bgp_dest_get_bgp_table_info(dest
);
12269 longest_pfx
= NULL
;
12270 is_exact_pfxlen_match
= false;
12272 * Search through all the prefixes for a match. The
12273 * pfx's are enumerated in ascending order of pfxlens.
12274 * So, the last pfx match is the longest match. Set
12275 * is_exact_pfxlen_match when we get exact pfxlen match
12277 for (rm
= bgp_table_top(table
); rm
;
12278 rm
= bgp_route_next(rm
)) {
12279 const struct prefix
*rm_p
=
12280 bgp_dest_get_prefix(rm
);
12282 * Get prefixlen of the ip-prefix within type5
12285 if (evpn_type5_prefix_match(rm_p
, &match
)
12289 bgp_evpn_get_type5_prefixlen(
12291 if (type5_pfxlen
== match
.prefixlen
) {
12292 is_exact_pfxlen_match
= true;
12293 bgp_dest_unlock_node(rm
);
12302 if (prefix_check
&& !is_exact_pfxlen_match
)
12306 bgp_dest_lock_node(rm
);
12308 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12309 bgp
, afi
, safi
, json
, pathtype
,
12310 &display
, rpki_target_state
);
12312 bgp_dest_unlock_node(rm
);
12314 } else if (safi
== SAFI_FLOWSPEC
) {
12316 json_paths
= json_object_new_array();
12318 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12319 &match
, prefix_check
,
12325 json_object_object_add(json
, "paths",
12328 json_object_free(json_paths
);
12331 dest
= bgp_node_match(rib
, &match
);
12332 if (dest
!= NULL
) {
12333 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12335 || dest_p
->prefixlen
== match
.prefixlen
) {
12336 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12337 safi
, json
, pathtype
,
12338 &display
, rpki_target_state
);
12341 bgp_dest_unlock_node(dest
);
12346 vty_json(vty
, json
);
12349 vty_out(vty
, "%% Network not in table\n");
12350 return CMD_WARNING
;
12354 return CMD_SUCCESS
;
12357 /* Display specified route of Main RIB */
12358 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12359 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12360 int prefix_check
, enum bgp_path_type pathtype
,
12361 enum rpki_states rpki_target_state
, bool use_json
)
12364 bgp
= bgp_get_default();
12367 vty_out(vty
, "No BGP process is configured\n");
12369 vty_out(vty
, "{}\n");
12370 return CMD_WARNING
;
12374 /* labeled-unicast routes live in the unicast table */
12375 if (safi
== SAFI_LABELED_UNICAST
)
12376 safi
= SAFI_UNICAST
;
12378 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12379 afi
, safi
, rpki_target_state
, prd
,
12380 prefix_check
, pathtype
, use_json
);
12383 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12384 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12385 safi_t safi
, bool uj
)
12387 struct lcommunity
*lcom
;
12392 uint16_t show_flags
= 0;
12396 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12398 b
= buffer_new(1024);
12399 for (i
= 0; i
< argc
; i
++) {
12401 buffer_putc(b
, ' ');
12403 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12405 buffer_putstr(b
, argv
[i
]->arg
);
12409 buffer_putc(b
, '\0');
12411 str
= buffer_getstr(b
);
12414 lcom
= lcommunity_str2com(str
);
12415 XFREE(MTYPE_TMP
, str
);
12417 vty_out(vty
, "%% Large-community malformed\n");
12418 return CMD_WARNING
;
12421 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12422 (exact
? bgp_show_type_lcommunity_exact
12423 : bgp_show_type_lcommunity
),
12424 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12426 lcommunity_free(&lcom
);
12430 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12431 const char *lcom
, bool exact
, afi_t afi
,
12432 safi_t safi
, bool uj
)
12434 struct community_list
*list
;
12435 uint16_t show_flags
= 0;
12438 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12441 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12442 LARGE_COMMUNITY_LIST_MASTER
);
12443 if (list
== NULL
) {
12444 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12446 return CMD_WARNING
;
12449 return bgp_show(vty
, bgp
, afi
, safi
,
12450 (exact
? bgp_show_type_lcommunity_list_exact
12451 : bgp_show_type_lcommunity_list
),
12452 list
, show_flags
, RPKI_NOT_BEING_USED
);
12455 DEFUN (show_ip_bgp_large_community_list
,
12456 show_ip_bgp_large_community_list_cmd
,
12457 "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]",
12461 BGP_INSTANCE_HELP_STR
12463 BGP_SAFI_WITH_LABEL_HELP_STR
12464 "Display routes matching the large-community-list\n"
12465 "large-community-list number\n"
12466 "large-community-list name\n"
12467 "Exact match of the large-communities\n"
12470 afi_t afi
= AFI_IP6
;
12471 safi_t safi
= SAFI_UNICAST
;
12473 bool exact_match
= 0;
12474 struct bgp
*bgp
= NULL
;
12475 bool uj
= use_json(argc
, argv
);
12480 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12483 return CMD_WARNING
;
12485 argv_find(argv
, argc
, "large-community-list", &idx
);
12487 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12489 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12492 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12493 exact_match
, afi
, safi
, uj
);
12495 DEFUN (show_ip_bgp_large_community
,
12496 show_ip_bgp_large_community_cmd
,
12497 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12501 BGP_INSTANCE_HELP_STR
12503 BGP_SAFI_WITH_LABEL_HELP_STR
12504 "Display routes matching the large-communities\n"
12505 "List of large-community numbers\n"
12506 "Exact match of the large-communities\n"
12509 afi_t afi
= AFI_IP6
;
12510 safi_t safi
= SAFI_UNICAST
;
12512 bool exact_match
= 0;
12513 struct bgp
*bgp
= NULL
;
12514 bool uj
= use_json(argc
, argv
);
12515 uint16_t show_flags
= 0;
12519 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12522 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12525 return CMD_WARNING
;
12527 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12528 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12532 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12533 exact_match
, afi
, safi
, uj
);
12535 return bgp_show(vty
, bgp
, afi
, safi
,
12536 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12537 RPKI_NOT_BEING_USED
);
12540 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12541 safi_t safi
, struct json_object
*json_array
);
12542 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12543 safi_t safi
, struct json_object
*json
);
12546 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12547 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12548 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12549 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12551 bool uj
= use_json(argc
, argv
);
12552 struct bgp
*bgp
= NULL
;
12553 safi_t safi
= SAFI_UNICAST
;
12554 afi_t afi
= AFI_IP6
;
12556 struct json_object
*json_all
= NULL
;
12557 struct json_object
*json_afi_safi
= NULL
;
12559 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12562 return CMD_WARNING
;
12565 json_all
= json_object_new_object();
12567 FOREACH_AFI_SAFI (afi
, safi
) {
12569 * So limit output to those afi/safi pairs that
12570 * actually have something interesting in them
12572 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12577 json_afi_safi
= json_object_new_array();
12578 json_object_object_add(
12580 get_afi_safi_str(afi
, safi
, true),
12583 json_afi_safi
= NULL
;
12586 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12590 vty_json(vty
, json_all
);
12592 return CMD_SUCCESS
;
12595 /* BGP route print out function without JSON */
12596 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12597 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12598 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12602 BGP_INSTANCE_HELP_STR
12605 "BGP RIB advertisement statistics\n"
12608 afi_t afi
= AFI_IP6
;
12609 safi_t safi
= SAFI_UNICAST
;
12610 struct bgp
*bgp
= NULL
;
12612 bool uj
= use_json(argc
, argv
);
12613 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12615 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12618 return CMD_WARNING
;
12621 json_afi_safi
= json_object_new_array();
12623 json_afi_safi
= NULL
;
12625 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12628 json
= json_object_new_object();
12629 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12631 vty_json(vty
, json
);
12636 /* BGP route print out function without JSON */
12637 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12638 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12639 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12641 statistics [json]",
12642 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12643 BGP_SAFI_WITH_LABEL_HELP_STR
12644 "BGP RIB advertisement statistics\n" JSON_STR
)
12646 afi_t afi
= AFI_IP6
;
12647 safi_t safi
= SAFI_UNICAST
;
12648 struct bgp
*bgp
= NULL
;
12650 bool uj
= use_json(argc
, argv
);
12651 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12653 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12656 return CMD_WARNING
;
12659 json_afi_safi
= json_object_new_array();
12661 json_afi_safi
= NULL
;
12663 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12666 json
= json_object_new_object();
12667 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12669 vty_json(vty
, json
);
12674 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12675 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12676 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12677 "]] [all$all] dampening parameters [json]",
12678 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12679 BGP_SAFI_WITH_LABEL_HELP_STR
12680 "Display the entries for all address families\n"
12681 "Display detailed information about dampening\n"
12682 "Display detail of configured dampening parameters\n"
12685 afi_t afi
= AFI_IP6
;
12686 safi_t safi
= SAFI_UNICAST
;
12687 struct bgp
*bgp
= NULL
;
12689 uint16_t show_flags
= 0;
12690 bool uj
= use_json(argc
, argv
);
12694 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12697 /* [<ipv4|ipv6> [all]] */
12699 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12700 if (argv_find(argv
, argc
, "ipv4", &idx
))
12701 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12703 if (argv_find(argv
, argc
, "ipv6", &idx
))
12704 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12707 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12710 return CMD_WARNING
;
12712 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12715 /* BGP route print out function */
12716 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12717 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12718 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12722 |dampening <flap-statistics|dampened-paths>\
12723 |community [AA:NN|local-AS|no-advertise|no-export\
12724 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12725 |accept-own|accept-own-nexthop|route-filter-v6\
12726 |route-filter-v4|route-filter-translated-v6\
12727 |route-filter-translated-v4] [exact-match]\
12728 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12729 |filter-list AS_PATH_FILTER_NAME\
12731 |access-list ACCESSLIST_NAME\
12732 |route-map RMAP_NAME\
12733 |rpki <invalid|valid|notfound>\
12734 |version (1-4294967295)\
12736 |A.B.C.D/M longer-prefixes\
12737 |X:X::X:X/M longer-prefixes\
12738 |"BGP_SELF_ORIG_CMD_STR
"\
12739 |detail-routes$detail_routes\
12740 ] [json$uj [detail$detail_json] | wide$wide]",
12741 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12742 BGP_SAFI_WITH_LABEL_HELP_STR
12743 "Display the entries for all address families\n"
12744 "Display only routes with non-natural netmasks\n"
12745 "Display detailed information about dampening\n"
12746 "Display flap statistics of routes\n"
12747 "Display paths suppressed due to dampening\n"
12748 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12749 "Do not send outside local AS (well-known community)\n"
12750 "Do not advertise to any peer (well-known community)\n"
12751 "Do not export to next AS (well-known community)\n"
12752 "Graceful shutdown (well-known community)\n"
12753 "Do not export to any peer (well-known community)\n"
12754 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12755 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12756 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12757 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12758 "Should accept VPN route with local nexthop (well-known community)\n"
12759 "RT VPNv6 route filtering (well-known community)\n"
12760 "RT VPNv4 route filtering (well-known community)\n"
12761 "RT translated VPNv6 route filtering (well-known community)\n"
12762 "RT translated VPNv4 route filtering (well-known community)\n"
12763 "Exact match of the communities\n"
12764 "Community-list number\n"
12765 "Community-list name\n"
12766 "Display routes matching the community-list\n"
12767 "Exact match of the communities\n"
12768 "Display routes conforming to the filter-list\n"
12769 "Regular expression access list name\n"
12770 "Display routes conforming to the prefix-list\n"
12771 "Prefix-list name\n"
12772 "Display routes conforming to the access-list\n"
12773 "Access-list name\n"
12774 "Display routes matching the route-map\n"
12775 "A route-map to match on\n"
12776 "RPKI route types\n"
12777 "A valid path as determined by rpki\n"
12778 "A invalid path as determined by rpki\n"
12779 "A path that has no rpki data\n"
12780 "Display prefixes with matching version numbers\n"
12781 "Version number and above\n"
12782 "Display prefixes with matching BGP community alias\n"
12783 "BGP community alias\n"
12785 "Display route and more specific routes\n"
12787 "Display route and more specific routes\n"
12788 BGP_SELF_ORIG_HELP_STR
12789 "Display detailed version of all routes\n"
12791 "Display detailed version of JSON output\n"
12792 "Increase table width for longer prefixes\n")
12794 afi_t afi
= AFI_IP6
;
12795 safi_t safi
= SAFI_UNICAST
;
12796 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12797 void *output_arg
= NULL
;
12798 struct bgp
*bgp
= NULL
;
12800 int exact_match
= 0;
12801 char *community
= NULL
;
12803 uint16_t show_flags
= 0;
12804 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12809 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12813 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12816 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12818 /* [<ipv4|ipv6> [all]] */
12820 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12822 if (argv_find(argv
, argc
, "ipv4", &idx
))
12823 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12825 if (argv_find(argv
, argc
, "ipv6", &idx
))
12826 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12830 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12832 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12835 return CMD_WARNING
;
12837 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12838 sh_type
= bgp_show_type_cidr_only
;
12840 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12841 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12842 sh_type
= bgp_show_type_dampend_paths
;
12843 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12844 sh_type
= bgp_show_type_flap_statistics
;
12847 if (argv_find(argv
, argc
, "community", &idx
)) {
12848 char *maybecomm
= NULL
;
12850 if (idx
+ 1 < argc
) {
12851 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12852 maybecomm
= argv
[idx
+ 1]->arg
;
12854 maybecomm
= argv
[idx
+ 1]->text
;
12857 if (maybecomm
&& !strmatch(maybecomm
, "json")
12858 && !strmatch(maybecomm
, "exact-match"))
12859 community
= maybecomm
;
12861 if (argv_find(argv
, argc
, "exact-match", &idx
))
12865 sh_type
= bgp_show_type_community_all
;
12868 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12869 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12870 struct community_list
*list
;
12872 if (argv_find(argv
, argc
, "exact-match", &idx
))
12875 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12876 COMMUNITY_LIST_MASTER
);
12877 if (list
== NULL
) {
12878 vty_out(vty
, "%% %s community-list not found\n",
12879 clist_number_or_name
);
12880 return CMD_WARNING
;
12884 sh_type
= bgp_show_type_community_list_exact
;
12886 sh_type
= bgp_show_type_community_list
;
12890 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12891 const char *filter
= argv
[++idx
]->arg
;
12892 struct as_list
*as_list
;
12894 as_list
= as_list_lookup(filter
);
12895 if (as_list
== NULL
) {
12896 vty_out(vty
, "%% %s AS-path access-list not found\n",
12898 return CMD_WARNING
;
12901 sh_type
= bgp_show_type_filter_list
;
12902 output_arg
= as_list
;
12905 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12906 const char *prefix_list_str
= argv
[++idx
]->arg
;
12907 struct prefix_list
*plist
;
12909 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12910 if (plist
== NULL
) {
12911 vty_out(vty
, "%% %s prefix-list not found\n",
12913 return CMD_WARNING
;
12916 sh_type
= bgp_show_type_prefix_list
;
12917 output_arg
= plist
;
12920 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12921 const char *access_list_str
= argv
[++idx
]->arg
;
12922 struct access_list
*alist
;
12924 alist
= access_list_lookup(afi
, access_list_str
);
12926 vty_out(vty
, "%% %s access-list not found\n",
12928 return CMD_WARNING
;
12931 sh_type
= bgp_show_type_access_list
;
12932 output_arg
= alist
;
12935 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12936 const char *rmap_str
= argv
[++idx
]->arg
;
12937 struct route_map
*rmap
;
12939 rmap
= route_map_lookup_by_name(rmap_str
);
12941 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12942 return CMD_WARNING
;
12945 sh_type
= bgp_show_type_route_map
;
12949 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12950 sh_type
= bgp_show_type_rpki
;
12951 if (argv_find(argv
, argc
, "valid", &idx
))
12952 rpki_target_state
= RPKI_VALID
;
12953 else if (argv_find(argv
, argc
, "invalid", &idx
))
12954 rpki_target_state
= RPKI_INVALID
;
12957 /* Display prefixes with matching version numbers */
12958 if (argv_find(argv
, argc
, "version", &idx
)) {
12959 sh_type
= bgp_show_type_prefix_version
;
12960 output_arg
= argv
[idx
+ 1]->arg
;
12963 /* Display prefixes with matching BGP community alias */
12964 if (argv_find(argv
, argc
, "alias", &idx
)) {
12965 sh_type
= bgp_show_type_community_alias
;
12966 output_arg
= argv
[idx
+ 1]->arg
;
12969 /* prefix-longer */
12970 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12971 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12972 const char *prefix_str
= argv
[idx
]->arg
;
12974 if (!str2prefix(prefix_str
, &p
)) {
12975 vty_out(vty
, "%% Malformed Prefix\n");
12976 return CMD_WARNING
;
12979 sh_type
= bgp_show_type_prefix_longer
;
12983 /* self originated only */
12984 if (argv_find(argv
, argc
, BGP_SELF_ORIG_CMD_STR
, &idx
))
12985 sh_type
= bgp_show_type_self_originated
;
12988 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12990 return bgp_show_community(vty
, bgp
, community
,
12991 exact_match
, afi
, safi
,
12994 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12995 output_arg
, show_flags
,
12996 rpki_target_state
);
12998 struct listnode
*node
;
13000 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
13004 vty_out(vty
, "{\n");
13006 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13007 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
13008 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13011 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
13012 FOREACH_SAFI (safi
) {
13013 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
13021 vty_out(vty
, ",\n");
13022 vty_out(vty
, "\"%s\":{\n",
13023 get_afi_safi_str(afi
,
13028 "\nFor address family: %s\n",
13034 bgp_show_community(
13035 vty
, abgp
, community
,
13036 exact_match
, afi
, safi
,
13039 bgp_show(vty
, abgp
, afi
, safi
,
13040 sh_type
, output_arg
,
13042 rpki_target_state
);
13044 vty_out(vty
, "}\n");
13048 /* show <ip> bgp all: for each AFI and SAFI*/
13049 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
13050 FOREACH_AFI_SAFI (afi
, safi
) {
13051 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
13059 vty_out(vty
, ",\n");
13061 vty_out(vty
, "\"%s\":{\n",
13062 get_afi_safi_str(afi
,
13067 "\nFor address family: %s\n",
13073 bgp_show_community(
13074 vty
, abgp
, community
,
13075 exact_match
, afi
, safi
,
13078 bgp_show(vty
, abgp
, afi
, safi
,
13079 sh_type
, output_arg
,
13081 rpki_target_state
);
13083 vty_out(vty
, "}\n");
13088 vty_out(vty
, "}\n");
13090 return CMD_SUCCESS
;
13093 DEFUN (show_ip_bgp_route
,
13094 show_ip_bgp_route_cmd
,
13095 "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]",
13099 BGP_INSTANCE_HELP_STR
13101 BGP_SAFI_WITH_LABEL_HELP_STR
13102 "Network in the BGP routing table to display\n"
13104 "Network in the BGP routing table to display\n"
13106 "Display only the bestpath\n"
13107 "Display only multipaths\n"
13108 "Display only paths that match the specified rpki state\n"
13109 "A valid path as determined by rpki\n"
13110 "A invalid path as determined by rpki\n"
13111 "A path that has no rpki data\n"
13114 int prefix_check
= 0;
13116 afi_t afi
= AFI_IP6
;
13117 safi_t safi
= SAFI_UNICAST
;
13118 char *prefix
= NULL
;
13119 struct bgp
*bgp
= NULL
;
13120 enum bgp_path_type path_type
;
13121 bool uj
= use_json(argc
, argv
);
13125 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13128 return CMD_WARNING
;
13132 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13133 return CMD_WARNING
;
13136 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13137 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13138 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13140 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13141 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13144 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13145 && afi
!= AFI_IP6
) {
13147 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13148 return CMD_WARNING
;
13150 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13151 && afi
!= AFI_IP
) {
13153 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13154 return CMD_WARNING
;
13157 prefix
= argv
[idx
]->arg
;
13159 /* [<bestpath|multipath>] */
13160 if (argv_find(argv
, argc
, "bestpath", &idx
))
13161 path_type
= BGP_PATH_SHOW_BESTPATH
;
13162 else if (argv_find(argv
, argc
, "multipath", &idx
))
13163 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13165 path_type
= BGP_PATH_SHOW_ALL
;
13167 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13168 path_type
, RPKI_NOT_BEING_USED
, uj
);
13171 DEFUN (show_ip_bgp_regexp
,
13172 show_ip_bgp_regexp_cmd
,
13173 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13177 BGP_INSTANCE_HELP_STR
13179 BGP_SAFI_WITH_LABEL_HELP_STR
13180 "Display routes matching the AS path regular expression\n"
13181 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13184 afi_t afi
= AFI_IP6
;
13185 safi_t safi
= SAFI_UNICAST
;
13186 struct bgp
*bgp
= NULL
;
13187 bool uj
= use_json(argc
, argv
);
13188 char *regstr
= NULL
;
13191 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13194 return CMD_WARNING
;
13196 // get index of regex
13197 if (argv_find(argv
, argc
, "REGEX", &idx
))
13198 regstr
= argv
[idx
]->arg
;
13201 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13202 bgp_show_type_regexp
, uj
);
13205 DEFPY (show_ip_bgp_instance_all
,
13206 show_ip_bgp_instance_all_cmd
,
13207 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13211 BGP_INSTANCE_ALL_HELP_STR
13213 BGP_SAFI_WITH_LABEL_HELP_STR
13215 "Increase table width for longer prefixes\n")
13217 afi_t afi
= AFI_IP6
;
13218 safi_t safi
= SAFI_UNICAST
;
13219 struct bgp
*bgp
= NULL
;
13221 uint16_t show_flags
= 0;
13225 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13229 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13231 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13234 return CMD_WARNING
;
13236 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13237 return CMD_SUCCESS
;
13240 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13241 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13246 uint16_t show_flags
= 0;
13249 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13251 if (!config_bgp_aspath_validate(regstr
)) {
13252 vty_out(vty
, "Invalid character in REGEX %s\n",
13254 return CMD_WARNING_CONFIG_FAILED
;
13257 regex
= bgp_regcomp(regstr
);
13259 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13260 return CMD_WARNING
;
13263 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13264 RPKI_NOT_BEING_USED
);
13265 bgp_regex_free(regex
);
13269 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13270 const char *comstr
, int exact
, afi_t afi
,
13271 safi_t safi
, uint16_t show_flags
)
13273 struct community
*com
;
13276 com
= community_str2com(comstr
);
13278 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13279 return CMD_WARNING
;
13282 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13283 (exact
? bgp_show_type_community_exact
13284 : bgp_show_type_community
),
13285 com
, show_flags
, RPKI_NOT_BEING_USED
);
13286 community_free(&com
);
13292 BGP_STATS_MAXBITLEN
= 0,
13294 BGP_STATS_PREFIXES
,
13296 BGP_STATS_UNAGGREGATEABLE
,
13297 BGP_STATS_MAX_AGGREGATEABLE
,
13298 BGP_STATS_AGGREGATES
,
13300 BGP_STATS_ASPATH_COUNT
,
13301 BGP_STATS_ASPATH_MAXHOPS
,
13302 BGP_STATS_ASPATH_TOTHOPS
,
13303 BGP_STATS_ASPATH_MAXSIZE
,
13304 BGP_STATS_ASPATH_TOTSIZE
,
13305 BGP_STATS_ASN_HIGHEST
,
13309 #define TABLE_STATS_IDX_VTY 0
13310 #define TABLE_STATS_IDX_JSON 1
13312 static const char *table_stats_strs
[][2] = {
13313 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13314 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13315 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13316 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13317 "unaggregateablePrefixes"},
13318 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13319 "maximumAggregateablePrefixes"},
13320 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13321 "bgpAggregateAdvertisements"},
13322 [BGP_STATS_SPACE
] = {"Address space advertised",
13323 "addressSpaceAdvertised"},
13324 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13325 "advertisementsWithPaths"},
13326 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13328 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13330 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13331 "averageAsPathLengthHops"},
13332 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13333 "averageAsPathSizeBytes"},
13334 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13335 [BGP_STATS_MAX
] = {NULL
, NULL
}
13338 struct bgp_table_stats
{
13339 struct bgp_table
*table
;
13340 unsigned long long counts
[BGP_STATS_MAX
];
13343 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13346 double total_space
;
13349 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13350 struct bgp_table_stats
*ts
, unsigned int space
)
13352 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13353 struct bgp_path_info
*pi
;
13354 const struct prefix
*rn_p
;
13356 if (!bgp_dest_has_bgp_path_info_data(dest
))
13359 rn_p
= bgp_dest_get_prefix(dest
);
13360 ts
->counts
[BGP_STATS_PREFIXES
]++;
13361 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13363 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13364 /* check if the prefix is included by any other announcements */
13365 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13366 pdest
= bgp_dest_parent_nolock(pdest
);
13368 if (pdest
== NULL
|| pdest
== top
) {
13369 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13370 /* announced address space */
13372 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13373 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13374 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13377 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13378 ts
->counts
[BGP_STATS_RIB
]++;
13380 if (CHECK_FLAG(pi
->attr
->flag
,
13381 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13382 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13384 /* as-path stats */
13385 if (pi
->attr
->aspath
) {
13386 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13387 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13388 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13390 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13392 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13393 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13395 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13396 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13398 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13399 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13400 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13401 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13406 static void bgp_table_stats_walker(struct event
*t
)
13408 struct bgp_dest
*dest
, *ndest
;
13409 struct bgp_dest
*top
;
13410 struct bgp_table_stats
*ts
= EVENT_ARG(t
);
13411 unsigned int space
= 0;
13413 if (!(top
= bgp_table_top(ts
->table
)))
13416 switch (ts
->table
->afi
) {
13418 space
= IPV4_MAX_BITLEN
;
13421 space
= IPV6_MAX_BITLEN
;
13424 space
= EVPN_ROUTE_PREFIXLEN
;
13431 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13433 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13434 if (ts
->table
->safi
== SAFI_MPLS_VPN
13435 || ts
->table
->safi
== SAFI_ENCAP
13436 || ts
->table
->safi
== SAFI_EVPN
) {
13437 struct bgp_table
*table
;
13439 table
= bgp_dest_get_bgp_table_info(dest
);
13443 top
= bgp_table_top(table
);
13444 for (ndest
= bgp_table_top(table
); ndest
;
13445 ndest
= bgp_route_next(ndest
))
13446 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13448 bgp_table_stats_rn(dest
, top
, ts
, space
);
13453 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13454 struct json_object
*json_array
)
13456 struct listnode
*node
, *nnode
;
13459 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13460 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13463 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13464 safi_t safi
, struct json_object
*json_array
)
13466 struct bgp_table_stats ts
;
13468 int ret
= CMD_SUCCESS
;
13470 struct json_object
*json
= NULL
;
13471 uint32_t bitlen
= 0;
13472 struct json_object
*json_bitlen
;
13475 json
= json_object_new_object();
13477 if (!bgp
->rib
[afi
][safi
]) {
13478 char warning_msg
[50];
13480 snprintf(warning_msg
, sizeof(warning_msg
),
13481 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13485 vty_out(vty
, "%s\n", warning_msg
);
13487 json_object_string_add(json
, "warning", warning_msg
);
13490 goto end_table_stats
;
13494 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13495 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13497 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13499 /* labeled-unicast routes live in the unicast table */
13500 if (safi
== SAFI_LABELED_UNICAST
)
13501 safi
= SAFI_UNICAST
;
13503 memset(&ts
, 0, sizeof(ts
));
13504 ts
.table
= bgp
->rib
[afi
][safi
];
13505 event_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13507 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13508 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13509 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13513 case BGP_STATS_ASPATH_TOTHOPS
:
13514 case BGP_STATS_ASPATH_TOTSIZE
:
13517 temp_buf
, sizeof(temp_buf
), "%12.2f",
13519 ? (float)ts
.counts
[i
]
13521 [BGP_STATS_ASPATH_COUNT
]
13523 vty_out(vty
, "%-30s: %s",
13524 table_stats_strs
[i
]
13525 [TABLE_STATS_IDX_VTY
],
13528 json_object_double_add(
13530 table_stats_strs
[i
]
13531 [TABLE_STATS_IDX_JSON
],
13533 ? (double)ts
.counts
[i
]
13534 / (double)ts
.counts
13535 [BGP_STATS_ASPATH_COUNT
]
13539 case BGP_STATS_TOTPLEN
:
13542 temp_buf
, sizeof(temp_buf
), "%12.2f",
13544 ? (float)ts
.counts
[i
]
13546 [BGP_STATS_PREFIXES
]
13548 vty_out(vty
, "%-30s: %s",
13549 table_stats_strs
[i
]
13550 [TABLE_STATS_IDX_VTY
],
13553 json_object_double_add(
13555 table_stats_strs
[i
]
13556 [TABLE_STATS_IDX_JSON
],
13558 ? (double)ts
.counts
[i
]
13559 / (double)ts
.counts
13560 [BGP_STATS_PREFIXES
]
13564 case BGP_STATS_SPACE
:
13566 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13568 vty_out(vty
, "%-30s: %s\n",
13569 table_stats_strs
[i
]
13570 [TABLE_STATS_IDX_VTY
],
13573 json_object_double_add(
13575 table_stats_strs
[i
]
13576 [TABLE_STATS_IDX_JSON
],
13577 (double)ts
.total_space
);
13579 if (afi
== AFI_IP6
) {
13581 snprintf(temp_buf
, sizeof(temp_buf
),
13584 * pow(2.0, -128 + 32));
13585 vty_out(vty
, "%30s: %s\n",
13586 "/32 equivalent %s\n",
13589 json_object_double_add(
13590 json
, "/32equivalent",
13591 (double)(ts
.total_space
13596 snprintf(temp_buf
, sizeof(temp_buf
),
13599 * pow(2.0, -128 + 48));
13600 vty_out(vty
, "%30s: %s\n",
13601 "/48 equivalent %s\n",
13604 json_object_double_add(
13605 json
, "/48equivalent",
13606 (double)(ts
.total_space
13612 snprintf(temp_buf
, sizeof(temp_buf
),
13614 ts
.total_space
* 100.
13616 vty_out(vty
, "%30s: %s\n",
13617 "% announced ", temp_buf
);
13619 json_object_double_add(
13620 json
, "%announced",
13621 (double)(ts
.total_space
* 100.
13625 snprintf(temp_buf
, sizeof(temp_buf
),
13628 * pow(2.0, -32 + 8));
13629 vty_out(vty
, "%30s: %s\n",
13630 "/8 equivalent ", temp_buf
);
13632 json_object_double_add(
13633 json
, "/8equivalent",
13634 (double)(ts
.total_space
13635 * pow(2.0, -32 + 8)));
13638 snprintf(temp_buf
, sizeof(temp_buf
),
13641 * pow(2.0, -32 + 24));
13642 vty_out(vty
, "%30s: %s\n",
13643 "/24 equivalent ", temp_buf
);
13645 json_object_double_add(
13646 json
, "/24equivalent",
13647 (double)(ts
.total_space
13648 * pow(2.0, -32 + 24)));
13654 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13656 vty_out(vty
, "%-30s: %s",
13657 table_stats_strs
[i
]
13658 [TABLE_STATS_IDX_VTY
],
13661 json_object_int_add(
13663 table_stats_strs
[i
]
13664 [TABLE_STATS_IDX_JSON
],
13669 vty_out(vty
, "\n");
13674 bitlen
= IPV4_MAX_BITLEN
;
13677 bitlen
= IPV6_MAX_BITLEN
;
13680 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13688 json_bitlen
= json_object_new_array();
13690 for (i
= 0; i
<= bitlen
; i
++) {
13691 struct json_object
*ind_bit
= json_object_new_object();
13693 if (!ts
.prefix_len_count
[i
])
13696 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13697 json_object_int_add(ind_bit
, temp_buf
,
13698 ts
.prefix_len_count
[i
]);
13699 json_object_array_add(json_bitlen
, ind_bit
);
13701 json_object_object_add(json
, "prefixLength", json_bitlen
);
13706 json_object_array_add(json_array
, json
);
13710 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13711 safi_t safi
, struct json_object
*json_array
)
13714 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13715 return CMD_SUCCESS
;
13718 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13730 PCOUNT_BPATH_SELECTED
,
13731 PCOUNT_PFCNT
, /* the figure we display to users */
13735 static const char *const pcount_strs
[] = {
13736 [PCOUNT_ADJ_IN
] = "Adj-in",
13737 [PCOUNT_DAMPED
] = "Damped",
13738 [PCOUNT_REMOVED
] = "Removed",
13739 [PCOUNT_HISTORY
] = "History",
13740 [PCOUNT_STALE
] = "Stale",
13741 [PCOUNT_VALID
] = "Valid",
13742 [PCOUNT_ALL
] = "All RIB",
13743 [PCOUNT_COUNTED
] = "PfxCt counted",
13744 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13745 [PCOUNT_PFCNT
] = "Useable",
13746 [PCOUNT_MAX
] = NULL
,
13749 struct peer_pcounts
{
13750 unsigned int count
[PCOUNT_MAX
];
13751 const struct peer
*peer
;
13752 const struct bgp_table
*table
;
13756 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13758 const struct bgp_adj_in
*ain
;
13759 const struct bgp_path_info
*pi
;
13760 const struct peer
*peer
= pc
->peer
;
13762 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13763 if (ain
->peer
== peer
)
13764 pc
->count
[PCOUNT_ADJ_IN
]++;
13766 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13768 if (pi
->peer
!= peer
)
13771 pc
->count
[PCOUNT_ALL
]++;
13773 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13774 pc
->count
[PCOUNT_DAMPED
]++;
13775 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13776 pc
->count
[PCOUNT_HISTORY
]++;
13777 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13778 pc
->count
[PCOUNT_REMOVED
]++;
13779 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13780 pc
->count
[PCOUNT_STALE
]++;
13781 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13782 pc
->count
[PCOUNT_VALID
]++;
13783 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13784 pc
->count
[PCOUNT_PFCNT
]++;
13785 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13786 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13788 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13789 pc
->count
[PCOUNT_COUNTED
]++;
13790 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13792 EC_LIB_DEVELOPMENT
,
13793 "Attempting to count but flags say it is unusable");
13795 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13797 EC_LIB_DEVELOPMENT
,
13798 "Not counted but flags say we should");
13803 static void bgp_peer_count_walker(struct event
*t
)
13805 struct bgp_dest
*rn
, *rm
;
13806 const struct bgp_table
*table
;
13807 struct peer_pcounts
*pc
= EVENT_ARG(t
);
13809 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13810 || pc
->safi
== SAFI_EVPN
) {
13811 /* Special handling for 2-level routing tables. */
13812 for (rn
= bgp_table_top(pc
->table
); rn
;
13813 rn
= bgp_route_next(rn
)) {
13814 table
= bgp_dest_get_bgp_table_info(rn
);
13816 for (rm
= bgp_table_top(table
); rm
;
13817 rm
= bgp_route_next(rm
))
13818 bgp_peer_count_proc(rm
, pc
);
13821 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13822 bgp_peer_count_proc(rn
, pc
);
13825 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13826 safi_t safi
, bool use_json
)
13828 struct peer_pcounts pcounts
= {.peer
= peer
};
13830 json_object
*json
= NULL
;
13831 json_object
*json_loop
= NULL
;
13834 json
= json_object_new_object();
13835 json_loop
= json_object_new_object();
13838 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13839 || !peer
->bgp
->rib
[afi
][safi
]) {
13841 json_object_string_add(
13843 "No such neighbor or address family");
13844 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13845 json_object_free(json
);
13846 json_object_free(json_loop
);
13848 vty_out(vty
, "%% No such neighbor or address family\n");
13850 return CMD_WARNING
;
13853 memset(&pcounts
, 0, sizeof(pcounts
));
13854 pcounts
.peer
= peer
;
13855 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13856 pcounts
.safi
= safi
;
13858 /* in-place call via thread subsystem so as to record execution time
13859 * stats for the thread-walk (i.e. ensure this can't be blamed on
13860 * on just vty_read()).
13862 event_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13865 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13866 json_object_string_add(json
, "multiProtocol",
13867 get_afi_safi_str(afi
, safi
, true));
13868 json_object_int_add(json
, "pfxCounter",
13869 peer
->pcount
[afi
][safi
]);
13871 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13872 json_object_int_add(json_loop
, pcount_strs
[i
],
13875 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13877 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13878 json_object_string_add(json
, "pfxctDriftFor",
13880 json_object_string_add(
13881 json
, "recommended",
13882 "Please report this bug, with the above command output");
13884 vty_json(vty
, json
);
13888 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13889 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13890 peer
->hostname
, peer
->host
,
13891 get_afi_safi_str(afi
, safi
, false));
13893 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13894 get_afi_safi_str(afi
, safi
, false));
13897 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13898 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13900 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13901 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13904 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13905 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13907 "Please report this bug, with the above command output\n");
13911 return CMD_SUCCESS
;
13914 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13915 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13916 "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]",
13920 BGP_INSTANCE_HELP_STR
13923 "Detailed information on TCP and BGP neighbor connections\n"
13924 "Neighbor to display information about\n"
13925 "Neighbor to display information about\n"
13926 "Neighbor on BGP configured interface\n"
13927 "Display detailed prefix count information\n"
13930 afi_t afi
= AFI_IP6
;
13931 safi_t safi
= SAFI_UNICAST
;
13934 struct bgp
*bgp
= NULL
;
13935 bool uj
= use_json(argc
, argv
);
13940 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13943 return CMD_WARNING
;
13945 argv_find(argv
, argc
, "neighbors", &idx
);
13946 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13948 return CMD_WARNING
;
13950 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13953 #ifdef KEEP_OLD_VPN_COMMANDS
13954 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13955 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13956 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13961 "Display information about all VPNv4 NLRIs\n"
13962 "Detailed information on TCP and BGP neighbor connections\n"
13963 "Neighbor to display information about\n"
13964 "Neighbor to display information about\n"
13965 "Neighbor on BGP configured interface\n"
13966 "Display detailed prefix count information\n"
13971 bool uj
= use_json(argc
, argv
);
13973 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13975 return CMD_WARNING
;
13977 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13980 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13981 show_ip_bgp_vpn_all_route_prefix_cmd
,
13982 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13987 "Display information about all VPNv4 NLRIs\n"
13988 "Network in the BGP routing table to display\n"
13989 "Network in the BGP routing table to display\n"
13993 char *network
= NULL
;
13994 struct bgp
*bgp
= bgp_get_default();
13996 vty_out(vty
, "Can't find default instance\n");
13997 return CMD_WARNING
;
14000 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
14001 network
= argv
[idx
]->arg
;
14002 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
14003 network
= argv
[idx
]->arg
;
14005 vty_out(vty
, "Unable to figure out Network\n");
14006 return CMD_WARNING
;
14009 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
14010 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14011 use_json(argc
, argv
));
14013 #endif /* KEEP_OLD_VPN_COMMANDS */
14015 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
14016 show_bgp_l2vpn_evpn_route_prefix_cmd
,
14017 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
14022 "Network in the BGP routing table to display\n"
14023 "Network in the BGP routing table to display\n"
14024 "Network in the BGP routing table to display\n"
14025 "Network in the BGP routing table to display\n"
14029 char *network
= NULL
;
14030 int prefix_check
= 0;
14032 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
14033 argv_find(argv
, argc
, "X:X::X:X", &idx
))
14034 network
= argv
[idx
]->arg
;
14035 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
14036 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
14037 network
= argv
[idx
]->arg
;
14040 vty_out(vty
, "Unable to figure out Network\n");
14041 return CMD_WARNING
;
14043 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
14044 prefix_check
, BGP_PATH_SHOW_ALL
,
14045 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
14048 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
14049 struct bgp_table
*table
, int *header1
,
14050 int *header2
, json_object
*json
,
14051 json_object
*json_scode
,
14052 json_object
*json_ocode
, bool wide
,
14055 uint64_t version
= table
? table
->version
: 0;
14059 json_object_int_add(json
, "bgpTableVersion", version
);
14060 json_object_string_addf(json
, "bgpLocalRouterId",
14061 "%pI4", &peer
->bgp
->router_id
);
14062 json_object_int_add(json
, "defaultLocPrf",
14063 peer
->bgp
->default_local_pref
);
14064 json_object_int_add(json
, "localAS",
14065 peer
->change_local_as
14066 ? peer
->change_local_as
14068 json_object_object_add(json
, "bgpStatusCodes",
14070 json_object_object_add(json
, "bgpOriginCodes",
14074 "BGP table version is %" PRIu64
14075 ", local router ID is %pI4, vrf id ",
14076 version
, &peer
->bgp
->router_id
);
14077 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
14078 vty_out(vty
, "%s", VRFID_NONE_STR
);
14080 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
14081 vty_out(vty
, "\n");
14082 vty_out(vty
, "Default local pref %u, ",
14083 peer
->bgp
->default_local_pref
);
14084 vty_out(vty
, "local AS %u\n",
14085 peer
->change_local_as
? peer
->change_local_as
14088 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14089 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14090 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14091 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14097 if (!json
&& !detail
)
14098 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14099 : BGP_SHOW_HEADER
));
14105 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14106 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14107 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14108 json_object
*json_scode
, json_object
*json_ocode
,
14109 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14110 const struct prefix
*match
, unsigned long *output_count
,
14111 unsigned long *filtered_count
)
14113 struct bgp_adj_in
*ain
= NULL
;
14114 struct bgp_adj_out
*adj
= NULL
;
14115 struct bgp_dest
*dest
;
14119 struct update_subgroup
*subgrp
;
14120 struct peer_af
*paf
= NULL
;
14121 bool route_filtered
;
14122 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14123 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14124 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14125 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14126 || (safi
== SAFI_EVPN
))
14130 json_object
*json_net
= NULL
;
14134 /* If the user supplied a prefix, look for a matching route instead
14135 * of walking the whole table.
14138 dest
= bgp_node_match(table
, match
);
14141 vty_out(vty
, "Network not in table\n");
14145 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14147 if (rn_p
->prefixlen
!= match
->prefixlen
) {
14149 vty_out(vty
, "Network not in table\n");
14150 bgp_dest_unlock_node(dest
);
14154 if (type
== bgp_show_adj_route_received
||
14155 type
== bgp_show_adj_route_filtered
) {
14156 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14157 if (ain
->peer
== peer
) {
14162 /* bail out if if adj_out is empty, or
14163 * if the prefix isn't in this peer's
14166 if (!ain
|| ain
->peer
!= peer
) {
14168 vty_out(vty
, "Network not in table\n");
14169 bgp_dest_unlock_node(dest
);
14172 } else if (type
== bgp_show_adj_route_advertised
) {
14173 bool peer_found
= false;
14175 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
) {
14176 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14177 if (paf
->peer
== peer
&& adj
->attr
) {
14186 /* bail out if if adj_out is empty, or
14187 * if the prefix isn't in this peer's
14190 if (!paf
|| !peer_found
) {
14192 vty_out(vty
, "Network not in table\n");
14193 bgp_dest_unlock_node(dest
);
14198 ret
= bgp_output_modifier(peer
, rn_p
, &attr
, afi
, safi
,
14201 if (ret
!= RMAP_DENY
) {
14202 show_adj_route_header(vty
, peer
, table
, header1
,
14203 header2
, json
, json_scode
,
14204 json_ocode
, wide
, detail
);
14207 json_net
= json_object_new_object();
14209 bgp_show_path_info(NULL
/* prefix_rd */, dest
, vty
, bgp
,
14210 afi
, safi
, json_net
,
14211 BGP_PATH_SHOW_ALL
, &display
,
14212 RPKI_NOT_BEING_USED
);
14214 json_object_object_addf(json_ar
, json_net
,
14218 (*filtered_count
)++;
14220 bgp_attr_flush(&attr
);
14221 bgp_dest_unlock_node(dest
);
14226 subgrp
= peer_subgroup(peer
, afi
, safi
);
14228 if (type
== bgp_show_adj_route_advertised
&& subgrp
14229 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14231 json_object_int_add(json
, "bgpTableVersion",
14233 json_object_string_addf(json
, "bgpLocalRouterId",
14234 "%pI4", &bgp
->router_id
);
14235 json_object_int_add(json
, "defaultLocPrf",
14236 bgp
->default_local_pref
);
14237 json_object_int_add(json
, "localAS",
14238 peer
->change_local_as
14239 ? peer
->change_local_as
14241 json_object_object_add(json
, "bgpStatusCodes",
14243 json_object_object_add(json
, "bgpOriginCodes",
14245 json_object_string_add(
14246 json
, "bgpOriginatingDefaultNetwork",
14247 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14250 "BGP table version is %" PRIu64
14251 ", local router ID is %pI4, vrf id ",
14252 table
->version
, &bgp
->router_id
);
14253 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14254 vty_out(vty
, "%s", VRFID_NONE_STR
);
14256 vty_out(vty
, "%u", bgp
->vrf_id
);
14257 vty_out(vty
, "\n");
14258 vty_out(vty
, "Default local pref %u, ",
14259 bgp
->default_local_pref
);
14260 vty_out(vty
, "local AS %u\n",
14261 peer
->change_local_as
? peer
->change_local_as
14264 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14265 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14266 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14267 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14270 vty_out(vty
, "Originating default network %s\n\n",
14271 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14277 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14278 if (type
== bgp_show_adj_route_received
14279 || type
== bgp_show_adj_route_filtered
) {
14280 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14281 if (ain
->peer
!= peer
)
14283 show_adj_route_header(vty
, peer
, table
, header1
,
14284 header2
, json
, json_scode
,
14285 json_ocode
, wide
, detail
);
14287 if ((safi
== SAFI_MPLS_VPN
)
14288 || (safi
== SAFI_ENCAP
)
14289 || (safi
== SAFI_EVPN
)) {
14291 json_object_string_add(
14292 json_ar
, "rd", rd_str
);
14293 else if (show_rd
&& rd_str
) {
14295 "Route Distinguisher: %s\n",
14302 route_filtered
= false;
14304 /* Filter prefix using distribute list,
14305 * filter list or prefix list
14307 const struct prefix
*rn_p
=
14308 bgp_dest_get_prefix(dest
);
14309 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14312 route_filtered
= true;
14314 /* Filter prefix using route-map */
14315 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14316 safi
, rmap_name
, NULL
,
14319 if (type
== bgp_show_adj_route_filtered
&&
14320 !route_filtered
&& ret
!= RMAP_DENY
) {
14321 bgp_attr_flush(&attr
);
14325 if (type
== bgp_show_adj_route_received
14326 && (route_filtered
|| ret
== RMAP_DENY
))
14327 (*filtered_count
)++;
14332 json_object_new_object();
14334 struct bgp_path_info bpi
;
14335 struct bgp_dest buildit
= *dest
;
14336 struct bgp_dest
*pass_in
;
14338 if (route_filtered
||
14339 ret
== RMAP_DENY
) {
14342 buildit
.info
= &bpi
;
14344 pass_in
= &buildit
;
14347 bgp_show_path_info(
14348 NULL
, pass_in
, vty
, bgp
, afi
,
14350 BGP_PATH_SHOW_ALL
, &display
,
14351 RPKI_NOT_BEING_USED
);
14353 json_object_object_addf(
14357 route_vty_out_tmp(vty
, dest
, rn_p
,
14358 &attr
, safi
, use_json
,
14360 bgp_attr_flush(&attr
);
14363 } else if (type
== bgp_show_adj_route_advertised
) {
14364 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14365 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14366 if (paf
->peer
!= peer
|| !adj
->attr
)
14369 show_adj_route_header(
14370 vty
, peer
, table
, header1
,
14371 header2
, json
, json_scode
,
14372 json_ocode
, wide
, detail
);
14374 const struct prefix
*rn_p
=
14375 bgp_dest_get_prefix(dest
);
14378 ret
= bgp_output_modifier(
14379 peer
, rn_p
, &attr
, afi
, safi
,
14382 if (ret
!= RMAP_DENY
) {
14383 if ((safi
== SAFI_MPLS_VPN
)
14384 || (safi
== SAFI_ENCAP
)
14385 || (safi
== SAFI_EVPN
)) {
14387 json_object_string_add(
14394 "Route Distinguisher: %s\n",
14402 json_object_new_object();
14403 bgp_show_path_info(
14412 RPKI_NOT_BEING_USED
);
14414 json_object_object_addf(
14427 (*filtered_count
)++;
14430 bgp_attr_flush(&attr
);
14432 } else if (type
== bgp_show_adj_route_bestpath
) {
14433 struct bgp_path_info
*pi
;
14435 show_adj_route_header(vty
, peer
, table
, header1
,
14436 header2
, json
, json_scode
,
14437 json_ocode
, wide
, detail
);
14439 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14441 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14443 if (pi
->peer
!= peer
)
14446 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14452 json_object_new_object();
14453 bgp_show_path_info(
14454 NULL
/* prefix_rd */, dest
, vty
,
14455 bgp
, afi
, safi
, json_net
,
14456 BGP_PATH_SHOW_BESTPATH
,
14457 &display
, RPKI_NOT_BEING_USED
);
14459 json_object_object_addf(
14464 vty
, dest
, rn_p
, pi
->attr
, safi
,
14465 use_json
, json_ar
, wide
);
14472 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14473 safi_t safi
, enum bgp_show_adj_route_type type
,
14474 const char *rmap_name
, const struct prefix
*match
,
14475 uint16_t show_flags
)
14478 struct bgp_table
*table
;
14479 json_object
*json
= NULL
;
14480 json_object
*json_scode
= NULL
;
14481 json_object
*json_ocode
= NULL
;
14482 json_object
*json_ar
= NULL
;
14483 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14485 /* Init BGP headers here so they're only displayed once
14486 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14492 * Initialize variables for each RD
14493 * All prefixes under an RD is aggregated within "json_routes"
14495 char rd_str
[BUFSIZ
] = {0};
14496 json_object
*json_routes
= NULL
;
14499 /* For 2-tier tables, prefix counts need to be
14500 * maintained across multiple runs of show_adj_route()
14502 unsigned long output_count_per_rd
;
14503 unsigned long filtered_count_per_rd
;
14504 unsigned long output_count
= 0;
14505 unsigned long filtered_count
= 0;
14508 json
= json_object_new_object();
14509 json_ar
= json_object_new_object();
14510 json_scode
= json_object_new_object();
14511 json_ocode
= json_object_new_object();
14512 #if CONFDATE > 20231208
14513 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14515 json_object_string_add(json_scode
, "suppressed", "s");
14516 json_object_string_add(json_scode
, "damped", "d");
14517 json_object_string_add(json_scode
, "history", "h");
14518 json_object_string_add(json_scode
, "valid", "*");
14519 json_object_string_add(json_scode
, "best", ">");
14520 json_object_string_add(json_scode
, "multipath", "=");
14521 json_object_string_add(json_scode
, "internal", "i");
14522 json_object_string_add(json_scode
, "ribFailure", "r");
14523 json_object_string_add(json_scode
, "stale", "S");
14524 json_object_string_add(json_scode
, "removed", "R");
14526 #if CONFDATE > 20231208
14527 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14529 json_object_string_add(json_ocode
, "igp", "i");
14530 json_object_string_add(json_ocode
, "egp", "e");
14531 json_object_string_add(json_ocode
, "incomplete", "?");
14534 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14536 json_object_string_add(
14538 "No such neighbor or address family");
14539 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14540 json_object_free(json
);
14541 json_object_free(json_ar
);
14542 json_object_free(json_scode
);
14543 json_object_free(json_ocode
);
14545 vty_out(vty
, "%% No such neighbor or address family\n");
14547 return CMD_WARNING
;
14550 if ((type
== bgp_show_adj_route_received
14551 || type
== bgp_show_adj_route_filtered
)
14552 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14553 PEER_FLAG_SOFT_RECONFIG
)) {
14555 json_object_string_add(
14557 "Inbound soft reconfiguration not enabled");
14558 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14559 json_object_free(json
);
14560 json_object_free(json_ar
);
14561 json_object_free(json_scode
);
14562 json_object_free(json_ocode
);
14565 "%% Inbound soft reconfiguration not enabled\n");
14567 return CMD_WARNING
;
14572 /* labeled-unicast routes live in the unicast table */
14573 if (safi
== SAFI_LABELED_UNICAST
)
14574 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14576 table
= bgp
->rib
[afi
][safi
];
14578 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14579 || (safi
== SAFI_EVPN
)) {
14581 struct bgp_dest
*dest
;
14583 for (dest
= bgp_table_top(table
); dest
;
14584 dest
= bgp_route_next(dest
)) {
14585 table
= bgp_dest_get_bgp_table_info(dest
);
14589 output_count_per_rd
= 0;
14590 filtered_count_per_rd
= 0;
14593 json_routes
= json_object_new_object();
14595 const struct prefix_rd
*prd
;
14596 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14599 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
),
14603 vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14604 json
, json_routes
, json_scode
, json_ocode
,
14605 show_flags
, &header1
, &header2
, rd_str
, match
,
14606 &output_count_per_rd
, &filtered_count_per_rd
);
14608 /* Don't include an empty RD in the output! */
14609 if (json_routes
&& (output_count_per_rd
> 0))
14610 json_object_object_add(json_ar
, rd_str
,
14613 output_count
+= output_count_per_rd
;
14614 filtered_count
+= filtered_count_per_rd
;
14617 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14618 json
, json_ar
, json_scode
, json_ocode
,
14619 show_flags
, &header1
, &header2
, rd_str
, match
,
14620 &output_count
, &filtered_count
);
14623 if (type
== bgp_show_adj_route_advertised
)
14624 json_object_object_add(json
, "advertisedRoutes",
14627 json_object_object_add(json
, "receivedRoutes", json_ar
);
14628 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14629 json_object_int_add(json
, "filteredPrefixCounter",
14633 * These fields only give up ownership to `json` when `header1`
14634 * is used (set to zero). See code in `show_adj_route` and
14635 * `show_adj_route_header`.
14637 if (header1
== 1) {
14638 json_object_free(json_scode
);
14639 json_object_free(json_ocode
);
14642 vty_json(vty
, json
);
14643 } else if (output_count
> 0) {
14644 if (!match
&& filtered_count
> 0)
14646 "\nTotal number of prefixes %ld (%ld filtered)\n",
14647 output_count
, filtered_count
);
14649 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14653 return CMD_SUCCESS
;
14656 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14657 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14658 "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]",
14662 BGP_INSTANCE_HELP_STR
14664 BGP_SAFI_WITH_LABEL_HELP_STR
14665 "Detailed information on TCP and BGP neighbor connections\n"
14666 "Neighbor to display information about\n"
14667 "Neighbor to display information about\n"
14668 "Neighbor on BGP configured interface\n"
14669 "Display the routes selected by best path\n"
14670 "Display detailed version of routes\n"
14672 "Increase table width for longer prefixes\n")
14674 afi_t afi
= AFI_IP6
;
14675 safi_t safi
= SAFI_UNICAST
;
14676 char *rmap_name
= NULL
;
14677 char *peerstr
= NULL
;
14678 struct bgp
*bgp
= NULL
;
14680 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14682 uint16_t show_flags
= 0;
14685 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14688 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14691 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14693 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14697 return CMD_WARNING
;
14699 argv_find(argv
, argc
, "neighbors", &idx
);
14700 peerstr
= argv
[++idx
]->arg
;
14702 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14704 return CMD_WARNING
;
14706 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, NULL
,
14710 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14711 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14712 "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]",
14716 BGP_INSTANCE_HELP_STR
14718 BGP_SAFI_WITH_LABEL_HELP_STR
14719 "Display the entries for all address families\n"
14720 "Detailed information on TCP and BGP neighbor connections\n"
14721 "Neighbor to display information about\n"
14722 "Neighbor to display information about\n"
14723 "Neighbor on BGP configured interface\n"
14724 "Display the routes advertised to a BGP neighbor\n"
14725 "Display the received routes from neighbor\n"
14726 "Display the filtered routes received from neighbor\n"
14727 "Route-map to modify the attributes\n"
14728 "Name of the route map\n"
14731 "Display detailed version of routes\n"
14733 "Increase table width for longer prefixes\n")
14735 afi_t afi
= AFI_IP6
;
14736 safi_t safi
= SAFI_UNICAST
;
14737 char *peerstr
= NULL
;
14738 struct bgp
*bgp
= NULL
;
14740 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14743 uint16_t show_flags
= 0;
14744 struct listnode
*node
;
14747 if (detail
|| prefix_str
)
14748 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14752 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14756 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14757 if (argv_find(argv
, argc
, "ipv4", &idx
))
14758 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14760 if (argv_find(argv
, argc
, "ipv6", &idx
))
14761 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14765 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14767 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14770 return CMD_WARNING
;
14772 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14773 argv_find(argv
, argc
, "neighbors", &idx
);
14774 peerstr
= argv
[++idx
]->arg
;
14776 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14778 return CMD_WARNING
;
14780 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14781 type
= bgp_show_adj_route_advertised
;
14782 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14783 type
= bgp_show_adj_route_received
;
14784 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14785 type
= bgp_show_adj_route_filtered
;
14788 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14789 prefix_str
? prefix
: NULL
, show_flags
);
14791 vty_out(vty
, "{\n");
14793 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14794 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14795 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14797 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14798 FOREACH_SAFI (safi
) {
14799 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14806 vty_out(vty
, ",\n");
14807 vty_out(vty
, "\"%s\":",
14808 get_afi_safi_str(afi
, safi
,
14812 "\nFor address family: %s\n",
14813 get_afi_safi_str(afi
, safi
,
14816 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14817 route_map
, prefix
, show_flags
);
14821 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14822 FOREACH_AFI_SAFI (afi
, safi
) {
14823 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14830 vty_out(vty
, ",\n");
14831 vty_out(vty
, "\"%s\":",
14832 get_afi_safi_str(afi
, safi
,
14836 "\nFor address family: %s\n",
14837 get_afi_safi_str(afi
, safi
,
14840 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14841 route_map
, prefix
, show_flags
);
14846 vty_out(vty
, "}\n");
14848 return CMD_SUCCESS
;
14851 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14852 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14853 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14857 BGP_INSTANCE_HELP_STR
14860 BGP_AF_MODIFIER_STR
14861 "Detailed information on TCP and BGP neighbor connections\n"
14862 "Neighbor to display information about\n"
14863 "Neighbor to display information about\n"
14864 "Neighbor on BGP configured interface\n"
14865 "Display information received from a BGP neighbor\n"
14866 "Display the prefixlist filter\n"
14869 afi_t afi
= AFI_IP6
;
14870 safi_t safi
= SAFI_UNICAST
;
14871 char *peerstr
= NULL
;
14876 struct bgp
*bgp
= NULL
;
14877 bool uj
= use_json(argc
, argv
);
14882 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14885 return CMD_WARNING
;
14887 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14888 argv_find(argv
, argc
, "neighbors", &idx
);
14889 peerstr
= argv
[++idx
]->arg
;
14891 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14893 return CMD_WARNING
;
14895 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14896 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14899 vty_out(vty
, "Address Family: %s\n",
14900 get_afi_safi_str(afi
, safi
, false));
14901 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14904 vty_out(vty
, "{}\n");
14906 vty_out(vty
, "No functional output\n");
14909 return CMD_SUCCESS
;
14912 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14913 afi_t afi
, safi_t safi
,
14914 enum bgp_show_type type
, bool use_json
)
14916 uint16_t show_flags
= 0;
14919 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14921 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14923 json_object
*json_no
= NULL
;
14924 json_no
= json_object_new_object();
14925 json_object_string_add(
14926 json_no
, "warning",
14927 "No such neighbor or address family");
14928 vty_out(vty
, "%s\n",
14929 json_object_to_json_string(json_no
));
14930 json_object_free(json_no
);
14932 vty_out(vty
, "%% No such neighbor or address family\n");
14933 return CMD_WARNING
;
14936 /* labeled-unicast routes live in the unicast table */
14937 if (safi
== SAFI_LABELED_UNICAST
)
14938 safi
= SAFI_UNICAST
;
14940 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14941 RPKI_NOT_BEING_USED
);
14945 * Used for "detailed" output for cmds like show bgp <afi> <safi> (or)
14946 * show bgp <vrf> (or) show bgp <vrf> <afi> <safi>
14948 DEFPY(show_ip_bgp_vrf_afi_safi_routes_detailed
,
14949 show_ip_bgp_vrf_afi_safi_routes_detailed_cmd
,
14950 "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf_name] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] detail [json$uj]",
14954 BGP_INSTANCE_HELP_STR
14956 BGP_SAFI_WITH_LABEL_HELP_STR
14957 "Detailed information\n"
14960 afi_t afi
= AFI_IP6
;
14961 safi_t safi
= SAFI_UNICAST
;
14962 struct bgp
*bgp
= NULL
;
14964 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14967 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14969 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14972 return CMD_WARNING
;
14973 /* 'vrf all' case to iterate all vrfs & show output per vrf instance */
14974 if (vrf_name
&& strmatch(vrf_name
, "all")) {
14975 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
14976 return CMD_SUCCESS
;
14979 /* All other cases except vrf all */
14980 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14981 show_flags
, RPKI_NOT_BEING_USED
);
14984 DEFUN (show_ip_bgp_neighbor_routes
,
14985 show_ip_bgp_neighbor_routes_cmd
,
14986 "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]",
14990 BGP_INSTANCE_HELP_STR
14992 BGP_SAFI_WITH_LABEL_HELP_STR
14993 "Detailed information on TCP and BGP neighbor connections\n"
14994 "Neighbor to display information about\n"
14995 "Neighbor to display information about\n"
14996 "Neighbor on BGP configured interface\n"
14997 "Display flap statistics of the routes learned from neighbor\n"
14998 "Display the dampened routes received from neighbor\n"
14999 "Display routes learned from neighbor\n"
15002 char *peerstr
= NULL
;
15003 struct bgp
*bgp
= NULL
;
15004 afi_t afi
= AFI_IP6
;
15005 safi_t safi
= SAFI_UNICAST
;
15007 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
15009 bool uj
= use_json(argc
, argv
);
15014 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
15017 return CMD_WARNING
;
15019 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
15020 argv_find(argv
, argc
, "neighbors", &idx
);
15021 peerstr
= argv
[++idx
]->arg
;
15023 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
15025 return CMD_WARNING
;
15027 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
15028 sh_type
= bgp_show_type_flap_neighbor
;
15029 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
15030 sh_type
= bgp_show_type_damp_neighbor
;
15031 else if (argv_find(argv
, argc
, "routes", &idx
))
15032 sh_type
= bgp_show_type_neighbor
;
15034 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
15037 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
15039 struct bgp_distance
{
15040 /* Distance value for the IP source prefix. */
15043 /* Name of the access-list to be matched. */
15047 DEFUN (show_bgp_afi_vpn_rd_route
,
15048 show_bgp_afi_vpn_rd_route_cmd
,
15049 "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]",
15053 BGP_AF_MODIFIER_STR
15054 "Display information for a route distinguisher\n"
15055 "Route Distinguisher\n"
15056 "All Route Distinguishers\n"
15057 "Network in the BGP routing table to display\n"
15058 "Network in the BGP routing table to display\n"
15062 struct prefix_rd prd
;
15063 afi_t afi
= AFI_MAX
;
15066 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
15067 vty_out(vty
, "%% Malformed Address Family\n");
15068 return CMD_WARNING
;
15071 if (!strcmp(argv
[5]->arg
, "all"))
15072 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
15073 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
15074 RPKI_NOT_BEING_USED
,
15075 use_json(argc
, argv
));
15077 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
15079 vty_out(vty
, "%% Malformed Route Distinguisher\n");
15080 return CMD_WARNING
;
15083 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
15084 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
15085 use_json(argc
, argv
));
15088 static struct bgp_distance
*bgp_distance_new(void)
15090 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
15093 static void bgp_distance_free(struct bgp_distance
*bdistance
)
15095 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
15098 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
15099 const char *ip_str
, const char *access_list_str
)
15106 struct bgp_dest
*dest
;
15107 struct bgp_distance
*bdistance
;
15109 afi
= bgp_node_afi(vty
);
15110 safi
= bgp_node_safi(vty
);
15112 ret
= str2prefix(ip_str
, &p
);
15114 vty_out(vty
, "Malformed prefix\n");
15115 return CMD_WARNING_CONFIG_FAILED
;
15118 distance
= atoi(distance_str
);
15120 /* Get BGP distance node. */
15121 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
15122 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15124 bgp_dest_unlock_node(dest
);
15126 bdistance
= bgp_distance_new();
15127 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
15130 /* Set distance value. */
15131 bdistance
->distance
= distance
;
15133 /* Reset access-list configuration. */
15134 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15135 if (access_list_str
)
15136 bdistance
->access_list
=
15137 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
15139 return CMD_SUCCESS
;
15142 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
15143 const char *ip_str
, const char *access_list_str
)
15150 struct bgp_dest
*dest
;
15151 struct bgp_distance
*bdistance
;
15153 afi
= bgp_node_afi(vty
);
15154 safi
= bgp_node_safi(vty
);
15156 ret
= str2prefix(ip_str
, &p
);
15158 vty_out(vty
, "Malformed prefix\n");
15159 return CMD_WARNING_CONFIG_FAILED
;
15162 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
15164 vty_out(vty
, "Can't find specified prefix\n");
15165 return CMD_WARNING_CONFIG_FAILED
;
15168 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15169 distance
= atoi(distance_str
);
15171 if (bdistance
->distance
!= distance
) {
15172 vty_out(vty
, "Distance does not match configured\n");
15173 bgp_dest_unlock_node(dest
);
15174 return CMD_WARNING_CONFIG_FAILED
;
15177 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15178 bgp_distance_free(bdistance
);
15180 bgp_dest_set_bgp_path_info(dest
, NULL
);
15181 bgp_dest_unlock_node(dest
);
15182 bgp_dest_unlock_node(dest
);
15184 return CMD_SUCCESS
;
15187 /* Apply BGP information to distance method. */
15188 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
15189 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
15191 struct bgp_dest
*dest
;
15192 struct prefix q
= {0};
15194 struct bgp_distance
*bdistance
;
15195 struct access_list
*alist
;
15196 struct bgp_static
*bgp_static
;
15197 struct bgp_path_info
*bpi_ultimate
;
15202 peer
= pinfo
->peer
;
15204 if (pinfo
->attr
->distance
)
15205 return pinfo
->attr
->distance
;
15207 /* get peer origin to calculate appropriate distance */
15208 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
15209 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
15210 peer
= bpi_ultimate
->peer
;
15213 /* Check source address.
15214 * Note: for aggregate route, peer can have unspec af type.
15216 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
15217 && !sockunion2hostprefix(&peer
->su
, &q
))
15220 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
15222 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15223 bgp_dest_unlock_node(dest
);
15225 if (bdistance
->access_list
) {
15226 alist
= access_list_lookup(afi
, bdistance
->access_list
);
15228 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
15229 return bdistance
->distance
;
15231 return bdistance
->distance
;
15234 /* Backdoor check. */
15235 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
15237 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15238 bgp_dest_unlock_node(dest
);
15240 if (bgp_static
->backdoor
) {
15241 if (bgp
->distance_local
[afi
][safi
])
15242 return bgp
->distance_local
[afi
][safi
];
15244 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15248 if (peer
->sort
== BGP_PEER_EBGP
) {
15249 if (bgp
->distance_ebgp
[afi
][safi
])
15250 return bgp
->distance_ebgp
[afi
][safi
];
15251 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15252 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15253 if (bgp
->distance_ibgp
[afi
][safi
])
15254 return bgp
->distance_ibgp
[afi
][safi
];
15255 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15257 if (bgp
->distance_local
[afi
][safi
])
15258 return bgp
->distance_local
[afi
][safi
];
15259 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15263 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15264 * we should tell ZEBRA update the routes for a specific
15265 * AFI/SAFI to reflect changes in RIB.
15267 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15269 safi_t update_safi
)
15274 FOREACH_AFI_SAFI (afi
, safi
) {
15275 if (!bgp_fibupd_safi(safi
))
15278 if (afi
!= update_afi
&& safi
!= update_safi
)
15281 if (BGP_DEBUG(zebra
, ZEBRA
))
15283 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15284 __func__
, afi
, safi
);
15285 bgp_zebra_announce_table(bgp
, afi
, safi
);
15289 DEFUN (bgp_distance
,
15291 "distance bgp (1-255) (1-255) (1-255)",
15292 "Define an administrative distance\n"
15294 "Distance for routes external to the AS\n"
15295 "Distance for routes internal to the AS\n"
15296 "Distance for local routes\n")
15298 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15299 int idx_number
= 2;
15300 int idx_number_2
= 3;
15301 int idx_number_3
= 4;
15302 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15303 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15304 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15308 afi
= bgp_node_afi(vty
);
15309 safi
= bgp_node_safi(vty
);
15311 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15312 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15313 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15314 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15315 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15316 bgp
->distance_local
[afi
][safi
] = distance_local
;
15317 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15319 return CMD_SUCCESS
;
15322 DEFUN (no_bgp_distance
,
15323 no_bgp_distance_cmd
,
15324 "no distance bgp [(1-255) (1-255) (1-255)]",
15326 "Define an administrative distance\n"
15328 "Distance for routes external to the AS\n"
15329 "Distance for routes internal to the AS\n"
15330 "Distance for local routes\n")
15332 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15336 afi
= bgp_node_afi(vty
);
15337 safi
= bgp_node_safi(vty
);
15339 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15340 || bgp
->distance_ibgp
[afi
][safi
] != 0
15341 || bgp
->distance_local
[afi
][safi
] != 0) {
15342 bgp
->distance_ebgp
[afi
][safi
] = 0;
15343 bgp
->distance_ibgp
[afi
][safi
] = 0;
15344 bgp
->distance_local
[afi
][safi
] = 0;
15345 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15347 return CMD_SUCCESS
;
15351 DEFUN (bgp_distance_source
,
15352 bgp_distance_source_cmd
,
15353 "distance (1-255) A.B.C.D/M",
15354 "Define an administrative distance\n"
15355 "Administrative distance\n"
15356 "IP source prefix\n")
15358 int idx_number
= 1;
15359 int idx_ipv4_prefixlen
= 2;
15360 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15361 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15362 return CMD_SUCCESS
;
15365 DEFUN (no_bgp_distance_source
,
15366 no_bgp_distance_source_cmd
,
15367 "no distance (1-255) A.B.C.D/M",
15369 "Define an administrative distance\n"
15370 "Administrative distance\n"
15371 "IP source prefix\n")
15373 int idx_number
= 2;
15374 int idx_ipv4_prefixlen
= 3;
15375 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15376 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15377 return CMD_SUCCESS
;
15380 DEFUN (bgp_distance_source_access_list
,
15381 bgp_distance_source_access_list_cmd
,
15382 "distance (1-255) A.B.C.D/M WORD",
15383 "Define an administrative distance\n"
15384 "Administrative distance\n"
15385 "IP source prefix\n"
15386 "Access list name\n")
15388 int idx_number
= 1;
15389 int idx_ipv4_prefixlen
= 2;
15391 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15392 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15393 return CMD_SUCCESS
;
15396 DEFUN (no_bgp_distance_source_access_list
,
15397 no_bgp_distance_source_access_list_cmd
,
15398 "no distance (1-255) A.B.C.D/M WORD",
15400 "Define an administrative distance\n"
15401 "Administrative distance\n"
15402 "IP source prefix\n"
15403 "Access list name\n")
15405 int idx_number
= 2;
15406 int idx_ipv4_prefixlen
= 3;
15408 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15409 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15410 return CMD_SUCCESS
;
15413 DEFUN (ipv6_bgp_distance_source
,
15414 ipv6_bgp_distance_source_cmd
,
15415 "distance (1-255) X:X::X:X/M",
15416 "Define an administrative distance\n"
15417 "Administrative distance\n"
15418 "IP source prefix\n")
15420 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15421 return CMD_SUCCESS
;
15424 DEFUN (no_ipv6_bgp_distance_source
,
15425 no_ipv6_bgp_distance_source_cmd
,
15426 "no distance (1-255) X:X::X:X/M",
15428 "Define an administrative distance\n"
15429 "Administrative distance\n"
15430 "IP source prefix\n")
15432 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15433 return CMD_SUCCESS
;
15436 DEFUN (ipv6_bgp_distance_source_access_list
,
15437 ipv6_bgp_distance_source_access_list_cmd
,
15438 "distance (1-255) X:X::X:X/M WORD",
15439 "Define an administrative distance\n"
15440 "Administrative distance\n"
15441 "IP source prefix\n"
15442 "Access list name\n")
15444 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15445 return CMD_SUCCESS
;
15448 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15449 no_ipv6_bgp_distance_source_access_list_cmd
,
15450 "no distance (1-255) X:X::X:X/M WORD",
15452 "Define an administrative distance\n"
15453 "Administrative distance\n"
15454 "IP source prefix\n"
15455 "Access list name\n")
15457 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15458 return CMD_SUCCESS
;
15461 DEFUN (bgp_damp_set
,
15463 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15464 "BGP Specific commands\n"
15465 "Enable route-flap dampening\n"
15466 "Half-life time for the penalty\n"
15467 "Value to start reusing a route\n"
15468 "Value to start suppressing a route\n"
15469 "Maximum duration to suppress a stable route\n")
15471 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15472 int idx_half_life
= 2;
15474 int idx_suppress
= 4;
15475 int idx_max_suppress
= 5;
15476 int half
= DEFAULT_HALF_LIFE
* 60;
15477 int reuse
= DEFAULT_REUSE
;
15478 int suppress
= DEFAULT_SUPPRESS
;
15479 int max
= 4 * half
;
15482 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15483 reuse
= atoi(argv
[idx_reuse
]->arg
);
15484 suppress
= atoi(argv
[idx_suppress
]->arg
);
15485 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15486 } else if (argc
== 3) {
15487 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15492 * These can't be 0 but our SA doesn't understand the
15493 * way our cli is constructed
15497 if (suppress
< reuse
) {
15499 "Suppress value cannot be less than reuse value \n");
15503 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15504 reuse
, suppress
, max
);
15507 DEFUN (bgp_damp_unset
,
15508 bgp_damp_unset_cmd
,
15509 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15511 "BGP Specific commands\n"
15512 "Enable route-flap dampening\n"
15513 "Half-life time for the penalty\n"
15514 "Value to start reusing a route\n"
15515 "Value to start suppressing a route\n"
15516 "Maximum duration to suppress a stable route\n")
15518 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15519 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15522 /* Display specified route of BGP table. */
15523 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15524 const char *ip_str
, afi_t afi
, safi_t safi
,
15525 struct prefix_rd
*prd
, int prefix_check
)
15528 struct prefix match
;
15529 struct bgp_dest
*dest
;
15530 struct bgp_dest
*rm
;
15531 struct bgp_path_info
*pi
;
15532 struct bgp_path_info
*pi_temp
;
15534 struct bgp_table
*table
;
15536 /* BGP structure lookup. */
15538 bgp
= bgp_lookup_by_name(view_name
);
15540 vty_out(vty
, "%% Can't find BGP instance %s\n",
15542 return CMD_WARNING
;
15545 bgp
= bgp_get_default();
15547 vty_out(vty
, "%% No BGP process is configured\n");
15548 return CMD_WARNING
;
15552 /* Check IP address argument. */
15553 ret
= str2prefix(ip_str
, &match
);
15555 vty_out(vty
, "%% address is malformed\n");
15556 return CMD_WARNING
;
15559 match
.family
= afi2family(afi
);
15561 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15562 || (safi
== SAFI_EVPN
)) {
15563 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15564 dest
= bgp_route_next(dest
)) {
15565 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15567 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15569 table
= bgp_dest_get_bgp_table_info(dest
);
15572 rm
= bgp_node_match(table
, &match
);
15576 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15579 || rm_p
->prefixlen
== match
.prefixlen
) {
15580 pi
= bgp_dest_get_bgp_path_info(rm
);
15582 if (pi
->extra
&& pi
->extra
->damp_info
) {
15583 pi_temp
= pi
->next
;
15584 bgp_damp_info_free(
15585 pi
->extra
->damp_info
,
15593 bgp_dest_unlock_node(rm
);
15596 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15597 if (dest
!= NULL
) {
15598 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15601 || dest_p
->prefixlen
== match
.prefixlen
) {
15602 pi
= bgp_dest_get_bgp_path_info(dest
);
15604 if (pi
->extra
&& pi
->extra
->damp_info
) {
15605 pi_temp
= pi
->next
;
15606 bgp_damp_info_free(
15607 pi
->extra
->damp_info
,
15615 bgp_dest_unlock_node(dest
);
15619 return CMD_SUCCESS
;
15622 DEFUN (clear_ip_bgp_dampening
,
15623 clear_ip_bgp_dampening_cmd
,
15624 "clear ip bgp dampening",
15628 "Clear route flap dampening information\n")
15630 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15631 return CMD_SUCCESS
;
15634 DEFUN (clear_ip_bgp_dampening_prefix
,
15635 clear_ip_bgp_dampening_prefix_cmd
,
15636 "clear ip bgp dampening A.B.C.D/M",
15640 "Clear route flap dampening information\n"
15643 int idx_ipv4_prefixlen
= 4;
15644 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15645 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15648 DEFUN (clear_ip_bgp_dampening_address
,
15649 clear_ip_bgp_dampening_address_cmd
,
15650 "clear ip bgp dampening A.B.C.D",
15654 "Clear route flap dampening information\n"
15655 "Network to clear damping information\n")
15658 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15659 SAFI_UNICAST
, NULL
, 0);
15662 DEFUN (clear_ip_bgp_dampening_address_mask
,
15663 clear_ip_bgp_dampening_address_mask_cmd
,
15664 "clear ip bgp dampening A.B.C.D A.B.C.D",
15668 "Clear route flap dampening information\n"
15669 "Network to clear damping information\n"
15673 int idx_ipv4_2
= 5;
15675 char prefix_str
[BUFSIZ
];
15677 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15678 prefix_str
, sizeof(prefix_str
));
15680 vty_out(vty
, "%% Inconsistent address and mask\n");
15681 return CMD_WARNING
;
15684 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15688 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15690 struct vty
*vty
= arg
;
15691 struct peer
*peer
= bucket
->data
;
15693 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15696 DEFUN (show_bgp_listeners
,
15697 show_bgp_listeners_cmd
,
15698 "show bgp listeners",
15701 "Display Listen Sockets and who created them\n")
15703 bgp_dump_listener_info(vty
);
15705 return CMD_SUCCESS
;
15708 DEFUN (show_bgp_peerhash
,
15709 show_bgp_peerhash_cmd
,
15710 "show bgp peerhash",
15713 "Display information about the BGP peerhash\n")
15715 struct list
*instances
= bm
->bgp
;
15716 struct listnode
*node
;
15719 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15720 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15721 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15725 return CMD_SUCCESS
;
15728 /* also used for encap safi */
15729 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15730 afi_t afi
, safi_t safi
)
15732 struct bgp_dest
*pdest
;
15733 struct bgp_dest
*dest
;
15734 struct bgp_table
*table
;
15735 const struct prefix
*p
;
15736 struct bgp_static
*bgp_static
;
15737 mpls_label_t label
;
15739 /* Network configuration. */
15740 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15741 pdest
= bgp_route_next(pdest
)) {
15742 table
= bgp_dest_get_bgp_table_info(pdest
);
15746 for (dest
= bgp_table_top(table
); dest
;
15747 dest
= bgp_route_next(dest
)) {
15748 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15749 if (bgp_static
== NULL
)
15752 p
= bgp_dest_get_prefix(dest
);
15754 /* "network" configuration display. */
15755 label
= decode_label(&bgp_static
->label
);
15757 vty_out(vty
, " network %pFX rd %s", p
,
15758 bgp_static
->prd_pretty
);
15759 if (safi
== SAFI_MPLS_VPN
)
15760 vty_out(vty
, " label %u", label
);
15762 if (bgp_static
->rmap
.name
)
15763 vty_out(vty
, " route-map %s",
15764 bgp_static
->rmap
.name
);
15766 if (bgp_static
->backdoor
)
15767 vty_out(vty
, " backdoor");
15769 vty_out(vty
, "\n");
15774 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15775 afi_t afi
, safi_t safi
)
15777 struct bgp_dest
*pdest
;
15778 struct bgp_dest
*dest
;
15779 struct bgp_table
*table
;
15780 const struct prefix
*p
;
15781 struct bgp_static
*bgp_static
;
15782 char buf
[PREFIX_STRLEN
* 2];
15783 char buf2
[SU_ADDRSTRLEN
];
15784 char esi_buf
[ESI_STR_LEN
];
15786 /* Network configuration. */
15787 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15788 pdest
= bgp_route_next(pdest
)) {
15789 table
= bgp_dest_get_bgp_table_info(pdest
);
15793 for (dest
= bgp_table_top(table
); dest
;
15794 dest
= bgp_route_next(dest
)) {
15795 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15796 if (bgp_static
== NULL
)
15799 char *macrouter
= NULL
;
15801 if (bgp_static
->router_mac
)
15802 macrouter
= prefix_mac2str(
15803 bgp_static
->router_mac
, NULL
, 0);
15804 if (bgp_static
->eth_s_id
)
15805 esi_to_str(bgp_static
->eth_s_id
,
15806 esi_buf
, sizeof(esi_buf
));
15807 p
= bgp_dest_get_prefix(dest
);
15809 /* "network" configuration display. */
15810 if (p
->u
.prefix_evpn
.route_type
== 5) {
15811 char local_buf
[PREFIX_STRLEN
];
15813 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15814 struct prefix_evpn
*)p
)
15818 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15820 local_buf
, sizeof(local_buf
));
15821 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15822 p
->u
.prefix_evpn
.prefix_addr
15823 .ip_prefix_length
);
15825 prefix2str(p
, buf
, sizeof(buf
));
15828 if (bgp_static
->gatewayIp
.family
== AF_INET
15829 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15830 inet_ntop(bgp_static
->gatewayIp
.family
,
15831 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15834 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15835 buf
, bgp_static
->prd_pretty
,
15836 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15837 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15840 XFREE(MTYPE_TMP
, macrouter
);
15845 /* Configuration of static route announcement and aggregate
15847 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15850 struct bgp_dest
*dest
;
15851 const struct prefix
*p
;
15852 struct bgp_static
*bgp_static
;
15853 struct bgp_aggregate
*bgp_aggregate
;
15855 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15856 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15860 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15861 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15865 /* Network configuration. */
15866 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15867 dest
= bgp_route_next(dest
)) {
15868 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15869 if (bgp_static
== NULL
)
15872 p
= bgp_dest_get_prefix(dest
);
15874 vty_out(vty
, " network %pFX", p
);
15876 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15877 vty_out(vty
, " label-index %u",
15878 bgp_static
->label_index
);
15880 if (bgp_static
->rmap
.name
)
15881 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15883 if (bgp_static
->backdoor
)
15884 vty_out(vty
, " backdoor");
15886 vty_out(vty
, "\n");
15889 /* Aggregate-address configuration. */
15890 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15891 dest
= bgp_route_next(dest
)) {
15892 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15893 if (bgp_aggregate
== NULL
)
15896 p
= bgp_dest_get_prefix(dest
);
15898 vty_out(vty
, " aggregate-address %pFX", p
);
15900 if (bgp_aggregate
->as_set
)
15901 vty_out(vty
, " as-set");
15903 if (bgp_aggregate
->summary_only
)
15904 vty_out(vty
, " summary-only");
15906 if (bgp_aggregate
->rmap
.name
)
15907 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15909 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15910 vty_out(vty
, " origin %s",
15911 bgp_origin2str(bgp_aggregate
->origin
));
15913 if (bgp_aggregate
->match_med
)
15914 vty_out(vty
, " matching-MED-only");
15916 if (bgp_aggregate
->suppress_map_name
)
15917 vty_out(vty
, " suppress-map %s",
15918 bgp_aggregate
->suppress_map_name
);
15920 vty_out(vty
, "\n");
15924 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15927 struct bgp_dest
*dest
;
15928 struct bgp_distance
*bdistance
;
15930 /* Distance configuration. */
15931 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15932 && bgp
->distance_local
[afi
][safi
]
15933 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15934 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15935 || bgp
->distance_local
[afi
][safi
]
15936 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15937 vty_out(vty
, " distance bgp %d %d %d\n",
15938 bgp
->distance_ebgp
[afi
][safi
],
15939 bgp
->distance_ibgp
[afi
][safi
],
15940 bgp
->distance_local
[afi
][safi
]);
15943 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15944 dest
= bgp_route_next(dest
)) {
15945 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15946 if (bdistance
!= NULL
)
15947 vty_out(vty
, " distance %d %pBD %s\n",
15948 bdistance
->distance
, dest
,
15949 bdistance
->access_list
? bdistance
->access_list
15954 /* Allocate routing table structure and install commands. */
15955 void bgp_route_init(void)
15960 /* Init BGP distance table. */
15961 FOREACH_AFI_SAFI (afi
, safi
)
15962 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15964 /* IPv4 BGP commands. */
15965 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15966 install_element(BGP_NODE
, &bgp_network_cmd
);
15967 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15969 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15971 /* IPv4 unicast configuration. */
15972 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15973 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15974 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15976 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15978 /* IPv4 multicast configuration. */
15979 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15980 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15981 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15982 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15984 /* IPv4 labeled-unicast configuration. */
15985 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15986 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15988 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15989 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15990 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15991 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15992 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15993 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15994 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15995 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15997 install_element(VIEW_NODE
,
15998 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15999 install_element(VIEW_NODE
,
16000 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
16001 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
16002 install_element(VIEW_NODE
,
16003 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
16004 #ifdef KEEP_OLD_VPN_COMMANDS
16005 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
16006 #endif /* KEEP_OLD_VPN_COMMANDS */
16007 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
16008 install_element(VIEW_NODE
,
16009 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
16011 /* BGP dampening clear commands */
16012 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
16013 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
16015 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
16016 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
16019 install_element(ENABLE_NODE
,
16020 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
16021 #ifdef KEEP_OLD_VPN_COMMANDS
16022 install_element(ENABLE_NODE
,
16023 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
16024 #endif /* KEEP_OLD_VPN_COMMANDS */
16026 /* New config IPv6 BGP commands. */
16027 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
16028 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
16029 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
16031 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
16033 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
16035 /* IPv6 labeled unicast address family. */
16036 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
16037 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
16039 install_element(BGP_NODE
, &bgp_distance_cmd
);
16040 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
16041 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
16042 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
16043 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
16044 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
16045 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
16046 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
16047 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
16048 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
16049 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
16050 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
16051 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
16052 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
16053 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
16054 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
16055 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
16056 install_element(BGP_IPV4M_NODE
,
16057 &no_bgp_distance_source_access_list_cmd
);
16058 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
16059 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
16060 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
16061 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
16062 install_element(BGP_IPV6_NODE
,
16063 &ipv6_bgp_distance_source_access_list_cmd
);
16064 install_element(BGP_IPV6_NODE
,
16065 &no_ipv6_bgp_distance_source_access_list_cmd
);
16066 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
16067 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
16068 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
16069 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
16070 install_element(BGP_IPV6M_NODE
,
16071 &ipv6_bgp_distance_source_access_list_cmd
);
16072 install_element(BGP_IPV6M_NODE
,
16073 &no_ipv6_bgp_distance_source_access_list_cmd
);
16075 /* BGP dampening */
16076 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
16077 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
16078 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
16079 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
16080 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
16081 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
16082 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
16083 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
16084 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
16085 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
16086 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
16087 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
16088 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
16089 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
16091 /* Large Communities */
16092 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
16093 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
16095 /* show bgp vrf <afi> <safi> detailed */
16096 install_element(VIEW_NODE
,
16097 &show_ip_bgp_vrf_afi_safi_routes_detailed_cmd
);
16099 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
16100 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
16103 void bgp_route_finish(void)
16108 FOREACH_AFI_SAFI (afi
, safi
) {
16109 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
16110 bgp_distance_table
[afi
][safi
] = NULL
;