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 (pi
&& bgp_aggregate_info_same(pi
, 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
);
8679 if (p
->family
== AF_INET6
)
8680 UNSET_FLAG(attr
.flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
));
8683 case NEXTHOP_TYPE_IFINDEX
:
8684 switch (p
->family
) {
8686 attr
.nexthop
.s_addr
= INADDR_ANY
;
8687 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8688 attr
.mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
8691 memset(&attr
.mp_nexthop_global
, 0,
8692 sizeof(attr
.mp_nexthop_global
));
8693 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8697 case NEXTHOP_TYPE_IPV4
:
8698 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8699 attr
.nexthop
= nexthop
->ipv4
;
8700 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8701 attr
.mp_nexthop_global_in
= nexthop
->ipv4
;
8703 case NEXTHOP_TYPE_IPV6
:
8704 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8705 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8706 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8708 case NEXTHOP_TYPE_BLACKHOLE
:
8709 switch (p
->family
) {
8711 attr
.nexthop
.s_addr
= INADDR_ANY
;
8712 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8713 attr
.mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
8716 memset(&attr
.mp_nexthop_global
, 0,
8717 sizeof(attr
.mp_nexthop_global
));
8718 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8721 attr
.bh_type
= bhtype
;
8724 attr
.nh_type
= nhtype
;
8725 attr
.nh_ifindex
= ifindex
;
8728 attr
.distance
= distance
;
8729 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8733 bgp_attr_set_aigp_metric(&attr
, metric
);
8735 afi
= family2afi(p
->family
);
8737 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8739 struct attr attr_new
;
8741 /* Copy attribute for modification. */
8744 if (red
->redist_metric_flag
) {
8745 attr_new
.med
= red
->redist_metric
;
8746 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8749 /* Apply route-map. */
8750 if (red
->rmap
.name
) {
8751 memset(&rmap_path
, 0, sizeof(rmap_path
));
8752 rmap_path
.peer
= bgp
->peer_self
;
8753 rmap_path
.attr
= &attr_new
;
8755 SET_FLAG(bgp
->peer_self
->rmap_type
,
8756 PEER_RMAP_TYPE_REDISTRIBUTE
);
8758 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8760 bgp
->peer_self
->rmap_type
= 0;
8762 if (ret
== RMAP_DENYMATCH
) {
8763 /* Free uninterned attribute. */
8764 bgp_attr_flush(&attr_new
);
8766 /* Unintern original. */
8767 aspath_unintern(&attr
.aspath
);
8768 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8773 if (bgp_in_graceful_shutdown(bgp
))
8774 bgp_attr_add_gshut_community(&attr_new
);
8776 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8777 SAFI_UNICAST
, p
, NULL
);
8779 new_attr
= bgp_attr_intern(&attr_new
);
8781 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8782 if (bpi
->peer
== bgp
->peer_self
8783 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8787 /* Ensure the (source route) type is updated. */
8789 if (attrhash_cmp(bpi
->attr
, new_attr
)
8790 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8791 bgp_attr_unintern(&new_attr
);
8792 aspath_unintern(&attr
.aspath
);
8793 bgp_dest_unlock_node(bn
);
8796 /* The attribute is changed. */
8797 bgp_path_info_set_flag(bn
, bpi
,
8798 BGP_PATH_ATTR_CHANGED
);
8800 /* Rewrite BGP route information. */
8801 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8802 bgp_path_info_restore(bn
, bpi
);
8804 bgp_aggregate_decrement(
8805 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8806 bgp_attr_unintern(&bpi
->attr
);
8807 bpi
->attr
= new_attr
;
8808 bpi
->uptime
= monotime(NULL
);
8810 /* Process change. */
8811 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8813 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8814 bgp_dest_unlock_node(bn
);
8815 aspath_unintern(&attr
.aspath
);
8817 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8819 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8821 vpn_leak_from_vrf_update(
8822 bgp_get_default(), bgp
, bpi
);
8828 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8829 bgp
->peer_self
, new_attr
, bn
);
8830 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8832 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8833 bgp_path_info_add(bn
, new);
8834 bgp_dest_unlock_node(bn
);
8835 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8836 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8838 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8839 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8841 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8845 /* Unintern original. */
8846 aspath_unintern(&attr
.aspath
);
8849 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8850 unsigned short instance
)
8853 struct bgp_dest
*dest
;
8854 struct bgp_path_info
*pi
;
8855 struct bgp_redist
*red
;
8857 afi
= family2afi(p
->family
);
8859 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8861 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8862 SAFI_UNICAST
, p
, NULL
);
8864 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8865 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8869 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8870 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8872 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8875 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8876 bgp_path_info_delete(dest
, pi
);
8877 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8879 bgp_dest_unlock_node(dest
);
8883 /* Withdraw specified route type's route. */
8884 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8885 unsigned short instance
)
8887 struct bgp_dest
*dest
;
8888 struct bgp_path_info
*pi
;
8889 struct bgp_table
*table
;
8891 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8893 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8894 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8895 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8896 && pi
->instance
== instance
)
8900 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8901 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8903 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8906 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8907 pi
, afi
, SAFI_UNICAST
);
8908 bgp_path_info_delete(dest
, pi
);
8909 if (!CHECK_FLAG(bgp
->flags
,
8910 BGP_FLAG_DELETE_IN_PROGRESS
))
8911 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8913 bgp_path_info_reap(dest
, pi
);
8918 /* Static function to display route. */
8919 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8920 struct vty
*vty
, json_object
*json
, bool wide
)
8923 char buf
[INET6_ADDRSTRLEN
];
8925 if (p
->family
== AF_INET
) {
8927 len
= vty_out(vty
, "%pFX", p
);
8929 json_object_string_add(json
, "prefix",
8930 inet_ntop(p
->family
,
8933 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8934 json_object_string_addf(json
, "network", "%pFX", p
);
8935 json_object_int_add(json
, "version", dest
->version
);
8937 } else if (p
->family
== AF_ETHERNET
) {
8938 len
= vty_out(vty
, "%pFX", p
);
8939 } else if (p
->family
== AF_EVPN
) {
8941 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8943 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8944 } else if (p
->family
== AF_FLOWSPEC
) {
8945 route_vty_out_flowspec(vty
, p
, NULL
,
8947 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8948 NLRI_STRING_FORMAT_MIN
, json
);
8951 len
= vty_out(vty
, "%pFX", p
);
8953 json_object_string_add(json
, "prefix",
8954 inet_ntop(p
->family
,
8957 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8958 json_object_string_addf(json
, "network", "%pFX", p
);
8959 json_object_int_add(json
, "version", dest
->version
);
8964 len
= wide
? (45 - len
) : (17 - len
);
8966 vty_out(vty
, "\n%*s", 20, " ");
8968 vty_out(vty
, "%*s", len
, " ");
8972 enum bgp_display_type
{
8976 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8979 case bgp_path_selection_none
:
8980 return "Nothing to Select";
8981 case bgp_path_selection_first
:
8982 return "First path received";
8983 case bgp_path_selection_evpn_sticky_mac
:
8984 return "EVPN Sticky Mac";
8985 case bgp_path_selection_evpn_seq
:
8986 return "EVPN sequence number";
8987 case bgp_path_selection_evpn_lower_ip
:
8988 return "EVPN lower IP";
8989 case bgp_path_selection_evpn_local_path
:
8990 return "EVPN local ES path";
8991 case bgp_path_selection_evpn_non_proxy
:
8992 return "EVPN non proxy";
8993 case bgp_path_selection_weight
:
8995 case bgp_path_selection_local_pref
:
8996 return "Local Pref";
8997 case bgp_path_selection_accept_own
:
8998 return "Accept Own";
8999 case bgp_path_selection_local_route
:
9000 return "Local Route";
9001 case bgp_path_selection_aigp
:
9003 case bgp_path_selection_confed_as_path
:
9004 return "Confederation based AS Path";
9005 case bgp_path_selection_as_path
:
9007 case bgp_path_selection_origin
:
9009 case bgp_path_selection_med
:
9011 case bgp_path_selection_peer
:
9013 case bgp_path_selection_confed
:
9014 return "Confed Peer Type";
9015 case bgp_path_selection_igp_metric
:
9016 return "IGP Metric";
9017 case bgp_path_selection_older
:
9018 return "Older Path";
9019 case bgp_path_selection_router_id
:
9021 case bgp_path_selection_cluster_length
:
9022 return "Cluster length";
9023 case bgp_path_selection_stale
:
9024 return "Path Staleness";
9025 case bgp_path_selection_local_configured
:
9026 return "Locally configured route";
9027 case bgp_path_selection_neighbor_ip
:
9028 return "Neighbor IP";
9029 case bgp_path_selection_default
:
9030 return "Nothing left to compare";
9032 return "Invalid (internal error)";
9035 /* Print the short form route status for a bgp_path_info */
9036 static void route_vty_short_status_out(struct vty
*vty
,
9037 struct bgp_path_info
*path
,
9038 const struct prefix
*p
,
9039 json_object
*json_path
)
9041 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
9045 /* Route status display. */
9046 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9047 json_object_boolean_true_add(json_path
, "removed");
9049 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9050 json_object_boolean_true_add(json_path
, "stale");
9052 if (path
->extra
&& bgp_path_suppressed(path
))
9053 json_object_boolean_true_add(json_path
, "suppressed");
9055 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9056 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9057 json_object_boolean_true_add(json_path
, "valid");
9060 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9061 json_object_boolean_true_add(json_path
, "history");
9063 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9064 json_object_boolean_true_add(json_path
, "damped");
9066 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9067 json_object_boolean_true_add(json_path
, "bestpath");
9068 json_object_string_add(json_path
, "selectionReason",
9069 bgp_path_selection_reason2str(
9070 path
->net
->reason
));
9073 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9074 json_object_boolean_true_add(json_path
, "multipath");
9076 /* Internal route. */
9077 if ((path
->peer
->as
)
9078 && (path
->peer
->as
== path
->peer
->local_as
))
9079 json_object_string_add(json_path
, "pathFrom",
9082 json_object_string_add(json_path
, "pathFrom",
9088 /* RPKI validation state */
9090 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9092 if (rpki_state
== RPKI_VALID
)
9094 else if (rpki_state
== RPKI_INVALID
)
9096 else if (rpki_state
== RPKI_NOTFOUND
)
9101 /* Route status display. */
9102 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9104 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9106 else if (bgp_path_suppressed(path
))
9108 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9109 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9115 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9117 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9119 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9121 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9126 /* Internal route. */
9127 if (path
->peer
&& (path
->peer
->as
)
9128 && (path
->peer
->as
== path
->peer
->local_as
))
9134 static char *bgp_nexthop_hostname(struct peer
*peer
,
9135 struct bgp_nexthop_cache
*bnc
)
9138 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9139 return peer
->hostname
;
9143 /* called from terminal list command */
9144 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9145 struct bgp_path_info
*path
, int display
, safi_t safi
,
9146 json_object
*json_paths
, bool wide
)
9149 struct attr
*attr
= path
->attr
;
9150 json_object
*json_path
= NULL
;
9151 json_object
*json_nexthops
= NULL
;
9152 json_object
*json_nexthop_global
= NULL
;
9153 json_object
*json_nexthop_ll
= NULL
;
9154 json_object
*json_ext_community
= NULL
;
9155 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9157 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9158 bool nexthop_othervrf
= false;
9159 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9160 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9161 char *nexthop_hostname
=
9162 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9163 char esi_buf
[ESI_STR_LEN
];
9166 json_path
= json_object_new_object();
9168 /* short status lead text */
9169 route_vty_short_status_out(vty
, path
, p
, json_path
);
9172 /* print prefix and mask */
9174 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9176 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9178 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9182 * If vrf id of nexthop is different from that of prefix,
9183 * set up printable string to append
9185 if (path
->extra
&& path
->extra
->bgp_orig
) {
9186 const char *self
= "";
9191 nexthop_othervrf
= true;
9192 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9194 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9195 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9196 "@%s%s", VRFID_NONE_STR
, self
);
9198 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9199 path
->extra
->bgp_orig
->vrf_id
, self
);
9201 if (path
->extra
->bgp_orig
->inst_type
9202 != BGP_INSTANCE_TYPE_DEFAULT
)
9204 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9206 const char *self
= "";
9211 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9215 * For ENCAP and EVPN routes, nexthop address family is not
9216 * neccessarily the same as the prefix address family.
9217 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9218 * EVPN routes are also exchanged with a MP nexthop. Currently,
9220 * is only IPv4, the value will be present in either
9222 * attr->mp_nexthop_global_in
9224 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9226 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9230 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9231 &attr
->mp_nexthop_global_in
);
9234 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9235 &attr
->mp_nexthop_global
);
9238 snprintf(nexthop
, sizeof(nexthop
), "?");
9243 json_nexthop_global
= json_object_new_object();
9245 json_object_string_add(json_nexthop_global
, "ip",
9248 if (path
->peer
->hostname
)
9249 json_object_string_add(json_nexthop_global
,
9251 path
->peer
->hostname
);
9253 json_object_string_add(json_nexthop_global
, "afi",
9254 (af
== AF_INET
) ? "ipv4"
9256 json_object_boolean_true_add(json_nexthop_global
,
9259 if (nexthop_hostname
)
9260 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9261 nexthop_hostname
, vrf_id_str
);
9263 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9265 len
= wide
? (41 - len
) : (16 - len
);
9267 vty_out(vty
, "\n%*s", 36, " ");
9269 vty_out(vty
, "%*s", len
, " ");
9271 } else if (safi
== SAFI_EVPN
) {
9273 json_nexthop_global
= json_object_new_object();
9275 json_object_string_addf(json_nexthop_global
, "ip",
9277 &attr
->mp_nexthop_global_in
);
9279 if (path
->peer
->hostname
)
9280 json_object_string_add(json_nexthop_global
,
9282 path
->peer
->hostname
);
9284 json_object_string_add(json_nexthop_global
, "afi",
9286 json_object_boolean_true_add(json_nexthop_global
,
9289 if (nexthop_hostname
)
9290 len
= vty_out(vty
, "%pI4(%s)%s",
9291 &attr
->mp_nexthop_global_in
,
9292 nexthop_hostname
, vrf_id_str
);
9294 len
= vty_out(vty
, "%pI4%s",
9295 &attr
->mp_nexthop_global_in
,
9298 len
= wide
? (41 - len
) : (16 - len
);
9300 vty_out(vty
, "\n%*s", 36, " ");
9302 vty_out(vty
, "%*s", len
, " ");
9304 } else if (safi
== SAFI_FLOWSPEC
) {
9305 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9307 json_nexthop_global
= json_object_new_object();
9309 json_object_string_add(json_nexthop_global
,
9311 json_object_string_addf(json_nexthop_global
,
9315 if (path
->peer
->hostname
)
9316 json_object_string_add(
9317 json_nexthop_global
, "hostname",
9318 path
->peer
->hostname
);
9320 json_object_boolean_true_add(
9321 json_nexthop_global
,
9324 if (nexthop_hostname
)
9325 len
= vty_out(vty
, "%pI4(%s)%s",
9330 len
= vty_out(vty
, "%pI4%s",
9334 len
= wide
? (41 - len
) : (16 - len
);
9336 vty_out(vty
, "\n%*s", 36, " ");
9338 vty_out(vty
, "%*s", len
, " ");
9341 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9343 json_nexthop_global
= json_object_new_object();
9345 json_object_string_addf(json_nexthop_global
, "ip",
9346 "%pI4", &attr
->nexthop
);
9348 if (path
->peer
->hostname
)
9349 json_object_string_add(json_nexthop_global
,
9351 path
->peer
->hostname
);
9353 json_object_string_add(json_nexthop_global
, "afi",
9355 json_object_boolean_true_add(json_nexthop_global
,
9358 if (nexthop_hostname
)
9359 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9360 nexthop_hostname
, vrf_id_str
);
9362 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9365 len
= wide
? (41 - len
) : (16 - len
);
9367 vty_out(vty
, "\n%*s", 36, " ");
9369 vty_out(vty
, "%*s", len
, " ");
9374 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9376 json_nexthop_global
= json_object_new_object();
9377 json_object_string_addf(json_nexthop_global
, "ip",
9379 &attr
->mp_nexthop_global
);
9381 if (path
->peer
->hostname
)
9382 json_object_string_add(json_nexthop_global
,
9384 path
->peer
->hostname
);
9386 json_object_string_add(json_nexthop_global
, "afi",
9388 json_object_string_add(json_nexthop_global
, "scope",
9391 /* We display both LL & GL if both have been
9393 if ((attr
->mp_nexthop_len
9394 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9395 || (path
->peer
->conf_if
)) {
9396 json_nexthop_ll
= json_object_new_object();
9397 json_object_string_addf(
9398 json_nexthop_ll
, "ip", "%pI6",
9399 &attr
->mp_nexthop_local
);
9401 if (path
->peer
->hostname
)
9402 json_object_string_add(
9403 json_nexthop_ll
, "hostname",
9404 path
->peer
->hostname
);
9406 json_object_string_add(json_nexthop_ll
, "afi",
9408 json_object_string_add(json_nexthop_ll
, "scope",
9411 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9412 &attr
->mp_nexthop_local
)
9414 && !attr
->mp_nexthop_prefer_global
)
9415 json_object_boolean_true_add(
9416 json_nexthop_ll
, "used");
9418 json_object_boolean_true_add(
9419 json_nexthop_global
, "used");
9421 json_object_boolean_true_add(
9422 json_nexthop_global
, "used");
9424 /* Display LL if LL/Global both in table unless
9425 * prefer-global is set */
9426 if (((attr
->mp_nexthop_len
9427 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9428 && !attr
->mp_nexthop_prefer_global
)
9429 || (path
->peer
->conf_if
)) {
9430 if (path
->peer
->conf_if
) {
9431 len
= vty_out(vty
, "%s",
9432 path
->peer
->conf_if
);
9433 /* len of IPv6 addr + max len of def
9435 len
= wide
? (41 - len
) : (16 - len
);
9438 vty_out(vty
, "\n%*s", 36, " ");
9440 vty_out(vty
, "%*s", len
, " ");
9442 if (nexthop_hostname
)
9445 &attr
->mp_nexthop_local
,
9451 &attr
->mp_nexthop_local
,
9454 len
= wide
? (41 - len
) : (16 - len
);
9457 vty_out(vty
, "\n%*s", 36, " ");
9459 vty_out(vty
, "%*s", len
, " ");
9462 if (nexthop_hostname
)
9463 len
= vty_out(vty
, "%pI6(%s)%s",
9464 &attr
->mp_nexthop_global
,
9468 len
= vty_out(vty
, "%pI6%s",
9469 &attr
->mp_nexthop_global
,
9472 len
= wide
? (41 - len
) : (16 - len
);
9475 vty_out(vty
, "\n%*s", 36, " ");
9477 vty_out(vty
, "%*s", len
, " ");
9483 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9485 json_object_int_add(json_path
, "metric", attr
->med
);
9487 vty_out(vty
, "%7u", attr
->med
);
9489 vty_out(vty
, "%10u", attr
->med
);
9490 else if (!json_paths
) {
9492 vty_out(vty
, "%*s", 7, " ");
9494 vty_out(vty
, "%*s", 10, " ");
9498 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9500 json_object_int_add(json_path
, "locPrf",
9503 vty_out(vty
, "%7u", attr
->local_pref
);
9504 else if (!json_paths
)
9508 json_object_int_add(json_path
, "weight", attr
->weight
);
9510 vty_out(vty
, "%7u ", attr
->weight
);
9513 json_object_string_addf(json_path
, "peerId", "%pSU",
9519 json_object_string_add(json_path
, "path",
9522 aspath_print_vty(vty
, attr
->aspath
);
9527 json_object_string_add(json_path
, "origin",
9528 bgp_origin_long_str
[attr
->origin
]);
9530 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9533 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9534 json_object_string_add(json_path
, "esi",
9535 esi_to_str(&attr
->esi
,
9536 esi_buf
, sizeof(esi_buf
)));
9538 if (safi
== SAFI_EVPN
&&
9539 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9540 json_ext_community
= json_object_new_object();
9541 json_object_string_add(
9542 json_ext_community
, "string",
9543 bgp_attr_get_ecommunity(attr
)->str
);
9544 json_object_object_add(json_path
,
9545 "extendedCommunity",
9546 json_ext_community
);
9550 json_object_boolean_true_add(json_path
,
9551 "announceNexthopSelf");
9552 if (nexthop_othervrf
) {
9553 json_object_string_add(json_path
, "nhVrfName",
9556 json_object_int_add(json_path
, "nhVrfId",
9557 ((nexthop_vrfid
== VRF_UNKNOWN
)
9559 : (int)nexthop_vrfid
));
9564 if (json_nexthop_global
|| json_nexthop_ll
) {
9565 json_nexthops
= json_object_new_array();
9567 if (json_nexthop_global
)
9568 json_object_array_add(json_nexthops
,
9569 json_nexthop_global
);
9571 if (json_nexthop_ll
)
9572 json_object_array_add(json_nexthops
,
9575 json_object_object_add(json_path
, "nexthops",
9579 json_object_array_add(json_paths
, json_path
);
9583 if (safi
== SAFI_EVPN
) {
9584 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9585 /* XXX - add these params to the json out */
9586 vty_out(vty
, "%*s", 20, " ");
9587 vty_out(vty
, "ESI:%s",
9588 esi_to_str(&attr
->esi
, esi_buf
,
9594 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9595 vty_out(vty
, "%*s", 20, " ");
9596 vty_out(vty
, "%s\n",
9597 bgp_attr_get_ecommunity(attr
)->str
);
9601 #ifdef ENABLE_BGP_VNC
9602 /* prints an additional line, indented, with VNC info, if
9604 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9605 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9610 /* called from terminal list command */
9611 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9612 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9613 bool use_json
, json_object
*json_ar
, bool wide
)
9615 json_object
*json_status
= NULL
;
9616 json_object
*json_net
= NULL
;
9620 /* Route status display. */
9622 json_status
= json_object_new_object();
9623 json_net
= json_object_new_object();
9630 /* print prefix and mask */
9632 if (safi
== SAFI_EVPN
)
9633 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9634 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9635 json_object_string_add(
9636 json_net
, "addrPrefix",
9637 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9639 json_object_int_add(json_net
, "prefixLen",
9641 json_object_string_addf(json_net
, "network", "%pFX", p
);
9644 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9646 /* Print attribute */
9649 if (p
->family
== AF_INET
&&
9650 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9651 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9652 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9653 json_object_string_addf(
9654 json_net
, "nextHop", "%pI4",
9655 &attr
->mp_nexthop_global_in
);
9657 json_object_string_addf(
9658 json_net
, "nextHop", "%pI4",
9660 } else if (p
->family
== AF_INET6
||
9661 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9662 json_object_string_addf(
9663 json_net
, "nextHopGlobal", "%pI6",
9664 &attr
->mp_nexthop_global
);
9665 } else if (p
->family
== AF_EVPN
&&
9666 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9667 json_object_string_addf(
9668 json_net
, "nextHop", "%pI4",
9669 &attr
->mp_nexthop_global_in
);
9673 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9674 json_object_int_add(json_net
, "metric",
9677 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9678 json_object_int_add(json_net
, "locPrf",
9681 json_object_int_add(json_net
, "weight", attr
->weight
);
9685 json_object_string_add(json_net
, "path",
9689 #if CONFDATE > 20231208
9690 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9692 json_object_string_add(json_net
, "bgpOriginCode",
9693 bgp_origin_str
[attr
->origin
]);
9694 json_object_string_add(
9696 bgp_origin_long_str
[attr
->origin
]);
9698 if (p
->family
== AF_INET
&&
9699 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9700 safi
== SAFI_EVPN
||
9701 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9702 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9703 || safi
== SAFI_EVPN
)
9704 vty_out(vty
, "%-16pI4",
9705 &attr
->mp_nexthop_global_in
);
9707 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9709 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9710 } else if (p
->family
== AF_INET6
||
9711 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9712 len
= vty_out(vty
, "%pI6",
9713 &attr
->mp_nexthop_global
);
9714 len
= wide
? (41 - len
) : (16 - len
);
9716 vty_out(vty
, "\n%*s", 36, " ");
9718 vty_out(vty
, "%*s", len
, " ");
9721 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9723 vty_out(vty
, "%7u", attr
->med
);
9725 vty_out(vty
, "%10u", attr
->med
);
9731 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9732 vty_out(vty
, "%7u", attr
->local_pref
);
9736 vty_out(vty
, "%7u ", attr
->weight
);
9740 aspath_print_vty(vty
, attr
->aspath
);
9743 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9747 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9749 #if CONFDATE > 20231208
9750 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9752 json_object_boolean_true_add(json_status
, "*");
9753 json_object_boolean_true_add(json_status
, ">");
9754 json_object_boolean_true_add(json_net
, "valid");
9755 json_object_boolean_true_add(json_net
, "best");
9757 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9758 json_object_boolean_true_add(json_status
, "=");
9759 json_object_boolean_true_add(json_net
, "multipath");
9761 json_object_object_add(json_net
, "appliedStatusSymbols",
9763 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9768 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9769 struct bgp_path_info
*path
, int display
, safi_t safi
,
9772 json_object
*json_out
= NULL
;
9774 mpls_label_t label
= MPLS_INVALID_LABEL
;
9780 json_out
= json_object_new_object();
9782 /* short status lead text */
9783 route_vty_short_status_out(vty
, path
, p
, json_out
);
9785 /* print prefix and mask */
9788 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9790 vty_out(vty
, "%*s", 17, " ");
9793 /* Print attribute */
9795 if (((p
->family
== AF_INET
) &&
9796 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9797 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9798 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9799 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9800 || safi
== SAFI_EVPN
) {
9802 json_object_string_addf(
9803 json_out
, "mpNexthopGlobalIn", "%pI4",
9804 &attr
->mp_nexthop_global_in
);
9806 vty_out(vty
, "%-16pI4",
9807 &attr
->mp_nexthop_global_in
);
9810 json_object_string_addf(json_out
, "nexthop",
9811 "%pI4", &attr
->nexthop
);
9813 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9815 } else if (((p
->family
== AF_INET6
) &&
9816 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9817 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9818 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9821 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9823 json_object_string_addf(
9824 json_out
, "mpNexthopGlobalIn", "%pI6",
9825 &attr
->mp_nexthop_global
);
9829 &attr
->mp_nexthop_global
,
9830 buf_a
, sizeof(buf_a
)));
9831 } else if (attr
->mp_nexthop_len
9832 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9833 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9834 &attr
->mp_nexthop_global
,
9835 &attr
->mp_nexthop_local
);
9837 json_object_string_add(json_out
,
9838 "mpNexthopGlobalLocal",
9841 vty_out(vty
, "%s", buf_a
);
9845 label
= decode_label(&path
->extra
->label
[0]);
9847 if (bgp_is_valid_label(&label
)) {
9849 json_object_int_add(json_out
, "notag", label
);
9850 json_object_array_add(json
, json_out
);
9852 vty_out(vty
, "notag/%d", label
);
9859 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9860 struct bgp_path_info
*path
, int display
,
9861 json_object
*json_paths
)
9864 json_object
*json_path
= NULL
;
9865 json_object
*json_nexthop
= NULL
;
9866 json_object
*json_overlay
= NULL
;
9872 json_path
= json_object_new_object();
9873 json_overlay
= json_object_new_object();
9874 json_nexthop
= json_object_new_object();
9877 /* short status lead text */
9878 route_vty_short_status_out(vty
, path
, p
, json_path
);
9880 /* print prefix and mask */
9882 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9884 vty_out(vty
, "%*s", 17, " ");
9886 /* Print attribute */
9888 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9893 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9895 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9896 &attr
->mp_nexthop_global_in
);
9898 json_object_string_add(json_nexthop
, "afi", "ipv4");
9900 json_object_object_add(json_path
, "nexthop",
9906 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9907 &attr
->mp_nexthop_local
);
9909 json_object_string_addf(json_nexthop
, "ipv6Global",
9911 &attr
->mp_nexthop_global
);
9913 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9915 &attr
->mp_nexthop_local
);
9917 json_object_string_add(json_nexthop
, "afi", "ipv6");
9919 json_object_object_add(json_path
, "nexthop",
9927 json_object_string_add(json_nexthop
, "error",
9928 "Unsupported address-family");
9932 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9935 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9937 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9939 if (bgp_attr_get_ecommunity(attr
)) {
9941 struct ecommunity_val
*routermac
= ecommunity_lookup(
9942 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9943 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9946 mac
= ecom_mac2str((char *)routermac
->val
);
9949 vty_out(vty
, "/%s", mac
);
9951 json_object_string_add(json_overlay
, "rmac",
9954 XFREE(MTYPE_TMP
, mac
);
9961 json_object_object_add(json_path
, "overlay", json_overlay
);
9963 json_object_array_add(json_paths
, json_path
);
9967 /* dampening route */
9968 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9969 struct bgp_path_info
*path
, int display
,
9970 afi_t afi
, safi_t safi
, bool use_json
,
9971 json_object
*json_paths
)
9973 struct attr
*attr
= path
->attr
;
9975 char timebuf
[BGP_UPTIME_LEN
];
9976 json_object
*json_path
= NULL
;
9979 json_path
= json_object_new_object();
9981 /* short status lead text */
9982 route_vty_short_status_out(vty
, path
, p
, json_path
);
9984 /* print prefix and mask */
9987 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9989 vty_out(vty
, "%*s", 17, " ");
9991 len
= vty_out(vty
, "%s", path
->peer
->host
);
9995 vty_out(vty
, "\n%*s", 34, " ");
9997 vty_out(vty
, "%*s", len
, " ");
10000 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10001 BGP_UPTIME_LEN
, afi
, safi
,
10005 aspath_print_vty(vty
, attr
->aspath
);
10007 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10009 vty_out(vty
, "\n");
10011 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
10012 safi
, use_json
, json_path
);
10015 json_object_string_add(json_path
, "asPath",
10016 attr
->aspath
->str
);
10018 json_object_string_add(json_path
, "origin",
10019 bgp_origin_str
[attr
->origin
]);
10020 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10022 json_object_array_add(json_paths
, json_path
);
10027 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
10028 struct bgp_path_info
*path
, int display
,
10029 afi_t afi
, safi_t safi
, bool use_json
,
10030 json_object
*json_paths
)
10032 struct attr
*attr
= path
->attr
;
10033 struct bgp_damp_info
*bdi
;
10034 char timebuf
[BGP_UPTIME_LEN
];
10036 json_object
*json_path
= NULL
;
10042 json_path
= json_object_new_object();
10044 bdi
= path
->extra
->damp_info
;
10046 /* short status lead text */
10047 route_vty_short_status_out(vty
, path
, p
, json_path
);
10051 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10053 vty_out(vty
, "%*s", 17, " ");
10055 len
= vty_out(vty
, "%s", path
->peer
->host
);
10058 vty_out(vty
, "\n%*s", 33, " ");
10060 vty_out(vty
, "%*s", len
, " ");
10062 len
= vty_out(vty
, "%d", bdi
->flap
);
10067 vty_out(vty
, "%*s", len
, " ");
10069 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10070 BGP_UPTIME_LEN
, 0, NULL
));
10072 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10073 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10074 vty_out(vty
, "%s ",
10075 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10076 BGP_UPTIME_LEN
, afi
,
10077 safi
, use_json
, NULL
));
10079 vty_out(vty
, "%*s ", 8, " ");
10082 aspath_print_vty(vty
, attr
->aspath
);
10084 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10086 vty_out(vty
, "\n");
10088 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10089 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10091 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10094 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10095 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10096 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10097 BGP_UPTIME_LEN
, afi
, safi
,
10098 use_json
, json_path
);
10101 json_object_string_add(json_path
, "asPath",
10102 attr
->aspath
->str
);
10104 json_object_string_add(json_path
, "origin",
10105 bgp_origin_str
[attr
->origin
]);
10107 json_object_array_add(json_paths
, json_path
);
10111 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10112 int *first
, const char *header
,
10113 json_object
*json_adv_to
)
10115 json_object
*json_peer
= NULL
;
10118 /* 'advertised-to' is a dictionary of peers we have advertised
10120 * prefix too. The key is the peer's IP or swpX, the value is
10122 * hostname if we know it and "" if not.
10124 json_peer
= json_object_new_object();
10126 if (peer
->hostname
)
10127 json_object_string_add(json_peer
, "hostname",
10131 json_object_object_add(json_adv_to
, peer
->conf_if
,
10134 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10138 vty_out(vty
, "%s", header
);
10143 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10145 vty_out(vty
, " %s(%s)", peer
->hostname
,
10148 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10152 vty_out(vty
, " %s", peer
->conf_if
);
10154 vty_out(vty
, " %pSU", &peer
->su
);
10159 static void route_vty_out_tx_ids(struct vty
*vty
,
10160 struct bgp_addpath_info_data
*d
)
10164 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10165 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10166 d
->addpath_tx_id
[i
],
10167 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10171 static void route_vty_out_detail_es_info(struct vty
*vty
,
10172 struct bgp_path_info
*pi
,
10174 json_object
*json_path
)
10176 char esi_buf
[ESI_STR_LEN
];
10177 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10178 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10179 ATTR_ES_PEER_ROUTER
);
10180 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10181 ATTR_ES_PEER_ACTIVE
);
10182 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10183 ATTR_ES_PEER_PROXY
);
10184 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10186 json_object
*json_es_info
= NULL
;
10188 json_object_string_add(
10191 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10192 json_es_info
= json_object_new_object();
10194 json_object_boolean_true_add(
10195 json_es_info
, "localEs");
10197 json_object_boolean_true_add(
10198 json_es_info
, "peerActive");
10200 json_object_boolean_true_add(
10201 json_es_info
, "peerProxy");
10203 json_object_boolean_true_add(
10204 json_es_info
, "peerRouter");
10205 if (attr
->mm_sync_seqnum
)
10206 json_object_int_add(
10207 json_es_info
, "peerSeq",
10208 attr
->mm_sync_seqnum
);
10209 json_object_object_add(
10210 json_path
, "es_info",
10214 if (bgp_evpn_attr_is_sync(attr
))
10216 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10218 es_local
? "local-es":"",
10219 peer_proxy
? "proxy " : "",
10220 peer_active
? "active ":"",
10221 peer_router
? "router ":"",
10222 attr
->mm_sync_seqnum
);
10224 vty_out(vty
, " ESI %s %s\n",
10226 es_local
? "local-es":"");
10230 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10231 const struct prefix
*p
, struct bgp_path_info
*path
,
10232 afi_t afi
, safi_t safi
,
10233 enum rpki_states rpki_curr_state
,
10234 json_object
*json_paths
)
10236 char buf
[INET6_ADDRSTRLEN
];
10238 struct attr
*attr
= path
->attr
;
10240 json_object
*json_bestpath
= NULL
;
10241 json_object
*json_cluster_list
= NULL
;
10242 json_object
*json_cluster_list_list
= NULL
;
10243 json_object
*json_ext_community
= NULL
;
10244 json_object
*json_last_update
= NULL
;
10245 json_object
*json_pmsi
= NULL
;
10246 json_object
*json_nexthop_global
= NULL
;
10247 json_object
*json_nexthop_ll
= NULL
;
10248 json_object
*json_nexthops
= NULL
;
10249 json_object
*json_path
= NULL
;
10250 json_object
*json_peer
= NULL
;
10251 json_object
*json_string
= NULL
;
10252 json_object
*json_adv_to
= NULL
;
10254 struct listnode
*node
, *nnode
;
10256 bool addpath_capable
;
10258 unsigned int first_as
;
10259 bool nexthop_self
=
10260 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10262 char *nexthop_hostname
=
10263 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10267 mpls_label_t label
= MPLS_INVALID_LABEL
;
10269 struct bgp_path_info
*bpi_ultimate
=
10270 bgp_get_imported_bpi_ultimate(path
);
10273 json_path
= json_object_new_object();
10274 json_peer
= json_object_new_object();
10275 json_nexthop_global
= json_object_new_object();
10278 if (safi
== SAFI_EVPN
) {
10280 vty_out(vty
, " Route %pFX", p
);
10284 if (path
->extra
&& path
->extra
->num_labels
) {
10285 bgp_evpn_label2str(path
->extra
->label
,
10286 path
->extra
->num_labels
, tag_buf
,
10289 if (safi
== SAFI_EVPN
) {
10291 if (tag_buf
[0] != '\0')
10292 vty_out(vty
, " VNI %s", tag_buf
);
10295 json_object_string_add(json_path
, "vni",
10301 if (safi
== SAFI_EVPN
10302 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10303 char gwip_buf
[INET6_ADDRSTRLEN
];
10305 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10309 json_object_string_add(json_path
, "gatewayIP",
10312 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10315 if (safi
== SAFI_EVPN
&& !json_path
)
10316 vty_out(vty
, "\n");
10319 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10320 struct bgp_path_info
*parent_ri
;
10321 struct bgp_dest
*dest
, *pdest
;
10323 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10324 dest
= parent_ri
->net
;
10325 if (dest
&& dest
->pdest
) {
10326 pdest
= dest
->pdest
;
10327 if (is_pi_family_evpn(parent_ri
)) {
10328 vty_out(vty
, " Imported from ");
10329 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10330 (struct prefix_rd
*)bgp_dest_get_prefix(
10332 vty_out(vty
, ":%pFX, VNI %s",
10333 (struct prefix_evpn
*)
10334 bgp_dest_get_prefix(dest
),
10336 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10337 vty_out(vty
, ", L3NHG %s",
10340 ATTR_ES_L3_NHG_ACTIVE
)
10343 vty_out(vty
, "\n");
10346 vty_out(vty
, " Imported from ");
10347 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10348 (struct prefix_rd
*)bgp_dest_get_prefix(
10350 vty_out(vty
, ":%pFX\n",
10351 (struct prefix_evpn
*)
10352 bgp_dest_get_prefix(dest
));
10357 /* Line1 display AS-path, Aggregator */
10358 if (attr
->aspath
) {
10360 if (!attr
->aspath
->json
)
10361 aspath_str_update(attr
->aspath
, true);
10362 json_object_lock(attr
->aspath
->json
);
10363 json_object_object_add(json_path
, "aspath",
10364 attr
->aspath
->json
);
10366 if (attr
->aspath
->segments
)
10367 vty_out(vty
, " %s", attr
->aspath
->str
);
10369 vty_out(vty
, " Local");
10373 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10375 json_object_boolean_true_add(json_path
, "removed");
10377 vty_out(vty
, ", (removed)");
10380 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10382 json_object_boolean_true_add(json_path
, "stale");
10384 vty_out(vty
, ", (stale)");
10387 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10389 json_object_int_add(json_path
, "aggregatorAs",
10390 attr
->aggregator_as
);
10391 json_object_string_addf(json_path
, "aggregatorId",
10392 "%pI4", &attr
->aggregator_addr
);
10394 vty_out(vty
, ", (aggregated by %u %pI4)",
10395 attr
->aggregator_as
, &attr
->aggregator_addr
);
10399 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10400 PEER_FLAG_REFLECTOR_CLIENT
)) {
10402 json_object_boolean_true_add(json_path
,
10403 "rxedFromRrClient");
10405 vty_out(vty
, ", (Received from a RR-client)");
10408 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10409 PEER_FLAG_RSERVER_CLIENT
)) {
10411 json_object_boolean_true_add(json_path
,
10412 "rxedFromRsClient");
10414 vty_out(vty
, ", (Received from a RS-client)");
10417 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10419 json_object_boolean_true_add(json_path
,
10420 "dampeningHistoryEntry");
10422 vty_out(vty
, ", (history entry)");
10423 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10425 json_object_boolean_true_add(json_path
,
10426 "dampeningSuppressed");
10428 vty_out(vty
, ", (suppressed due to dampening)");
10432 vty_out(vty
, "\n");
10434 /* Line2 display Next-hop, Neighbor, Router-id */
10435 /* Display the nexthop */
10437 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10438 p
->family
== AF_EVPN
) &&
10439 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10440 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10441 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10442 || safi
== SAFI_EVPN
) {
10444 json_object_string_addf(
10445 json_nexthop_global
, "ip", "%pI4",
10446 &attr
->mp_nexthop_global_in
);
10448 if (path
->peer
->hostname
)
10449 json_object_string_add(
10450 json_nexthop_global
, "hostname",
10451 path
->peer
->hostname
);
10453 if (nexthop_hostname
)
10454 vty_out(vty
, " %pI4(%s)",
10455 &attr
->mp_nexthop_global_in
,
10458 vty_out(vty
, " %pI4",
10459 &attr
->mp_nexthop_global_in
);
10463 json_object_string_addf(json_nexthop_global
,
10467 if (path
->peer
->hostname
)
10468 json_object_string_add(
10469 json_nexthop_global
, "hostname",
10470 path
->peer
->hostname
);
10472 if (nexthop_hostname
)
10473 vty_out(vty
, " %pI4(%s)",
10477 vty_out(vty
, " %pI4",
10483 json_object_string_add(json_nexthop_global
, "afi",
10487 json_object_string_addf(json_nexthop_global
, "ip",
10489 &attr
->mp_nexthop_global
);
10491 if (path
->peer
->hostname
)
10492 json_object_string_add(json_nexthop_global
,
10494 path
->peer
->hostname
);
10496 json_object_string_add(json_nexthop_global
, "afi",
10498 json_object_string_add(json_nexthop_global
, "scope",
10501 if (nexthop_hostname
)
10502 vty_out(vty
, " %pI6(%s)",
10503 &attr
->mp_nexthop_global
,
10506 vty_out(vty
, " %pI6",
10507 &attr
->mp_nexthop_global
);
10511 /* Display the IGP cost or 'inaccessible' */
10512 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10513 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10516 json_object_boolean_false_add(json_nexthop_global
,
10518 json_object_boolean_add(json_nexthop_global
,
10519 "importCheckEnabled", import
);
10521 vty_out(vty
, " (inaccessible%s)",
10522 import
? ", import-check enabled" : "");
10525 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10527 json_object_int_add(
10528 json_nexthop_global
, "metric",
10529 bpi_ultimate
->extra
->igpmetric
);
10531 vty_out(vty
, " (metric %u)",
10532 bpi_ultimate
->extra
->igpmetric
);
10535 /* IGP cost is 0, display this only for json */
10538 json_object_int_add(json_nexthop_global
,
10543 json_object_boolean_true_add(json_nexthop_global
,
10547 /* Display peer "from" output */
10548 /* This path was originated locally */
10549 if (path
->peer
== bgp
->peer_self
) {
10551 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10552 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10554 json_object_string_add(json_peer
, "peerId",
10557 vty_out(vty
, " from 0.0.0.0 ");
10560 json_object_string_add(json_peer
, "peerId",
10563 vty_out(vty
, " from :: ");
10567 json_object_string_addf(json_peer
, "routerId", "%pI4",
10570 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10573 /* We RXed this path from one of our peers */
10577 json_object_string_addf(json_peer
, "peerId", "%pSU",
10579 json_object_string_addf(json_peer
, "routerId", "%pI4",
10580 &path
->peer
->remote_id
);
10582 if (path
->peer
->hostname
)
10583 json_object_string_add(json_peer
, "hostname",
10584 path
->peer
->hostname
);
10586 if (path
->peer
->domainname
)
10587 json_object_string_add(json_peer
, "domainname",
10588 path
->peer
->domainname
);
10590 if (path
->peer
->conf_if
)
10591 json_object_string_add(json_peer
, "interface",
10592 path
->peer
->conf_if
);
10594 if (path
->peer
->conf_if
) {
10595 if (path
->peer
->hostname
10596 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10597 BGP_FLAG_SHOW_HOSTNAME
))
10598 vty_out(vty
, " from %s(%s)",
10599 path
->peer
->hostname
,
10600 path
->peer
->conf_if
);
10602 vty_out(vty
, " from %s",
10603 path
->peer
->conf_if
);
10605 if (path
->peer
->hostname
10606 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10607 BGP_FLAG_SHOW_HOSTNAME
))
10608 vty_out(vty
, " from %s(%s)",
10609 path
->peer
->hostname
,
10612 vty_out(vty
, " from %pSU",
10616 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10617 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10619 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10624 * Note when vrfid of nexthop is different from that of prefix
10626 if (path
->extra
&& path
->extra
->bgp_orig
) {
10627 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10632 if (path
->extra
->bgp_orig
->inst_type
10633 == BGP_INSTANCE_TYPE_DEFAULT
)
10634 vn
= VRF_DEFAULT_NAME
;
10636 vn
= path
->extra
->bgp_orig
->name
;
10638 json_object_string_add(json_path
, "nhVrfName", vn
);
10640 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10641 json_object_int_add(json_path
, "nhVrfId", -1);
10643 json_object_int_add(json_path
, "nhVrfId",
10644 (int)nexthop_vrfid
);
10647 if (nexthop_vrfid
== VRF_UNKNOWN
)
10648 vty_out(vty
, " vrf ?");
10652 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10653 vty_out(vty
, " vrf %s(%u)",
10654 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10659 if (nexthop_self
) {
10661 json_object_boolean_true_add(json_path
,
10662 "announceNexthopSelf");
10664 vty_out(vty
, " announce-nh-self");
10669 vty_out(vty
, "\n");
10671 /* display the link-local nexthop */
10672 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10674 json_nexthop_ll
= json_object_new_object();
10675 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10676 &attr
->mp_nexthop_local
);
10678 if (path
->peer
->hostname
)
10679 json_object_string_add(json_nexthop_ll
,
10681 path
->peer
->hostname
);
10683 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10684 json_object_string_add(json_nexthop_ll
, "scope",
10687 json_object_boolean_true_add(json_nexthop_ll
,
10690 if (!attr
->mp_nexthop_prefer_global
)
10691 json_object_boolean_true_add(json_nexthop_ll
,
10694 json_object_boolean_true_add(
10695 json_nexthop_global
, "used");
10697 vty_out(vty
, " (%s) %s\n",
10698 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10699 buf
, INET6_ADDRSTRLEN
),
10700 attr
->mp_nexthop_prefer_global
10701 ? "(prefer-global)"
10705 /* If we do not have a link-local nexthop then we must flag the
10706 global as "used" */
10709 json_object_boolean_true_add(json_nexthop_global
,
10713 if (safi
== SAFI_EVPN
&&
10714 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10715 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10718 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10719 * Int/Ext/Local, Atomic, best */
10721 json_object_string_add(json_path
, "origin",
10722 bgp_origin_long_str
[attr
->origin
]);
10724 vty_out(vty
, " Origin %s",
10725 bgp_origin_long_str
[attr
->origin
]);
10727 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10729 json_object_int_add(json_path
, "metric", attr
->med
);
10731 vty_out(vty
, ", metric %u", attr
->med
);
10734 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10736 json_object_int_add(json_path
, "locPrf",
10739 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10742 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10744 json_object_int_add(json_path
, "aigpMetric",
10745 bgp_attr_get_aigp_metric(attr
));
10747 vty_out(vty
, ", aigp-metric %" PRIu64
,
10748 bgp_attr_get_aigp_metric(attr
));
10751 if (attr
->weight
!= 0) {
10753 json_object_int_add(json_path
, "weight", attr
->weight
);
10755 vty_out(vty
, ", weight %u", attr
->weight
);
10758 if (attr
->tag
!= 0) {
10760 json_object_int_add(json_path
, "tag", attr
->tag
);
10762 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10765 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10767 json_object_boolean_false_add(json_path
, "valid");
10769 vty_out(vty
, ", invalid");
10770 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10772 json_object_boolean_true_add(json_path
, "valid");
10774 vty_out(vty
, ", valid");
10778 json_object_int_add(json_path
, "version", bn
->version
);
10780 if (path
->peer
!= bgp
->peer_self
) {
10781 if (path
->peer
->as
== path
->peer
->local_as
) {
10782 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10784 json_object_string_add(
10786 "confed-internal");
10788 vty_out(vty
, ", confed-internal");
10791 json_object_string_add(
10792 json_peer
, "type", "internal");
10794 vty_out(vty
, ", internal");
10797 if (bgp_confederation_peers_check(bgp
,
10800 json_object_string_add(
10802 "confed-external");
10804 vty_out(vty
, ", confed-external");
10807 json_object_string_add(
10808 json_peer
, "type", "external");
10810 vty_out(vty
, ", external");
10813 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10815 json_object_boolean_true_add(json_path
, "aggregated");
10816 json_object_boolean_true_add(json_path
, "local");
10818 vty_out(vty
, ", aggregated, local");
10820 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10822 json_object_boolean_true_add(json_path
, "sourced");
10824 vty_out(vty
, ", sourced");
10827 json_object_boolean_true_add(json_path
, "sourced");
10828 json_object_boolean_true_add(json_path
, "local");
10830 vty_out(vty
, ", sourced, local");
10834 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10836 json_object_boolean_true_add(json_path
,
10837 "atomicAggregate");
10839 vty_out(vty
, ", atomic-aggregate");
10842 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10844 json_object_int_add(json_path
, "otc", attr
->otc
);
10846 vty_out(vty
, ", otc %u", attr
->otc
);
10849 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10850 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10851 && bgp_path_info_mpath_count(path
))) {
10853 json_object_boolean_true_add(json_path
, "multipath");
10855 vty_out(vty
, ", multipath");
10858 // Mark the bestpath(s)
10859 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10860 first_as
= aspath_get_first_as(attr
->aspath
);
10863 if (!json_bestpath
)
10864 json_bestpath
= json_object_new_object();
10865 json_object_int_add(json_bestpath
, "bestpathFromAs",
10869 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10871 vty_out(vty
, ", bestpath-from-AS Local");
10875 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10877 if (!json_bestpath
)
10878 json_bestpath
= json_object_new_object();
10879 json_object_boolean_true_add(json_bestpath
, "overall");
10880 json_object_string_add(
10881 json_bestpath
, "selectionReason",
10882 bgp_path_selection_reason2str(bn
->reason
));
10884 vty_out(vty
, ", best");
10885 vty_out(vty
, " (%s)",
10886 bgp_path_selection_reason2str(bn
->reason
));
10890 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10892 json_object_string_add(
10893 json_path
, "rpkiValidationState",
10894 bgp_rpki_validation2str(rpki_curr_state
));
10896 vty_out(vty
, ", rpki validation-state: %s",
10897 bgp_rpki_validation2str(rpki_curr_state
));
10901 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10904 vty_out(vty
, "\n");
10906 /* Line 4 display Community */
10907 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10909 if (!bgp_attr_get_community(attr
)->json
)
10910 community_str(bgp_attr_get_community(attr
),
10912 json_object_lock(bgp_attr_get_community(attr
)->json
);
10913 json_object_object_add(
10914 json_path
, "community",
10915 bgp_attr_get_community(attr
)->json
);
10917 vty_out(vty
, " Community: %s\n",
10918 bgp_attr_get_community(attr
)->str
);
10922 /* Line 5 display Extended-community */
10923 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10925 json_ext_community
= json_object_new_object();
10926 json_object_string_add(
10927 json_ext_community
, "string",
10928 bgp_attr_get_ecommunity(attr
)->str
);
10929 json_object_object_add(json_path
, "extendedCommunity",
10930 json_ext_community
);
10932 vty_out(vty
, " Extended Community: %s\n",
10933 bgp_attr_get_ecommunity(attr
)->str
);
10937 /* Line 6 display Large community */
10938 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10940 if (!bgp_attr_get_lcommunity(attr
)->json
)
10941 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10943 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10944 json_object_object_add(
10945 json_path
, "largeCommunity",
10946 bgp_attr_get_lcommunity(attr
)->json
);
10948 vty_out(vty
, " Large Community: %s\n",
10949 bgp_attr_get_lcommunity(attr
)->str
);
10953 /* Line 7 display Originator, Cluster-id */
10954 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10955 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10956 char buf
[BUFSIZ
] = {0};
10958 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10960 json_object_string_addf(json_path
,
10961 "originatorId", "%pI4",
10962 &attr
->originator_id
);
10964 vty_out(vty
, " Originator: %pI4",
10965 &attr
->originator_id
);
10968 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10969 struct cluster_list
*cluster
=
10970 bgp_attr_get_cluster(attr
);
10974 json_cluster_list
= json_object_new_object();
10975 json_cluster_list_list
=
10976 json_object_new_array();
10978 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10979 json_string
= json_object_new_string(
10982 buf
, sizeof(buf
)));
10983 json_object_array_add(
10984 json_cluster_list_list
,
10989 * struct cluster_list does not have
10990 * "str" variable like aspath and community
10991 * do. Add this someday if someone asks
10993 * json_object_string_add(json_cluster_list,
10994 * "string", cluster->str);
10996 json_object_object_add(json_cluster_list
,
10998 json_cluster_list_list
);
10999 json_object_object_add(json_path
, "clusterList",
11000 json_cluster_list
);
11002 vty_out(vty
, ", Cluster list: ");
11004 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
11005 vty_out(vty
, "%pI4 ",
11006 &cluster
->list
[i
]);
11012 vty_out(vty
, "\n");
11015 if (path
->extra
&& path
->extra
->damp_info
)
11016 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
11019 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
11020 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
11021 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
11025 json_object_int_add(json_path
, "remoteLabel", label
);
11027 vty_out(vty
, " Remote label: %d\n", label
);
11031 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
11033 json_object_string_addf(json_path
, "remoteSid", "%pI6",
11034 &path
->extra
->sid
[0].sid
);
11036 vty_out(vty
, " Remote SID: %pI6\n",
11037 &path
->extra
->sid
[0].sid
);
11041 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
11043 json_object_int_add(json_path
, "labelIndex",
11044 attr
->label_index
);
11046 vty_out(vty
, " Label Index: %d\n",
11047 attr
->label_index
);
11050 /* Line 8 display Addpath IDs */
11051 if (path
->addpath_rx_id
11052 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11054 json_object_int_add(json_path
, "addpathRxId",
11055 path
->addpath_rx_id
);
11057 /* Keep backwards compatibility with the old API
11058 * by putting TX All's ID in the old field
11060 json_object_int_add(
11061 json_path
, "addpathTxId",
11063 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11065 /* ... but create a specific field for each
11068 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11069 json_object_int_add(
11071 bgp_addpath_names(i
)->id_json_name
,
11072 path
->tx_addpath
.addpath_tx_id
[i
]);
11075 vty_out(vty
, " AddPath ID: RX %u, ",
11076 path
->addpath_rx_id
);
11078 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11082 /* If we used addpath to TX a non-bestpath we need to display
11083 * "Advertised to" on a path-by-path basis
11085 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11088 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11090 bgp_addpath_encode_tx(peer
, afi
, safi
);
11091 has_adj
= bgp_adj_out_lookup(
11093 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11094 &path
->tx_addpath
));
11096 if ((addpath_capable
&& has_adj
)
11097 || (!addpath_capable
&& has_adj
11098 && CHECK_FLAG(path
->flags
,
11099 BGP_PATH_SELECTED
))) {
11100 if (json_path
&& !json_adv_to
)
11101 json_adv_to
= json_object_new_object();
11103 route_vty_out_advertised_to(
11105 " Advertised to:", json_adv_to
);
11111 json_object_object_add(
11112 json_path
, "advertisedTo", json_adv_to
);
11116 vty_out(vty
, "\n");
11121 /* Line 9 display Uptime */
11122 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11124 json_last_update
= json_object_new_object();
11125 json_object_int_add(json_last_update
, "epoch", tbuf
);
11126 json_object_string_add(json_last_update
, "string",
11128 json_object_object_add(json_path
, "lastUpdate",
11131 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11133 /* Line 10 display PMSI tunnel attribute, if present */
11134 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11135 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11136 bgp_attr_get_pmsi_tnl_type(attr
),
11137 PMSI_TNLTYPE_STR_DEFAULT
);
11140 json_pmsi
= json_object_new_object();
11141 json_object_string_add(json_pmsi
, "tunnelType", str
);
11142 json_object_int_add(json_pmsi
, "label",
11143 label2vni(&attr
->label
));
11144 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11146 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11147 str
, label2vni(&attr
->label
));
11150 if (path
->peer
->t_gr_restart
&&
11151 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11152 unsigned long gr_remaining
=
11153 event_timer_remain_second(path
->peer
->t_gr_restart
);
11156 json_object_int_add(json_path
,
11157 "gracefulRestartSecondsRemaining",
11161 " Time until Graceful Restart stale route deleted: %lu\n",
11165 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11166 bgp_attr_get_community(attr
) &&
11167 community_include(bgp_attr_get_community(attr
),
11168 COMMUNITY_LLGR_STALE
)) {
11169 unsigned long llgr_remaining
= event_timer_remain_second(
11170 path
->peer
->t_llgr_stale
[afi
][safi
]);
11173 json_object_int_add(json_path
, "llgrSecondsRemaining",
11177 " Time until Long-lived stale route deleted: %lu\n",
11181 /* Output some debug about internal state of the dest flags */
11183 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11184 json_object_boolean_true_add(json_path
, "processScheduled");
11185 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11186 json_object_boolean_true_add(json_path
, "userCleared");
11187 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11188 json_object_boolean_true_add(json_path
, "labelChanged");
11189 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11190 json_object_boolean_true_add(json_path
, "registeredForLabel");
11191 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11192 json_object_boolean_true_add(json_path
, "selectDefered");
11193 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11194 json_object_boolean_true_add(json_path
, "fibInstalled");
11195 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11196 json_object_boolean_true_add(json_path
, "fibPending");
11198 if (json_nexthop_global
|| json_nexthop_ll
) {
11199 json_nexthops
= json_object_new_array();
11201 if (json_nexthop_global
)
11202 json_object_array_add(json_nexthops
,
11203 json_nexthop_global
);
11205 if (json_nexthop_ll
)
11206 json_object_array_add(json_nexthops
,
11209 json_object_object_add(json_path
, "nexthops",
11213 json_object_object_add(json_path
, "peer", json_peer
);
11214 json_object_array_add(json_paths
, json_path
);
11218 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11219 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11220 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11222 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11223 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11225 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11226 const char *comstr
, int exact
, afi_t afi
,
11227 safi_t safi
, uint16_t show_flags
);
11229 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11230 struct bgp_table
*table
, enum bgp_show_type type
,
11231 void *output_arg
, const char *rd
, int is_last
,
11232 unsigned long *output_cum
, unsigned long *total_cum
,
11233 unsigned long *json_header_depth
, uint16_t show_flags
,
11234 enum rpki_states rpki_target_state
)
11236 struct bgp_path_info
*pi
;
11237 struct bgp_dest
*dest
;
11238 bool header
= true;
11239 bool json_detail_header
= false;
11241 unsigned long output_count
= 0;
11242 unsigned long total_count
= 0;
11244 json_object
*json_paths
= NULL
;
11246 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11247 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11248 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11249 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11250 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11252 if (output_cum
&& *output_cum
!= 0)
11255 if (use_json
&& !*json_header_depth
) {
11257 *json_header_depth
= 1;
11259 vty_out(vty
, "{\n");
11260 *json_header_depth
= 2;
11263 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11264 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11266 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11267 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11270 table
->version
, &bgp
->router_id
,
11271 bgp
->default_local_pref
);
11272 if ((bgp
->asnotation
== ASNOTATION_PLAIN
) ||
11273 ((bgp
->asnotation
== ASNOTATION_DOT
) &&
11274 (bgp
->as
< UINT16_MAX
)))
11275 vty_out(vty
, "%u", bgp
->as
);
11277 vty_out(vty
, "\"");
11278 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
), &bgp
->as
);
11279 vty_out(vty
, "\"");
11281 vty_out(vty
, ",\n \"routes\": { ");
11283 vty_out(vty
, " \"routeDistinguishers\" : {");
11284 ++*json_header_depth
;
11288 if (use_json
&& rd
) {
11289 vty_out(vty
, " \"%s\" : { ", rd
);
11292 /* Check for 'json detail', where we need header output once per dest */
11293 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11294 type
!= bgp_show_type_damp_neighbor
&&
11295 type
!= bgp_show_type_flap_statistics
&&
11296 type
!= bgp_show_type_flap_neighbor
)
11297 json_detail_header
= true;
11299 /* Start processing of routes. */
11300 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11301 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11302 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11303 bool json_detail_header_used
= false;
11305 pi
= bgp_dest_get_bgp_path_info(dest
);
11311 json_paths
= json_object_new_array();
11315 for (; pi
; pi
= pi
->next
) {
11316 struct community
*picomm
= NULL
;
11318 picomm
= bgp_attr_get_community(pi
->attr
);
11322 if (type
== bgp_show_type_prefix_version
) {
11324 strtoul(output_arg
, NULL
, 10);
11325 if (dest
->version
< version
)
11329 if (type
== bgp_show_type_community_alias
) {
11330 char *alias
= output_arg
;
11331 char **communities
;
11333 bool found
= false;
11336 frrstr_split(picomm
->str
, " ",
11337 &communities
, &num
);
11338 for (int i
= 0; i
< num
; i
++) {
11339 const char *com2alias
=
11340 bgp_community2alias(
11343 && strcmp(alias
, com2alias
)
11349 XFREE(MTYPE_TMP
, communities
);
11353 bgp_attr_get_lcommunity(pi
->attr
)) {
11354 frrstr_split(bgp_attr_get_lcommunity(
11357 " ", &communities
, &num
);
11358 for (int i
= 0; i
< num
; i
++) {
11359 const char *com2alias
=
11360 bgp_community2alias(
11363 && strcmp(alias
, com2alias
)
11369 XFREE(MTYPE_TMP
, communities
);
11376 if (type
== bgp_show_type_rpki
) {
11377 if (dest_p
->family
== AF_INET
11378 || dest_p
->family
== AF_INET6
)
11379 rpki_curr_state
= hook_call(
11380 bgp_rpki_prefix_status
,
11381 pi
->peer
, pi
->attr
, dest_p
);
11382 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11383 && rpki_curr_state
!= rpki_target_state
)
11387 if (type
== bgp_show_type_flap_statistics
11388 || type
== bgp_show_type_flap_neighbor
11389 || type
== bgp_show_type_dampend_paths
11390 || type
== bgp_show_type_damp_neighbor
) {
11391 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11394 if (type
== bgp_show_type_regexp
) {
11395 regex_t
*regex
= output_arg
;
11397 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11401 if (type
== bgp_show_type_prefix_list
) {
11402 struct prefix_list
*plist
= output_arg
;
11404 if (prefix_list_apply(plist
, dest_p
)
11408 if (type
== bgp_show_type_access_list
) {
11409 struct access_list
*alist
= output_arg
;
11411 if (access_list_apply(alist
, dest_p
) !=
11415 if (type
== bgp_show_type_filter_list
) {
11416 struct as_list
*as_list
= output_arg
;
11418 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11419 != AS_FILTER_PERMIT
)
11422 if (type
== bgp_show_type_route_map
) {
11423 struct route_map
*rmap
= output_arg
;
11424 struct bgp_path_info path
;
11425 struct bgp_path_info_extra extra
;
11426 struct attr dummy_attr
= {};
11427 route_map_result_t ret
;
11429 dummy_attr
= *pi
->attr
;
11431 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11432 pi
->peer
, &dummy_attr
);
11434 ret
= route_map_apply(rmap
, dest_p
, &path
);
11435 bgp_attr_flush(&dummy_attr
);
11436 if (ret
== RMAP_DENYMATCH
)
11439 if (type
== bgp_show_type_neighbor
11440 || type
== bgp_show_type_flap_neighbor
11441 || type
== bgp_show_type_damp_neighbor
) {
11442 union sockunion
*su
= output_arg
;
11444 if (pi
->peer
== NULL
11445 || pi
->peer
->su_remote
== NULL
11446 || !sockunion_same(pi
->peer
->su_remote
, su
))
11449 if (type
== bgp_show_type_cidr_only
) {
11450 uint32_t destination
;
11452 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11453 if (IN_CLASSC(destination
)
11454 && dest_p
->prefixlen
== 24)
11456 if (IN_CLASSB(destination
)
11457 && dest_p
->prefixlen
== 16)
11459 if (IN_CLASSA(destination
)
11460 && dest_p
->prefixlen
== 8)
11463 if (type
== bgp_show_type_prefix_longer
) {
11465 if (!prefix_match(p
, dest_p
))
11468 if (type
== bgp_show_type_community_all
) {
11472 if (type
== bgp_show_type_community
) {
11473 struct community
*com
= output_arg
;
11475 if (!picomm
|| !community_match(picomm
, com
))
11478 if (type
== bgp_show_type_community_exact
) {
11479 struct community
*com
= output_arg
;
11481 if (!picomm
|| !community_cmp(picomm
, com
))
11484 if (type
== bgp_show_type_community_list
) {
11485 struct community_list
*list
= output_arg
;
11487 if (!community_list_match(picomm
, list
))
11490 if (type
== bgp_show_type_community_list_exact
) {
11491 struct community_list
*list
= output_arg
;
11493 if (!community_list_exact_match(picomm
, list
))
11496 if (type
== bgp_show_type_lcommunity
) {
11497 struct lcommunity
*lcom
= output_arg
;
11499 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11501 bgp_attr_get_lcommunity(pi
->attr
),
11506 if (type
== bgp_show_type_lcommunity_exact
) {
11507 struct lcommunity
*lcom
= output_arg
;
11509 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11511 bgp_attr_get_lcommunity(pi
->attr
),
11515 if (type
== bgp_show_type_lcommunity_list
) {
11516 struct community_list
*list
= output_arg
;
11518 if (!lcommunity_list_match(
11519 bgp_attr_get_lcommunity(pi
->attr
),
11524 == bgp_show_type_lcommunity_list_exact
) {
11525 struct community_list
*list
= output_arg
;
11527 if (!lcommunity_list_exact_match(
11528 bgp_attr_get_lcommunity(pi
->attr
),
11532 if (type
== bgp_show_type_lcommunity_all
) {
11533 if (!bgp_attr_get_lcommunity(pi
->attr
))
11536 if (type
== bgp_show_type_dampend_paths
11537 || type
== bgp_show_type_damp_neighbor
) {
11538 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11539 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11542 if (type
== bgp_show_type_self_originated
) {
11543 if (pi
->peer
!= bgp
->peer_self
)
11547 if (!use_json
&& header
) {
11549 "BGP table version is %" PRIu64
11550 ", local router ID is %pI4, vrf id ",
11551 table
->version
, &bgp
->router_id
);
11552 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11553 vty_out(vty
, "%s", VRFID_NONE_STR
);
11555 vty_out(vty
, "%u", bgp
->vrf_id
);
11556 vty_out(vty
, "\n");
11557 vty_out(vty
, "Default local pref %u, ",
11558 bgp
->default_local_pref
);
11559 vty_out(vty
, "local AS ");
11560 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
),
11562 vty_out(vty
, "\n");
11563 if (!detail_routes
) {
11564 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11565 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11566 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11567 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11569 if (type
== bgp_show_type_dampend_paths
11570 || type
== bgp_show_type_damp_neighbor
)
11571 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11572 else if (type
== bgp_show_type_flap_statistics
11573 || type
== bgp_show_type_flap_neighbor
)
11574 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11575 else if (!detail_routes
)
11576 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11577 : BGP_SHOW_HEADER
));
11581 if (rd
!= NULL
&& !display
&& !output_count
) {
11584 "Route Distinguisher: %s\n",
11587 if (type
== bgp_show_type_dampend_paths
11588 || type
== bgp_show_type_damp_neighbor
)
11589 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11590 AFI_IP
, safi
, use_json
,
11592 else if (type
== bgp_show_type_flap_statistics
11593 || type
== bgp_show_type_flap_neighbor
)
11594 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11595 AFI_IP
, safi
, use_json
,
11598 if (detail_routes
|| detail_json
) {
11599 const struct prefix_rd
*prd
= NULL
;
11602 prd
= bgp_rd_from_dest(
11603 dest
->pdest
, safi
);
11606 route_vty_out_detail_header(
11608 bgp_dest_get_prefix(
11610 prd
, table
->afi
, safi
,
11613 route_vty_out_detail(
11614 vty
, bgp
, dest
, dest_p
, pi
,
11615 family2afi(dest_p
->family
),
11616 safi
, RPKI_NOT_BEING_USED
,
11619 route_vty_out(vty
, dest_p
, pi
, display
,
11620 safi
, json_paths
, wide
);
11631 /* encode prefix */
11632 if (dest_p
->family
== AF_FLOWSPEC
) {
11633 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11636 bgp_fs_nlri_get_string(
11638 dest_p
->u
.prefix_flowspec
.ptr
,
11639 dest_p
->u
.prefix_flowspec
.prefixlen
,
11640 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11641 family2afi(dest_p
->u
11642 .prefix_flowspec
.family
));
11644 vty_out(vty
, "\"%s/%d\": ", retstr
,
11645 dest_p
->u
.prefix_flowspec
11648 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11649 dest_p
->u
.prefix_flowspec
11653 vty_out(vty
, "\"%pFX\": ", dest_p
);
11655 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11658 /* This is used for 'json detail' vty keywords.
11660 * In plain 'json' the per-prefix header is encoded
11661 * as a standalone dictionary in the first json_paths
11663 * "<prefix>": [{header}, {path-1}, {path-N}]
11664 * (which is confusing and borderline broken)
11666 * For 'json detail' this changes the value
11667 * of each prefix-key to be a dictionary where each
11668 * header item has its own key, and json_paths is
11669 * tucked under the "paths" key:
11671 * "<header-key-1>": <header-val-1>,
11672 * "<header-key-N>": <header-val-N>,
11673 * "paths": [{path-1}, {path-N}]
11676 if (json_detail_header
&& json_paths
!= NULL
) {
11677 const struct prefix_rd
*prd
;
11679 /* Start per-prefix dictionary */
11680 vty_out(vty
, "{\n");
11682 prd
= bgp_rd_from_dest(dest
, safi
);
11684 route_vty_out_detail_header(
11686 bgp_dest_get_prefix(dest
), prd
,
11687 table
->afi
, safi
, json_paths
, true);
11689 vty_out(vty
, "\"paths\": ");
11690 json_detail_header_used
= true;
11694 * We are using no_pretty here because under
11695 * extremely high settings( say lots and lots of
11696 * routes with lots and lots of ways to reach
11697 * that route via different paths ) this can
11698 * save several minutes of output when FRR
11699 * is run on older cpu's or more underperforming
11700 * routers out there
11702 vty_json_no_pretty(vty
, json_paths
);
11704 /* End per-prefix dictionary */
11705 if (json_detail_header_used
)
11706 vty_out(vty
, "} ");
11711 json_object_free(json_paths
);
11715 output_count
+= *output_cum
;
11716 *output_cum
= output_count
;
11719 total_count
+= *total_cum
;
11720 *total_cum
= total_count
;
11724 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11728 for (i
= 0; i
< *json_header_depth
; ++i
)
11729 vty_out(vty
, " } ");
11731 vty_out(vty
, "\n");
11735 /* No route is displayed */
11736 if (output_count
== 0) {
11737 if (type
== bgp_show_type_normal
)
11739 "No BGP prefixes displayed, %ld exist\n",
11743 "\nDisplayed %ld routes and %ld total paths\n",
11744 output_count
, total_count
);
11748 return CMD_SUCCESS
;
11751 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11752 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11753 enum bgp_show_type type
, void *output_arg
,
11754 uint16_t show_flags
)
11756 struct bgp_dest
*dest
, *next
;
11757 unsigned long output_cum
= 0;
11758 unsigned long total_cum
= 0;
11759 unsigned long json_header_depth
= 0;
11760 struct bgp_table
*itable
;
11762 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11764 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11766 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11767 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11769 next
= bgp_route_next(dest
);
11770 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11773 itable
= bgp_dest_get_bgp_table_info(dest
);
11774 if (itable
!= NULL
) {
11775 struct prefix_rd prd
;
11776 char rd
[RD_ADDRSTRLEN
];
11778 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11779 prefix_rd2str(&prd
, rd
, sizeof(rd
), bgp
->asnotation
);
11780 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11781 rd
, next
== NULL
, &output_cum
,
11782 &total_cum
, &json_header_depth
,
11783 show_flags
, RPKI_NOT_BEING_USED
);
11789 if (output_cum
== 0)
11790 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11794 "\nDisplayed %ld routes and %ld total paths\n",
11795 output_cum
, total_cum
);
11797 if (use_json
&& output_cum
== 0)
11798 vty_out(vty
, "{}\n");
11800 return CMD_SUCCESS
;
11803 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11804 enum bgp_show_type type
, void *output_arg
,
11805 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11807 struct bgp_table
*table
;
11808 unsigned long json_header_depth
= 0;
11809 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11812 bgp
= bgp_get_default();
11817 vty_out(vty
, "No BGP process is configured\n");
11819 vty_out(vty
, "{}\n");
11820 return CMD_WARNING
;
11823 /* Labeled-unicast routes live in the unicast table. */
11824 if (safi
== SAFI_LABELED_UNICAST
)
11825 safi
= SAFI_UNICAST
;
11827 table
= bgp
->rib
[afi
][safi
];
11828 /* use MPLS and ENCAP specific shows until they are merged */
11829 if (safi
== SAFI_MPLS_VPN
) {
11830 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11831 output_arg
, show_flags
);
11834 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11835 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11836 output_arg
, use_json
,
11840 if (safi
== SAFI_EVPN
)
11841 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11843 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11844 NULL
, NULL
, &json_header_depth
, show_flags
,
11845 rpki_target_state
);
11848 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11849 safi_t safi
, uint16_t show_flags
)
11851 struct listnode
*node
, *nnode
;
11854 bool route_output
= false;
11855 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11858 vty_out(vty
, "{\n");
11860 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11861 route_output
= true;
11864 vty_out(vty
, ",\n");
11868 vty_out(vty
, "\"%s\":",
11869 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11873 vty_out(vty
, "\nInstance %s:\n",
11874 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11878 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11879 show_flags
, RPKI_NOT_BEING_USED
);
11883 vty_out(vty
, "}\n");
11884 else if (!route_output
)
11885 vty_out(vty
, "%% BGP instance not found\n");
11888 /* Header of detailed BGP route information */
11889 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11890 struct bgp_dest
*dest
, const struct prefix
*p
,
11891 const struct prefix_rd
*prd
, afi_t afi
,
11892 safi_t safi
, json_object
*json
,
11893 bool incremental_print
)
11895 struct bgp_path_info
*pi
;
11897 struct listnode
*node
, *nnode
;
11898 char buf1
[RD_ADDRSTRLEN
];
11902 int accept_own
= 0;
11903 int route_filter_translated_v4
= 0;
11904 int route_filter_v4
= 0;
11905 int route_filter_translated_v6
= 0;
11906 int route_filter_v6
= 0;
11907 int llgr_stale
= 0;
11909 int accept_own_nexthop
= 0;
11912 int no_advertise
= 0;
11916 int has_valid_label
= 0;
11917 mpls_label_t label
= 0;
11918 json_object
*json_adv_to
= NULL
;
11923 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11925 has_valid_label
= bgp_is_valid_label(&label
);
11927 if (safi
== SAFI_EVPN
) {
11929 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11930 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11933 prd
? ":" : "", (struct prefix_evpn
*)p
);
11935 json_object_string_add(
11937 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11940 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11945 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11947 (((safi
== SAFI_MPLS_VPN
||
11948 safi
== SAFI_ENCAP
) &&
11950 ? prefix_rd2str(prd
, buf1
,
11954 safi
== SAFI_MPLS_VPN
&& prd
? ":" : "", p
,
11958 if (incremental_print
) {
11959 vty_out(vty
, "\"prefix\": \"%pFX\",\n", p
);
11960 vty_out(vty
, "\"version\": \"%" PRIu64
"\",\n",
11963 json_object_string_addf(json
, "prefix", "%pFX",
11965 json_object_int_add(json
, "version",
11971 if (has_valid_label
) {
11973 if (incremental_print
)
11974 vty_out(vty
, "\"localLabel\": \"%u\",\n",
11977 json_object_int_add(json
, "localLabel", label
);
11979 vty_out(vty
, "Local label: %d\n", label
);
11983 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11984 vty_out(vty
, "not allocated\n");
11986 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11987 struct community
*picomm
= NULL
;
11989 picomm
= bgp_attr_get_community(pi
->attr
);
11992 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11994 if (bgp_path_suppressed(pi
))
12000 no_advertise
+= community_include(
12001 picomm
, COMMUNITY_NO_ADVERTISE
);
12003 community_include(picomm
, COMMUNITY_NO_EXPORT
);
12005 community_include(picomm
, COMMUNITY_LOCAL_AS
);
12007 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
12008 route_filter_translated_v4
+= community_include(
12009 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
12010 route_filter_translated_v6
+= community_include(
12011 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
12012 route_filter_v4
+= community_include(
12013 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
12014 route_filter_v6
+= community_include(
12015 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
12017 community_include(picomm
, COMMUNITY_LLGR_STALE
);
12018 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
12019 accept_own_nexthop
+= community_include(
12020 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
12022 community_include(picomm
, COMMUNITY_BLACKHOLE
);
12023 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
12028 vty_out(vty
, "Paths: (%d available", count
);
12030 vty_out(vty
, ", best #%d", best
);
12031 if (safi
== SAFI_UNICAST
) {
12032 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
12033 vty_out(vty
, ", table %s",
12036 vty_out(vty
, ", vrf %s",
12040 vty_out(vty
, ", no best path");
12044 ", accept own local route exported and imported in different VRF");
12045 else if (route_filter_translated_v4
)
12047 ", mark translated RTs for VPNv4 route filtering");
12048 else if (route_filter_v4
)
12050 ", attach RT as-is for VPNv4 route filtering");
12051 else if (route_filter_translated_v6
)
12053 ", mark translated RTs for VPNv6 route filtering");
12054 else if (route_filter_v6
)
12056 ", attach RT as-is for VPNv6 route filtering");
12057 else if (llgr_stale
)
12059 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
12062 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
12063 else if (accept_own_nexthop
)
12065 ", accept local nexthop");
12066 else if (blackhole
)
12067 vty_out(vty
, ", inform peer to blackhole prefix");
12068 else if (no_export
)
12069 vty_out(vty
, ", not advertised to EBGP peer");
12070 else if (no_advertise
)
12071 vty_out(vty
, ", not advertised to any peer");
12073 vty_out(vty
, ", not advertised outside local AS");
12076 ", inform EBGP peer not to advertise to their EBGP peers");
12080 ", Advertisements suppressed by an aggregate.");
12081 vty_out(vty
, ")\n");
12084 /* If we are not using addpath then we can display Advertised to and
12086 * show what peers we advertised the bestpath to. If we are using
12088 * though then we must display Advertised to on a path-by-path basis. */
12089 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12090 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12091 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12092 if (json
&& !json_adv_to
)
12093 json_adv_to
= json_object_new_object();
12095 route_vty_out_advertised_to(
12097 " Advertised to non peer-group peers:\n ",
12102 if (json
&& json_adv_to
) {
12103 if (incremental_print
) {
12104 vty_out(vty
, "\"advertisedTo\": ");
12105 vty_json(vty
, json_adv_to
);
12108 json_object_object_add(json
, "advertisedTo",
12111 if (!json
&& first
)
12112 vty_out(vty
, " Not advertised to any peer");
12113 vty_out(vty
, "\n");
12118 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12119 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12120 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12121 json_object
*json
, enum bgp_path_type pathtype
,
12122 int *display
, enum rpki_states rpki_target_state
)
12124 struct bgp_path_info
*pi
;
12126 json_object
*json_header
= NULL
;
12127 json_object
*json_paths
= NULL
;
12128 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12130 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12131 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12133 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12134 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12135 pi
->peer
, pi
->attr
, p
);
12137 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12138 && rpki_curr_state
!= rpki_target_state
)
12141 if (json
&& !json_paths
) {
12142 /* Instantiate json_paths only if path is valid */
12143 json_paths
= json_object_new_array();
12145 json_header
= json_object_new_object();
12147 json_header
= json
;
12151 route_vty_out_detail_header(
12152 vty
, bgp
, bgp_node
,
12153 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12154 safi
, json_header
, false);
12159 if (pathtype
== BGP_PATH_SHOW_ALL
12160 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12161 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12162 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12163 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12164 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12165 route_vty_out_detail(vty
, bgp
, bgp_node
,
12166 bgp_dest_get_prefix(bgp_node
), pi
,
12167 AFI_IP
, safi
, rpki_curr_state
,
12171 if (json
&& json_paths
) {
12172 json_object_object_add(json_header
, "paths", json_paths
);
12175 json_object_object_addf(
12177 BGP_RD_AS_FORMAT(bgp
->asnotation
), pfx_rd
);
12182 * Return rd based on safi
12184 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12188 case SAFI_MPLS_VPN
:
12191 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12194 case SAFI_MULTICAST
:
12195 case SAFI_LABELED_UNICAST
:
12196 case SAFI_FLOWSPEC
:
12201 assert(!"Reached end of function when we were not expecting it");
12204 /* Display specified route of BGP table. */
12205 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12206 struct bgp_table
*rib
, const char *ip_str
,
12207 afi_t afi
, safi_t safi
,
12208 enum rpki_states rpki_target_state
,
12209 struct prefix_rd
*prd
, int prefix_check
,
12210 enum bgp_path_type pathtype
, bool use_json
)
12214 struct prefix match
;
12215 struct bgp_dest
*dest
;
12216 struct bgp_dest
*rm
;
12217 struct bgp_table
*table
;
12218 json_object
*json
= NULL
;
12219 json_object
*json_paths
= NULL
;
12221 /* Check IP address argument. */
12222 ret
= str2prefix(ip_str
, &match
);
12224 vty_out(vty
, "address is malformed\n");
12225 return CMD_WARNING
;
12228 match
.family
= afi2family(afi
);
12231 json
= json_object_new_object();
12233 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12234 for (dest
= bgp_table_top(rib
); dest
;
12235 dest
= bgp_route_next(dest
)) {
12236 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12238 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12240 table
= bgp_dest_get_bgp_table_info(dest
);
12244 rm
= bgp_node_match(table
, &match
);
12248 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12250 && rm_p
->prefixlen
!= match
.prefixlen
) {
12251 bgp_dest_unlock_node(rm
);
12255 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12256 bgp
, afi
, safi
, json
, pathtype
,
12257 &display
, rpki_target_state
);
12259 bgp_dest_unlock_node(rm
);
12261 } else if (safi
== SAFI_EVPN
) {
12262 struct bgp_dest
*longest_pfx
;
12263 bool is_exact_pfxlen_match
= false;
12265 for (dest
= bgp_table_top(rib
); dest
;
12266 dest
= bgp_route_next(dest
)) {
12267 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12269 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12271 table
= bgp_dest_get_bgp_table_info(dest
);
12275 longest_pfx
= NULL
;
12276 is_exact_pfxlen_match
= false;
12278 * Search through all the prefixes for a match. The
12279 * pfx's are enumerated in ascending order of pfxlens.
12280 * So, the last pfx match is the longest match. Set
12281 * is_exact_pfxlen_match when we get exact pfxlen match
12283 for (rm
= bgp_table_top(table
); rm
;
12284 rm
= bgp_route_next(rm
)) {
12285 const struct prefix
*rm_p
=
12286 bgp_dest_get_prefix(rm
);
12288 * Get prefixlen of the ip-prefix within type5
12291 if (evpn_type5_prefix_match(rm_p
, &match
)
12295 bgp_evpn_get_type5_prefixlen(
12297 if (type5_pfxlen
== match
.prefixlen
) {
12298 is_exact_pfxlen_match
= true;
12299 bgp_dest_unlock_node(rm
);
12308 if (prefix_check
&& !is_exact_pfxlen_match
)
12312 bgp_dest_lock_node(rm
);
12314 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12315 bgp
, afi
, safi
, json
, pathtype
,
12316 &display
, rpki_target_state
);
12318 bgp_dest_unlock_node(rm
);
12320 } else if (safi
== SAFI_FLOWSPEC
) {
12322 json_paths
= json_object_new_array();
12324 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12325 &match
, prefix_check
,
12331 json_object_object_add(json
, "paths",
12334 json_object_free(json_paths
);
12337 dest
= bgp_node_match(rib
, &match
);
12338 if (dest
!= NULL
) {
12339 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12341 || dest_p
->prefixlen
== match
.prefixlen
) {
12342 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12343 safi
, json
, pathtype
,
12344 &display
, rpki_target_state
);
12347 bgp_dest_unlock_node(dest
);
12352 vty_json(vty
, json
);
12355 vty_out(vty
, "%% Network not in table\n");
12356 return CMD_WARNING
;
12360 return CMD_SUCCESS
;
12363 /* Display specified route of Main RIB */
12364 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12365 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12366 int prefix_check
, enum bgp_path_type pathtype
,
12367 enum rpki_states rpki_target_state
, bool use_json
)
12370 bgp
= bgp_get_default();
12373 vty_out(vty
, "No BGP process is configured\n");
12375 vty_out(vty
, "{}\n");
12376 return CMD_WARNING
;
12380 /* labeled-unicast routes live in the unicast table */
12381 if (safi
== SAFI_LABELED_UNICAST
)
12382 safi
= SAFI_UNICAST
;
12384 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12385 afi
, safi
, rpki_target_state
, prd
,
12386 prefix_check
, pathtype
, use_json
);
12389 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12390 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12391 safi_t safi
, bool uj
)
12393 struct lcommunity
*lcom
;
12398 uint16_t show_flags
= 0;
12402 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12404 b
= buffer_new(1024);
12405 for (i
= 0; i
< argc
; i
++) {
12407 buffer_putc(b
, ' ');
12409 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12411 buffer_putstr(b
, argv
[i
]->arg
);
12415 buffer_putc(b
, '\0');
12417 str
= buffer_getstr(b
);
12420 lcom
= lcommunity_str2com(str
);
12421 XFREE(MTYPE_TMP
, str
);
12423 vty_out(vty
, "%% Large-community malformed\n");
12424 return CMD_WARNING
;
12427 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12428 (exact
? bgp_show_type_lcommunity_exact
12429 : bgp_show_type_lcommunity
),
12430 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12432 lcommunity_free(&lcom
);
12436 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12437 const char *lcom
, bool exact
, afi_t afi
,
12438 safi_t safi
, bool uj
)
12440 struct community_list
*list
;
12441 uint16_t show_flags
= 0;
12444 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12447 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12448 LARGE_COMMUNITY_LIST_MASTER
);
12449 if (list
== NULL
) {
12450 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12452 return CMD_WARNING
;
12455 return bgp_show(vty
, bgp
, afi
, safi
,
12456 (exact
? bgp_show_type_lcommunity_list_exact
12457 : bgp_show_type_lcommunity_list
),
12458 list
, show_flags
, RPKI_NOT_BEING_USED
);
12461 DEFUN (show_ip_bgp_large_community_list
,
12462 show_ip_bgp_large_community_list_cmd
,
12463 "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]",
12467 BGP_INSTANCE_HELP_STR
12469 BGP_SAFI_WITH_LABEL_HELP_STR
12470 "Display routes matching the large-community-list\n"
12471 "large-community-list number\n"
12472 "large-community-list name\n"
12473 "Exact match of the large-communities\n"
12476 afi_t afi
= AFI_IP6
;
12477 safi_t safi
= SAFI_UNICAST
;
12479 bool exact_match
= 0;
12480 struct bgp
*bgp
= NULL
;
12481 bool uj
= use_json(argc
, argv
);
12486 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12489 return CMD_WARNING
;
12491 argv_find(argv
, argc
, "large-community-list", &idx
);
12493 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12495 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12498 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12499 exact_match
, afi
, safi
, uj
);
12501 DEFUN (show_ip_bgp_large_community
,
12502 show_ip_bgp_large_community_cmd
,
12503 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12507 BGP_INSTANCE_HELP_STR
12509 BGP_SAFI_WITH_LABEL_HELP_STR
12510 "Display routes matching the large-communities\n"
12511 "List of large-community numbers\n"
12512 "Exact match of the large-communities\n"
12515 afi_t afi
= AFI_IP6
;
12516 safi_t safi
= SAFI_UNICAST
;
12518 bool exact_match
= 0;
12519 struct bgp
*bgp
= NULL
;
12520 bool uj
= use_json(argc
, argv
);
12521 uint16_t show_flags
= 0;
12525 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12528 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12531 return CMD_WARNING
;
12533 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12534 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12538 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12539 exact_match
, afi
, safi
, uj
);
12541 return bgp_show(vty
, bgp
, afi
, safi
,
12542 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12543 RPKI_NOT_BEING_USED
);
12546 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12547 safi_t safi
, struct json_object
*json_array
);
12548 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12549 safi_t safi
, struct json_object
*json
);
12552 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12553 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12554 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12555 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12557 bool uj
= use_json(argc
, argv
);
12558 struct bgp
*bgp
= NULL
;
12559 safi_t safi
= SAFI_UNICAST
;
12560 afi_t afi
= AFI_IP6
;
12562 struct json_object
*json_all
= NULL
;
12563 struct json_object
*json_afi_safi
= NULL
;
12565 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12568 return CMD_WARNING
;
12571 json_all
= json_object_new_object();
12573 FOREACH_AFI_SAFI (afi
, safi
) {
12575 * So limit output to those afi/safi pairs that
12576 * actually have something interesting in them
12578 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12583 json_afi_safi
= json_object_new_array();
12584 json_object_object_add(
12586 get_afi_safi_str(afi
, safi
, true),
12589 json_afi_safi
= NULL
;
12592 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12596 vty_json(vty
, json_all
);
12598 return CMD_SUCCESS
;
12601 /* BGP route print out function without JSON */
12602 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12603 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12604 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12608 BGP_INSTANCE_HELP_STR
12611 "BGP RIB advertisement statistics\n"
12614 afi_t afi
= AFI_IP6
;
12615 safi_t safi
= SAFI_UNICAST
;
12616 struct bgp
*bgp
= NULL
;
12618 bool uj
= use_json(argc
, argv
);
12619 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12621 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12624 return CMD_WARNING
;
12627 json_afi_safi
= json_object_new_array();
12629 json_afi_safi
= NULL
;
12631 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12634 json
= json_object_new_object();
12635 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12637 vty_json(vty
, json
);
12642 /* BGP route print out function without JSON */
12643 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12644 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12645 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12647 statistics [json]",
12648 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12649 BGP_SAFI_WITH_LABEL_HELP_STR
12650 "BGP RIB advertisement statistics\n" JSON_STR
)
12652 afi_t afi
= AFI_IP6
;
12653 safi_t safi
= SAFI_UNICAST
;
12654 struct bgp
*bgp
= NULL
;
12656 bool uj
= use_json(argc
, argv
);
12657 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12659 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12662 return CMD_WARNING
;
12665 json_afi_safi
= json_object_new_array();
12667 json_afi_safi
= NULL
;
12669 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12672 json
= json_object_new_object();
12673 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12675 vty_json(vty
, json
);
12680 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12681 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12682 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12683 "]] [all$all] dampening parameters [json]",
12684 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12685 BGP_SAFI_WITH_LABEL_HELP_STR
12686 "Display the entries for all address families\n"
12687 "Display detailed information about dampening\n"
12688 "Display detail of configured dampening parameters\n"
12691 afi_t afi
= AFI_IP6
;
12692 safi_t safi
= SAFI_UNICAST
;
12693 struct bgp
*bgp
= NULL
;
12695 uint16_t show_flags
= 0;
12696 bool uj
= use_json(argc
, argv
);
12700 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12703 /* [<ipv4|ipv6> [all]] */
12705 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12706 if (argv_find(argv
, argc
, "ipv4", &idx
))
12707 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12709 if (argv_find(argv
, argc
, "ipv6", &idx
))
12710 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12713 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12716 return CMD_WARNING
;
12718 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12721 /* BGP route print out function */
12722 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12723 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12724 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12728 |dampening <flap-statistics|dampened-paths>\
12729 |community [AA:NN|local-AS|no-advertise|no-export\
12730 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12731 |accept-own|accept-own-nexthop|route-filter-v6\
12732 |route-filter-v4|route-filter-translated-v6\
12733 |route-filter-translated-v4] [exact-match]\
12734 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12735 |filter-list AS_PATH_FILTER_NAME\
12737 |access-list ACCESSLIST_NAME\
12738 |route-map RMAP_NAME\
12739 |rpki <invalid|valid|notfound>\
12740 |version (1-4294967295)\
12742 |A.B.C.D/M longer-prefixes\
12743 |X:X::X:X/M longer-prefixes\
12744 |"BGP_SELF_ORIG_CMD_STR
"\
12745 |detail-routes$detail_routes\
12746 ] [json$uj [detail$detail_json] | wide$wide]",
12747 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12748 BGP_SAFI_WITH_LABEL_HELP_STR
12749 "Display the entries for all address families\n"
12750 "Display only routes with non-natural netmasks\n"
12751 "Display detailed information about dampening\n"
12752 "Display flap statistics of routes\n"
12753 "Display paths suppressed due to dampening\n"
12754 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12755 "Do not send outside local AS (well-known community)\n"
12756 "Do not advertise to any peer (well-known community)\n"
12757 "Do not export to next AS (well-known community)\n"
12758 "Graceful shutdown (well-known community)\n"
12759 "Do not export to any peer (well-known community)\n"
12760 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12761 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12762 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12763 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12764 "Should accept VPN route with local nexthop (well-known community)\n"
12765 "RT VPNv6 route filtering (well-known community)\n"
12766 "RT VPNv4 route filtering (well-known community)\n"
12767 "RT translated VPNv6 route filtering (well-known community)\n"
12768 "RT translated VPNv4 route filtering (well-known community)\n"
12769 "Exact match of the communities\n"
12770 "Community-list number\n"
12771 "Community-list name\n"
12772 "Display routes matching the community-list\n"
12773 "Exact match of the communities\n"
12774 "Display routes conforming to the filter-list\n"
12775 "Regular expression access list name\n"
12776 "Display routes conforming to the prefix-list\n"
12777 "Prefix-list name\n"
12778 "Display routes conforming to the access-list\n"
12779 "Access-list name\n"
12780 "Display routes matching the route-map\n"
12781 "A route-map to match on\n"
12782 "RPKI route types\n"
12783 "A valid path as determined by rpki\n"
12784 "A invalid path as determined by rpki\n"
12785 "A path that has no rpki data\n"
12786 "Display prefixes with matching version numbers\n"
12787 "Version number and above\n"
12788 "Display prefixes with matching BGP community alias\n"
12789 "BGP community alias\n"
12791 "Display route and more specific routes\n"
12793 "Display route and more specific routes\n"
12794 BGP_SELF_ORIG_HELP_STR
12795 "Display detailed version of all routes\n"
12797 "Display detailed version of JSON output\n"
12798 "Increase table width for longer prefixes\n")
12800 afi_t afi
= AFI_IP6
;
12801 safi_t safi
= SAFI_UNICAST
;
12802 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12803 void *output_arg
= NULL
;
12804 struct bgp
*bgp
= NULL
;
12806 int exact_match
= 0;
12807 char *community
= NULL
;
12809 uint16_t show_flags
= 0;
12810 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12815 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12819 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12822 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12824 /* [<ipv4|ipv6> [all]] */
12826 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12828 if (argv_find(argv
, argc
, "ipv4", &idx
))
12829 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12831 if (argv_find(argv
, argc
, "ipv6", &idx
))
12832 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12836 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12838 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12841 return CMD_WARNING
;
12843 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12844 sh_type
= bgp_show_type_cidr_only
;
12846 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12847 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12848 sh_type
= bgp_show_type_dampend_paths
;
12849 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12850 sh_type
= bgp_show_type_flap_statistics
;
12853 if (argv_find(argv
, argc
, "community", &idx
)) {
12854 char *maybecomm
= NULL
;
12856 if (idx
+ 1 < argc
) {
12857 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12858 maybecomm
= argv
[idx
+ 1]->arg
;
12860 maybecomm
= argv
[idx
+ 1]->text
;
12863 if (maybecomm
&& !strmatch(maybecomm
, "json")
12864 && !strmatch(maybecomm
, "exact-match"))
12865 community
= maybecomm
;
12867 if (argv_find(argv
, argc
, "exact-match", &idx
))
12871 sh_type
= bgp_show_type_community_all
;
12874 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12875 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12876 struct community_list
*list
;
12878 if (argv_find(argv
, argc
, "exact-match", &idx
))
12881 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12882 COMMUNITY_LIST_MASTER
);
12883 if (list
== NULL
) {
12884 vty_out(vty
, "%% %s community-list not found\n",
12885 clist_number_or_name
);
12886 return CMD_WARNING
;
12890 sh_type
= bgp_show_type_community_list_exact
;
12892 sh_type
= bgp_show_type_community_list
;
12896 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12897 const char *filter
= argv
[++idx
]->arg
;
12898 struct as_list
*as_list
;
12900 as_list
= as_list_lookup(filter
);
12901 if (as_list
== NULL
) {
12902 vty_out(vty
, "%% %s AS-path access-list not found\n",
12904 return CMD_WARNING
;
12907 sh_type
= bgp_show_type_filter_list
;
12908 output_arg
= as_list
;
12911 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12912 const char *prefix_list_str
= argv
[++idx
]->arg
;
12913 struct prefix_list
*plist
;
12915 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12916 if (plist
== NULL
) {
12917 vty_out(vty
, "%% %s prefix-list not found\n",
12919 return CMD_WARNING
;
12922 sh_type
= bgp_show_type_prefix_list
;
12923 output_arg
= plist
;
12926 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12927 const char *access_list_str
= argv
[++idx
]->arg
;
12928 struct access_list
*alist
;
12930 alist
= access_list_lookup(afi
, access_list_str
);
12932 vty_out(vty
, "%% %s access-list not found\n",
12934 return CMD_WARNING
;
12937 sh_type
= bgp_show_type_access_list
;
12938 output_arg
= alist
;
12941 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12942 const char *rmap_str
= argv
[++idx
]->arg
;
12943 struct route_map
*rmap
;
12945 rmap
= route_map_lookup_by_name(rmap_str
);
12947 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12948 return CMD_WARNING
;
12951 sh_type
= bgp_show_type_route_map
;
12955 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12956 sh_type
= bgp_show_type_rpki
;
12957 if (argv_find(argv
, argc
, "valid", &idx
))
12958 rpki_target_state
= RPKI_VALID
;
12959 else if (argv_find(argv
, argc
, "invalid", &idx
))
12960 rpki_target_state
= RPKI_INVALID
;
12963 /* Display prefixes with matching version numbers */
12964 if (argv_find(argv
, argc
, "version", &idx
)) {
12965 sh_type
= bgp_show_type_prefix_version
;
12966 output_arg
= argv
[idx
+ 1]->arg
;
12969 /* Display prefixes with matching BGP community alias */
12970 if (argv_find(argv
, argc
, "alias", &idx
)) {
12971 sh_type
= bgp_show_type_community_alias
;
12972 output_arg
= argv
[idx
+ 1]->arg
;
12975 /* prefix-longer */
12976 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12977 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12978 const char *prefix_str
= argv
[idx
]->arg
;
12980 if (!str2prefix(prefix_str
, &p
)) {
12981 vty_out(vty
, "%% Malformed Prefix\n");
12982 return CMD_WARNING
;
12985 sh_type
= bgp_show_type_prefix_longer
;
12989 /* self originated only */
12990 if (argv_find(argv
, argc
, BGP_SELF_ORIG_CMD_STR
, &idx
))
12991 sh_type
= bgp_show_type_self_originated
;
12994 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12996 return bgp_show_community(vty
, bgp
, community
,
12997 exact_match
, afi
, safi
,
13000 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
13001 output_arg
, show_flags
,
13002 rpki_target_state
);
13004 struct listnode
*node
;
13006 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
13010 vty_out(vty
, "{\n");
13012 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13013 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
13014 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13017 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
13018 FOREACH_SAFI (safi
) {
13019 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
13027 vty_out(vty
, ",\n");
13028 vty_out(vty
, "\"%s\":{\n",
13029 get_afi_safi_str(afi
,
13034 "\nFor address family: %s\n",
13040 bgp_show_community(
13041 vty
, abgp
, community
,
13042 exact_match
, afi
, safi
,
13045 bgp_show(vty
, abgp
, afi
, safi
,
13046 sh_type
, output_arg
,
13048 rpki_target_state
);
13050 vty_out(vty
, "}\n");
13054 /* show <ip> bgp all: for each AFI and SAFI*/
13055 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
13056 FOREACH_AFI_SAFI (afi
, safi
) {
13057 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
13065 vty_out(vty
, ",\n");
13067 vty_out(vty
, "\"%s\":{\n",
13068 get_afi_safi_str(afi
,
13073 "\nFor address family: %s\n",
13079 bgp_show_community(
13080 vty
, abgp
, community
,
13081 exact_match
, afi
, safi
,
13084 bgp_show(vty
, abgp
, afi
, safi
,
13085 sh_type
, output_arg
,
13087 rpki_target_state
);
13089 vty_out(vty
, "}\n");
13094 vty_out(vty
, "}\n");
13096 return CMD_SUCCESS
;
13099 DEFUN (show_ip_bgp_route
,
13100 show_ip_bgp_route_cmd
,
13101 "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]",
13105 BGP_INSTANCE_HELP_STR
13107 BGP_SAFI_WITH_LABEL_HELP_STR
13108 "Network in the BGP routing table to display\n"
13110 "Network in the BGP routing table to display\n"
13112 "Display only the bestpath\n"
13113 "Display only multipaths\n"
13114 "Display only paths that match the specified rpki state\n"
13115 "A valid path as determined by rpki\n"
13116 "A invalid path as determined by rpki\n"
13117 "A path that has no rpki data\n"
13120 int prefix_check
= 0;
13122 afi_t afi
= AFI_IP6
;
13123 safi_t safi
= SAFI_UNICAST
;
13124 char *prefix
= NULL
;
13125 struct bgp
*bgp
= NULL
;
13126 enum bgp_path_type path_type
;
13127 bool uj
= use_json(argc
, argv
);
13131 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13134 return CMD_WARNING
;
13138 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13139 return CMD_WARNING
;
13142 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13143 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13144 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13146 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13147 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13150 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13151 && afi
!= AFI_IP6
) {
13153 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13154 return CMD_WARNING
;
13156 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13157 && afi
!= AFI_IP
) {
13159 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13160 return CMD_WARNING
;
13163 prefix
= argv
[idx
]->arg
;
13165 /* [<bestpath|multipath>] */
13166 if (argv_find(argv
, argc
, "bestpath", &idx
))
13167 path_type
= BGP_PATH_SHOW_BESTPATH
;
13168 else if (argv_find(argv
, argc
, "multipath", &idx
))
13169 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13171 path_type
= BGP_PATH_SHOW_ALL
;
13173 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13174 path_type
, RPKI_NOT_BEING_USED
, uj
);
13177 DEFUN (show_ip_bgp_regexp
,
13178 show_ip_bgp_regexp_cmd
,
13179 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13183 BGP_INSTANCE_HELP_STR
13185 BGP_SAFI_WITH_LABEL_HELP_STR
13186 "Display routes matching the AS path regular expression\n"
13187 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13190 afi_t afi
= AFI_IP6
;
13191 safi_t safi
= SAFI_UNICAST
;
13192 struct bgp
*bgp
= NULL
;
13193 bool uj
= use_json(argc
, argv
);
13194 char *regstr
= NULL
;
13197 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13200 return CMD_WARNING
;
13202 // get index of regex
13203 if (argv_find(argv
, argc
, "REGEX", &idx
))
13204 regstr
= argv
[idx
]->arg
;
13207 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13208 bgp_show_type_regexp
, uj
);
13211 DEFPY (show_ip_bgp_instance_all
,
13212 show_ip_bgp_instance_all_cmd
,
13213 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13217 BGP_INSTANCE_ALL_HELP_STR
13219 BGP_SAFI_WITH_LABEL_HELP_STR
13221 "Increase table width for longer prefixes\n")
13223 afi_t afi
= AFI_IP6
;
13224 safi_t safi
= SAFI_UNICAST
;
13225 struct bgp
*bgp
= NULL
;
13227 uint16_t show_flags
= 0;
13231 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13235 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13237 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13240 return CMD_WARNING
;
13242 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13243 return CMD_SUCCESS
;
13246 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13247 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13252 uint16_t show_flags
= 0;
13255 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13257 if (!config_bgp_aspath_validate(regstr
)) {
13258 vty_out(vty
, "Invalid character in REGEX %s\n",
13260 return CMD_WARNING_CONFIG_FAILED
;
13263 regex
= bgp_regcomp(regstr
);
13265 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13266 return CMD_WARNING
;
13269 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13270 RPKI_NOT_BEING_USED
);
13271 bgp_regex_free(regex
);
13275 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13276 const char *comstr
, int exact
, afi_t afi
,
13277 safi_t safi
, uint16_t show_flags
)
13279 struct community
*com
;
13282 com
= community_str2com(comstr
);
13284 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13285 return CMD_WARNING
;
13288 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13289 (exact
? bgp_show_type_community_exact
13290 : bgp_show_type_community
),
13291 com
, show_flags
, RPKI_NOT_BEING_USED
);
13292 community_free(&com
);
13298 BGP_STATS_MAXBITLEN
= 0,
13300 BGP_STATS_PREFIXES
,
13302 BGP_STATS_UNAGGREGATEABLE
,
13303 BGP_STATS_MAX_AGGREGATEABLE
,
13304 BGP_STATS_AGGREGATES
,
13306 BGP_STATS_ASPATH_COUNT
,
13307 BGP_STATS_ASPATH_MAXHOPS
,
13308 BGP_STATS_ASPATH_TOTHOPS
,
13309 BGP_STATS_ASPATH_MAXSIZE
,
13310 BGP_STATS_ASPATH_TOTSIZE
,
13311 BGP_STATS_ASN_HIGHEST
,
13315 #define TABLE_STATS_IDX_VTY 0
13316 #define TABLE_STATS_IDX_JSON 1
13318 static const char *table_stats_strs
[][2] = {
13319 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13320 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13321 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13322 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13323 "unaggregateablePrefixes"},
13324 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13325 "maximumAggregateablePrefixes"},
13326 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13327 "bgpAggregateAdvertisements"},
13328 [BGP_STATS_SPACE
] = {"Address space advertised",
13329 "addressSpaceAdvertised"},
13330 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13331 "advertisementsWithPaths"},
13332 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13334 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13336 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13337 "averageAsPathLengthHops"},
13338 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13339 "averageAsPathSizeBytes"},
13340 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13341 [BGP_STATS_MAX
] = {NULL
, NULL
}
13344 struct bgp_table_stats
{
13345 struct bgp_table
*table
;
13346 unsigned long long counts
[BGP_STATS_MAX
];
13349 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13352 double total_space
;
13355 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13356 struct bgp_table_stats
*ts
, unsigned int space
)
13358 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13359 struct bgp_path_info
*pi
;
13360 const struct prefix
*rn_p
;
13362 if (!bgp_dest_has_bgp_path_info_data(dest
))
13365 rn_p
= bgp_dest_get_prefix(dest
);
13366 ts
->counts
[BGP_STATS_PREFIXES
]++;
13367 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13369 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13370 /* check if the prefix is included by any other announcements */
13371 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13372 pdest
= bgp_dest_parent_nolock(pdest
);
13374 if (pdest
== NULL
|| pdest
== top
) {
13375 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13376 /* announced address space */
13378 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13379 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13380 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13383 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13384 ts
->counts
[BGP_STATS_RIB
]++;
13386 if (CHECK_FLAG(pi
->attr
->flag
,
13387 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13388 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13390 /* as-path stats */
13391 if (pi
->attr
->aspath
) {
13392 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13393 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13394 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13396 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13398 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13399 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13401 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13402 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13404 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13405 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13406 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13407 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13412 static void bgp_table_stats_walker(struct event
*t
)
13414 struct bgp_dest
*dest
, *ndest
;
13415 struct bgp_dest
*top
;
13416 struct bgp_table_stats
*ts
= EVENT_ARG(t
);
13417 unsigned int space
= 0;
13419 if (!(top
= bgp_table_top(ts
->table
)))
13422 switch (ts
->table
->afi
) {
13424 space
= IPV4_MAX_BITLEN
;
13427 space
= IPV6_MAX_BITLEN
;
13430 space
= EVPN_ROUTE_PREFIXLEN
;
13437 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13439 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13440 if (ts
->table
->safi
== SAFI_MPLS_VPN
13441 || ts
->table
->safi
== SAFI_ENCAP
13442 || ts
->table
->safi
== SAFI_EVPN
) {
13443 struct bgp_table
*table
;
13445 table
= bgp_dest_get_bgp_table_info(dest
);
13449 top
= bgp_table_top(table
);
13450 for (ndest
= bgp_table_top(table
); ndest
;
13451 ndest
= bgp_route_next(ndest
))
13452 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13454 bgp_table_stats_rn(dest
, top
, ts
, space
);
13459 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13460 struct json_object
*json_array
)
13462 struct listnode
*node
, *nnode
;
13465 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13466 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13469 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13470 safi_t safi
, struct json_object
*json_array
)
13472 struct bgp_table_stats ts
;
13474 int ret
= CMD_SUCCESS
;
13476 struct json_object
*json
= NULL
;
13477 uint32_t bitlen
= 0;
13478 struct json_object
*json_bitlen
;
13481 json
= json_object_new_object();
13483 if (!bgp
->rib
[afi
][safi
]) {
13484 char warning_msg
[50];
13486 snprintf(warning_msg
, sizeof(warning_msg
),
13487 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13491 vty_out(vty
, "%s\n", warning_msg
);
13493 json_object_string_add(json
, "warning", warning_msg
);
13496 goto end_table_stats
;
13500 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13501 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13503 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13505 /* labeled-unicast routes live in the unicast table */
13506 if (safi
== SAFI_LABELED_UNICAST
)
13507 safi
= SAFI_UNICAST
;
13509 memset(&ts
, 0, sizeof(ts
));
13510 ts
.table
= bgp
->rib
[afi
][safi
];
13511 event_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13513 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13514 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13515 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13519 case BGP_STATS_ASPATH_TOTHOPS
:
13520 case BGP_STATS_ASPATH_TOTSIZE
:
13523 temp_buf
, sizeof(temp_buf
), "%12.2f",
13525 ? (float)ts
.counts
[i
]
13527 [BGP_STATS_ASPATH_COUNT
]
13529 vty_out(vty
, "%-30s: %s",
13530 table_stats_strs
[i
]
13531 [TABLE_STATS_IDX_VTY
],
13534 json_object_double_add(
13536 table_stats_strs
[i
]
13537 [TABLE_STATS_IDX_JSON
],
13539 ? (double)ts
.counts
[i
]
13540 / (double)ts
.counts
13541 [BGP_STATS_ASPATH_COUNT
]
13545 case BGP_STATS_TOTPLEN
:
13548 temp_buf
, sizeof(temp_buf
), "%12.2f",
13550 ? (float)ts
.counts
[i
]
13552 [BGP_STATS_PREFIXES
]
13554 vty_out(vty
, "%-30s: %s",
13555 table_stats_strs
[i
]
13556 [TABLE_STATS_IDX_VTY
],
13559 json_object_double_add(
13561 table_stats_strs
[i
]
13562 [TABLE_STATS_IDX_JSON
],
13564 ? (double)ts
.counts
[i
]
13565 / (double)ts
.counts
13566 [BGP_STATS_PREFIXES
]
13570 case BGP_STATS_SPACE
:
13572 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13574 vty_out(vty
, "%-30s: %s\n",
13575 table_stats_strs
[i
]
13576 [TABLE_STATS_IDX_VTY
],
13579 json_object_double_add(
13581 table_stats_strs
[i
]
13582 [TABLE_STATS_IDX_JSON
],
13583 (double)ts
.total_space
);
13585 if (afi
== AFI_IP6
) {
13587 snprintf(temp_buf
, sizeof(temp_buf
),
13590 * pow(2.0, -128 + 32));
13591 vty_out(vty
, "%30s: %s\n",
13592 "/32 equivalent %s\n",
13595 json_object_double_add(
13596 json
, "/32equivalent",
13597 (double)(ts
.total_space
13602 snprintf(temp_buf
, sizeof(temp_buf
),
13605 * pow(2.0, -128 + 48));
13606 vty_out(vty
, "%30s: %s\n",
13607 "/48 equivalent %s\n",
13610 json_object_double_add(
13611 json
, "/48equivalent",
13612 (double)(ts
.total_space
13618 snprintf(temp_buf
, sizeof(temp_buf
),
13620 ts
.total_space
* 100.
13622 vty_out(vty
, "%30s: %s\n",
13623 "% announced ", temp_buf
);
13625 json_object_double_add(
13626 json
, "%announced",
13627 (double)(ts
.total_space
* 100.
13631 snprintf(temp_buf
, sizeof(temp_buf
),
13634 * pow(2.0, -32 + 8));
13635 vty_out(vty
, "%30s: %s\n",
13636 "/8 equivalent ", temp_buf
);
13638 json_object_double_add(
13639 json
, "/8equivalent",
13640 (double)(ts
.total_space
13641 * pow(2.0, -32 + 8)));
13644 snprintf(temp_buf
, sizeof(temp_buf
),
13647 * pow(2.0, -32 + 24));
13648 vty_out(vty
, "%30s: %s\n",
13649 "/24 equivalent ", temp_buf
);
13651 json_object_double_add(
13652 json
, "/24equivalent",
13653 (double)(ts
.total_space
13654 * pow(2.0, -32 + 24)));
13660 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13662 vty_out(vty
, "%-30s: %s",
13663 table_stats_strs
[i
]
13664 [TABLE_STATS_IDX_VTY
],
13667 json_object_int_add(
13669 table_stats_strs
[i
]
13670 [TABLE_STATS_IDX_JSON
],
13675 vty_out(vty
, "\n");
13680 bitlen
= IPV4_MAX_BITLEN
;
13683 bitlen
= IPV6_MAX_BITLEN
;
13686 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13694 json_bitlen
= json_object_new_array();
13696 for (i
= 0; i
<= bitlen
; i
++) {
13697 struct json_object
*ind_bit
= json_object_new_object();
13699 if (!ts
.prefix_len_count
[i
])
13702 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13703 json_object_int_add(ind_bit
, temp_buf
,
13704 ts
.prefix_len_count
[i
]);
13705 json_object_array_add(json_bitlen
, ind_bit
);
13707 json_object_object_add(json
, "prefixLength", json_bitlen
);
13712 json_object_array_add(json_array
, json
);
13716 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13717 safi_t safi
, struct json_object
*json_array
)
13720 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13721 return CMD_SUCCESS
;
13724 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13736 PCOUNT_BPATH_SELECTED
,
13737 PCOUNT_PFCNT
, /* the figure we display to users */
13741 static const char *const pcount_strs
[] = {
13742 [PCOUNT_ADJ_IN
] = "Adj-in",
13743 [PCOUNT_DAMPED
] = "Damped",
13744 [PCOUNT_REMOVED
] = "Removed",
13745 [PCOUNT_HISTORY
] = "History",
13746 [PCOUNT_STALE
] = "Stale",
13747 [PCOUNT_VALID
] = "Valid",
13748 [PCOUNT_ALL
] = "All RIB",
13749 [PCOUNT_COUNTED
] = "PfxCt counted",
13750 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13751 [PCOUNT_PFCNT
] = "Useable",
13752 [PCOUNT_MAX
] = NULL
,
13755 struct peer_pcounts
{
13756 unsigned int count
[PCOUNT_MAX
];
13757 const struct peer
*peer
;
13758 const struct bgp_table
*table
;
13762 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13764 const struct bgp_adj_in
*ain
;
13765 const struct bgp_path_info
*pi
;
13766 const struct peer
*peer
= pc
->peer
;
13768 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13769 if (ain
->peer
== peer
)
13770 pc
->count
[PCOUNT_ADJ_IN
]++;
13772 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13774 if (pi
->peer
!= peer
)
13777 pc
->count
[PCOUNT_ALL
]++;
13779 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13780 pc
->count
[PCOUNT_DAMPED
]++;
13781 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13782 pc
->count
[PCOUNT_HISTORY
]++;
13783 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13784 pc
->count
[PCOUNT_REMOVED
]++;
13785 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13786 pc
->count
[PCOUNT_STALE
]++;
13787 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13788 pc
->count
[PCOUNT_VALID
]++;
13789 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13790 pc
->count
[PCOUNT_PFCNT
]++;
13791 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13792 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13794 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13795 pc
->count
[PCOUNT_COUNTED
]++;
13796 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13798 EC_LIB_DEVELOPMENT
,
13799 "Attempting to count but flags say it is unusable");
13801 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13803 EC_LIB_DEVELOPMENT
,
13804 "Not counted but flags say we should");
13809 static void bgp_peer_count_walker(struct event
*t
)
13811 struct bgp_dest
*rn
, *rm
;
13812 const struct bgp_table
*table
;
13813 struct peer_pcounts
*pc
= EVENT_ARG(t
);
13815 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13816 || pc
->safi
== SAFI_EVPN
) {
13817 /* Special handling for 2-level routing tables. */
13818 for (rn
= bgp_table_top(pc
->table
); rn
;
13819 rn
= bgp_route_next(rn
)) {
13820 table
= bgp_dest_get_bgp_table_info(rn
);
13822 for (rm
= bgp_table_top(table
); rm
;
13823 rm
= bgp_route_next(rm
))
13824 bgp_peer_count_proc(rm
, pc
);
13827 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13828 bgp_peer_count_proc(rn
, pc
);
13831 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13832 safi_t safi
, bool use_json
)
13834 struct peer_pcounts pcounts
= {.peer
= peer
};
13836 json_object
*json
= NULL
;
13837 json_object
*json_loop
= NULL
;
13840 json
= json_object_new_object();
13841 json_loop
= json_object_new_object();
13844 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13845 || !peer
->bgp
->rib
[afi
][safi
]) {
13847 json_object_string_add(
13849 "No such neighbor or address family");
13850 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13851 json_object_free(json
);
13852 json_object_free(json_loop
);
13854 vty_out(vty
, "%% No such neighbor or address family\n");
13856 return CMD_WARNING
;
13859 memset(&pcounts
, 0, sizeof(pcounts
));
13860 pcounts
.peer
= peer
;
13861 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13862 pcounts
.safi
= safi
;
13864 /* in-place call via thread subsystem so as to record execution time
13865 * stats for the thread-walk (i.e. ensure this can't be blamed on
13866 * on just vty_read()).
13868 event_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13871 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13872 json_object_string_add(json
, "multiProtocol",
13873 get_afi_safi_str(afi
, safi
, true));
13874 json_object_int_add(json
, "pfxCounter",
13875 peer
->pcount
[afi
][safi
]);
13877 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13878 json_object_int_add(json_loop
, pcount_strs
[i
],
13881 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13883 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13884 json_object_string_add(json
, "pfxctDriftFor",
13886 json_object_string_add(
13887 json
, "recommended",
13888 "Please report this bug, with the above command output");
13890 vty_json(vty
, json
);
13894 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13895 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13896 peer
->hostname
, peer
->host
,
13897 get_afi_safi_str(afi
, safi
, false));
13899 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13900 get_afi_safi_str(afi
, safi
, false));
13903 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13904 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13906 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13907 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13910 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13911 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13913 "Please report this bug, with the above command output\n");
13917 return CMD_SUCCESS
;
13920 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13921 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13922 "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]",
13926 BGP_INSTANCE_HELP_STR
13929 "Detailed information on TCP and BGP neighbor connections\n"
13930 "Neighbor to display information about\n"
13931 "Neighbor to display information about\n"
13932 "Neighbor on BGP configured interface\n"
13933 "Display detailed prefix count information\n"
13936 afi_t afi
= AFI_IP6
;
13937 safi_t safi
= SAFI_UNICAST
;
13940 struct bgp
*bgp
= NULL
;
13941 bool uj
= use_json(argc
, argv
);
13946 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13949 return CMD_WARNING
;
13951 argv_find(argv
, argc
, "neighbors", &idx
);
13952 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13954 return CMD_WARNING
;
13956 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13959 #ifdef KEEP_OLD_VPN_COMMANDS
13960 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13961 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13962 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13967 "Display information about all VPNv4 NLRIs\n"
13968 "Detailed information on TCP and BGP neighbor connections\n"
13969 "Neighbor to display information about\n"
13970 "Neighbor to display information about\n"
13971 "Neighbor on BGP configured interface\n"
13972 "Display detailed prefix count information\n"
13977 bool uj
= use_json(argc
, argv
);
13979 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13981 return CMD_WARNING
;
13983 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13986 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13987 show_ip_bgp_vpn_all_route_prefix_cmd
,
13988 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13993 "Display information about all VPNv4 NLRIs\n"
13994 "Network in the BGP routing table to display\n"
13995 "Network in the BGP routing table to display\n"
13999 char *network
= NULL
;
14000 struct bgp
*bgp
= bgp_get_default();
14002 vty_out(vty
, "Can't find default instance\n");
14003 return CMD_WARNING
;
14006 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
14007 network
= argv
[idx
]->arg
;
14008 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
14009 network
= argv
[idx
]->arg
;
14011 vty_out(vty
, "Unable to figure out Network\n");
14012 return CMD_WARNING
;
14015 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
14016 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14017 use_json(argc
, argv
));
14019 #endif /* KEEP_OLD_VPN_COMMANDS */
14021 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
14022 show_bgp_l2vpn_evpn_route_prefix_cmd
,
14023 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
14028 "Network in the BGP routing table to display\n"
14029 "Network in the BGP routing table to display\n"
14030 "Network in the BGP routing table to display\n"
14031 "Network in the BGP routing table to display\n"
14035 char *network
= NULL
;
14036 int prefix_check
= 0;
14038 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
14039 argv_find(argv
, argc
, "X:X::X:X", &idx
))
14040 network
= argv
[idx
]->arg
;
14041 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
14042 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
14043 network
= argv
[idx
]->arg
;
14046 vty_out(vty
, "Unable to figure out Network\n");
14047 return CMD_WARNING
;
14049 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
14050 prefix_check
, BGP_PATH_SHOW_ALL
,
14051 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
14054 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
14055 struct bgp_table
*table
, int *header1
,
14056 int *header2
, json_object
*json
,
14057 json_object
*json_scode
,
14058 json_object
*json_ocode
, bool wide
,
14061 uint64_t version
= table
? table
->version
: 0;
14065 json_object_int_add(json
, "bgpTableVersion", version
);
14066 json_object_string_addf(json
, "bgpLocalRouterId",
14067 "%pI4", &peer
->bgp
->router_id
);
14068 json_object_int_add(json
, "defaultLocPrf",
14069 peer
->bgp
->default_local_pref
);
14070 json_object_int_add(json
, "localAS",
14071 peer
->change_local_as
14072 ? peer
->change_local_as
14074 json_object_object_add(json
, "bgpStatusCodes",
14076 json_object_object_add(json
, "bgpOriginCodes",
14080 "BGP table version is %" PRIu64
14081 ", local router ID is %pI4, vrf id ",
14082 version
, &peer
->bgp
->router_id
);
14083 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
14084 vty_out(vty
, "%s", VRFID_NONE_STR
);
14086 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
14087 vty_out(vty
, "\n");
14088 vty_out(vty
, "Default local pref %u, ",
14089 peer
->bgp
->default_local_pref
);
14090 vty_out(vty
, "local AS %u\n",
14091 peer
->change_local_as
? peer
->change_local_as
14094 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14095 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14096 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14097 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14103 if (!json
&& !detail
)
14104 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14105 : BGP_SHOW_HEADER
));
14111 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14112 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14113 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14114 json_object
*json_scode
, json_object
*json_ocode
,
14115 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14116 const struct prefix
*match
, unsigned long *output_count
,
14117 unsigned long *filtered_count
)
14119 struct bgp_adj_in
*ain
= NULL
;
14120 struct bgp_adj_out
*adj
= NULL
;
14121 struct bgp_dest
*dest
;
14125 struct update_subgroup
*subgrp
;
14126 struct peer_af
*paf
= NULL
;
14127 bool route_filtered
;
14128 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14129 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14130 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14131 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14132 || (safi
== SAFI_EVPN
))
14136 json_object
*json_net
= NULL
;
14140 /* If the user supplied a prefix, look for a matching route instead
14141 * of walking the whole table.
14144 dest
= bgp_node_match(table
, match
);
14147 vty_out(vty
, "Network not in table\n");
14151 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14153 if (rn_p
->prefixlen
!= match
->prefixlen
) {
14155 vty_out(vty
, "Network not in table\n");
14156 bgp_dest_unlock_node(dest
);
14160 if (type
== bgp_show_adj_route_received
||
14161 type
== bgp_show_adj_route_filtered
) {
14162 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14163 if (ain
->peer
== peer
) {
14168 /* bail out if if adj_out is empty, or
14169 * if the prefix isn't in this peer's
14172 if (!ain
|| ain
->peer
!= peer
) {
14174 vty_out(vty
, "Network not in table\n");
14175 bgp_dest_unlock_node(dest
);
14178 } else if (type
== bgp_show_adj_route_advertised
) {
14179 bool peer_found
= false;
14181 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
) {
14182 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14183 if (paf
->peer
== peer
&& adj
->attr
) {
14192 /* bail out if if adj_out is empty, or
14193 * if the prefix isn't in this peer's
14196 if (!paf
|| !peer_found
) {
14198 vty_out(vty
, "Network not in table\n");
14199 bgp_dest_unlock_node(dest
);
14204 ret
= bgp_output_modifier(peer
, rn_p
, &attr
, afi
, safi
,
14207 if (ret
!= RMAP_DENY
) {
14208 show_adj_route_header(vty
, peer
, table
, header1
,
14209 header2
, json
, json_scode
,
14210 json_ocode
, wide
, detail
);
14213 json_net
= json_object_new_object();
14215 bgp_show_path_info(NULL
/* prefix_rd */, dest
, vty
, bgp
,
14216 afi
, safi
, json_net
,
14217 BGP_PATH_SHOW_ALL
, &display
,
14218 RPKI_NOT_BEING_USED
);
14220 json_object_object_addf(json_ar
, json_net
,
14224 (*filtered_count
)++;
14226 bgp_attr_flush(&attr
);
14227 bgp_dest_unlock_node(dest
);
14232 subgrp
= peer_subgroup(peer
, afi
, safi
);
14234 if (type
== bgp_show_adj_route_advertised
&& subgrp
14235 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14237 json_object_int_add(json
, "bgpTableVersion",
14239 json_object_string_addf(json
, "bgpLocalRouterId",
14240 "%pI4", &bgp
->router_id
);
14241 json_object_int_add(json
, "defaultLocPrf",
14242 bgp
->default_local_pref
);
14243 json_object_int_add(json
, "localAS",
14244 peer
->change_local_as
14245 ? peer
->change_local_as
14247 json_object_object_add(json
, "bgpStatusCodes",
14249 json_object_object_add(json
, "bgpOriginCodes",
14251 json_object_string_add(
14252 json
, "bgpOriginatingDefaultNetwork",
14253 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14256 "BGP table version is %" PRIu64
14257 ", local router ID is %pI4, vrf id ",
14258 table
->version
, &bgp
->router_id
);
14259 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14260 vty_out(vty
, "%s", VRFID_NONE_STR
);
14262 vty_out(vty
, "%u", bgp
->vrf_id
);
14263 vty_out(vty
, "\n");
14264 vty_out(vty
, "Default local pref %u, ",
14265 bgp
->default_local_pref
);
14266 vty_out(vty
, "local AS %u\n",
14267 peer
->change_local_as
? peer
->change_local_as
14270 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14271 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14272 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14273 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14276 vty_out(vty
, "Originating default network %s\n\n",
14277 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14283 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14284 if (type
== bgp_show_adj_route_received
14285 || type
== bgp_show_adj_route_filtered
) {
14286 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14287 if (ain
->peer
!= peer
)
14289 show_adj_route_header(vty
, peer
, table
, header1
,
14290 header2
, json
, json_scode
,
14291 json_ocode
, wide
, detail
);
14293 if ((safi
== SAFI_MPLS_VPN
)
14294 || (safi
== SAFI_ENCAP
)
14295 || (safi
== SAFI_EVPN
)) {
14297 json_object_string_add(
14298 json_ar
, "rd", rd_str
);
14299 else if (show_rd
&& rd_str
) {
14301 "Route Distinguisher: %s\n",
14308 route_filtered
= false;
14310 /* Filter prefix using distribute list,
14311 * filter list or prefix list
14313 const struct prefix
*rn_p
=
14314 bgp_dest_get_prefix(dest
);
14315 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14318 route_filtered
= true;
14320 /* Filter prefix using route-map */
14321 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14322 safi
, rmap_name
, NULL
,
14325 if (type
== bgp_show_adj_route_filtered
&&
14326 !route_filtered
&& ret
!= RMAP_DENY
) {
14327 bgp_attr_flush(&attr
);
14331 if (type
== bgp_show_adj_route_received
14332 && (route_filtered
|| ret
== RMAP_DENY
))
14333 (*filtered_count
)++;
14338 json_object_new_object();
14340 struct bgp_path_info bpi
;
14341 struct bgp_dest buildit
= *dest
;
14342 struct bgp_dest
*pass_in
;
14344 if (route_filtered
||
14345 ret
== RMAP_DENY
) {
14348 buildit
.info
= &bpi
;
14350 pass_in
= &buildit
;
14353 bgp_show_path_info(
14354 NULL
, pass_in
, vty
, bgp
, afi
,
14356 BGP_PATH_SHOW_ALL
, &display
,
14357 RPKI_NOT_BEING_USED
);
14359 json_object_object_addf(
14363 route_vty_out_tmp(vty
, dest
, rn_p
,
14364 &attr
, safi
, use_json
,
14366 bgp_attr_flush(&attr
);
14369 } else if (type
== bgp_show_adj_route_advertised
) {
14370 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14371 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14372 if (paf
->peer
!= peer
|| !adj
->attr
)
14375 show_adj_route_header(
14376 vty
, peer
, table
, header1
,
14377 header2
, json
, json_scode
,
14378 json_ocode
, wide
, detail
);
14380 const struct prefix
*rn_p
=
14381 bgp_dest_get_prefix(dest
);
14384 ret
= bgp_output_modifier(
14385 peer
, rn_p
, &attr
, afi
, safi
,
14388 if (ret
!= RMAP_DENY
) {
14389 if ((safi
== SAFI_MPLS_VPN
)
14390 || (safi
== SAFI_ENCAP
)
14391 || (safi
== SAFI_EVPN
)) {
14393 json_object_string_add(
14400 "Route Distinguisher: %s\n",
14408 json_object_new_object();
14409 bgp_show_path_info(
14418 RPKI_NOT_BEING_USED
);
14420 json_object_object_addf(
14433 (*filtered_count
)++;
14436 bgp_attr_flush(&attr
);
14438 } else if (type
== bgp_show_adj_route_bestpath
) {
14439 struct bgp_path_info
*pi
;
14441 show_adj_route_header(vty
, peer
, table
, header1
,
14442 header2
, json
, json_scode
,
14443 json_ocode
, wide
, detail
);
14445 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14447 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14449 if (pi
->peer
!= peer
)
14452 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14458 json_object_new_object();
14459 bgp_show_path_info(
14460 NULL
/* prefix_rd */, dest
, vty
,
14461 bgp
, afi
, safi
, json_net
,
14462 BGP_PATH_SHOW_BESTPATH
,
14463 &display
, RPKI_NOT_BEING_USED
);
14465 json_object_object_addf(
14470 vty
, dest
, rn_p
, pi
->attr
, safi
,
14471 use_json
, json_ar
, wide
);
14478 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14479 safi_t safi
, enum bgp_show_adj_route_type type
,
14480 const char *rmap_name
, const struct prefix
*match
,
14481 uint16_t show_flags
)
14484 struct bgp_table
*table
;
14485 json_object
*json
= NULL
;
14486 json_object
*json_scode
= NULL
;
14487 json_object
*json_ocode
= NULL
;
14488 json_object
*json_ar
= NULL
;
14489 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14491 /* Init BGP headers here so they're only displayed once
14492 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14498 * Initialize variables for each RD
14499 * All prefixes under an RD is aggregated within "json_routes"
14501 char rd_str
[BUFSIZ
] = {0};
14502 json_object
*json_routes
= NULL
;
14505 /* For 2-tier tables, prefix counts need to be
14506 * maintained across multiple runs of show_adj_route()
14508 unsigned long output_count_per_rd
;
14509 unsigned long filtered_count_per_rd
;
14510 unsigned long output_count
= 0;
14511 unsigned long filtered_count
= 0;
14514 json
= json_object_new_object();
14515 json_ar
= json_object_new_object();
14516 json_scode
= json_object_new_object();
14517 json_ocode
= json_object_new_object();
14518 #if CONFDATE > 20231208
14519 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14521 json_object_string_add(json_scode
, "suppressed", "s");
14522 json_object_string_add(json_scode
, "damped", "d");
14523 json_object_string_add(json_scode
, "history", "h");
14524 json_object_string_add(json_scode
, "valid", "*");
14525 json_object_string_add(json_scode
, "best", ">");
14526 json_object_string_add(json_scode
, "multipath", "=");
14527 json_object_string_add(json_scode
, "internal", "i");
14528 json_object_string_add(json_scode
, "ribFailure", "r");
14529 json_object_string_add(json_scode
, "stale", "S");
14530 json_object_string_add(json_scode
, "removed", "R");
14532 #if CONFDATE > 20231208
14533 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14535 json_object_string_add(json_ocode
, "igp", "i");
14536 json_object_string_add(json_ocode
, "egp", "e");
14537 json_object_string_add(json_ocode
, "incomplete", "?");
14540 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14542 json_object_string_add(
14544 "No such neighbor or address family");
14545 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14546 json_object_free(json
);
14547 json_object_free(json_ar
);
14548 json_object_free(json_scode
);
14549 json_object_free(json_ocode
);
14551 vty_out(vty
, "%% No such neighbor or address family\n");
14553 return CMD_WARNING
;
14556 if ((type
== bgp_show_adj_route_received
14557 || type
== bgp_show_adj_route_filtered
)
14558 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14559 PEER_FLAG_SOFT_RECONFIG
)) {
14561 json_object_string_add(
14563 "Inbound soft reconfiguration not enabled");
14564 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14565 json_object_free(json
);
14566 json_object_free(json_ar
);
14567 json_object_free(json_scode
);
14568 json_object_free(json_ocode
);
14571 "%% Inbound soft reconfiguration not enabled\n");
14573 return CMD_WARNING
;
14578 /* labeled-unicast routes live in the unicast table */
14579 if (safi
== SAFI_LABELED_UNICAST
)
14580 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14582 table
= bgp
->rib
[afi
][safi
];
14584 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14585 || (safi
== SAFI_EVPN
)) {
14587 struct bgp_dest
*dest
;
14589 for (dest
= bgp_table_top(table
); dest
;
14590 dest
= bgp_route_next(dest
)) {
14591 table
= bgp_dest_get_bgp_table_info(dest
);
14595 output_count_per_rd
= 0;
14596 filtered_count_per_rd
= 0;
14599 json_routes
= json_object_new_object();
14601 const struct prefix_rd
*prd
;
14602 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14605 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
),
14609 vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14610 json
, json_routes
, json_scode
, json_ocode
,
14611 show_flags
, &header1
, &header2
, rd_str
, match
,
14612 &output_count_per_rd
, &filtered_count_per_rd
);
14614 /* Don't include an empty RD in the output! */
14615 if (json_routes
&& (output_count_per_rd
> 0))
14616 json_object_object_add(json_ar
, rd_str
,
14619 output_count
+= output_count_per_rd
;
14620 filtered_count
+= filtered_count_per_rd
;
14623 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14624 json
, json_ar
, json_scode
, json_ocode
,
14625 show_flags
, &header1
, &header2
, rd_str
, match
,
14626 &output_count
, &filtered_count
);
14629 if (type
== bgp_show_adj_route_advertised
)
14630 json_object_object_add(json
, "advertisedRoutes",
14633 json_object_object_add(json
, "receivedRoutes", json_ar
);
14634 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14635 json_object_int_add(json
, "filteredPrefixCounter",
14639 * These fields only give up ownership to `json` when `header1`
14640 * is used (set to zero). See code in `show_adj_route` and
14641 * `show_adj_route_header`.
14643 if (header1
== 1) {
14644 json_object_free(json_scode
);
14645 json_object_free(json_ocode
);
14648 vty_json(vty
, json
);
14649 } else if (output_count
> 0) {
14650 if (!match
&& filtered_count
> 0)
14652 "\nTotal number of prefixes %ld (%ld filtered)\n",
14653 output_count
, filtered_count
);
14655 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14659 return CMD_SUCCESS
;
14662 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14663 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14664 "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]",
14668 BGP_INSTANCE_HELP_STR
14670 BGP_SAFI_WITH_LABEL_HELP_STR
14671 "Detailed information on TCP and BGP neighbor connections\n"
14672 "Neighbor to display information about\n"
14673 "Neighbor to display information about\n"
14674 "Neighbor on BGP configured interface\n"
14675 "Display the routes selected by best path\n"
14676 "Display detailed version of routes\n"
14678 "Increase table width for longer prefixes\n")
14680 afi_t afi
= AFI_IP6
;
14681 safi_t safi
= SAFI_UNICAST
;
14682 char *rmap_name
= NULL
;
14683 char *peerstr
= NULL
;
14684 struct bgp
*bgp
= NULL
;
14686 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14688 uint16_t show_flags
= 0;
14691 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14694 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14697 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14699 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14703 return CMD_WARNING
;
14705 argv_find(argv
, argc
, "neighbors", &idx
);
14706 peerstr
= argv
[++idx
]->arg
;
14708 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14710 return CMD_WARNING
;
14712 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, NULL
,
14716 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14717 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14718 "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]",
14722 BGP_INSTANCE_HELP_STR
14724 BGP_SAFI_WITH_LABEL_HELP_STR
14725 "Display the entries for all address families\n"
14726 "Detailed information on TCP and BGP neighbor connections\n"
14727 "Neighbor to display information about\n"
14728 "Neighbor to display information about\n"
14729 "Neighbor on BGP configured interface\n"
14730 "Display the routes advertised to a BGP neighbor\n"
14731 "Display the received routes from neighbor\n"
14732 "Display the filtered routes received from neighbor\n"
14733 "Route-map to modify the attributes\n"
14734 "Name of the route map\n"
14737 "Display detailed version of routes\n"
14739 "Increase table width for longer prefixes\n")
14741 afi_t afi
= AFI_IP6
;
14742 safi_t safi
= SAFI_UNICAST
;
14743 char *peerstr
= NULL
;
14744 struct bgp
*bgp
= NULL
;
14746 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14749 uint16_t show_flags
= 0;
14750 struct listnode
*node
;
14753 if (detail
|| prefix_str
)
14754 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14758 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14762 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14763 if (argv_find(argv
, argc
, "ipv4", &idx
))
14764 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14766 if (argv_find(argv
, argc
, "ipv6", &idx
))
14767 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14771 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14773 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14776 return CMD_WARNING
;
14778 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14779 argv_find(argv
, argc
, "neighbors", &idx
);
14780 peerstr
= argv
[++idx
]->arg
;
14782 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14784 return CMD_WARNING
;
14786 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14787 type
= bgp_show_adj_route_advertised
;
14788 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14789 type
= bgp_show_adj_route_received
;
14790 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14791 type
= bgp_show_adj_route_filtered
;
14794 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14795 prefix_str
? prefix
: NULL
, show_flags
);
14797 vty_out(vty
, "{\n");
14799 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14800 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14801 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14803 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14804 FOREACH_SAFI (safi
) {
14805 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14812 vty_out(vty
, ",\n");
14813 vty_out(vty
, "\"%s\":",
14814 get_afi_safi_str(afi
, safi
,
14818 "\nFor address family: %s\n",
14819 get_afi_safi_str(afi
, safi
,
14822 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14823 route_map
, prefix
, show_flags
);
14827 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14828 FOREACH_AFI_SAFI (afi
, safi
) {
14829 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14836 vty_out(vty
, ",\n");
14837 vty_out(vty
, "\"%s\":",
14838 get_afi_safi_str(afi
, safi
,
14842 "\nFor address family: %s\n",
14843 get_afi_safi_str(afi
, safi
,
14846 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14847 route_map
, prefix
, show_flags
);
14852 vty_out(vty
, "}\n");
14854 return CMD_SUCCESS
;
14857 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14858 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14859 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14863 BGP_INSTANCE_HELP_STR
14866 BGP_AF_MODIFIER_STR
14867 "Detailed information on TCP and BGP neighbor connections\n"
14868 "Neighbor to display information about\n"
14869 "Neighbor to display information about\n"
14870 "Neighbor on BGP configured interface\n"
14871 "Display information received from a BGP neighbor\n"
14872 "Display the prefixlist filter\n"
14875 afi_t afi
= AFI_IP6
;
14876 safi_t safi
= SAFI_UNICAST
;
14877 char *peerstr
= NULL
;
14882 struct bgp
*bgp
= NULL
;
14883 bool uj
= use_json(argc
, argv
);
14888 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14891 return CMD_WARNING
;
14893 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14894 argv_find(argv
, argc
, "neighbors", &idx
);
14895 peerstr
= argv
[++idx
]->arg
;
14897 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14899 return CMD_WARNING
;
14901 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14902 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14905 vty_out(vty
, "Address Family: %s\n",
14906 get_afi_safi_str(afi
, safi
, false));
14907 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14910 vty_out(vty
, "{}\n");
14912 vty_out(vty
, "No functional output\n");
14915 return CMD_SUCCESS
;
14918 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14919 afi_t afi
, safi_t safi
,
14920 enum bgp_show_type type
, bool use_json
)
14922 uint16_t show_flags
= 0;
14925 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14927 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14929 json_object
*json_no
= NULL
;
14930 json_no
= json_object_new_object();
14931 json_object_string_add(
14932 json_no
, "warning",
14933 "No such neighbor or address family");
14934 vty_out(vty
, "%s\n",
14935 json_object_to_json_string(json_no
));
14936 json_object_free(json_no
);
14938 vty_out(vty
, "%% No such neighbor or address family\n");
14939 return CMD_WARNING
;
14942 /* labeled-unicast routes live in the unicast table */
14943 if (safi
== SAFI_LABELED_UNICAST
)
14944 safi
= SAFI_UNICAST
;
14946 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14947 RPKI_NOT_BEING_USED
);
14951 * Used for "detailed" output for cmds like show bgp <afi> <safi> (or)
14952 * show bgp <vrf> (or) show bgp <vrf> <afi> <safi>
14954 DEFPY(show_ip_bgp_vrf_afi_safi_routes_detailed
,
14955 show_ip_bgp_vrf_afi_safi_routes_detailed_cmd
,
14956 "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf_name] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] detail [json$uj]",
14960 BGP_INSTANCE_HELP_STR
14962 BGP_SAFI_WITH_LABEL_HELP_STR
14963 "Detailed information\n"
14966 afi_t afi
= AFI_IP6
;
14967 safi_t safi
= SAFI_UNICAST
;
14968 struct bgp
*bgp
= NULL
;
14970 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14973 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14975 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14978 return CMD_WARNING
;
14979 /* 'vrf all' case to iterate all vrfs & show output per vrf instance */
14980 if (vrf_name
&& strmatch(vrf_name
, "all")) {
14981 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
14982 return CMD_SUCCESS
;
14985 /* All other cases except vrf all */
14986 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14987 show_flags
, RPKI_NOT_BEING_USED
);
14990 DEFUN (show_ip_bgp_neighbor_routes
,
14991 show_ip_bgp_neighbor_routes_cmd
,
14992 "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]",
14996 BGP_INSTANCE_HELP_STR
14998 BGP_SAFI_WITH_LABEL_HELP_STR
14999 "Detailed information on TCP and BGP neighbor connections\n"
15000 "Neighbor to display information about\n"
15001 "Neighbor to display information about\n"
15002 "Neighbor on BGP configured interface\n"
15003 "Display flap statistics of the routes learned from neighbor\n"
15004 "Display the dampened routes received from neighbor\n"
15005 "Display routes learned from neighbor\n"
15008 char *peerstr
= NULL
;
15009 struct bgp
*bgp
= NULL
;
15010 afi_t afi
= AFI_IP6
;
15011 safi_t safi
= SAFI_UNICAST
;
15013 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
15015 bool uj
= use_json(argc
, argv
);
15020 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
15023 return CMD_WARNING
;
15025 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
15026 argv_find(argv
, argc
, "neighbors", &idx
);
15027 peerstr
= argv
[++idx
]->arg
;
15029 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
15031 return CMD_WARNING
;
15033 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
15034 sh_type
= bgp_show_type_flap_neighbor
;
15035 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
15036 sh_type
= bgp_show_type_damp_neighbor
;
15037 else if (argv_find(argv
, argc
, "routes", &idx
))
15038 sh_type
= bgp_show_type_neighbor
;
15040 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
15043 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
15045 struct bgp_distance
{
15046 /* Distance value for the IP source prefix. */
15049 /* Name of the access-list to be matched. */
15053 DEFUN (show_bgp_afi_vpn_rd_route
,
15054 show_bgp_afi_vpn_rd_route_cmd
,
15055 "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]",
15059 BGP_AF_MODIFIER_STR
15060 "Display information for a route distinguisher\n"
15061 "Route Distinguisher\n"
15062 "All Route Distinguishers\n"
15063 "Network in the BGP routing table to display\n"
15064 "Network in the BGP routing table to display\n"
15068 struct prefix_rd prd
;
15069 afi_t afi
= AFI_MAX
;
15072 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
15073 vty_out(vty
, "%% Malformed Address Family\n");
15074 return CMD_WARNING
;
15077 if (!strcmp(argv
[5]->arg
, "all"))
15078 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
15079 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
15080 RPKI_NOT_BEING_USED
,
15081 use_json(argc
, argv
));
15083 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
15085 vty_out(vty
, "%% Malformed Route Distinguisher\n");
15086 return CMD_WARNING
;
15089 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
15090 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
15091 use_json(argc
, argv
));
15094 static struct bgp_distance
*bgp_distance_new(void)
15096 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
15099 static void bgp_distance_free(struct bgp_distance
*bdistance
)
15101 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
15104 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
15105 const char *ip_str
, const char *access_list_str
)
15112 struct bgp_dest
*dest
;
15113 struct bgp_distance
*bdistance
;
15115 afi
= bgp_node_afi(vty
);
15116 safi
= bgp_node_safi(vty
);
15118 ret
= str2prefix(ip_str
, &p
);
15120 vty_out(vty
, "Malformed prefix\n");
15121 return CMD_WARNING_CONFIG_FAILED
;
15124 distance
= atoi(distance_str
);
15126 /* Get BGP distance node. */
15127 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
15128 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15130 bgp_dest_unlock_node(dest
);
15132 bdistance
= bgp_distance_new();
15133 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
15136 /* Set distance value. */
15137 bdistance
->distance
= distance
;
15139 /* Reset access-list configuration. */
15140 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15141 if (access_list_str
)
15142 bdistance
->access_list
=
15143 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
15145 return CMD_SUCCESS
;
15148 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
15149 const char *ip_str
, const char *access_list_str
)
15156 struct bgp_dest
*dest
;
15157 struct bgp_distance
*bdistance
;
15159 afi
= bgp_node_afi(vty
);
15160 safi
= bgp_node_safi(vty
);
15162 ret
= str2prefix(ip_str
, &p
);
15164 vty_out(vty
, "Malformed prefix\n");
15165 return CMD_WARNING_CONFIG_FAILED
;
15168 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
15170 vty_out(vty
, "Can't find specified prefix\n");
15171 return CMD_WARNING_CONFIG_FAILED
;
15174 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15175 distance
= atoi(distance_str
);
15177 if (bdistance
->distance
!= distance
) {
15178 vty_out(vty
, "Distance does not match configured\n");
15179 bgp_dest_unlock_node(dest
);
15180 return CMD_WARNING_CONFIG_FAILED
;
15183 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15184 bgp_distance_free(bdistance
);
15186 bgp_dest_set_bgp_path_info(dest
, NULL
);
15187 bgp_dest_unlock_node(dest
);
15188 bgp_dest_unlock_node(dest
);
15190 return CMD_SUCCESS
;
15193 /* Apply BGP information to distance method. */
15194 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
15195 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
15197 struct bgp_dest
*dest
;
15198 struct prefix q
= {0};
15200 struct bgp_distance
*bdistance
;
15201 struct access_list
*alist
;
15202 struct bgp_static
*bgp_static
;
15203 struct bgp_path_info
*bpi_ultimate
;
15208 peer
= pinfo
->peer
;
15210 if (pinfo
->attr
->distance
)
15211 return pinfo
->attr
->distance
;
15213 /* get peer origin to calculate appropriate distance */
15214 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
15215 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
15216 peer
= bpi_ultimate
->peer
;
15219 /* Check source address.
15220 * Note: for aggregate route, peer can have unspec af type.
15222 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
15223 && !sockunion2hostprefix(&peer
->su
, &q
))
15226 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
15228 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15229 bgp_dest_unlock_node(dest
);
15231 if (bdistance
->access_list
) {
15232 alist
= access_list_lookup(afi
, bdistance
->access_list
);
15234 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
15235 return bdistance
->distance
;
15237 return bdistance
->distance
;
15240 /* Backdoor check. */
15241 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
15243 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15244 bgp_dest_unlock_node(dest
);
15246 if (bgp_static
->backdoor
) {
15247 if (bgp
->distance_local
[afi
][safi
])
15248 return bgp
->distance_local
[afi
][safi
];
15250 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15254 if (peer
->sort
== BGP_PEER_EBGP
) {
15255 if (bgp
->distance_ebgp
[afi
][safi
])
15256 return bgp
->distance_ebgp
[afi
][safi
];
15257 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15258 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15259 if (bgp
->distance_ibgp
[afi
][safi
])
15260 return bgp
->distance_ibgp
[afi
][safi
];
15261 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15263 if (bgp
->distance_local
[afi
][safi
])
15264 return bgp
->distance_local
[afi
][safi
];
15265 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15269 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15270 * we should tell ZEBRA update the routes for a specific
15271 * AFI/SAFI to reflect changes in RIB.
15273 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15275 safi_t update_safi
)
15280 FOREACH_AFI_SAFI (afi
, safi
) {
15281 if (!bgp_fibupd_safi(safi
))
15284 if (afi
!= update_afi
&& safi
!= update_safi
)
15287 if (BGP_DEBUG(zebra
, ZEBRA
))
15289 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15290 __func__
, afi
, safi
);
15291 bgp_zebra_announce_table(bgp
, afi
, safi
);
15295 DEFUN (bgp_distance
,
15297 "distance bgp (1-255) (1-255) (1-255)",
15298 "Define an administrative distance\n"
15300 "Distance for routes external to the AS\n"
15301 "Distance for routes internal to the AS\n"
15302 "Distance for local routes\n")
15304 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15305 int idx_number
= 2;
15306 int idx_number_2
= 3;
15307 int idx_number_3
= 4;
15308 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15309 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15310 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15314 afi
= bgp_node_afi(vty
);
15315 safi
= bgp_node_safi(vty
);
15317 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15318 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15319 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15320 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15321 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15322 bgp
->distance_local
[afi
][safi
] = distance_local
;
15323 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15325 return CMD_SUCCESS
;
15328 DEFUN (no_bgp_distance
,
15329 no_bgp_distance_cmd
,
15330 "no distance bgp [(1-255) (1-255) (1-255)]",
15332 "Define an administrative distance\n"
15334 "Distance for routes external to the AS\n"
15335 "Distance for routes internal to the AS\n"
15336 "Distance for local routes\n")
15338 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15342 afi
= bgp_node_afi(vty
);
15343 safi
= bgp_node_safi(vty
);
15345 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15346 || bgp
->distance_ibgp
[afi
][safi
] != 0
15347 || bgp
->distance_local
[afi
][safi
] != 0) {
15348 bgp
->distance_ebgp
[afi
][safi
] = 0;
15349 bgp
->distance_ibgp
[afi
][safi
] = 0;
15350 bgp
->distance_local
[afi
][safi
] = 0;
15351 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15353 return CMD_SUCCESS
;
15357 DEFUN (bgp_distance_source
,
15358 bgp_distance_source_cmd
,
15359 "distance (1-255) A.B.C.D/M",
15360 "Define an administrative distance\n"
15361 "Administrative distance\n"
15362 "IP source prefix\n")
15364 int idx_number
= 1;
15365 int idx_ipv4_prefixlen
= 2;
15366 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15367 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15368 return CMD_SUCCESS
;
15371 DEFUN (no_bgp_distance_source
,
15372 no_bgp_distance_source_cmd
,
15373 "no distance (1-255) A.B.C.D/M",
15375 "Define an administrative distance\n"
15376 "Administrative distance\n"
15377 "IP source prefix\n")
15379 int idx_number
= 2;
15380 int idx_ipv4_prefixlen
= 3;
15381 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15382 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15383 return CMD_SUCCESS
;
15386 DEFUN (bgp_distance_source_access_list
,
15387 bgp_distance_source_access_list_cmd
,
15388 "distance (1-255) A.B.C.D/M WORD",
15389 "Define an administrative distance\n"
15390 "Administrative distance\n"
15391 "IP source prefix\n"
15392 "Access list name\n")
15394 int idx_number
= 1;
15395 int idx_ipv4_prefixlen
= 2;
15397 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15398 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15399 return CMD_SUCCESS
;
15402 DEFUN (no_bgp_distance_source_access_list
,
15403 no_bgp_distance_source_access_list_cmd
,
15404 "no distance (1-255) A.B.C.D/M WORD",
15406 "Define an administrative distance\n"
15407 "Administrative distance\n"
15408 "IP source prefix\n"
15409 "Access list name\n")
15411 int idx_number
= 2;
15412 int idx_ipv4_prefixlen
= 3;
15414 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15415 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15416 return CMD_SUCCESS
;
15419 DEFUN (ipv6_bgp_distance_source
,
15420 ipv6_bgp_distance_source_cmd
,
15421 "distance (1-255) X:X::X:X/M",
15422 "Define an administrative distance\n"
15423 "Administrative distance\n"
15424 "IP source prefix\n")
15426 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15427 return CMD_SUCCESS
;
15430 DEFUN (no_ipv6_bgp_distance_source
,
15431 no_ipv6_bgp_distance_source_cmd
,
15432 "no distance (1-255) X:X::X:X/M",
15434 "Define an administrative distance\n"
15435 "Administrative distance\n"
15436 "IP source prefix\n")
15438 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15439 return CMD_SUCCESS
;
15442 DEFUN (ipv6_bgp_distance_source_access_list
,
15443 ipv6_bgp_distance_source_access_list_cmd
,
15444 "distance (1-255) X:X::X:X/M WORD",
15445 "Define an administrative distance\n"
15446 "Administrative distance\n"
15447 "IP source prefix\n"
15448 "Access list name\n")
15450 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15451 return CMD_SUCCESS
;
15454 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15455 no_ipv6_bgp_distance_source_access_list_cmd
,
15456 "no distance (1-255) X:X::X:X/M WORD",
15458 "Define an administrative distance\n"
15459 "Administrative distance\n"
15460 "IP source prefix\n"
15461 "Access list name\n")
15463 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15464 return CMD_SUCCESS
;
15467 DEFUN (bgp_damp_set
,
15469 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15470 "BGP Specific commands\n"
15471 "Enable route-flap dampening\n"
15472 "Half-life time for the penalty\n"
15473 "Value to start reusing a route\n"
15474 "Value to start suppressing a route\n"
15475 "Maximum duration to suppress a stable route\n")
15477 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15478 int idx_half_life
= 2;
15480 int idx_suppress
= 4;
15481 int idx_max_suppress
= 5;
15482 int half
= DEFAULT_HALF_LIFE
* 60;
15483 int reuse
= DEFAULT_REUSE
;
15484 int suppress
= DEFAULT_SUPPRESS
;
15485 int max
= 4 * half
;
15488 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15489 reuse
= atoi(argv
[idx_reuse
]->arg
);
15490 suppress
= atoi(argv
[idx_suppress
]->arg
);
15491 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15492 } else if (argc
== 3) {
15493 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15498 * These can't be 0 but our SA doesn't understand the
15499 * way our cli is constructed
15503 if (suppress
< reuse
) {
15505 "Suppress value cannot be less than reuse value \n");
15509 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15510 reuse
, suppress
, max
);
15513 DEFUN (bgp_damp_unset
,
15514 bgp_damp_unset_cmd
,
15515 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15517 "BGP Specific commands\n"
15518 "Enable route-flap dampening\n"
15519 "Half-life time for the penalty\n"
15520 "Value to start reusing a route\n"
15521 "Value to start suppressing a route\n"
15522 "Maximum duration to suppress a stable route\n")
15524 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15525 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15528 /* Display specified route of BGP table. */
15529 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15530 const char *ip_str
, afi_t afi
, safi_t safi
,
15531 struct prefix_rd
*prd
, int prefix_check
)
15534 struct prefix match
;
15535 struct bgp_dest
*dest
;
15536 struct bgp_dest
*rm
;
15537 struct bgp_path_info
*pi
;
15538 struct bgp_path_info
*pi_temp
;
15540 struct bgp_table
*table
;
15542 /* BGP structure lookup. */
15544 bgp
= bgp_lookup_by_name(view_name
);
15546 vty_out(vty
, "%% Can't find BGP instance %s\n",
15548 return CMD_WARNING
;
15551 bgp
= bgp_get_default();
15553 vty_out(vty
, "%% No BGP process is configured\n");
15554 return CMD_WARNING
;
15558 /* Check IP address argument. */
15559 ret
= str2prefix(ip_str
, &match
);
15561 vty_out(vty
, "%% address is malformed\n");
15562 return CMD_WARNING
;
15565 match
.family
= afi2family(afi
);
15567 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15568 || (safi
== SAFI_EVPN
)) {
15569 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15570 dest
= bgp_route_next(dest
)) {
15571 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15573 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15575 table
= bgp_dest_get_bgp_table_info(dest
);
15578 rm
= bgp_node_match(table
, &match
);
15582 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15585 || rm_p
->prefixlen
== match
.prefixlen
) {
15586 pi
= bgp_dest_get_bgp_path_info(rm
);
15588 if (pi
->extra
&& pi
->extra
->damp_info
) {
15589 pi_temp
= pi
->next
;
15590 bgp_damp_info_free(
15591 pi
->extra
->damp_info
,
15599 bgp_dest_unlock_node(rm
);
15602 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15603 if (dest
!= NULL
) {
15604 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15607 || dest_p
->prefixlen
== match
.prefixlen
) {
15608 pi
= bgp_dest_get_bgp_path_info(dest
);
15610 if (pi
->extra
&& pi
->extra
->damp_info
) {
15611 pi_temp
= pi
->next
;
15612 bgp_damp_info_free(
15613 pi
->extra
->damp_info
,
15621 bgp_dest_unlock_node(dest
);
15625 return CMD_SUCCESS
;
15628 DEFUN (clear_ip_bgp_dampening
,
15629 clear_ip_bgp_dampening_cmd
,
15630 "clear ip bgp dampening",
15634 "Clear route flap dampening information\n")
15636 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15637 return CMD_SUCCESS
;
15640 DEFUN (clear_ip_bgp_dampening_prefix
,
15641 clear_ip_bgp_dampening_prefix_cmd
,
15642 "clear ip bgp dampening A.B.C.D/M",
15646 "Clear route flap dampening information\n"
15649 int idx_ipv4_prefixlen
= 4;
15650 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15651 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15654 DEFUN (clear_ip_bgp_dampening_address
,
15655 clear_ip_bgp_dampening_address_cmd
,
15656 "clear ip bgp dampening A.B.C.D",
15660 "Clear route flap dampening information\n"
15661 "Network to clear damping information\n")
15664 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15665 SAFI_UNICAST
, NULL
, 0);
15668 DEFUN (clear_ip_bgp_dampening_address_mask
,
15669 clear_ip_bgp_dampening_address_mask_cmd
,
15670 "clear ip bgp dampening A.B.C.D A.B.C.D",
15674 "Clear route flap dampening information\n"
15675 "Network to clear damping information\n"
15679 int idx_ipv4_2
= 5;
15681 char prefix_str
[BUFSIZ
];
15683 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15684 prefix_str
, sizeof(prefix_str
));
15686 vty_out(vty
, "%% Inconsistent address and mask\n");
15687 return CMD_WARNING
;
15690 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15694 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15696 struct vty
*vty
= arg
;
15697 struct peer
*peer
= bucket
->data
;
15699 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15702 DEFUN (show_bgp_listeners
,
15703 show_bgp_listeners_cmd
,
15704 "show bgp listeners",
15707 "Display Listen Sockets and who created them\n")
15709 bgp_dump_listener_info(vty
);
15711 return CMD_SUCCESS
;
15714 DEFUN (show_bgp_peerhash
,
15715 show_bgp_peerhash_cmd
,
15716 "show bgp peerhash",
15719 "Display information about the BGP peerhash\n")
15721 struct list
*instances
= bm
->bgp
;
15722 struct listnode
*node
;
15725 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15726 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15727 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15731 return CMD_SUCCESS
;
15734 /* also used for encap safi */
15735 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15736 afi_t afi
, safi_t safi
)
15738 struct bgp_dest
*pdest
;
15739 struct bgp_dest
*dest
;
15740 struct bgp_table
*table
;
15741 const struct prefix
*p
;
15742 struct bgp_static
*bgp_static
;
15743 mpls_label_t label
;
15745 /* Network configuration. */
15746 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15747 pdest
= bgp_route_next(pdest
)) {
15748 table
= bgp_dest_get_bgp_table_info(pdest
);
15752 for (dest
= bgp_table_top(table
); dest
;
15753 dest
= bgp_route_next(dest
)) {
15754 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15755 if (bgp_static
== NULL
)
15758 p
= bgp_dest_get_prefix(dest
);
15760 /* "network" configuration display. */
15761 label
= decode_label(&bgp_static
->label
);
15763 vty_out(vty
, " network %pFX rd %s", p
,
15764 bgp_static
->prd_pretty
);
15765 if (safi
== SAFI_MPLS_VPN
)
15766 vty_out(vty
, " label %u", label
);
15768 if (bgp_static
->rmap
.name
)
15769 vty_out(vty
, " route-map %s",
15770 bgp_static
->rmap
.name
);
15772 if (bgp_static
->backdoor
)
15773 vty_out(vty
, " backdoor");
15775 vty_out(vty
, "\n");
15780 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15781 afi_t afi
, safi_t safi
)
15783 struct bgp_dest
*pdest
;
15784 struct bgp_dest
*dest
;
15785 struct bgp_table
*table
;
15786 const struct prefix
*p
;
15787 struct bgp_static
*bgp_static
;
15788 char buf
[PREFIX_STRLEN
* 2];
15789 char buf2
[SU_ADDRSTRLEN
];
15790 char esi_buf
[ESI_STR_LEN
];
15792 /* Network configuration. */
15793 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15794 pdest
= bgp_route_next(pdest
)) {
15795 table
= bgp_dest_get_bgp_table_info(pdest
);
15799 for (dest
= bgp_table_top(table
); dest
;
15800 dest
= bgp_route_next(dest
)) {
15801 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15802 if (bgp_static
== NULL
)
15805 char *macrouter
= NULL
;
15807 if (bgp_static
->router_mac
)
15808 macrouter
= prefix_mac2str(
15809 bgp_static
->router_mac
, NULL
, 0);
15810 if (bgp_static
->eth_s_id
)
15811 esi_to_str(bgp_static
->eth_s_id
,
15812 esi_buf
, sizeof(esi_buf
));
15813 p
= bgp_dest_get_prefix(dest
);
15815 /* "network" configuration display. */
15816 if (p
->u
.prefix_evpn
.route_type
== 5) {
15817 char local_buf
[PREFIX_STRLEN
];
15819 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15820 struct prefix_evpn
*)p
)
15824 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15826 local_buf
, sizeof(local_buf
));
15827 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15828 p
->u
.prefix_evpn
.prefix_addr
15829 .ip_prefix_length
);
15831 prefix2str(p
, buf
, sizeof(buf
));
15834 if (bgp_static
->gatewayIp
.family
== AF_INET
15835 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15836 inet_ntop(bgp_static
->gatewayIp
.family
,
15837 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15840 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15841 buf
, bgp_static
->prd_pretty
,
15842 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15843 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15846 XFREE(MTYPE_TMP
, macrouter
);
15851 /* Configuration of static route announcement and aggregate
15853 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15856 struct bgp_dest
*dest
;
15857 const struct prefix
*p
;
15858 struct bgp_static
*bgp_static
;
15859 struct bgp_aggregate
*bgp_aggregate
;
15861 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15862 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15866 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15867 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15871 /* Network configuration. */
15872 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15873 dest
= bgp_route_next(dest
)) {
15874 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15875 if (bgp_static
== NULL
)
15878 p
= bgp_dest_get_prefix(dest
);
15880 vty_out(vty
, " network %pFX", p
);
15882 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15883 vty_out(vty
, " label-index %u",
15884 bgp_static
->label_index
);
15886 if (bgp_static
->rmap
.name
)
15887 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15889 if (bgp_static
->backdoor
)
15890 vty_out(vty
, " backdoor");
15892 vty_out(vty
, "\n");
15895 /* Aggregate-address configuration. */
15896 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15897 dest
= bgp_route_next(dest
)) {
15898 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15899 if (bgp_aggregate
== NULL
)
15902 p
= bgp_dest_get_prefix(dest
);
15904 vty_out(vty
, " aggregate-address %pFX", p
);
15906 if (bgp_aggregate
->as_set
)
15907 vty_out(vty
, " as-set");
15909 if (bgp_aggregate
->summary_only
)
15910 vty_out(vty
, " summary-only");
15912 if (bgp_aggregate
->rmap
.name
)
15913 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15915 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15916 vty_out(vty
, " origin %s",
15917 bgp_origin2str(bgp_aggregate
->origin
));
15919 if (bgp_aggregate
->match_med
)
15920 vty_out(vty
, " matching-MED-only");
15922 if (bgp_aggregate
->suppress_map_name
)
15923 vty_out(vty
, " suppress-map %s",
15924 bgp_aggregate
->suppress_map_name
);
15926 vty_out(vty
, "\n");
15930 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15933 struct bgp_dest
*dest
;
15934 struct bgp_distance
*bdistance
;
15936 /* Distance configuration. */
15937 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15938 && bgp
->distance_local
[afi
][safi
]
15939 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15940 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15941 || bgp
->distance_local
[afi
][safi
]
15942 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15943 vty_out(vty
, " distance bgp %d %d %d\n",
15944 bgp
->distance_ebgp
[afi
][safi
],
15945 bgp
->distance_ibgp
[afi
][safi
],
15946 bgp
->distance_local
[afi
][safi
]);
15949 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15950 dest
= bgp_route_next(dest
)) {
15951 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15952 if (bdistance
!= NULL
)
15953 vty_out(vty
, " distance %d %pBD %s\n",
15954 bdistance
->distance
, dest
,
15955 bdistance
->access_list
? bdistance
->access_list
15960 /* Allocate routing table structure and install commands. */
15961 void bgp_route_init(void)
15966 /* Init BGP distance table. */
15967 FOREACH_AFI_SAFI (afi
, safi
)
15968 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15970 /* IPv4 BGP commands. */
15971 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15972 install_element(BGP_NODE
, &bgp_network_cmd
);
15973 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15975 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15977 /* IPv4 unicast configuration. */
15978 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15979 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15980 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15982 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15984 /* IPv4 multicast configuration. */
15985 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15986 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15987 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15988 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15990 /* IPv4 labeled-unicast configuration. */
15991 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15992 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15994 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15995 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15996 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15997 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15998 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15999 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
16000 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
16001 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
16003 install_element(VIEW_NODE
,
16004 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
16005 install_element(VIEW_NODE
,
16006 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
16007 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
16008 install_element(VIEW_NODE
,
16009 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
16010 #ifdef KEEP_OLD_VPN_COMMANDS
16011 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
16012 #endif /* KEEP_OLD_VPN_COMMANDS */
16013 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
16014 install_element(VIEW_NODE
,
16015 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
16017 /* BGP dampening clear commands */
16018 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
16019 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
16021 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
16022 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
16025 install_element(ENABLE_NODE
,
16026 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
16027 #ifdef KEEP_OLD_VPN_COMMANDS
16028 install_element(ENABLE_NODE
,
16029 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
16030 #endif /* KEEP_OLD_VPN_COMMANDS */
16032 /* New config IPv6 BGP commands. */
16033 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
16034 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
16035 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
16037 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
16039 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
16041 /* IPv6 labeled unicast address family. */
16042 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
16043 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
16045 install_element(BGP_NODE
, &bgp_distance_cmd
);
16046 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
16047 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
16048 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
16049 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
16050 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
16051 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
16052 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
16053 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
16054 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
16055 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
16056 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
16057 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
16058 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
16059 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
16060 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
16061 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
16062 install_element(BGP_IPV4M_NODE
,
16063 &no_bgp_distance_source_access_list_cmd
);
16064 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
16065 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
16066 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
16067 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
16068 install_element(BGP_IPV6_NODE
,
16069 &ipv6_bgp_distance_source_access_list_cmd
);
16070 install_element(BGP_IPV6_NODE
,
16071 &no_ipv6_bgp_distance_source_access_list_cmd
);
16072 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
16073 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
16074 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
16075 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
16076 install_element(BGP_IPV6M_NODE
,
16077 &ipv6_bgp_distance_source_access_list_cmd
);
16078 install_element(BGP_IPV6M_NODE
,
16079 &no_ipv6_bgp_distance_source_access_list_cmd
);
16081 /* BGP dampening */
16082 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
16083 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
16084 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
16085 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
16086 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
16087 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
16088 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
16089 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
16090 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
16091 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
16092 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
16093 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
16094 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
16095 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
16097 /* Large Communities */
16098 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
16099 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
16101 /* show bgp vrf <afi> <safi> detailed */
16102 install_element(VIEW_NODE
,
16103 &show_ip_bgp_vrf_afi_safi_routes_detailed_cmd
);
16105 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
16106 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
16109 void bgp_route_finish(void)
16114 FOREACH_AFI_SAFI (afi
, safi
) {
16115 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
16116 bgp_distance_table
[afi
][safi
] = NULL
;