1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "sockunion.h"
39 #include "workqueue.h"
44 #include "lib_errors.h"
46 #include "bgpd/bgpd.h"
47 #include "bgpd/bgp_table.h"
48 #include "bgpd/bgp_route.h"
49 #include "bgpd/bgp_attr.h"
50 #include "bgpd/bgp_debug.h"
51 #include "bgpd/bgp_errors.h"
52 #include "bgpd/bgp_aspath.h"
53 #include "bgpd/bgp_regex.h"
54 #include "bgpd/bgp_community.h"
55 #include "bgpd/bgp_community_alias.h"
56 #include "bgpd/bgp_ecommunity.h"
57 #include "bgpd/bgp_lcommunity.h"
58 #include "bgpd/bgp_clist.h"
59 #include "bgpd/bgp_packet.h"
60 #include "bgpd/bgp_filter.h"
61 #include "bgpd/bgp_fsm.h"
62 #include "bgpd/bgp_mplsvpn.h"
63 #include "bgpd/bgp_nexthop.h"
64 #include "bgpd/bgp_damp.h"
65 #include "bgpd/bgp_advertise.h"
66 #include "bgpd/bgp_zebra.h"
67 #include "bgpd/bgp_vty.h"
68 #include "bgpd/bgp_mpath.h"
69 #include "bgpd/bgp_nht.h"
70 #include "bgpd/bgp_updgrp.h"
71 #include "bgpd/bgp_label.h"
72 #include "bgpd/bgp_addpath.h"
73 #include "bgpd/bgp_mac.h"
74 #include "bgpd/bgp_network.h"
75 #include "bgpd/bgp_trace.h"
76 #include "bgpd/bgp_rpki.h"
79 #include "bgpd/rfapi/rfapi_backend.h"
80 #include "bgpd/rfapi/vnc_import_bgp.h"
81 #include "bgpd/rfapi/vnc_export_bgp.h"
83 #include "bgpd/bgp_encap_types.h"
84 #include "bgpd/bgp_encap_tlv.h"
85 #include "bgpd/bgp_evpn.h"
86 #include "bgpd/bgp_evpn_mh.h"
87 #include "bgpd/bgp_evpn_vty.h"
88 #include "bgpd/bgp_flowspec.h"
89 #include "bgpd/bgp_flowspec_util.h"
90 #include "bgpd/bgp_pbr.h"
92 #include "bgpd/bgp_route_clippy.c"
94 DEFINE_HOOK(bgp_snmp_update_stats
,
95 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
98 DEFINE_HOOK(bgp_rpki_prefix_status
,
99 (struct peer
*peer
, struct attr
*attr
,
100 const struct prefix
*prefix
),
101 (peer
, attr
, prefix
));
103 /* Extern from bgp_dump.c */
104 extern const char *bgp_origin_str
[];
105 extern const char *bgp_origin_long_str
[];
108 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
109 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
110 static const struct message bgp_pmsi_tnltype_str
[] = {
111 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
112 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
113 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
114 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
115 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
116 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
117 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
118 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
122 #define VRFID_NONE_STR "-"
123 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
125 DEFINE_HOOK(bgp_process
,
126 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
127 struct peer
*peer
, bool withdraw
),
128 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
130 /** Test if path is suppressed. */
131 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
133 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
136 return listcount(pi
->extra
->aggr_suppressors
) > 0;
139 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
140 safi_t safi
, const struct prefix
*p
,
141 struct prefix_rd
*prd
)
143 struct bgp_dest
*dest
;
144 struct bgp_dest
*pdest
= NULL
;
148 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
149 || (safi
== SAFI_EVPN
)) {
150 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
152 if (!bgp_dest_has_bgp_path_info_data(pdest
))
153 bgp_dest_set_bgp_table_info(
154 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
156 bgp_dest_unlock_node(pdest
);
157 table
= bgp_dest_get_bgp_table_info(pdest
);
160 dest
= bgp_node_get(table
, p
);
162 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
163 || (safi
== SAFI_EVPN
))
169 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
170 safi_t safi
, const struct prefix
*p
,
171 struct prefix_rd
*prd
)
173 struct bgp_dest
*dest
;
174 struct bgp_dest
*pdest
= NULL
;
179 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
180 || (safi
== SAFI_EVPN
)) {
181 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
185 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
186 bgp_dest_unlock_node(pdest
);
190 table
= bgp_dest_get_bgp_table_info(pdest
);
193 dest
= bgp_node_lookup(table
, p
);
198 /* Allocate bgp_path_info_extra */
199 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
201 struct bgp_path_info_extra
*new;
202 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
203 sizeof(struct bgp_path_info_extra
));
204 new->label
[0] = MPLS_INVALID_LABEL
;
206 new->bgp_fs_pbr
= NULL
;
207 new->bgp_fs_iprule
= NULL
;
211 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
213 struct bgp_path_info_extra
*e
;
215 if (!extra
|| !*extra
)
220 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
225 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
228 /* FIXME: since multiple e may have the same e->parent
229 * and e->parent->net is holding a refcount for each
230 * of them, we need to do some fudging here.
232 * WARNING: if bpi->net->lock drops to 0, bpi may be
233 * freed as well (because bpi->net was holding the
234 * last reference to bpi) => write after free!
238 bpi
= bgp_path_info_lock(bpi
);
239 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
240 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
243 bgp_path_info_unlock(bpi
);
245 bgp_path_info_unlock(e
->parent
);
250 bgp_unlock(e
->bgp_orig
);
253 peer_unlock(e
->peer_orig
);
255 if (e
->aggr_suppressors
)
256 list_delete(&e
->aggr_suppressors
);
259 bgp_evpn_path_mh_info_free(e
->mh_info
);
261 if ((*extra
)->bgp_fs_iprule
)
262 list_delete(&((*extra
)->bgp_fs_iprule
));
263 if ((*extra
)->bgp_fs_pbr
)
264 list_delete(&((*extra
)->bgp_fs_pbr
));
265 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
268 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
269 * allocated if required.
271 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
274 pi
->extra
= bgp_path_info_extra_new();
278 /* Free bgp route information. */
279 void bgp_path_info_free_with_caller(const char *name
,
280 struct bgp_path_info
*path
)
282 frrtrace(2, frr_bgp
, bgp_path_info_free
, path
, name
);
283 bgp_attr_unintern(&path
->attr
);
285 bgp_unlink_nexthop(path
);
286 bgp_path_info_extra_free(&path
->extra
);
287 bgp_path_info_mpath_free(&path
->mpath
);
289 bgp_addpath_free_info_data(&path
->tx_addpath
,
290 &path
->net
->tx_addpath
);
292 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
294 XFREE(MTYPE_BGP_ROUTE
, path
);
297 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
303 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
305 assert(path
&& path
->lock
> 0);
308 if (path
->lock
== 0) {
309 bgp_path_info_free(path
);
316 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
317 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
320 struct bgp_path_info
*old_pi
, *nextpi
;
321 bool set_flag
= false;
322 struct bgp
*bgp
= NULL
;
323 struct bgp_table
*table
= NULL
;
327 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
328 * then the route selection is deferred
330 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
333 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
334 if (BGP_DEBUG(update
, UPDATE_OUT
))
336 "Route %pBD is in workqueue and being processed, not deferred.",
342 table
= bgp_dest_table(dest
);
349 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
350 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
351 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
354 /* Route selection is deferred if there is a stale path which
355 * which indicates peer is in restart mode
357 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
358 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
361 /* If the peer is graceful restart capable and peer is
362 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
365 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
366 && BGP_PEER_RESTARTING_MODE(peer
)
368 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
376 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
379 if (set_flag
&& table
) {
380 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
381 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
382 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
383 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
384 if (BGP_DEBUG(update
, UPDATE_OUT
))
385 zlog_debug("DEFER route %pBD, dest %p", dest
,
393 void bgp_path_info_add_with_caller(const char *name
, struct bgp_dest
*dest
,
394 struct bgp_path_info
*pi
)
396 frrtrace(3, frr_bgp
, bgp_path_info_add
, dest
, pi
, name
);
397 struct bgp_path_info
*top
;
399 top
= bgp_dest_get_bgp_path_info(dest
);
405 bgp_dest_set_bgp_path_info(dest
, pi
);
407 bgp_path_info_lock(pi
);
408 bgp_dest_lock_node(dest
);
409 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
410 bgp_dest_set_defer_flag(dest
, false);
411 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
414 /* Do the actual removal of info from RIB, for use by bgp_process
415 completion callback *only* */
416 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
419 pi
->next
->prev
= pi
->prev
;
421 pi
->prev
->next
= pi
->next
;
423 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
425 bgp_path_info_mpath_dequeue(pi
);
426 bgp_path_info_unlock(pi
);
427 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
428 bgp_dest_unlock_node(dest
);
431 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
433 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
434 /* set of previous already took care of pcount */
435 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
438 /* undo the effects of a previous call to bgp_path_info_delete; typically
439 called when a route is deleted and then quickly re-added before the
440 deletion has been processed */
441 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
443 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
444 /* unset of previous already took care of pcount */
445 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
448 /* Adjust pcount as required */
449 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
451 struct bgp_table
*table
;
453 assert(dest
&& bgp_dest_table(dest
));
454 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
456 table
= bgp_dest_table(dest
);
458 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
461 if (!BGP_PATH_COUNTABLE(pi
)
462 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
464 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
466 /* slight hack, but more robust against errors. */
467 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
468 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
470 flog_err(EC_LIB_DEVELOPMENT
,
471 "Asked to decrement 0 prefix count for peer");
472 } else if (BGP_PATH_COUNTABLE(pi
)
473 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
474 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
475 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
479 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
480 struct bgp_path_info
*pi2
)
482 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
485 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
486 * This is here primarily to keep prefix-count in check.
488 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
491 SET_FLAG(pi
->flags
, flag
);
493 /* early bath if we know it's not a flag that changes countability state
495 if (!CHECK_FLAG(flag
,
496 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
499 bgp_pcount_adjust(dest
, pi
);
502 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
505 UNSET_FLAG(pi
->flags
, flag
);
507 /* early bath if we know it's not a flag that changes countability state
509 if (!CHECK_FLAG(flag
,
510 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
513 bgp_pcount_adjust(dest
, pi
);
516 /* Get MED value. If MED value is missing and "bgp bestpath
517 missing-as-worst" is specified, treat it as the worst value. */
518 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
520 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
523 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
530 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
533 if (pi
->addpath_rx_id
)
534 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
535 pi
->peer
->host
, pi
->addpath_rx_id
);
537 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
542 * Get the ultimate path info.
544 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
546 struct bgp_path_info
*bpi_ultimate
;
548 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
551 for (bpi_ultimate
= info
;
552 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
553 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
559 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
561 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
562 struct bgp_path_info
*exist
, int *paths_eq
,
563 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
564 char *pfx_buf
, afi_t afi
, safi_t safi
,
565 enum bgp_path_selection_reason
*reason
)
567 const struct prefix
*new_p
;
568 struct attr
*newattr
, *existattr
;
569 enum bgp_peer_sort new_sort
;
570 enum bgp_peer_sort exist_sort
;
576 uint32_t exist_weight
;
577 uint32_t newm
, existm
;
578 struct in_addr new_id
;
579 struct in_addr exist_id
;
582 int internal_as_route
;
585 int igp_metric_ret
= 0;
586 int peer_sort_ret
= -1;
587 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
588 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
590 uint32_t exist_mm_seq
;
597 bool new_origin
, exist_origin
;
598 struct bgp_path_info
*bpi_ultimate
;
604 *reason
= bgp_path_selection_none
;
606 zlog_debug("%s: new is NULL", pfx_buf
);
611 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
612 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
617 *reason
= bgp_path_selection_first
;
619 zlog_debug("%s(%s): %s is the initial bestpath",
620 pfx_buf
, bgp
->name_pretty
, new_buf
);
625 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
626 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
628 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
629 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
630 exist_buf
, exist
->flags
);
634 existattr
= exist
->attr
;
636 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
637 * Capability" to a neighbor MUST perform the following upon receiving
638 * a route from that neighbor with the "LLGR_STALE" community, or upon
639 * attaching the "LLGR_STALE" community itself per Section 4.2:
641 * Treat the route as the least-preferred in route selection (see
642 * below). See the Risks of Depreferencing Routes section (Section 5.2)
643 * for a discussion of potential risks inherent in doing this.
645 if (bgp_attr_get_community(newattr
) &&
646 community_include(bgp_attr_get_community(newattr
),
647 COMMUNITY_LLGR_STALE
)) {
650 "%s: %s wins over %s due to LLGR_STALE community",
651 pfx_buf
, new_buf
, exist_buf
);
655 if (bgp_attr_get_community(existattr
) &&
656 community_include(bgp_attr_get_community(existattr
),
657 COMMUNITY_LLGR_STALE
)) {
660 "%s: %s loses to %s due to LLGR_STALE community",
661 pfx_buf
, new_buf
, exist_buf
);
665 new_p
= bgp_dest_get_prefix(new->net
);
667 /* For EVPN routes, we cannot just go by local vs remote, we have to
668 * look at the MAC mobility sequence number, if present.
670 if ((safi
== SAFI_EVPN
)
671 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
672 /* This is an error condition described in RFC 7432 Section
674 * states that in this scenario "the PE MUST alert the operator"
676 * does not state what other action to take. In order to provide
678 * consistency in this scenario we are going to prefer the path
682 if (newattr
->sticky
!= existattr
->sticky
) {
684 prefix2str(new_p
, pfx_buf
,
686 * PREFIX2STR_BUFFER
);
687 bgp_path_info_path_with_addpath_rx_str(
688 new, new_buf
, sizeof(new_buf
));
689 bgp_path_info_path_with_addpath_rx_str(
690 exist
, exist_buf
, sizeof(exist_buf
));
693 if (newattr
->sticky
&& !existattr
->sticky
) {
694 *reason
= bgp_path_selection_evpn_sticky_mac
;
697 "%s: %s wins over %s due to sticky MAC flag",
698 pfx_buf
, new_buf
, exist_buf
);
702 if (!newattr
->sticky
&& existattr
->sticky
) {
703 *reason
= bgp_path_selection_evpn_sticky_mac
;
706 "%s: %s loses to %s due to sticky MAC flag",
707 pfx_buf
, new_buf
, exist_buf
);
712 new_esi
= bgp_evpn_attr_get_esi(newattr
);
713 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
714 if (bgp_evpn_is_esi_valid(new_esi
) &&
715 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
721 /* If both paths have the same non-zero ES and
722 * one path is local it wins.
723 * PS: Note the local path wins even if the remote
724 * has the higher MM seq. The local path's
725 * MM seq will be fixed up to match the highest
726 * rem seq, subsequently.
729 char esi_buf
[ESI_STR_LEN
];
731 if (bgp_evpn_is_path_local(bgp
, new)) {
732 *reason
= bgp_path_selection_evpn_local_path
;
735 "%s: %s wins over %s as ES %s is same and local",
736 pfx_buf
, new_buf
, exist_buf
,
737 esi_to_str(new_esi
, esi_buf
,
741 if (bgp_evpn_is_path_local(bgp
, exist
)) {
742 *reason
= bgp_path_selection_evpn_local_path
;
745 "%s: %s loses to %s as ES %s is same and local",
746 pfx_buf
, new_buf
, exist_buf
,
747 esi_to_str(new_esi
, esi_buf
,
753 new_mm_seq
= mac_mobility_seqnum(newattr
);
754 exist_mm_seq
= mac_mobility_seqnum(existattr
);
756 if (new_mm_seq
> exist_mm_seq
) {
757 *reason
= bgp_path_selection_evpn_seq
;
760 "%s: %s wins over %s due to MM seq %u > %u",
761 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
766 if (new_mm_seq
< exist_mm_seq
) {
767 *reason
= bgp_path_selection_evpn_seq
;
770 "%s: %s loses to %s due to MM seq %u < %u",
771 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
776 /* if the sequence numbers and ESI are the same and one path
777 * is non-proxy it wins (over proxy)
779 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
780 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
781 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
782 old_proxy
!= new_proxy
) {
784 *reason
= bgp_path_selection_evpn_non_proxy
;
787 "%s: %s wins over %s, same seq/es and non-proxy",
788 pfx_buf
, new_buf
, exist_buf
);
792 *reason
= bgp_path_selection_evpn_non_proxy
;
795 "%s: %s loses to %s, same seq/es and non-proxy",
796 pfx_buf
, new_buf
, exist_buf
);
801 * if sequence numbers are the same path with the lowest IP
804 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
806 *reason
= bgp_path_selection_evpn_lower_ip
;
809 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
810 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
811 &new->attr
->nexthop
);
815 *reason
= bgp_path_selection_evpn_lower_ip
;
818 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
819 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
820 &new->attr
->nexthop
);
825 /* 1. Weight check. */
826 new_weight
= newattr
->weight
;
827 exist_weight
= existattr
->weight
;
829 if (new_weight
> exist_weight
) {
830 *reason
= bgp_path_selection_weight
;
832 zlog_debug("%s: %s wins over %s due to weight %d > %d",
833 pfx_buf
, new_buf
, exist_buf
, new_weight
,
838 if (new_weight
< exist_weight
) {
839 *reason
= bgp_path_selection_weight
;
841 zlog_debug("%s: %s loses to %s due to weight %d < %d",
842 pfx_buf
, new_buf
, exist_buf
, new_weight
,
847 /* 2. Local preference check. */
848 new_pref
= exist_pref
= bgp
->default_local_pref
;
850 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
851 new_pref
= newattr
->local_pref
;
852 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
853 exist_pref
= existattr
->local_pref
;
855 if (new_pref
> exist_pref
) {
856 *reason
= bgp_path_selection_local_pref
;
859 "%s: %s wins over %s due to localpref %d > %d",
860 pfx_buf
, new_buf
, exist_buf
, new_pref
,
865 if (new_pref
< exist_pref
) {
866 *reason
= bgp_path_selection_local_pref
;
869 "%s: %s loses to %s due to localpref %d < %d",
870 pfx_buf
, new_buf
, exist_buf
, new_pref
,
875 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
876 * extensions defined in this document, the following step is inserted
877 * after the LOCAL_PREF comparison step in the BGP decision process:
878 * When comparing a pair of routes for a BGP destination, the
879 * route with the ACCEPT_OWN community attached is preferred over
880 * the route that does not have the community.
881 * This extra step MUST only be invoked during the best path selection
882 * process of VPN-IP routes.
884 if (safi
== SAFI_MPLS_VPN
&&
885 (CHECK_FLAG(new->peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
) ||
886 CHECK_FLAG(exist
->peer
->af_flags
[afi
][safi
],
887 PEER_FLAG_ACCEPT_OWN
))) {
888 bool new_accept_own
= false;
889 bool exist_accept_own
= false;
890 uint32_t accept_own
= COMMUNITY_ACCEPT_OWN
;
892 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
893 new_accept_own
= community_include(
894 bgp_attr_get_community(newattr
), accept_own
);
895 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
896 exist_accept_own
= community_include(
897 bgp_attr_get_community(existattr
), accept_own
);
899 if (new_accept_own
&& !exist_accept_own
) {
900 *reason
= bgp_path_selection_accept_own
;
903 "%s: %s wins over %s due to accept-own",
904 pfx_buf
, new_buf
, exist_buf
);
908 if (!new_accept_own
&& exist_accept_own
) {
909 *reason
= bgp_path_selection_accept_own
;
912 "%s: %s loses to %s due to accept-own",
913 pfx_buf
, new_buf
, exist_buf
);
918 /* Tie-breaker - AIGP (Metric TLV) attribute */
919 if (CHECK_FLAG(newattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
920 CHECK_FLAG(existattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
921 CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_AIGP
)) {
922 uint64_t new_aigp
= bgp_attr_get_aigp_metric(newattr
);
923 uint64_t exist_aigp
= bgp_attr_get_aigp_metric(existattr
);
925 if (new_aigp
< exist_aigp
) {
926 *reason
= bgp_path_selection_aigp
;
929 "%s: %s wins over %s due to AIGP %" PRIu64
931 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
936 if (new_aigp
> exist_aigp
) {
937 *reason
= bgp_path_selection_aigp
;
940 "%s: %s loses to %s due to AIGP %" PRIu64
942 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
948 /* 3. Local route check. We prefer:
950 * - BGP_ROUTE_AGGREGATE
951 * - BGP_ROUTE_REDISTRIBUTE
953 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
954 new->sub_type
== BGP_ROUTE_IMPORTED
);
955 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
956 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
958 if (new_origin
&& !exist_origin
) {
959 *reason
= bgp_path_selection_local_route
;
962 "%s: %s wins over %s due to preferred BGP_ROUTE type",
963 pfx_buf
, new_buf
, exist_buf
);
967 if (!new_origin
&& exist_origin
) {
968 *reason
= bgp_path_selection_local_route
;
971 "%s: %s loses to %s due to preferred BGP_ROUTE type",
972 pfx_buf
, new_buf
, exist_buf
);
976 /* Here if these are imported routes then get ultimate pi for
979 new = bgp_get_imported_bpi_ultimate(new);
980 exist
= bgp_get_imported_bpi_ultimate(exist
);
982 existattr
= exist
->attr
;
984 /* 4. AS path length check. */
985 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
986 int exist_hops
= aspath_count_hops(existattr
->aspath
);
987 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
989 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
992 aspath_hops
= aspath_count_hops(newattr
->aspath
);
993 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
995 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
996 *reason
= bgp_path_selection_confed_as_path
;
999 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
1000 pfx_buf
, new_buf
, exist_buf
,
1002 (exist_hops
+ exist_confeds
));
1006 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
1007 *reason
= bgp_path_selection_confed_as_path
;
1010 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1011 pfx_buf
, new_buf
, exist_buf
,
1013 (exist_hops
+ exist_confeds
));
1017 int newhops
= aspath_count_hops(newattr
->aspath
);
1019 if (newhops
< exist_hops
) {
1020 *reason
= bgp_path_selection_as_path
;
1023 "%s: %s wins over %s due to aspath hopcount %d < %d",
1024 pfx_buf
, new_buf
, exist_buf
,
1025 newhops
, exist_hops
);
1029 if (newhops
> exist_hops
) {
1030 *reason
= bgp_path_selection_as_path
;
1033 "%s: %s loses to %s due to aspath hopcount %d > %d",
1034 pfx_buf
, new_buf
, exist_buf
,
1035 newhops
, exist_hops
);
1041 /* 5. Origin check. */
1042 if (newattr
->origin
< existattr
->origin
) {
1043 *reason
= bgp_path_selection_origin
;
1045 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1046 pfx_buf
, new_buf
, exist_buf
,
1047 bgp_origin_long_str
[newattr
->origin
],
1048 bgp_origin_long_str
[existattr
->origin
]);
1052 if (newattr
->origin
> existattr
->origin
) {
1053 *reason
= bgp_path_selection_origin
;
1055 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1056 pfx_buf
, new_buf
, exist_buf
,
1057 bgp_origin_long_str
[newattr
->origin
],
1058 bgp_origin_long_str
[existattr
->origin
]);
1063 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
1064 && aspath_count_hops(existattr
->aspath
) == 0);
1065 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
1066 && aspath_count_confeds(existattr
->aspath
) > 0
1067 && aspath_count_hops(newattr
->aspath
) == 0
1068 && aspath_count_hops(existattr
->aspath
) == 0);
1070 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1071 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1072 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1073 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1074 || internal_as_route
) {
1075 new_med
= bgp_med_value(new->attr
, bgp
);
1076 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1078 if (new_med
< exist_med
) {
1079 *reason
= bgp_path_selection_med
;
1082 "%s: %s wins over %s due to MED %d < %d",
1083 pfx_buf
, new_buf
, exist_buf
, new_med
,
1088 if (new_med
> exist_med
) {
1089 *reason
= bgp_path_selection_med
;
1092 "%s: %s loses to %s due to MED %d > %d",
1093 pfx_buf
, new_buf
, exist_buf
, new_med
,
1099 /* 7. Peer type check. */
1100 new_sort
= new->peer
->sort
;
1101 exist_sort
= exist
->peer
->sort
;
1103 if (new_sort
== BGP_PEER_EBGP
1104 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1105 *reason
= bgp_path_selection_peer
;
1108 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1109 pfx_buf
, new_buf
, exist_buf
);
1110 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1115 if (exist_sort
== BGP_PEER_EBGP
1116 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1117 *reason
= bgp_path_selection_peer
;
1120 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1121 pfx_buf
, new_buf
, exist_buf
);
1122 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1127 /* 8. IGP metric check. */
1131 newm
= new->extra
->igpmetric
;
1133 existm
= exist
->extra
->igpmetric
;
1135 if (newm
< existm
) {
1136 if (debug
&& peer_sort_ret
< 0)
1138 "%s: %s wins over %s due to IGP metric %u < %u",
1139 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1143 if (newm
> existm
) {
1144 if (debug
&& peer_sort_ret
< 0)
1146 "%s: %s loses to %s due to IGP metric %u > %u",
1147 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1151 /* 9. Same IGP metric. Compare the cluster list length as
1152 representative of IGP hops metric. Rewrite the metric value
1153 pair (newm, existm) with the cluster list length. Prefer the
1154 path with smaller cluster list length. */
1155 if (newm
== existm
) {
1156 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
&&
1157 peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
&&
1158 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1159 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1160 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1162 if (newm
< existm
) {
1163 if (debug
&& peer_sort_ret
< 0)
1165 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1166 pfx_buf
, new_buf
, exist_buf
,
1171 if (newm
> existm
) {
1172 if (debug
&& peer_sort_ret
< 0)
1174 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1175 pfx_buf
, new_buf
, exist_buf
,
1182 /* 10. confed-external vs. confed-internal */
1183 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1184 if (new_sort
== BGP_PEER_CONFED
1185 && exist_sort
== BGP_PEER_IBGP
) {
1186 *reason
= bgp_path_selection_confed
;
1189 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1190 pfx_buf
, new_buf
, exist_buf
);
1191 if (!CHECK_FLAG(bgp
->flags
,
1192 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1197 if (exist_sort
== BGP_PEER_CONFED
1198 && new_sort
== BGP_PEER_IBGP
) {
1199 *reason
= bgp_path_selection_confed
;
1202 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1203 pfx_buf
, new_buf
, exist_buf
);
1204 if (!CHECK_FLAG(bgp
->flags
,
1205 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1211 /* 11. Maximum path check. */
1212 if (newm
== existm
) {
1213 /* If one path has a label but the other does not, do not treat
1214 * them as equals for multipath
1216 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1218 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1221 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1222 pfx_buf
, new_buf
, exist_buf
);
1223 } else if (CHECK_FLAG(bgp
->flags
,
1224 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1227 * For the two paths, all comparison steps till IGP
1229 * have succeeded - including AS_PATH hop count. Since
1231 * bestpath as-path multipath-relax' knob is on, we
1233 * an exact match of AS_PATH. Thus, mark the paths are
1235 * That will trigger both these paths to get into the
1243 "%s: %s and %s are equal via multipath-relax",
1244 pfx_buf
, new_buf
, exist_buf
);
1245 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1246 if (aspath_cmp(new->attr
->aspath
,
1247 exist
->attr
->aspath
)) {
1252 "%s: %s and %s are equal via matching aspaths",
1253 pfx_buf
, new_buf
, exist_buf
);
1255 } else if (new->peer
->as
== exist
->peer
->as
) {
1260 "%s: %s and %s are equal via same remote-as",
1261 pfx_buf
, new_buf
, exist_buf
);
1265 * TODO: If unequal cost ibgp multipath is enabled we can
1266 * mark the paths as equal here instead of returning
1269 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1270 * if either step 7 or 10 (peer type checks) yielded a winner,
1271 * that result was returned immediately. Returning from step 10
1272 * ignored the return value computed in steps 8 and 9 (IGP
1273 * metric checks). In order to preserve that behavior, if
1274 * peer_sort_ret is set, return that rather than igp_metric_ret.
1276 ret
= peer_sort_ret
;
1277 if (peer_sort_ret
< 0) {
1278 ret
= igp_metric_ret
;
1282 "%s: %s wins over %s after IGP metric comparison",
1283 pfx_buf
, new_buf
, exist_buf
);
1286 "%s: %s loses to %s after IGP metric comparison",
1287 pfx_buf
, new_buf
, exist_buf
);
1289 *reason
= bgp_path_selection_igp_metric
;
1295 * At this point, the decision whether to set *paths_eq = 1 has been
1296 * completed. If we deferred returning because of bestpath peer-type
1297 * relax configuration, return now.
1299 if (peer_sort_ret
>= 0)
1300 return peer_sort_ret
;
1302 /* 12. If both paths are external, prefer the path that was received
1303 first (the oldest one). This step minimizes route-flap, since a
1304 newer path won't displace an older one, even if it was the
1305 preferred route based on the additional decision criteria below. */
1306 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1307 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1308 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1309 *reason
= bgp_path_selection_older
;
1312 "%s: %s wins over %s due to oldest external",
1313 pfx_buf
, new_buf
, exist_buf
);
1317 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1318 *reason
= bgp_path_selection_older
;
1321 "%s: %s loses to %s due to oldest external",
1322 pfx_buf
, new_buf
, exist_buf
);
1327 /* 13. Router-ID comparison. */
1328 /* If one of the paths is "stale", the corresponding peer router-id will
1329 * be 0 and would always win over the other path. If originator id is
1330 * used for the comparison, it will decide which path is better.
1332 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1333 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1335 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1336 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1337 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1339 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1341 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1342 *reason
= bgp_path_selection_router_id
;
1345 "%s: %s wins over %s due to Router-ID comparison",
1346 pfx_buf
, new_buf
, exist_buf
);
1350 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1351 *reason
= bgp_path_selection_router_id
;
1354 "%s: %s loses to %s due to Router-ID comparison",
1355 pfx_buf
, new_buf
, exist_buf
);
1359 /* 14. Cluster length comparison. */
1360 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1361 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1363 if (new_cluster
< exist_cluster
) {
1364 *reason
= bgp_path_selection_cluster_length
;
1367 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1368 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1373 if (new_cluster
> exist_cluster
) {
1374 *reason
= bgp_path_selection_cluster_length
;
1377 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1378 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1383 /* 15. Neighbor address comparison. */
1384 /* Do this only if neither path is "stale" as stale paths do not have
1385 * valid peer information (as the connection may or may not be up).
1387 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1388 *reason
= bgp_path_selection_stale
;
1391 "%s: %s wins over %s due to latter path being STALE",
1392 pfx_buf
, new_buf
, exist_buf
);
1396 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1397 *reason
= bgp_path_selection_stale
;
1400 "%s: %s loses to %s due to former path being STALE",
1401 pfx_buf
, new_buf
, exist_buf
);
1405 /* locally configured routes to advertise do not have su_remote */
1406 if (new->peer
->su_remote
== NULL
) {
1407 *reason
= bgp_path_selection_local_configured
;
1410 if (exist
->peer
->su_remote
== NULL
) {
1411 *reason
= bgp_path_selection_local_configured
;
1415 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1418 *reason
= bgp_path_selection_neighbor_ip
;
1421 "%s: %s loses to %s due to Neighor IP comparison",
1422 pfx_buf
, new_buf
, exist_buf
);
1427 *reason
= bgp_path_selection_neighbor_ip
;
1430 "%s: %s wins over %s due to Neighor IP comparison",
1431 pfx_buf
, new_buf
, exist_buf
);
1435 *reason
= bgp_path_selection_default
;
1437 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1438 pfx_buf
, new_buf
, exist_buf
);
1444 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1445 struct bgp_path_info
*exist
, int *paths_eq
)
1447 enum bgp_path_selection_reason reason
;
1448 char pfx_buf
[PREFIX2STR_BUFFER
];
1450 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1451 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1454 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1455 * is preferred, or 0 if they are the same (usually will only occur if
1456 * multipath is enabled
1457 * This version is compatible with */
1458 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1459 struct bgp_path_info
*exist
, char *pfx_buf
,
1460 afi_t afi
, safi_t safi
,
1461 enum bgp_path_selection_reason
*reason
)
1465 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1479 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1480 const struct prefix
*p
,
1481 struct attr
*attr
, afi_t afi
,
1484 struct bgp_filter
*filter
;
1485 enum filter_type ret
= FILTER_PERMIT
;
1487 filter
= &peer
->filter
[afi
][safi
];
1489 #define FILTER_EXIST_WARN(F, f, filter) \
1490 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1491 zlog_debug("%s: Could not find configured input %s-list %s!", \
1492 peer->host, #f, F##_IN_NAME(filter));
1494 if (DISTRIBUTE_IN_NAME(filter
)) {
1495 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1497 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1504 if (PREFIX_LIST_IN_NAME(filter
)) {
1505 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1507 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1514 if (FILTER_LIST_IN_NAME(filter
)) {
1515 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1517 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1518 == AS_FILTER_DENY
) {
1525 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1526 char pfxprint
[PREFIX2STR_BUFFER
];
1528 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1529 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1530 ret
== FILTER_PERMIT
? "permit" : "deny");
1534 #undef FILTER_EXIST_WARN
1537 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1538 const struct prefix
*p
,
1539 struct attr
*attr
, afi_t afi
,
1542 struct bgp_filter
*filter
;
1543 enum filter_type ret
= FILTER_PERMIT
;
1545 filter
= &peer
->filter
[afi
][safi
];
1547 #define FILTER_EXIST_WARN(F, f, filter) \
1548 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1549 zlog_debug("%s: Could not find configured output %s-list %s!", \
1550 peer->host, #f, F##_OUT_NAME(filter));
1552 if (DISTRIBUTE_OUT_NAME(filter
)) {
1553 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1555 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1562 if (PREFIX_LIST_OUT_NAME(filter
)) {
1563 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1565 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1572 if (FILTER_LIST_OUT_NAME(filter
)) {
1573 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1575 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1576 == AS_FILTER_DENY
) {
1582 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1583 char pfxprint
[PREFIX2STR_BUFFER
];
1585 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1586 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1587 ret
== FILTER_PERMIT
? "permit" : "deny");
1592 #undef FILTER_EXIST_WARN
1595 /* If community attribute includes no_export then return 1. */
1596 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1598 if (bgp_attr_get_community(attr
)) {
1599 /* NO_ADVERTISE check. */
1600 if (community_include(bgp_attr_get_community(attr
),
1601 COMMUNITY_NO_ADVERTISE
))
1604 /* NO_EXPORT check. */
1605 if (peer
->sort
== BGP_PEER_EBGP
&&
1606 community_include(bgp_attr_get_community(attr
),
1607 COMMUNITY_NO_EXPORT
))
1610 /* NO_EXPORT_SUBCONFED check. */
1611 if (peer
->sort
== BGP_PEER_EBGP
1612 || peer
->sort
== BGP_PEER_CONFED
)
1613 if (community_include(bgp_attr_get_community(attr
),
1614 COMMUNITY_NO_EXPORT_SUBCONFED
))
1620 /* Route reflection loop check. */
1621 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1623 struct in_addr cluster_id
;
1624 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1627 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1628 cluster_id
= peer
->bgp
->cluster_id
;
1630 cluster_id
= peer
->bgp
->router_id
;
1632 if (cluster_loop_check(cluster
, cluster_id
))
1638 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1640 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1641 if (peer
->local_role
== ROLE_PROVIDER
||
1642 peer
->local_role
== ROLE_RS_SERVER
)
1644 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1648 if (peer
->local_role
== ROLE_CUSTOMER
||
1649 peer
->local_role
== ROLE_PEER
||
1650 peer
->local_role
== ROLE_RS_CLIENT
) {
1651 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1652 attr
->otc
= peer
->as
;
1657 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1659 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1660 if (peer
->local_role
== ROLE_CUSTOMER
||
1661 peer
->local_role
== ROLE_RS_CLIENT
||
1662 peer
->local_role
== ROLE_PEER
)
1666 if (peer
->local_role
== ROLE_PROVIDER
||
1667 peer
->local_role
== ROLE_PEER
||
1668 peer
->local_role
== ROLE_RS_SERVER
) {
1669 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1670 attr
->otc
= peer
->bgp
->as
;
1675 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1677 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1680 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1681 struct attr
*attr
, afi_t afi
, safi_t safi
,
1682 const char *rmap_name
, mpls_label_t
*label
,
1683 uint32_t num_labels
, struct bgp_dest
*dest
)
1685 struct bgp_filter
*filter
;
1686 struct bgp_path_info rmap_path
= { 0 };
1687 struct bgp_path_info_extra extra
= { 0 };
1688 route_map_result_t ret
;
1689 struct route_map
*rmap
= NULL
;
1691 filter
= &peer
->filter
[afi
][safi
];
1693 /* Apply default weight value. */
1694 if (peer
->weight
[afi
][safi
])
1695 attr
->weight
= peer
->weight
[afi
][safi
];
1698 rmap
= route_map_lookup_by_name(rmap_name
);
1703 if (ROUTE_MAP_IN_NAME(filter
)) {
1704 rmap
= ROUTE_MAP_IN(filter
);
1711 /* Route map apply. */
1713 memset(&rmap_path
, 0, sizeof(rmap_path
));
1714 /* Duplicate current value to new structure for modification. */
1715 rmap_path
.peer
= peer
;
1716 rmap_path
.attr
= attr
;
1717 rmap_path
.extra
= &extra
;
1718 rmap_path
.net
= dest
;
1720 extra
.num_labels
= num_labels
;
1721 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1722 memcpy(extra
.label
, label
,
1723 num_labels
* sizeof(mpls_label_t
));
1725 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1727 /* Apply BGP route map to the attribute. */
1728 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1730 peer
->rmap_type
= 0;
1732 if (ret
== RMAP_DENYMATCH
)
1738 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1739 struct attr
*attr
, afi_t afi
, safi_t safi
,
1740 const char *rmap_name
)
1742 struct bgp_path_info rmap_path
;
1743 route_map_result_t ret
;
1744 struct route_map
*rmap
= NULL
;
1748 * So if we get to this point and have no rmap_name
1749 * we want to just show the output as it currently
1755 /* Apply default weight value. */
1756 if (peer
->weight
[afi
][safi
])
1757 attr
->weight
= peer
->weight
[afi
][safi
];
1759 rmap
= route_map_lookup_by_name(rmap_name
);
1762 * If we have a route map name and we do not find
1763 * the routemap that means we have an implicit
1769 memset(&rmap_path
, 0, sizeof(rmap_path
));
1770 /* Route map apply. */
1771 /* Duplicate current value to new structure for modification. */
1772 rmap_path
.peer
= peer
;
1773 rmap_path
.attr
= attr
;
1775 rmap_type
= peer
->rmap_type
;
1776 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1778 /* Apply BGP route map to the attribute. */
1779 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1781 peer
->rmap_type
= rmap_type
;
1783 if (ret
== RMAP_DENYMATCH
)
1785 * caller has multiple error paths with bgp_attr_flush()
1792 /* If this is an EBGP peer with remove-private-AS */
1793 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1794 struct peer
*peer
, struct attr
*attr
)
1796 if (peer
->sort
== BGP_PEER_EBGP
1797 && (peer_af_flag_check(peer
, afi
, safi
,
1798 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1799 || peer_af_flag_check(peer
, afi
, safi
,
1800 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1801 || peer_af_flag_check(peer
, afi
, safi
,
1802 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1803 || peer_af_flag_check(peer
, afi
, safi
,
1804 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1805 // Take action on the entire aspath
1806 if (peer_af_flag_check(peer
, afi
, safi
,
1807 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1808 || peer_af_flag_check(peer
, afi
, safi
,
1809 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1810 if (peer_af_flag_check(
1812 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1813 attr
->aspath
= aspath_replace_private_asns(
1814 attr
->aspath
, bgp
->as
, peer
->as
);
1817 * Even if the aspath consists of just private ASNs we
1818 * need to walk the AS-Path to maintain all instances
1819 * of the peer's ASN to break possible loops.
1822 attr
->aspath
= aspath_remove_private_asns(
1823 attr
->aspath
, peer
->as
);
1826 // 'all' was not specified so the entire aspath must be private
1828 // for us to do anything
1829 else if (aspath_private_as_check(attr
->aspath
)) {
1830 if (peer_af_flag_check(
1832 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1833 attr
->aspath
= aspath_replace_private_asns(
1834 attr
->aspath
, bgp
->as
, peer
->as
);
1837 * Walk the aspath to retain any instances of
1840 attr
->aspath
= aspath_remove_private_asns(
1841 attr
->aspath
, peer
->as
);
1846 /* If this is an EBGP peer with as-override */
1847 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1848 struct peer
*peer
, struct attr
*attr
)
1850 struct aspath
*aspath
;
1852 if (peer
->sort
== BGP_PEER_EBGP
&&
1853 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1854 if (attr
->aspath
->refcnt
)
1855 aspath
= aspath_dup(attr
->aspath
);
1857 aspath
= attr
->aspath
;
1859 attr
->aspath
= aspath_intern(
1860 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1862 aspath_free(aspath
);
1866 void bgp_attr_add_llgr_community(struct attr
*attr
)
1868 struct community
*old
;
1869 struct community
*new;
1870 struct community
*merge
;
1871 struct community
*llgr
;
1873 old
= bgp_attr_get_community(attr
);
1874 llgr
= community_str2com("llgr-stale");
1879 merge
= community_merge(community_dup(old
), llgr
);
1881 if (old
->refcnt
== 0)
1882 community_free(&old
);
1884 new = community_uniq_sort(merge
);
1885 community_free(&merge
);
1887 new = community_dup(llgr
);
1890 community_free(&llgr
);
1892 bgp_attr_set_community(attr
, new);
1895 void bgp_attr_add_gshut_community(struct attr
*attr
)
1897 struct community
*old
;
1898 struct community
*new;
1899 struct community
*merge
;
1900 struct community
*gshut
;
1902 old
= bgp_attr_get_community(attr
);
1903 gshut
= community_str2com("graceful-shutdown");
1908 merge
= community_merge(community_dup(old
), gshut
);
1910 if (old
->refcnt
== 0)
1911 community_free(&old
);
1913 new = community_uniq_sort(merge
);
1914 community_free(&merge
);
1916 new = community_dup(gshut
);
1919 community_free(&gshut
);
1920 bgp_attr_set_community(attr
, new);
1922 /* When we add the graceful-shutdown community we must also
1923 * lower the local-preference */
1924 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1925 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1929 /* Notify BGP Conditional advertisement scanner process. */
1930 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1932 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1933 afi_t afi
= SUBGRP_AFI(subgrp
);
1934 safi_t safi
= SUBGRP_SAFI(subgrp
);
1935 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1937 if (!ADVERTISE_MAP_NAME(filter
))
1940 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1943 peer
->advmap_table_change
= true;
1947 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1949 if (family
== AF_INET
) {
1950 attr
->nexthop
.s_addr
= INADDR_ANY
;
1951 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1953 if (family
== AF_INET6
)
1954 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1955 if (family
== AF_EVPN
)
1956 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1959 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1960 struct update_subgroup
*subgrp
,
1961 const struct prefix
*p
, struct attr
*attr
,
1962 struct attr
*post_attr
)
1964 struct bgp_filter
*filter
;
1967 struct peer
*onlypeer
;
1969 struct attr
*piattr
;
1970 route_map_result_t ret
;
1975 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1976 bool nh_reset
= false;
1979 if (DISABLE_BGP_ANNOUNCE
)
1982 afi
= SUBGRP_AFI(subgrp
);
1983 safi
= SUBGRP_SAFI(subgrp
);
1984 peer
= SUBGRP_PEER(subgrp
);
1986 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1987 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1990 filter
= &peer
->filter
[afi
][safi
];
1991 bgp
= SUBGRP_INST(subgrp
);
1992 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1995 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
1996 peer
->pmax_out
[afi
][safi
] != 0 &&
1997 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
1998 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
1999 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
2000 zlog_debug("%s reached maximum prefix to be send (%u)",
2001 peer
->host
, peer
->pmax_out
[afi
][safi
]);
2006 #ifdef ENABLE_BGP_VNC
2007 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
2008 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
2009 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
2012 * direct and direct_ext type routes originate internally even
2013 * though they can have peer pointers that reference other
2016 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2022 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
2023 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
2024 && (pi
->type
== ZEBRA_ROUTE_BGP
)
2025 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2027 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2032 /* With addpath we may be asked to TX all kinds of paths so make sure
2034 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
2035 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
2036 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
2040 /* If this is not the bestpath then check to see if there is an enabled
2042 * feature that requires us to advertise it */
2043 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2044 if (!bgp_addpath_capable(pi
, peer
, afi
, safi
))
2047 /* Aggregate-address suppress check. */
2048 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
2052 * If we are doing VRF 2 VRF leaking via the import
2053 * statement, we want to prevent the route going
2054 * off box as that the RT and RD created are localy
2055 * significant and globaly useless.
2057 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
2058 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
2061 /* If it's labeled safi, make sure the route has a valid label. */
2062 if (safi
== SAFI_LABELED_UNICAST
) {
2063 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
2064 if (!bgp_is_valid_label(&label
)) {
2065 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2066 zlog_debug("u%" PRIu64
":s%" PRIu64
2067 " %pFX is filtered - no label (%p)",
2068 subgrp
->update_group
->id
, subgrp
->id
,
2074 /* Do not send back route to sender. */
2075 if (onlypeer
&& from
== onlypeer
) {
2079 /* Do not send the default route in the BGP table if the neighbor is
2080 * configured for default-originate */
2081 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2082 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2083 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2085 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2089 /* Transparency check. */
2090 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2091 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2096 /* If community is not disabled check the no-export and local. */
2097 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2098 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2099 zlog_debug("%s: community filter check fail for %pFX",
2104 /* If the attribute has originator-id and it is same as remote
2106 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2107 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2108 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2110 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2115 /* ORF prefix-list filter check */
2116 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2117 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2118 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2119 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2120 if (peer
->orf_plist
[afi
][safi
]) {
2121 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2123 if (bgp_debug_update(NULL
, p
,
2124 subgrp
->update_group
, 0))
2126 "%pBP [Update:SEND] %pFX is filtered via ORF",
2132 /* Output filter check. */
2133 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2134 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2135 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2140 /* AS path loop check. */
2141 if (peer
->as_path_loop_detection
&&
2142 aspath_loop_check(piattr
->aspath
, peer
->as
)) {
2143 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2145 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2150 /* If we're a CONFED we need to loop check the CONFED ID too */
2151 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2152 if (aspath_loop_check_confed(piattr
->aspath
, bgp
->confed_id
)) {
2153 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2155 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2156 peer
, bgp
->confed_id
);
2161 /* Route-Reflect check. */
2162 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2167 /* IBGP reflection check. */
2168 if (reflect
&& !samepeer_safe
) {
2169 /* A route from a Client peer. */
2170 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2171 PEER_FLAG_REFLECTOR_CLIENT
)) {
2172 /* Reflect to all the Non-Client peers and also to the
2173 Client peers other than the originator. Originator
2175 is already done. So there is noting to do. */
2176 /* no bgp client-to-client reflection check. */
2177 if (CHECK_FLAG(bgp
->flags
,
2178 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2179 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2180 PEER_FLAG_REFLECTOR_CLIENT
))
2183 /* A route from a Non-client peer. Reflect to all other
2185 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2186 PEER_FLAG_REFLECTOR_CLIENT
))
2191 /* For modify attribute, copy it to temporary structure.
2192 * post_attr comes from BGP conditional advertisements, where
2193 * attributes are already processed by advertise-map route-map,
2194 * and this needs to be saved instead of overwriting from the
2202 /* If local-preference is not set. */
2203 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2204 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2205 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2206 attr
->local_pref
= bgp
->default_local_pref
;
2209 /* If originator-id is not set and the route is to be reflected,
2210 set the originator id */
2212 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2213 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2214 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2217 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2219 if (peer
->sort
== BGP_PEER_EBGP
2220 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2221 if (from
!= bgp
->peer_self
&& !transparent
2222 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2223 PEER_FLAG_MED_UNCHANGED
))
2225 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2228 /* Since the nexthop attribute can vary per peer, it is not explicitly
2230 * in announce check, only certain flags and length (or number of
2232 * -- for IPv6/MP_REACH) are set here in order to guide the update
2234 * code in setting the nexthop(s) on a per peer basis in
2236 * Typically, the source nexthop in the attribute is preserved but in
2238 * scenarios where we know it will always be overwritten, we reset the
2239 * nexthop to "0" in an attempt to achieve better Update packing. An
2240 * example of this is when a prefix from each of 2 IBGP peers needs to
2242 * announced to an EBGP peer (and they have the same attributes barring
2246 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2248 #define NEXTHOP_IS_V6 \
2249 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2250 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2251 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2252 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2254 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2256 * the peer (group) is configured to receive link-local nexthop
2258 * and it is available in the prefix OR we're not reflecting the route,
2259 * link-local nexthop address is valid and
2260 * the peer (group) to whom we're going to announce is on a shared
2262 * and this is either a self-originated route or the peer is EBGP.
2263 * By checking if nexthop LL address is valid we are sure that
2264 * we do not announce LL address as `::`.
2266 if (NEXTHOP_IS_V6
) {
2267 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2268 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2269 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2270 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2271 || (!reflect
&& !transparent
2272 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2273 && peer
->shared_network
2274 && (from
== bgp
->peer_self
2275 || peer
->sort
== BGP_PEER_EBGP
))) {
2276 if (safi
== SAFI_MPLS_VPN
)
2277 attr
->mp_nexthop_len
=
2278 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
;
2280 attr
->mp_nexthop_len
=
2281 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2284 /* Clear off link-local nexthop in source, whenever it is not
2286 * ensure more prefixes share the same attribute for
2289 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2290 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2291 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2294 if (bgp_check_role_applicability(afi
, safi
) &&
2295 bgp_otc_egress(peer
, attr
))
2298 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2299 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2301 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2302 filter
->advmap
.aname
&&
2303 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2304 struct bgp_path_info rmap_path
= {0};
2305 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2306 struct attr dummy_attr
= *attr
;
2308 /* Fill temp path_info */
2309 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2310 pi
, peer
, &dummy_attr
);
2312 struct route_map
*amap
=
2313 route_map_lookup_by_name(filter
->advmap
.aname
);
2315 ret
= route_map_apply(amap
, p
, &rmap_path
);
2317 bgp_attr_flush(&dummy_attr
);
2320 * The conditional advertisement mode is Withdraw and this
2321 * prefix is a conditional prefix. Don't advertise it
2323 if (ret
== RMAP_PERMITMATCH
)
2327 /* Route map & unsuppress-map apply. */
2329 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2330 struct bgp_path_info rmap_path
= {0};
2331 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2332 struct attr dummy_attr
= {0};
2334 /* Fill temp path_info */
2335 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2338 /* don't confuse inbound and outbound setting */
2339 RESET_FLAG(attr
->rmap_change_flags
);
2342 * The route reflector is not allowed to modify the attributes
2343 * of the reflected IBGP routes unless explicitly allowed.
2345 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2346 && !CHECK_FLAG(bgp
->flags
,
2347 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2349 rmap_path
.attr
= &dummy_attr
;
2352 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2354 if (bgp_path_suppressed(pi
))
2355 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2358 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2361 bgp_attr_flush(&dummy_attr
);
2362 peer
->rmap_type
= 0;
2364 if (ret
== RMAP_DENYMATCH
) {
2365 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2367 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2368 peer
, p
, ROUTE_MAP_OUT_NAME(filter
));
2369 bgp_attr_flush(rmap_path
.attr
);
2374 /* RFC 8212 to prevent route leaks.
2375 * This specification intends to improve this situation by requiring the
2376 * explicit configuration of both BGP Import and Export Policies for any
2377 * External BGP (EBGP) session such as customers, peers, or
2378 * confederation boundaries for all enabled address families. Through
2379 * codification of the aforementioned requirement, operators will
2380 * benefit from consistent behavior across different BGP
2383 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2384 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2385 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2386 NULL
) > FIFTEENMINUTE2USEC
||
2387 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2389 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2390 monotime(&bgp
->ebgprequirespolicywarning
);
2395 /* draft-ietf-idr-deprecate-as-set-confed-set
2396 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2397 * Eventually, This document (if approved) updates RFC 4271
2398 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2399 * and obsoletes RFC 6472.
2401 if (peer
->bgp
->reject_as_sets
)
2402 if (aspath_check_as_sets(attr
->aspath
))
2405 /* If neighbor soo is configured, then check if the route has
2406 * SoO extended community and validate against the configured
2407 * one. If they match, do not announce, to prevent routing
2410 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2411 peer
->soo
[afi
][safi
]) {
2412 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2413 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2415 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2416 ECOMMUNITY_SITE_ORIGIN
) ||
2417 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2418 ECOMMUNITY_SITE_ORIGIN
) ||
2419 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2420 ECOMMUNITY_SITE_ORIGIN
)) &&
2421 ecommunity_include(ecomm
, ecomm_soo
)) {
2422 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2424 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2425 peer
, p
, ecommunity_str(ecomm_soo
));
2430 /* Codification of AS 0 Processing */
2431 if (aspath_check_as_zero(attr
->aspath
))
2434 if (bgp_in_graceful_shutdown(bgp
)) {
2435 if (peer
->sort
== BGP_PEER_IBGP
2436 || peer
->sort
== BGP_PEER_CONFED
) {
2437 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2438 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2440 bgp_attr_add_gshut_community(attr
);
2444 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2445 * Capability" to a neighbor MUST perform the following upon receiving
2446 * a route from that neighbor with the "LLGR_STALE" community, or upon
2447 * attaching the "LLGR_STALE" community itself per Section 4.2:
2449 * The route SHOULD NOT be advertised to any neighbor from which the
2450 * Long-lived Graceful Restart Capability has not been received.
2452 if (bgp_attr_get_community(attr
) &&
2453 community_include(bgp_attr_get_community(attr
),
2454 COMMUNITY_LLGR_STALE
) &&
2455 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2456 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2459 /* After route-map has been applied, we check to see if the nexthop to
2460 * be carried in the attribute (that is used for the announcement) can
2461 * be cleared off or not. We do this in all cases where we would be
2462 * setting the nexthop to "ourselves". For IPv6, we only need to
2464 * the global nexthop here; the link-local nexthop would have been
2466 * already, and if not, it is required by the update formation code.
2467 * Also see earlier comments in this function.
2470 * If route-map has performed some operation on the nexthop or the peer
2471 * configuration says to pass it unchanged, we cannot reset the nexthop
2472 * here, so only attempt to do it if these aren't true. Note that the
2473 * route-map handler itself might have cleared the nexthop, if for
2475 * it is configured as 'peer-address'.
2477 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2478 piattr
->rmap_change_flags
)
2480 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2481 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2482 /* We can reset the nexthop, if setting (or forcing) it to
2484 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2485 PEER_FLAG_NEXTHOP_SELF
)
2486 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2487 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2489 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2490 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2491 subgroup_announce_reset_nhop(
2492 (peer_cap_enhe(peer
, afi
, safi
)
2498 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2499 /* Can also reset the nexthop if announcing to EBGP, but
2501 * no peer in the subgroup is on a shared subnet.
2502 * Note: 3rd party nexthop currently implemented for
2505 if ((p
->family
== AF_INET
) &&
2506 (!bgp_subgrp_multiaccess_check_v4(
2509 subgroup_announce_reset_nhop(
2510 (peer_cap_enhe(peer
, afi
, safi
)
2517 if ((p
->family
== AF_INET6
) &&
2518 (!bgp_subgrp_multiaccess_check_v6(
2519 piattr
->mp_nexthop_global
,
2521 subgroup_announce_reset_nhop(
2522 (peer_cap_enhe(peer
, afi
, safi
)
2531 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2533 * This flag is used for leaked vpn-vrf routes
2535 int family
= p
->family
;
2537 if (peer_cap_enhe(peer
, afi
, safi
))
2540 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2542 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2543 __func__
, p
, family2str(family
));
2544 subgroup_announce_reset_nhop(family
, attr
);
2549 /* If IPv6/MP and nexthop does not have any override and happens
2551 * be a link-local address, reset it so that we don't pass along
2553 * source's link-local IPv6 address to recipients who may not be
2555 * the same interface.
2557 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2558 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2559 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2564 /* If this is an iBGP, send Origin Validation State (OVS)
2565 * extended community (rfc8097).
2567 if (peer
->sort
== BGP_PEER_IBGP
) {
2568 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2570 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2572 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2573 bgp_attr_set_ecommunity(
2574 attr
, ecommunity_add_origin_validation_state(
2576 bgp_attr_get_ecommunity(attr
)));
2580 * When the next hop is set to ourselves, if all multipaths have
2581 * link-bandwidth announce the cumulative bandwidth as that makes
2582 * the most sense. However, don't modify if the link-bandwidth has
2583 * been explicitly set by user policy.
2586 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2587 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2588 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2589 bgp_attr_set_ecommunity(
2591 ecommunity_replace_linkbw(
2592 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2595 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2600 static void bgp_route_select_timer_expire(struct thread
*thread
)
2602 struct afi_safi_info
*info
;
2607 info
= THREAD_ARG(thread
);
2612 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2613 XFREE(MTYPE_TMP
, info
);
2615 /* Best path selection */
2616 bgp_best_path_select_defer(bgp
, afi
, safi
);
2619 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2620 struct bgp_maxpaths_cfg
*mpath_cfg
,
2621 struct bgp_path_info_pair
*result
, afi_t afi
,
2624 struct bgp_path_info
*new_select
;
2625 struct bgp_path_info
*old_select
;
2626 struct bgp_path_info
*pi
;
2627 struct bgp_path_info
*pi1
;
2628 struct bgp_path_info
*pi2
;
2629 struct bgp_path_info
*nextpi
= NULL
;
2630 int paths_eq
, do_mpath
, debug
;
2631 struct list mp_list
;
2632 char pfx_buf
[PREFIX2STR_BUFFER
];
2633 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2635 bgp_mp_list_init(&mp_list
);
2637 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2639 debug
= bgp_debug_bestpath(dest
);
2642 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2644 dest
->reason
= bgp_path_selection_none
;
2645 /* bgp deterministic-med */
2647 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2649 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2650 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2652 bgp_path_info_unset_flag(dest
, pi1
,
2653 BGP_PATH_DMED_SELECTED
);
2655 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2657 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2659 if (BGP_PATH_HOLDDOWN(pi1
))
2661 if (pi1
->peer
!= bgp
->peer_self
)
2662 if (!peer_established(pi1
->peer
))
2667 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2668 if (CHECK_FLAG(pi2
->flags
,
2669 BGP_PATH_DMED_CHECK
))
2671 if (BGP_PATH_HOLDDOWN(pi2
))
2673 if (pi2
->peer
!= bgp
->peer_self
2676 PEER_STATUS_NSF_WAIT
))
2677 if (pi2
->peer
->status
2681 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2683 && !aspath_cmp_left_confed(
2688 if (bgp_path_info_cmp(
2689 bgp
, pi2
, new_select
,
2690 &paths_eq
, mpath_cfg
, debug
,
2693 bgp_path_info_unset_flag(
2695 BGP_PATH_DMED_SELECTED
);
2699 bgp_path_info_set_flag(
2700 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2703 bgp_path_info_set_flag(dest
, new_select
,
2704 BGP_PATH_DMED_CHECK
);
2705 bgp_path_info_set_flag(dest
, new_select
,
2706 BGP_PATH_DMED_SELECTED
);
2709 bgp_path_info_path_with_addpath_rx_str(
2710 new_select
, path_buf
, sizeof(path_buf
));
2712 "%pBD(%s): %s is the bestpath from AS %u",
2713 dest
, bgp
->name_pretty
, path_buf
,
2714 aspath_get_first_as(
2715 new_select
->attr
->aspath
));
2720 /* Check old selected route and new selected route. */
2723 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2724 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2725 enum bgp_path_selection_reason reason
;
2727 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2730 if (BGP_PATH_HOLDDOWN(pi
)) {
2731 /* reap REMOVED routes, if needs be
2732 * selected route must stay for a while longer though
2734 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2735 && (pi
!= old_select
))
2736 bgp_path_info_reap(dest
, pi
);
2739 zlog_debug("%s: pi %p in holddown", __func__
,
2745 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2746 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2747 if (!peer_established(pi
->peer
)) {
2751 "%s: pi %p non self peer %s not estab state",
2752 __func__
, pi
, pi
->peer
->host
);
2757 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2758 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2759 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2761 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2765 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2767 reason
= dest
->reason
;
2768 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2769 debug
, pfx_buf
, afi
, safi
,
2771 if (new_select
== NULL
&&
2772 reason
!= bgp_path_selection_none
)
2773 dest
->reason
= reason
;
2778 /* Now that we know which path is the bestpath see if any of the other
2780 * qualify as multipaths
2784 bgp_path_info_path_with_addpath_rx_str(
2785 new_select
, path_buf
, sizeof(path_buf
));
2787 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2789 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2790 dest
, bgp
->name_pretty
, path_buf
,
2791 old_select
? old_select
->peer
->host
: "NONE");
2794 if (do_mpath
&& new_select
) {
2795 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2796 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2799 bgp_path_info_path_with_addpath_rx_str(
2800 pi
, path_buf
, sizeof(path_buf
));
2802 if (pi
== new_select
) {
2805 "%pBD(%s): %s is the bestpath, add to the multipath list",
2806 dest
, bgp
->name_pretty
,
2808 bgp_mp_list_add(&mp_list
, pi
);
2812 if (BGP_PATH_HOLDDOWN(pi
))
2815 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2816 && !CHECK_FLAG(pi
->peer
->sflags
,
2817 PEER_STATUS_NSF_WAIT
))
2818 if (!peer_established(pi
->peer
))
2821 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2824 "%pBD: %s has the same nexthop as the bestpath, skip it",
2829 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2830 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2836 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2838 bgp_mp_list_add(&mp_list
, pi
);
2843 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2845 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2846 bgp_mp_list_clear(&mp_list
);
2848 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2850 result
->old
= old_select
;
2851 result
->new = new_select
;
2857 * A new route/change in bestpath of an existing route. Evaluate the path
2858 * for advertisement to the subgroup.
2860 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2861 struct bgp_path_info
*selected
,
2862 struct bgp_dest
*dest
,
2863 uint32_t addpath_tx_id
)
2865 const struct prefix
*p
;
2866 struct peer
*onlypeer
;
2873 p
= bgp_dest_get_prefix(dest
);
2874 afi
= SUBGRP_AFI(subgrp
);
2875 safi
= SUBGRP_SAFI(subgrp
);
2876 bgp
= SUBGRP_INST(subgrp
);
2877 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2880 if (BGP_DEBUG(update
, UPDATE_OUT
))
2881 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2883 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2884 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2885 PEER_STATUS_ORF_WAIT_REFRESH
))
2888 memset(&attr
, 0, sizeof(attr
));
2889 /* It's initialized in bgp_announce_check() */
2891 /* Announcement to the subgroup. If the route is filtered withdraw it.
2892 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2893 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2896 advertise
= bgp_check_advertise(bgp
, dest
);
2899 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2901 /* Route is selected, if the route is already installed
2902 * in FIB, then it is advertised
2905 if (!bgp_check_withdrawal(bgp
, dest
))
2906 bgp_adj_out_set_subgroup(
2907 dest
, subgrp
, &attr
, selected
);
2909 bgp_adj_out_unset_subgroup(
2910 dest
, subgrp
, 1, addpath_tx_id
);
2913 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2917 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2919 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2924 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2925 * This is called at the end of route processing.
2927 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2929 struct bgp_path_info
*pi
;
2931 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2932 if (BGP_PATH_HOLDDOWN(pi
))
2934 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2935 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2940 * Has the route changed from the RIB's perspective? This is invoked only
2941 * if the route selection returns the same best route as earlier - to
2942 * determine if we need to update zebra or not.
2944 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2946 struct bgp_path_info
*mpinfo
;
2948 /* If this is multipath, check all selected paths for any nexthop
2949 * change or attribute change. Some attribute changes (e.g., community)
2950 * aren't of relevance to the RIB, but we'll update zebra to ensure
2951 * we handle the case of BGP nexthop change. This is the behavior
2952 * when the best path has an attribute change anyway.
2954 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2955 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2956 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2960 * If this is multipath, check all selected paths for any nexthop change
2962 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2963 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2964 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2965 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2969 /* Nothing has changed from the RIB's perspective. */
2973 struct bgp_process_queue
{
2975 STAILQ_HEAD(, bgp_dest
) pqueue
;
2976 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2978 unsigned int queued
;
2981 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2982 safi_t safi
, struct bgp_dest
*dest
,
2983 struct bgp_path_info
*new_select
,
2984 struct bgp_path_info
*old_select
)
2986 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2988 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2991 if (advertise_type5_routes(bgp
, afi
) && new_select
2992 && is_route_injectable_into_evpn(new_select
)) {
2994 /* apply the route-map */
2995 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2996 route_map_result_t ret
;
2997 struct bgp_path_info rmap_path
;
2998 struct bgp_path_info_extra rmap_path_extra
;
2999 struct attr dummy_attr
;
3001 dummy_attr
= *new_select
->attr
;
3003 /* Fill temp path_info */
3004 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3005 new_select
, new_select
->peer
,
3008 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3010 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3013 if (ret
== RMAP_DENYMATCH
) {
3014 bgp_attr_flush(&dummy_attr
);
3015 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3018 bgp_evpn_advertise_type5_route(
3019 bgp
, p
, &dummy_attr
, afi
, safi
);
3021 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3024 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3025 && is_route_injectable_into_evpn(old_select
))
3026 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3030 * Utility to determine whether a particular path_info should use
3031 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3032 * in a path where we basically _know_ this is a BGP-LU route.
3034 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
3036 /* Certain types get imp null; so do paths where the nexthop is
3039 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3040 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3041 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3043 else if (new_select
->extra
== NULL
||
3044 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
3045 /* TODO -- should be configurable? */
3052 * old_select = The old best path
3053 * new_select = the new best path
3055 * if (!old_select && new_select)
3056 * We are sending new information on.
3058 * if (old_select && new_select) {
3059 * if (new_select != old_select)
3060 * We have a new best path send a change
3062 * We've received a update with new attributes that needs
3066 * if (old_select && !new_select)
3067 * We have no eligible route that we can announce or the rn
3070 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3071 afi_t afi
, safi_t safi
)
3073 struct bgp_path_info
*new_select
;
3074 struct bgp_path_info
*old_select
;
3075 struct bgp_path_info_pair old_and_new
;
3078 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3080 debug
= bgp_debug_bestpath(dest
);
3083 "%s: bgp delete in progress, ignoring event, p=%pBD",
3087 /* Is it end of initial update? (after startup) */
3089 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3090 sizeof(bgp
->update_delay_zebra_resume_time
));
3092 bgp
->main_zebra_update_hold
= 0;
3093 FOREACH_AFI_SAFI (afi
, safi
) {
3094 if (bgp_fibupd_safi(safi
))
3095 bgp_zebra_announce_table(bgp
, afi
, safi
);
3097 bgp
->main_peers_update_hold
= 0;
3099 bgp_start_routeadv(bgp
);
3103 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3105 debug
= bgp_debug_bestpath(dest
);
3107 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__
,
3108 dest
, bgp
->name_pretty
, afi2str(afi
),
3111 /* The best path calculation for the route is deferred if
3112 * BGP_NODE_SELECT_DEFER is set
3114 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3115 if (BGP_DEBUG(update
, UPDATE_OUT
))
3116 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
3120 /* Best path selection. */
3121 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3123 old_select
= old_and_new
.old
;
3124 new_select
= old_and_new
.new;
3126 /* Do we need to allocate or free labels?
3127 * Right now, since we only deal with per-prefix labels, it is not
3128 * necessary to do this upon changes to best path. Exceptions:
3129 * - label index has changed -> recalculate resulting label
3130 * - path_info sub_type changed -> switch to/from implicit-null
3131 * - no valid label (due to removed static label binding) -> get new one
3133 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3136 || bgp_label_index_differs(new_select
, old_select
)
3137 || new_select
->sub_type
!= old_select
->sub_type
3138 || !bgp_is_valid_label(&dest
->local_label
)) {
3139 /* Enforced penultimate hop popping:
3140 * implicit-null for local routes, aggregate
3141 * and redistributed routes
3143 if (bgp_lu_need_imp_null(new_select
)) {
3146 BGP_NODE_REGISTERED_FOR_LABEL
)
3149 BGP_NODE_LABEL_REQUESTED
))
3150 bgp_unregister_for_label(dest
);
3151 dest
->local_label
= mpls_lse_encode(
3152 MPLS_LABEL_IMPLICIT_NULL
, 0, 0,
3154 bgp_set_valid_label(&dest
->local_label
);
3156 bgp_register_for_label(dest
,
3159 } else if (CHECK_FLAG(dest
->flags
,
3160 BGP_NODE_REGISTERED_FOR_LABEL
)
3161 || CHECK_FLAG(dest
->flags
,
3162 BGP_NODE_LABEL_REQUESTED
)) {
3163 bgp_unregister_for_label(dest
);
3165 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3166 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3167 bgp_unregister_for_label(dest
);
3172 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3173 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3174 safi2str(safi
), old_select
, new_select
);
3176 /* If best route remains the same and this is not due to user-initiated
3177 * clear, see exactly what needs to be done.
3179 if (old_select
&& old_select
== new_select
3180 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3181 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3182 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3183 if (bgp_zebra_has_route_changed(old_select
)) {
3184 #ifdef ENABLE_BGP_VNC
3185 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3186 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3188 if (bgp_fibupd_safi(safi
)
3189 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3191 if (BGP_SUPPRESS_FIB_ENABLED(bgp
)
3192 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
3193 SET_FLAG(dest
->flags
,
3194 BGP_NODE_FIB_INSTALL_PENDING
);
3196 if (new_select
->type
== ZEBRA_ROUTE_BGP
3197 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3198 || new_select
->sub_type
3199 == BGP_ROUTE_IMPORTED
))
3201 bgp_zebra_announce(dest
, p
, old_select
,
3206 /* If there is a change of interest to peers, reannounce the
3208 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3209 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3210 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3211 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3213 /* unicast routes must also be annouced to
3214 * labeled-unicast update-groups */
3215 if (safi
== SAFI_UNICAST
)
3216 group_announce_route(bgp
, afi
,
3217 SAFI_LABELED_UNICAST
, dest
,
3220 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3221 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3224 /* advertise/withdraw type-5 routes */
3225 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3226 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3227 bgp_process_evpn_route_injection(
3228 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3230 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3231 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3232 bgp_zebra_clear_route_change_flags(dest
);
3233 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3237 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3239 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3241 /* bestpath has changed; bump version */
3242 if (old_select
|| new_select
) {
3243 bgp_bump_version(dest
);
3245 if (!bgp
->t_rmap_def_originate_eval
) {
3249 update_group_refresh_default_originate_route_map
,
3250 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3251 &bgp
->t_rmap_def_originate_eval
);
3256 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3259 zlog_debug("%s: setting SELECTED flag", __func__
);
3260 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3261 bgp_path_info_unset_flag(dest
, new_select
,
3262 BGP_PATH_ATTR_CHANGED
);
3263 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3264 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3267 #ifdef ENABLE_BGP_VNC
3268 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3269 if (old_select
!= new_select
) {
3271 vnc_import_bgp_exterior_del_route(bgp
, p
,
3273 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3276 vnc_import_bgp_exterior_add_route(bgp
, p
,
3278 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3284 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3286 /* unicast routes must also be annouced to labeled-unicast update-groups
3288 if (safi
== SAFI_UNICAST
)
3289 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3293 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3294 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3296 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3297 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3298 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3299 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3301 if (BGP_SUPPRESS_FIB_ENABLED(bgp
))
3302 SET_FLAG(dest
->flags
,
3303 BGP_NODE_FIB_INSTALL_PENDING
);
3305 /* if this is an evpn imported type-5 prefix,
3306 * we need to withdraw the route first to clear
3307 * the nh neigh and the RMAC entry.
3310 is_route_parent_evpn(old_select
))
3311 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3313 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3315 /* Withdraw the route from the kernel. */
3316 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3317 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3318 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3319 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3321 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3325 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3328 /* Clear any route change flags. */
3329 bgp_zebra_clear_route_change_flags(dest
);
3331 /* Reap old select bgp_path_info, if it has been removed */
3332 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3333 bgp_path_info_reap(dest
, old_select
);
3335 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3339 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3340 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3342 struct bgp_dest
*dest
;
3344 struct afi_safi_info
*thread_info
;
3346 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3347 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3349 thread_info
= THREAD_ARG(t
);
3350 XFREE(MTYPE_TMP
, thread_info
);
3351 THREAD_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3354 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3355 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3356 get_afi_safi_str(afi
, safi
, false),
3357 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3360 /* Process the route list */
3361 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3362 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3363 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3364 dest
= bgp_route_next(dest
)) {
3365 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3368 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3369 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3370 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3373 /* If iteration stopped before the entire table was traversed then the
3374 * node needs to be unlocked.
3377 bgp_dest_unlock_node(dest
);
3381 /* Send EOR message when all routes are processed */
3382 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3383 bgp_send_delayed_eor(bgp
);
3384 /* Send route processing complete message to RIB */
3385 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3386 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3390 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3392 thread_info
->afi
= afi
;
3393 thread_info
->safi
= safi
;
3394 thread_info
->bgp
= bgp
;
3396 /* If there are more routes to be processed, start the
3399 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3400 BGP_ROUTE_SELECT_DELAY
,
3401 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3404 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3406 struct bgp_process_queue
*pqnode
= data
;
3407 struct bgp
*bgp
= pqnode
->bgp
;
3408 struct bgp_table
*table
;
3409 struct bgp_dest
*dest
;
3412 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3413 bgp_process_main_one(bgp
, NULL
, 0, 0);
3414 /* should always have dedicated wq call */
3415 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3419 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3420 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3421 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3422 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3423 table
= bgp_dest_table(dest
);
3424 /* note, new DESTs may be added as part of processing */
3425 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3427 bgp_dest_unlock_node(dest
);
3428 bgp_table_unlock(table
);
3434 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3436 struct bgp_process_queue
*pqnode
= data
;
3438 bgp_unlock(pqnode
->bgp
);
3440 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3443 void bgp_process_queue_init(struct bgp
*bgp
)
3445 if (!bgp
->process_queue
) {
3448 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3449 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3452 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3453 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3454 bgp
->process_queue
->spec
.max_retries
= 0;
3455 bgp
->process_queue
->spec
.hold
= 50;
3456 /* Use a higher yield value of 50ms for main queue processing */
3457 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3460 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3462 struct bgp_process_queue
*pqnode
;
3464 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3465 sizeof(struct bgp_process_queue
));
3467 /* unlocked in bgp_processq_del */
3468 pqnode
->bgp
= bgp_lock(bgp
);
3469 STAILQ_INIT(&pqnode
->pqueue
);
3474 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3476 #define ARBITRARY_PROCESS_QLEN 10000
3477 struct work_queue
*wq
= bgp
->process_queue
;
3478 struct bgp_process_queue
*pqnode
;
3479 int pqnode_reuse
= 0;
3481 /* already scheduled for processing? */
3482 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3485 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3488 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3489 if (BGP_DEBUG(update
, UPDATE_OUT
))
3490 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3495 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3496 if (BGP_DEBUG(update
, UPDATE_OUT
))
3498 "Soft reconfigure table in progress for route %p",
3506 /* Add route nodes to an existing work queue item until reaching the
3507 limit only if is from the same BGP view and it's not an EOIU marker
3509 if (work_queue_item_count(wq
)) {
3510 struct work_queue_item
*item
= work_queue_last_item(wq
);
3511 pqnode
= item
->data
;
3513 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3514 || pqnode
->bgp
!= bgp
3515 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3516 pqnode
= bgp_processq_alloc(bgp
);
3520 pqnode
= bgp_processq_alloc(bgp
);
3521 /* all unlocked in bgp_process_wq */
3522 bgp_table_lock(bgp_dest_table(dest
));
3524 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3525 bgp_dest_lock_node(dest
);
3527 /* can't be enqueued twice */
3528 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3529 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3533 work_queue_add(wq
, pqnode
);
3538 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3540 struct bgp_process_queue
*pqnode
;
3542 if (bgp
->process_queue
== NULL
)
3545 pqnode
= bgp_processq_alloc(bgp
);
3547 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3548 work_queue_add(bgp
->process_queue
, pqnode
);
3551 static void bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3555 peer
= THREAD_ARG(thread
);
3556 peer
->t_pmax_restart
= NULL
;
3558 if (bgp_debug_neighbor_events(peer
))
3560 "%s Maximum-prefix restart timer expired, restore peering",
3563 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3564 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3567 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3571 bool filtered
= false;
3572 struct bgp_dest
*dest
;
3573 struct bgp_adj_in
*ain
;
3574 struct attr attr
= {};
3575 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3577 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3578 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3579 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3583 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3587 if (bgp_input_modifier(
3588 peer
, rn_p
, &attr
, afi
, safi
,
3589 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3597 bgp_attr_flush(&attr
);
3604 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3608 iana_safi_t pkt_safi
;
3609 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3610 PEER_FLAG_MAX_PREFIX_FORCE
))
3611 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3612 + peer
->pcount
[afi
][safi
]
3613 : peer
->pcount
[afi
][safi
];
3615 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3618 if (pcount
> peer
->pmax
[afi
][safi
]) {
3619 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3620 PEER_STATUS_PREFIX_LIMIT
)
3625 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3626 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3627 peer
->pmax
[afi
][safi
]);
3628 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3630 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3631 PEER_FLAG_MAX_PREFIX_WARNING
))
3634 /* Convert AFI, SAFI to values for packet. */
3635 pkt_afi
= afi_int2iana(afi
);
3636 pkt_safi
= safi_int2iana(safi
);
3640 ndata
[0] = (pkt_afi
>> 8);
3642 ndata
[2] = pkt_safi
;
3643 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3644 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3645 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3646 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3648 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3649 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3650 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3654 /* Dynamic peers will just close their connection. */
3655 if (peer_dynamic_neighbor(peer
))
3658 /* restart timer start */
3659 if (peer
->pmax_restart
[afi
][safi
]) {
3660 peer
->v_pmax_restart
=
3661 peer
->pmax_restart
[afi
][safi
] * 60;
3663 if (bgp_debug_neighbor_events(peer
))
3665 "%pBP Maximum-prefix restart timer started for %d secs",
3666 peer
, peer
->v_pmax_restart
);
3668 BGP_TIMER_ON(peer
->t_pmax_restart
,
3669 bgp_maximum_prefix_restart_timer
,
3670 peer
->v_pmax_restart
);
3675 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3676 PEER_STATUS_PREFIX_LIMIT
);
3679 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3680 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3681 PEER_STATUS_PREFIX_THRESHOLD
)
3686 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3687 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3688 peer
->pmax
[afi
][safi
]);
3689 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3690 PEER_STATUS_PREFIX_THRESHOLD
);
3692 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3693 PEER_STATUS_PREFIX_THRESHOLD
);
3697 /* Unconditionally remove the route from the RIB, without taking
3698 * damping into consideration (eg, because the session went down)
3700 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3701 struct peer
*peer
, afi_t afi
, safi_t safi
)
3704 struct bgp
*bgp
= NULL
;
3705 bool delete_route
= false;
3707 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3710 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3711 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3713 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3716 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3717 delete_route
= true;
3718 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3719 delete_route
= true;
3721 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3722 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3723 bgp
= pi
->peer
->bgp
;
3724 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3729 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3730 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3733 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3734 struct peer
*peer
, afi_t afi
, safi_t safi
,
3735 struct prefix_rd
*prd
)
3737 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3739 /* apply dampening, if result is suppressed, we'll be retaining
3740 * the bgp_path_info in the RIB for historical reference.
3742 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3743 && peer
->sort
== BGP_PEER_EBGP
)
3744 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3745 == BGP_DAMP_SUPPRESSED
) {
3746 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3751 #ifdef ENABLE_BGP_VNC
3752 if (safi
== SAFI_MPLS_VPN
) {
3753 struct bgp_dest
*pdest
= NULL
;
3754 struct bgp_table
*table
= NULL
;
3756 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3757 (struct prefix
*)prd
);
3758 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3759 table
= bgp_dest_get_bgp_table_info(pdest
);
3761 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3762 peer
->bgp
, prd
, table
, p
, pi
);
3764 bgp_dest_unlock_node(pdest
);
3766 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3767 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3769 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3770 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3775 /* If this is an EVPN route, process for un-import. */
3776 if (safi
== SAFI_EVPN
)
3777 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3779 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3782 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3783 struct peer
*peer
, struct attr
*attr
,
3784 struct bgp_dest
*dest
)
3786 struct bgp_path_info
*new;
3788 /* Make new BGP info. */
3789 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3791 new->instance
= instance
;
3792 new->sub_type
= sub_type
;
3795 new->uptime
= monotime(NULL
);
3800 /* Check if received nexthop is valid or not. */
3801 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3802 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3803 struct bgp_dest
*dest
)
3806 bool is_bgp_static_route
=
3807 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3811 * Only validated for unicast and multicast currently.
3812 * Also valid for EVPN where the nexthop is an IP address.
3813 * If we are a bgp static route being checked then there is
3814 * no need to check to see if the nexthop is martian as
3815 * that it should be ok.
3817 if (is_bgp_static_route
||
3818 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3821 /* If NEXT_HOP is present, validate it. */
3822 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3823 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3824 !ipv4_unicast_valid(&attr
->nexthop
) ||
3825 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3829 /* If MP_NEXTHOP is present, validate it. */
3830 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3831 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3832 * it is not an IPv6 link-local address.
3834 * If we receive an UPDATE with nexthop length set to 32 bytes
3835 * we shouldn't discard an UPDATE if it's set to (::).
3836 * The link-local (2st) is validated along the code path later.
3838 if (attr
->mp_nexthop_len
) {
3839 switch (attr
->mp_nexthop_len
) {
3840 case BGP_ATTR_NHLEN_IPV4
:
3841 case BGP_ATTR_NHLEN_VPNV4
:
3842 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3844 !ipv4_unicast_valid(
3845 &attr
->mp_nexthop_global_in
) ||
3846 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3850 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3851 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3852 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3853 &attr
->mp_nexthop_global
)
3854 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3855 || IN6_IS_ADDR_MULTICAST(
3856 &attr
->mp_nexthop_global
)
3857 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3860 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3861 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3862 || IN6_IS_ADDR_MULTICAST(
3863 &attr
->mp_nexthop_global
)
3864 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3877 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3879 struct community
*old
;
3880 struct community
*new;
3881 struct community
*merge
;
3882 struct community
*no_export
;
3884 old
= bgp_attr_get_community(attr
);
3885 no_export
= community_str2com("no-export");
3890 merge
= community_merge(community_dup(old
), no_export
);
3893 community_free(&old
);
3895 new = community_uniq_sort(merge
);
3896 community_free(&merge
);
3898 new = community_dup(no_export
);
3901 community_free(&no_export
);
3903 bgp_attr_set_community(attr
, new);
3906 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3907 struct attr
*attr
, const struct prefix
*prefix
,
3910 struct listnode
*node
, *nnode
;
3912 bool accept_own_found
= false;
3914 if (safi
!= SAFI_MPLS_VPN
)
3917 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3918 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3921 /* The route in question carries the ACCEPT_OWN community */
3922 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3923 struct community
*comm
= bgp_attr_get_community(attr
);
3925 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3926 accept_own_found
= true;
3929 /* The route in question is targeted to one or more destination VRFs
3930 * on the router (as determined by inspecting the Route Target(s)).
3932 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3933 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3936 if (accept_own_found
&&
3938 bgp
->vpn_policy
[afi
]
3939 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3940 bgp_attr_get_ecommunity(attr
))) {
3941 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3943 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3946 /* Treat this route as imported, because it's leaked
3947 * already from another VRF, and we got an updated
3948 * version from route-reflector with ACCEPT_OWN
3951 *sub_type
= BGP_ROUTE_IMPORTED
;
3960 void bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3961 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3962 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3963 uint32_t num_labels
, int soft_reconfig
,
3964 struct bgp_route_evpn
*evpn
)
3967 int aspath_loop_count
= 0;
3968 struct bgp_dest
*dest
;
3970 struct attr new_attr
;
3971 struct attr
*attr_new
;
3972 struct bgp_path_info
*pi
;
3973 struct bgp_path_info
*new = NULL
;
3974 struct bgp_path_info_extra
*extra
;
3976 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3978 int do_loop_check
= 1;
3979 int has_valid_label
= 0;
3981 bool force_evpn_import
= false;
3982 safi_t orig_safi
= safi
;
3983 bool leak_success
= true;
3986 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3987 char pfxprint
[PREFIX2STR_BUFFER
];
3989 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3990 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3994 #ifdef ENABLE_BGP_VNC
3995 int vnc_implicit_withdraw
= 0;
3998 const struct prefix
*bgp_nht_param_prefix
;
4000 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4001 if (orig_safi
== SAFI_LABELED_UNICAST
)
4002 safi
= SAFI_UNICAST
;
4004 memset(&new_attr
, 0, sizeof(new_attr
));
4005 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4006 new_attr
.label
= MPLS_INVALID_LABEL
;
4009 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4010 /* TODO: Check to see if we can get rid of "is_valid_label" */
4011 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4012 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4014 has_valid_label
= bgp_is_valid_label(label
);
4016 if (has_valid_label
)
4017 assert(label
!= NULL
);
4019 /* Update overlay index of the attribute */
4020 if (afi
== AFI_L2VPN
&& evpn
)
4021 memcpy(&attr
->evpn_overlay
, evpn
,
4022 sizeof(struct bgp_route_evpn
));
4024 /* When peer's soft reconfiguration enabled. Record input packet in
4027 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4028 && peer
!= bgp
->peer_self
)
4029 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4031 /* Update permitted loop count */
4032 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4033 allowas_in
= peer
->allowas_in
[afi
][safi
];
4035 /* Check previously received route. */
4036 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4037 if (pi
->peer
== peer
&& pi
->type
== type
4038 && pi
->sub_type
== sub_type
4039 && pi
->addpath_rx_id
== addpath_id
)
4042 /* AS path local-as loop check. */
4043 if (peer
->change_local_as
) {
4045 aspath_loop_count
= allowas_in
;
4046 else if (!CHECK_FLAG(peer
->flags
,
4047 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4048 aspath_loop_count
= 1;
4050 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4051 > aspath_loop_count
) {
4052 peer
->stat_pfx_aspath_loop
++;
4053 reason
= "as-path contains our own AS;";
4058 /* If the peer is configured for "allowas-in origin" and the last ASN in
4060 * as-path is our ASN then we do not need to call aspath_loop_check
4062 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4063 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4066 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4067 bgp_nht_param_prefix
= NULL
;
4069 bgp_nht_param_prefix
= p
;
4071 /* AS path loop check. */
4072 if (do_loop_check
) {
4073 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4074 peer
->allowas_in
[afi
][safi
]) {
4075 peer
->stat_pfx_aspath_loop
++;
4076 reason
= "as-path contains our own AS;";
4081 /* If we're a CONFED we need to loop check the CONFED ID too */
4082 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4083 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4084 peer
->allowas_in
[afi
][safi
]) {
4085 peer
->stat_pfx_aspath_loop
++;
4086 reason
= "as-path contains our own confed AS;";
4090 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4091 * enabled, then take care of that too.
4093 bool accept_own
= false;
4095 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4096 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4098 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4100 peer
->stat_pfx_originator_loop
++;
4101 reason
= "originator is us;";
4106 /* Route reflector cluster ID check. */
4107 if (bgp_cluster_filter(peer
, attr
)) {
4108 peer
->stat_pfx_cluster_loop
++;
4109 reason
= "reflected from the same cluster;";
4113 /* Apply incoming filter. */
4114 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4115 peer
->stat_pfx_filter
++;
4120 /* RFC 8212 to prevent route leaks.
4121 * This specification intends to improve this situation by requiring the
4122 * explicit configuration of both BGP Import and Export Policies for any
4123 * External BGP (EBGP) session such as customers, peers, or
4124 * confederation boundaries for all enabled address families. Through
4125 * codification of the aforementioned requirement, operators will
4126 * benefit from consistent behavior across different BGP
4129 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4130 if (!bgp_inbound_policy_exists(peer
,
4131 &peer
->filter
[afi
][safi
])) {
4132 reason
= "inbound policy missing";
4133 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4134 NULL
) > FIFTEENMINUTE2USEC
||
4135 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4137 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4138 monotime(&bgp
->ebgprequirespolicywarning
);
4143 /* draft-ietf-idr-deprecate-as-set-confed-set
4144 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4145 * Eventually, This document (if approved) updates RFC 4271
4146 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4147 * and obsoletes RFC 6472.
4149 if (peer
->bgp
->reject_as_sets
)
4150 if (aspath_check_as_sets(attr
->aspath
)) {
4152 "as-path contains AS_SET or AS_CONFED_SET type;";
4158 /* Apply incoming route-map.
4159 * NB: new_attr may now contain newly allocated values from route-map
4161 * commands, so we need bgp_attr_flush in the error paths, until we
4163 * the attr (which takes over the memory references) */
4164 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4167 peer
->stat_pfx_filter
++;
4168 reason
= "route-map;";
4169 bgp_attr_flush(&new_attr
);
4173 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4174 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4175 /* remove from RIB previous entry */
4176 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4179 if (peer
->sort
== BGP_PEER_EBGP
) {
4182 * A BGP speaker receiving an announcement tagged with the
4183 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4184 * NO_EXPORT community as defined in RFC1997, or a
4185 * similar community, to prevent propagation of the
4186 * prefix outside the local AS. The community to prevent
4187 * propagation SHOULD be chosen according to the operator's
4190 if (bgp_attr_get_community(&new_attr
) &&
4191 community_include(bgp_attr_get_community(&new_attr
),
4192 COMMUNITY_BLACKHOLE
))
4193 bgp_attr_add_no_export_community(&new_attr
);
4195 /* If we receive the graceful-shutdown community from an eBGP
4196 * peer we must lower local-preference */
4197 if (bgp_attr_get_community(&new_attr
) &&
4198 community_include(bgp_attr_get_community(&new_attr
),
4200 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4201 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4203 /* If graceful-shutdown is configured globally or
4204 * per neighbor, then add the GSHUT community to
4205 * all paths received from eBGP peers. */
4206 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4207 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4208 bgp_attr_add_gshut_community(&new_attr
);
4211 /* next hop check. */
4212 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4213 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4215 peer
->stat_pfx_nh_invalid
++;
4216 reason
= "martian or self next-hop;";
4217 bgp_attr_flush(&new_attr
);
4221 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4222 peer
->stat_pfx_nh_invalid
++;
4223 reason
= "self mac;";
4224 bgp_attr_flush(&new_attr
);
4228 if (bgp_check_role_applicability(afi
, safi
) &&
4229 bgp_otc_filter(peer
, &new_attr
)) {
4230 reason
= "failing otc validation";
4231 bgp_attr_flush(&new_attr
);
4234 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4236 * Suppress fib is enabled
4237 * BGP_OPT_NO_FIB is not enabled
4238 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4239 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4241 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
4242 && (sub_type
== BGP_ROUTE_NORMAL
)
4243 && (!bgp_option_check(BGP_OPT_NO_FIB
))
4244 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
4245 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
4247 /* If neighbor soo is configured, tag all incoming routes with
4248 * this SoO tag and then filter out advertisements in
4249 * subgroup_announce_check() if it matches the configured SoO
4250 * on the other peer.
4252 if (peer
->soo
[afi
][safi
]) {
4253 struct ecommunity
*old_ecomm
=
4254 bgp_attr_get_ecommunity(&new_attr
);
4255 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4256 struct ecommunity
*new_ecomm
;
4259 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4262 if (!old_ecomm
->refcnt
)
4263 ecommunity_free(&old_ecomm
);
4265 new_ecomm
= ecommunity_dup(ecomm_soo
);
4268 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4271 attr_new
= bgp_attr_intern(&new_attr
);
4273 /* If the update is implicit withdraw. */
4275 pi
->uptime
= monotime(NULL
);
4276 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4278 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4280 /* Same attribute comes in. */
4281 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4283 && (!has_valid_label
4284 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4285 num_labels
* sizeof(mpls_label_t
))
4287 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4288 BGP_CONFIG_DAMPENING
)
4289 && peer
->sort
== BGP_PEER_EBGP
4290 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4291 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4292 bgp_debug_rdpfxpath2str(
4293 afi
, safi
, prd
, p
, label
,
4294 num_labels
, addpath_id
? 1 : 0,
4295 addpath_id
, evpn
, pfx_buf
,
4297 zlog_debug("%pBP rcvd %s", peer
,
4301 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4302 != BGP_DAMP_SUPPRESSED
) {
4303 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4305 bgp_process(bgp
, dest
, afi
, safi
);
4307 } else /* Duplicate - odd */
4309 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4310 if (!peer
->rcvd_attr_printed
) {
4312 "%pBP rcvd UPDATE w/ attr: %s",
4314 peer
->rcvd_attr_str
);
4315 peer
->rcvd_attr_printed
= 1;
4318 bgp_debug_rdpfxpath2str(
4319 afi
, safi
, prd
, p
, label
,
4320 num_labels
, addpath_id
? 1 : 0,
4321 addpath_id
, evpn
, pfx_buf
,
4324 "%pBP rcvd %s...duplicate ignored",
4328 /* graceful restart STALE flag unset. */
4329 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4330 bgp_path_info_unset_flag(
4331 dest
, pi
, BGP_PATH_STALE
);
4332 bgp_dest_set_defer_flag(dest
, false);
4333 bgp_process(bgp
, dest
, afi
, safi
);
4337 bgp_dest_unlock_node(dest
);
4338 bgp_attr_unintern(&attr_new
);
4343 /* Withdraw/Announce before we fully processed the withdraw */
4344 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4345 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4346 bgp_debug_rdpfxpath2str(
4347 afi
, safi
, prd
, p
, label
, num_labels
,
4348 addpath_id
? 1 : 0, addpath_id
, evpn
,
4349 pfx_buf
, sizeof(pfx_buf
));
4351 "%pBP rcvd %s, flapped quicker than processing",
4355 bgp_path_info_restore(dest
, pi
);
4358 * If the BGP_PATH_REMOVED flag is set, then EVPN
4359 * routes would have been unimported already when a
4360 * prior BGP withdraw processing happened. Such routes
4361 * need to be imported again, so flag accordingly.
4363 force_evpn_import
= true;
4365 /* implicit withdraw, decrement aggregate and pcount
4366 * here. only if update is accepted, they'll increment
4369 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4372 /* Received Logging. */
4373 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4374 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4375 num_labels
, addpath_id
? 1 : 0,
4376 addpath_id
, evpn
, pfx_buf
,
4378 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4381 /* graceful restart STALE flag unset. */
4382 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4383 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4384 bgp_dest_set_defer_flag(dest
, false);
4387 /* The attribute is changed. */
4388 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4390 /* Update bgp route dampening information. */
4391 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4392 && peer
->sort
== BGP_PEER_EBGP
) {
4393 /* This is implicit withdraw so we should update
4396 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4397 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4399 #ifdef ENABLE_BGP_VNC
4400 if (safi
== SAFI_MPLS_VPN
) {
4401 struct bgp_dest
*pdest
= NULL
;
4402 struct bgp_table
*table
= NULL
;
4404 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4405 (struct prefix
*)prd
);
4406 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4407 table
= bgp_dest_get_bgp_table_info(pdest
);
4409 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4410 bgp
, prd
, table
, p
, pi
);
4412 bgp_dest_unlock_node(pdest
);
4414 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4415 && (safi
== SAFI_UNICAST
)) {
4416 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4418 * Implicit withdraw case.
4420 ++vnc_implicit_withdraw
;
4421 vnc_import_bgp_del_route(bgp
, p
, pi
);
4422 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4427 /* Special handling for EVPN update of an existing route. If the
4428 * extended community attribute has changed, we need to
4430 * the route using its existing extended community. It will be
4431 * subsequently processed for import with the new extended
4434 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4437 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4439 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4442 cmp
= ecommunity_cmp(
4443 bgp_attr_get_ecommunity(pi
->attr
),
4444 bgp_attr_get_ecommunity(attr_new
));
4446 if (bgp_debug_update(peer
, p
, NULL
, 1))
4448 "Change in EXT-COMM, existing %s new %s",
4450 bgp_attr_get_ecommunity(
4453 bgp_attr_get_ecommunity(
4455 if (safi
== SAFI_EVPN
)
4456 bgp_evpn_unimport_route(
4457 bgp
, afi
, safi
, p
, pi
);
4458 else /* SAFI_MPLS_VPN */
4459 vpn_leak_to_vrf_withdraw(bgp
,
4465 /* Update to new attribute. */
4466 bgp_attr_unintern(&pi
->attr
);
4467 pi
->attr
= attr_new
;
4469 /* Update MPLS label */
4470 if (has_valid_label
) {
4471 extra
= bgp_path_info_extra_get(pi
);
4472 if (extra
->label
!= label
) {
4473 memcpy(&extra
->label
, label
,
4474 num_labels
* sizeof(mpls_label_t
));
4475 extra
->num_labels
= num_labels
;
4477 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4478 bgp_set_valid_label(&extra
->label
[0]);
4481 /* Update SRv6 SID */
4482 if (attr
->srv6_l3vpn
) {
4483 extra
= bgp_path_info_extra_get(pi
);
4484 if (sid_diff(&extra
->sid
[0].sid
,
4485 &attr
->srv6_l3vpn
->sid
)) {
4486 sid_copy(&extra
->sid
[0].sid
,
4487 &attr
->srv6_l3vpn
->sid
);
4488 extra
->num_sids
= 1;
4490 extra
->sid
[0].loc_block_len
= 0;
4491 extra
->sid
[0].loc_node_len
= 0;
4492 extra
->sid
[0].func_len
= 0;
4493 extra
->sid
[0].arg_len
= 0;
4494 extra
->sid
[0].transposition_len
= 0;
4495 extra
->sid
[0].transposition_offset
= 0;
4497 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4498 extra
->sid
[0].loc_block_len
=
4499 attr
->srv6_l3vpn
->loc_block_len
;
4500 extra
->sid
[0].loc_node_len
=
4501 attr
->srv6_l3vpn
->loc_node_len
;
4502 extra
->sid
[0].func_len
=
4503 attr
->srv6_l3vpn
->func_len
;
4504 extra
->sid
[0].arg_len
=
4505 attr
->srv6_l3vpn
->arg_len
;
4506 extra
->sid
[0].transposition_len
=
4508 ->transposition_len
;
4509 extra
->sid
[0].transposition_offset
=
4511 ->transposition_offset
;
4514 } else if (attr
->srv6_vpn
) {
4515 extra
= bgp_path_info_extra_get(pi
);
4516 if (sid_diff(&extra
->sid
[0].sid
,
4517 &attr
->srv6_vpn
->sid
)) {
4518 sid_copy(&extra
->sid
[0].sid
,
4519 &attr
->srv6_vpn
->sid
);
4520 extra
->num_sids
= 1;
4524 #ifdef ENABLE_BGP_VNC
4525 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4526 && (safi
== SAFI_UNICAST
)) {
4527 if (vnc_implicit_withdraw
) {
4529 * Add back the route with its new attributes
4531 * The route is still selected, until the route
4533 * queued by bgp_process actually runs. We have
4535 * update to the VNC side immediately to avoid
4537 * configuration changes (e.g., route-map
4539 * trigger re-importation of the entire RIB.
4541 vnc_import_bgp_add_route(bgp
, p
, pi
);
4542 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4547 /* Update bgp route dampening information. */
4548 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4549 && peer
->sort
== BGP_PEER_EBGP
) {
4550 /* Now we do normal update dampening. */
4551 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4552 if (ret
== BGP_DAMP_SUPPRESSED
) {
4553 bgp_dest_unlock_node(dest
);
4558 /* Nexthop reachability check - for unicast and
4559 * labeled-unicast.. */
4560 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4561 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4562 || (safi
== SAFI_EVPN
&&
4563 bgp_evpn_is_prefix_nht_supported(p
))) {
4564 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4565 && peer
->ttl
== BGP_DEFAULT_TTL
4566 && !CHECK_FLAG(peer
->flags
,
4567 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4568 && !CHECK_FLAG(bgp
->flags
,
4569 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4574 struct bgp
*bgp_nexthop
= bgp
;
4576 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4577 bgp_nexthop
= pi
->extra
->bgp_orig
;
4579 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4581 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4582 safi
, pi
, NULL
, connected
,
4583 bgp_nht_param_prefix
) ||
4584 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4585 bgp_path_info_set_flag(dest
, pi
,
4588 if (BGP_DEBUG(nht
, NHT
)) {
4589 zlog_debug("%s(%pI4): NH unresolved",
4591 (in_addr_t
*)&attr_new
->nexthop
);
4593 bgp_path_info_unset_flag(dest
, pi
,
4598 bgp_path_info_set_flag(dest
, pi
,
4599 BGP_PATH_ACCEPT_OWN
);
4601 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4604 #ifdef ENABLE_BGP_VNC
4605 if (safi
== SAFI_MPLS_VPN
) {
4606 struct bgp_dest
*pdest
= NULL
;
4607 struct bgp_table
*table
= NULL
;
4609 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4610 (struct prefix
*)prd
);
4611 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4612 table
= bgp_dest_get_bgp_table_info(pdest
);
4614 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4615 bgp
, prd
, table
, p
, pi
);
4617 bgp_dest_unlock_node(pdest
);
4621 /* If this is an EVPN route and some attribute has changed,
4622 * or we are explicitly told to perform a route import, process
4623 * route for import. If the extended community has changed, we
4625 * have done the un-import earlier and the import would result
4627 * route getting injected into appropriate L2 VNIs. If it is
4629 * some other attribute change, the import will result in
4631 * the attributes for the route in the VNI(s).
4633 if (safi
== SAFI_EVPN
&&
4634 (!same_attr
|| force_evpn_import
) &&
4635 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4636 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4638 /* Process change. */
4639 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4641 bgp_process(bgp
, dest
, afi
, safi
);
4642 bgp_dest_unlock_node(dest
);
4644 if (SAFI_UNICAST
== safi
4645 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4646 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4648 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4650 if ((SAFI_MPLS_VPN
== safi
)
4651 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4652 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4655 #ifdef ENABLE_BGP_VNC
4656 if (SAFI_MPLS_VPN
== safi
) {
4657 mpls_label_t label_decoded
= decode_label(label
);
4659 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4660 type
, sub_type
, &label_decoded
);
4662 if (SAFI_ENCAP
== safi
) {
4663 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4664 type
, sub_type
, NULL
);
4667 if ((safi
== SAFI_MPLS_VPN
) &&
4668 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4669 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4671 bgp_unlink_nexthop(pi
);
4672 bgp_path_info_delete(dest
, pi
);
4675 } // End of implicit withdraw
4677 /* Received Logging. */
4678 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4679 if (!peer
->rcvd_attr_printed
) {
4680 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4681 peer
->rcvd_attr_str
);
4682 peer
->rcvd_attr_printed
= 1;
4685 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4686 addpath_id
? 1 : 0, addpath_id
, evpn
,
4687 pfx_buf
, sizeof(pfx_buf
));
4688 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4691 /* Make new BGP info. */
4692 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4694 /* Update MPLS label */
4695 if (has_valid_label
) {
4696 extra
= bgp_path_info_extra_get(new);
4697 if (extra
->label
!= label
) {
4698 memcpy(&extra
->label
, label
,
4699 num_labels
* sizeof(mpls_label_t
));
4700 extra
->num_labels
= num_labels
;
4702 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4703 bgp_set_valid_label(&extra
->label
[0]);
4706 /* Update SRv6 SID */
4707 if (safi
== SAFI_MPLS_VPN
) {
4708 extra
= bgp_path_info_extra_get(new);
4709 if (attr
->srv6_l3vpn
) {
4710 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4711 extra
->num_sids
= 1;
4713 extra
->sid
[0].loc_block_len
=
4714 attr
->srv6_l3vpn
->loc_block_len
;
4715 extra
->sid
[0].loc_node_len
=
4716 attr
->srv6_l3vpn
->loc_node_len
;
4717 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4718 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4719 extra
->sid
[0].transposition_len
=
4720 attr
->srv6_l3vpn
->transposition_len
;
4721 extra
->sid
[0].transposition_offset
=
4722 attr
->srv6_l3vpn
->transposition_offset
;
4723 } else if (attr
->srv6_vpn
) {
4724 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4725 extra
->num_sids
= 1;
4729 /* Nexthop reachability check. */
4730 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4731 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4732 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4733 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4734 && peer
->ttl
== BGP_DEFAULT_TTL
4735 && !CHECK_FLAG(peer
->flags
,
4736 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4737 && !CHECK_FLAG(bgp
->flags
,
4738 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4743 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4745 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4746 connected
, bgp_nht_param_prefix
) ||
4747 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4748 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4750 if (BGP_DEBUG(nht
, NHT
))
4751 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4752 &attr_new
->nexthop
);
4753 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4757 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4759 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4762 /* If maximum prefix count is configured and current prefix
4765 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4766 reason
= "maximum-prefix overflow";
4767 bgp_attr_flush(&new_attr
);
4772 new->addpath_rx_id
= addpath_id
;
4774 /* Increment prefix */
4775 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4777 /* Register new BGP information. */
4778 bgp_path_info_add(dest
, new);
4780 /* route_node_get lock */
4781 bgp_dest_unlock_node(dest
);
4783 #ifdef ENABLE_BGP_VNC
4784 if (safi
== SAFI_MPLS_VPN
) {
4785 struct bgp_dest
*pdest
= NULL
;
4786 struct bgp_table
*table
= NULL
;
4788 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4789 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4790 table
= bgp_dest_get_bgp_table_info(pdest
);
4792 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4793 bgp
, prd
, table
, p
, new);
4795 bgp_dest_unlock_node(pdest
);
4799 /* If this is an EVPN route, process for import. */
4800 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4801 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4803 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4805 /* Process change. */
4806 bgp_process(bgp
, dest
, afi
, safi
);
4808 if (SAFI_UNICAST
== safi
4809 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4810 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4811 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4813 if ((SAFI_MPLS_VPN
== safi
)
4814 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4815 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4817 #ifdef ENABLE_BGP_VNC
4818 if (SAFI_MPLS_VPN
== safi
) {
4819 mpls_label_t label_decoded
= decode_label(label
);
4821 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4822 sub_type
, &label_decoded
);
4824 if (SAFI_ENCAP
== safi
) {
4825 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4829 if ((safi
== SAFI_MPLS_VPN
) &&
4830 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4831 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4833 bgp_unlink_nexthop(new);
4834 bgp_path_info_delete(dest
, new);
4839 /* This BGP update is filtered. Log the reason then update BGP
4843 bgp_unlink_nexthop(new);
4844 bgp_path_info_delete(dest
, new);
4845 bgp_path_info_extra_free(&new->extra
);
4846 XFREE(MTYPE_BGP_ROUTE
, new);
4849 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4851 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4852 if (!peer
->rcvd_attr_printed
) {
4853 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4854 peer
->rcvd_attr_str
);
4855 peer
->rcvd_attr_printed
= 1;
4858 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4859 addpath_id
? 1 : 0, addpath_id
, evpn
,
4860 pfx_buf
, sizeof(pfx_buf
));
4861 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4862 peer
, pfx_buf
, reason
);
4866 /* If this is an EVPN route, un-import it as it is now filtered.
4868 if (safi
== SAFI_EVPN
)
4869 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4871 if (SAFI_UNICAST
== safi
4872 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4873 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4875 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4877 if ((SAFI_MPLS_VPN
== safi
)
4878 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4880 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4883 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4886 bgp_dest_unlock_node(dest
);
4888 #ifdef ENABLE_BGP_VNC
4890 * Filtered update is treated as an implicit withdrawal (see
4892 * a few lines above)
4894 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4895 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4903 void bgp_withdraw(struct peer
*peer
, const struct prefix
*p
,
4904 uint32_t addpath_id
, struct attr
*attr
, afi_t afi
,
4905 safi_t safi
, int type
, int sub_type
, struct prefix_rd
*prd
,
4906 mpls_label_t
*label
, uint32_t num_labels
,
4907 struct bgp_route_evpn
*evpn
)
4910 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4911 struct bgp_dest
*dest
;
4912 struct bgp_path_info
*pi
;
4914 #ifdef ENABLE_BGP_VNC
4915 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4916 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4924 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4926 /* If peer is soft reconfiguration enabled. Record input packet for
4927 * further calculation.
4929 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4930 * routes that are filtered. This tanks out Quagga RS pretty badly due
4932 * the iteration over all RS clients.
4933 * Since we need to remove the entry from adj_in anyway, do that first
4935 * if there was no entry, we don't need to do anything more.
4937 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4938 && peer
!= bgp
->peer_self
)
4939 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4940 peer
->stat_pfx_dup_withdraw
++;
4942 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4943 bgp_debug_rdpfxpath2str(
4944 afi
, safi
, prd
, p
, label
, num_labels
,
4945 addpath_id
? 1 : 0, addpath_id
, NULL
,
4946 pfx_buf
, sizeof(pfx_buf
));
4948 "%s withdrawing route %s not in adj-in",
4949 peer
->host
, pfx_buf
);
4951 bgp_dest_unlock_node(dest
);
4955 /* Lookup withdrawn route. */
4956 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4957 if (pi
->peer
== peer
&& pi
->type
== type
4958 && pi
->sub_type
== sub_type
4959 && pi
->addpath_rx_id
== addpath_id
)
4963 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4964 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4965 addpath_id
? 1 : 0, addpath_id
, NULL
,
4966 pfx_buf
, sizeof(pfx_buf
));
4967 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
4971 /* Withdraw specified route from routing table. */
4972 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4973 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4974 if (SAFI_UNICAST
== safi
4975 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4976 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4977 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4979 if ((SAFI_MPLS_VPN
== safi
)
4980 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4982 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4984 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4985 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4986 addpath_id
? 1 : 0, addpath_id
, NULL
,
4987 pfx_buf
, sizeof(pfx_buf
));
4988 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4991 /* Unlock bgp_node_get() lock. */
4992 bgp_dest_unlock_node(dest
);
4997 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
5000 struct update_subgroup
*subgrp
;
5001 subgrp
= peer_subgroup(peer
, afi
, safi
);
5002 subgroup_default_originate(subgrp
, withdraw
);
5007 * bgp_stop_announce_route_timer
5009 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5011 if (!paf
->t_announce_route
)
5014 THREAD_OFF(paf
->t_announce_route
);
5018 * bgp_announce_route_timer_expired
5020 * Callback that is invoked when the route announcement timer for a
5023 static void bgp_announce_route_timer_expired(struct thread
*t
)
5025 struct peer_af
*paf
;
5028 paf
= THREAD_ARG(t
);
5031 if (!peer_established(peer
))
5034 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5037 peer_af_announce_route(paf
, 1);
5039 /* Notify BGP conditional advertisement scanner percess */
5040 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5044 * bgp_announce_route
5046 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5048 * if force is true we will force an update even if the update
5049 * limiting code is attempted to kick in.
5051 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5053 struct peer_af
*paf
;
5054 struct update_subgroup
*subgrp
;
5056 paf
= peer_af_find(peer
, afi
, safi
);
5059 subgrp
= PAF_SUBGRP(paf
);
5062 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5063 * or a refresh has already been triggered.
5065 if (!subgrp
|| paf
->t_announce_route
)
5069 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5072 * Start a timer to stagger/delay the announce. This serves
5073 * two purposes - announcement can potentially be combined for
5074 * multiple peers and the announcement doesn't happen in the
5077 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5078 (subgrp
->peer_count
== 1)
5079 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5080 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5081 &paf
->t_announce_route
);
5085 * Announce routes from all AF tables to a peer.
5087 * This should ONLY be called when there is a need to refresh the
5088 * routes to the peer based on a policy change for this peer alone
5089 * or a route refresh request received from the peer.
5090 * The operation will result in splitting the peer from its existing
5091 * subgroups and putting it in new subgroups.
5093 void bgp_announce_route_all(struct peer
*peer
)
5098 FOREACH_AFI_SAFI (afi
, safi
)
5099 bgp_announce_route(peer
, afi
, safi
, false);
5102 /* Flag or unflag bgp_dest to determine whether it should be treated by
5103 * bgp_soft_reconfig_table_task.
5104 * Flag if flag is true. Unflag if flag is false.
5106 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5108 struct bgp_dest
*dest
;
5109 struct bgp_adj_in
*ain
;
5114 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5115 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5116 if (ain
->peer
!= NULL
)
5119 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5120 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5122 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5126 static void bgp_soft_reconfig_table_update(struct peer
*peer
,
5127 struct bgp_dest
*dest
,
5128 struct bgp_adj_in
*ain
, afi_t afi
,
5129 safi_t safi
, struct prefix_rd
*prd
)
5131 struct bgp_path_info
*pi
;
5132 uint32_t num_labels
= 0;
5133 mpls_label_t
*label_pnt
= NULL
;
5134 struct bgp_route_evpn evpn
;
5136 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5137 if (pi
->peer
== peer
)
5140 if (pi
&& pi
->extra
)
5141 num_labels
= pi
->extra
->num_labels
;
5143 label_pnt
= &pi
->extra
->label
[0];
5145 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5148 memset(&evpn
, 0, sizeof(evpn
));
5150 bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5151 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, prd
,
5152 label_pnt
, num_labels
, 1, &evpn
);
5155 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5156 struct bgp_table
*table
,
5157 struct prefix_rd
*prd
)
5159 struct bgp_dest
*dest
;
5160 struct bgp_adj_in
*ain
;
5163 table
= peer
->bgp
->rib
[afi
][safi
];
5165 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5166 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5167 if (ain
->peer
!= peer
)
5170 bgp_soft_reconfig_table_update(peer
, dest
, ain
, afi
,
5175 /* Do soft reconfig table per bgp table.
5176 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5177 * when BGP_NODE_SOFT_RECONFIG is set,
5178 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5179 * Schedule a new thread to continue the job.
5180 * Without splitting the full job into several part,
5181 * vtysh waits for the job to finish before responding to a BGP command
5183 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
5185 uint32_t iter
, max_iter
;
5186 struct bgp_dest
*dest
;
5187 struct bgp_adj_in
*ain
;
5189 struct bgp_table
*table
;
5190 struct prefix_rd
*prd
;
5191 struct listnode
*node
, *nnode
;
5193 table
= THREAD_ARG(thread
);
5196 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5197 if (table
->soft_reconfig_init
) {
5198 /* first call of the function with a new srta structure.
5199 * Don't do any treatment this time on nodes
5200 * in order vtysh to respond quickly
5205 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5206 dest
= bgp_route_next(dest
)) {
5207 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5210 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5212 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5213 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5215 if (ain
->peer
!= peer
)
5218 bgp_soft_reconfig_table_update(
5219 peer
, dest
, ain
, table
->afi
,
5226 /* we're either starting the initial iteration,
5227 * or we're going to continue an ongoing iteration
5229 if (dest
|| table
->soft_reconfig_init
) {
5230 table
->soft_reconfig_init
= false;
5231 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
5232 table
, 0, &table
->soft_reconfig_thread
);
5235 /* we're done, clean up the background iteration context info and
5236 schedule route annoucement
5238 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5239 listnode_delete(table
->soft_reconfig_peers
, peer
);
5240 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5243 list_delete(&table
->soft_reconfig_peers
);
5247 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5249 * - bgp cannot be NULL
5250 * - if table and peer are NULL, cancel all threads within the bgp instance
5251 * - if table is NULL and peer is not,
5252 * remove peer in all threads within the bgp instance
5253 * - if peer is NULL, cancel all threads matching table within the bgp instance
5255 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5256 const struct bgp_table
*table
,
5257 const struct peer
*peer
)
5260 struct listnode
*node
, *nnode
;
5262 struct bgp_table
*ntable
;
5267 FOREACH_AFI_SAFI (afi
, safi
) {
5268 ntable
= bgp
->rib
[afi
][safi
];
5271 if (table
&& table
!= ntable
)
5274 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5276 if (peer
&& peer
!= npeer
)
5278 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5281 if (!ntable
->soft_reconfig_peers
5282 || !list_isempty(ntable
->soft_reconfig_peers
))
5285 list_delete(&ntable
->soft_reconfig_peers
);
5286 bgp_soft_reconfig_table_flag(ntable
, false);
5287 THREAD_OFF(ntable
->soft_reconfig_thread
);
5292 * Returns false if the peer is not configured for soft reconfig in
5294 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5296 struct bgp_dest
*dest
;
5297 struct bgp_table
*table
;
5298 struct listnode
*node
, *nnode
;
5300 struct peer_af
*paf
;
5302 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5305 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5306 && (safi
!= SAFI_EVPN
)) {
5307 table
= peer
->bgp
->rib
[afi
][safi
];
5311 table
->soft_reconfig_init
= true;
5313 if (!table
->soft_reconfig_peers
)
5314 table
->soft_reconfig_peers
= list_new();
5316 /* add peer to the table soft_reconfig_peers if not already
5319 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5325 listnode_add(table
->soft_reconfig_peers
, peer
);
5327 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5328 * on table would start back at the beginning.
5330 bgp_soft_reconfig_table_flag(table
, true);
5332 if (!table
->soft_reconfig_thread
)
5333 thread_add_event(bm
->master
,
5334 bgp_soft_reconfig_table_task
, table
, 0,
5335 &table
->soft_reconfig_thread
);
5336 /* Cancel bgp_announce_route_timer_expired threads.
5337 * bgp_announce_route_timer_expired threads have been scheduled
5338 * to announce routes as soon as the soft_reconfigure process
5340 * In this case, soft_reconfigure is also scheduled by using
5341 * a thread but is planned after the
5342 * bgp_announce_route_timer_expired threads. It means that,
5343 * without cancelling the threads, the route announcement task
5344 * would run before the soft reconfiguration one. That would
5345 * useless and would block vtysh during several seconds. Route
5346 * announcements are rescheduled as soon as the soft_reconfigure
5349 paf
= peer_af_find(peer
, afi
, safi
);
5351 bgp_stop_announce_route_timer(paf
);
5353 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5354 dest
= bgp_route_next(dest
)) {
5355 table
= bgp_dest_get_bgp_table_info(dest
);
5360 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5361 struct prefix_rd prd
;
5363 prd
.family
= AF_UNSPEC
;
5365 memcpy(&prd
.val
, p
->u
.val
, 8);
5367 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5374 struct bgp_clear_node_queue
{
5375 struct bgp_dest
*dest
;
5378 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5380 struct bgp_clear_node_queue
*cnq
= data
;
5381 struct bgp_dest
*dest
= cnq
->dest
;
5382 struct peer
*peer
= wq
->spec
.data
;
5383 struct bgp_path_info
*pi
;
5385 afi_t afi
= bgp_dest_table(dest
)->afi
;
5386 safi_t safi
= bgp_dest_table(dest
)->safi
;
5388 assert(dest
&& peer
);
5391 /* It is possible that we have multiple paths for a prefix from a peer
5392 * if that peer is using AddPath.
5394 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5395 if (pi
->peer
!= peer
)
5398 /* graceful restart STALE flag set. */
5399 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5400 && peer
->nsf
[afi
][safi
])
5401 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5402 PEER_STATUS_ENHANCED_REFRESH
))
5403 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5404 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5405 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5407 /* If this is an EVPN route, process for
5409 if (safi
== SAFI_EVPN
)
5410 bgp_evpn_unimport_route(
5412 bgp_dest_get_prefix(dest
), pi
);
5413 /* Handle withdraw for VRF route-leaking and L3VPN */
5414 if (SAFI_UNICAST
== safi
5415 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5416 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5417 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5420 if (SAFI_MPLS_VPN
== safi
&&
5421 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5422 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5425 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5431 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5433 struct bgp_clear_node_queue
*cnq
= data
;
5434 struct bgp_dest
*dest
= cnq
->dest
;
5435 struct bgp_table
*table
= bgp_dest_table(dest
);
5437 bgp_dest_unlock_node(dest
);
5438 bgp_table_unlock(table
);
5439 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5442 static void bgp_clear_node_complete(struct work_queue
*wq
)
5444 struct peer
*peer
= wq
->spec
.data
;
5446 /* Tickle FSM to start moving again */
5447 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5449 peer_unlock(peer
); /* bgp_clear_route */
5452 static void bgp_clear_node_queue_init(struct peer
*peer
)
5454 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5456 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5457 #undef CLEAR_QUEUE_NAME_LEN
5459 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5460 peer
->clear_node_queue
->spec
.hold
= 10;
5461 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5462 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5463 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5464 peer
->clear_node_queue
->spec
.max_retries
= 0;
5466 /* we only 'lock' this peer reference when the queue is actually active
5468 peer
->clear_node_queue
->spec
.data
= peer
;
5471 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5472 struct bgp_table
*table
)
5474 struct bgp_dest
*dest
;
5475 int force
= peer
->bgp
->process_queue
? 0 : 1;
5478 table
= peer
->bgp
->rib
[afi
][safi
];
5480 /* If still no table => afi/safi isn't configured at all or smth. */
5484 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5485 struct bgp_path_info
*pi
, *next
;
5486 struct bgp_adj_in
*ain
;
5487 struct bgp_adj_in
*ain_next
;
5489 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5490 * queued for every clearing peer, regardless of whether it is
5491 * relevant to the peer at hand.
5493 * Overview: There are 3 different indices which need to be
5494 * scrubbed, potentially, when a peer is removed:
5496 * 1 peer's routes visible via the RIB (ie accepted routes)
5497 * 2 peer's routes visible by the (optional) peer's adj-in index
5498 * 3 other routes visible by the peer's adj-out index
5500 * 3 there is no hurry in scrubbing, once the struct peer is
5501 * removed from bgp->peer, we could just GC such deleted peer's
5502 * adj-outs at our leisure.
5504 * 1 and 2 must be 'scrubbed' in some way, at least made
5505 * invisible via RIB index before peer session is allowed to be
5506 * brought back up. So one needs to know when such a 'search' is
5511 * - there'd be a single global queue or a single RIB walker
5512 * - rather than tracking which route_nodes still need to be
5513 * examined on a peer basis, we'd track which peers still
5516 * Given that our per-peer prefix-counts now should be reliable,
5517 * this may actually be achievable. It doesn't seem to be a huge
5518 * problem at this time,
5520 * It is possible that we have multiple paths for a prefix from
5522 * if that peer is using AddPath.
5526 ain_next
= ain
->next
;
5528 if (ain
->peer
== peer
)
5529 bgp_adj_in_remove(dest
, ain
);
5534 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5536 if (pi
->peer
!= peer
)
5540 bgp_path_info_reap(dest
, pi
);
5542 struct bgp_clear_node_queue
*cnq
;
5544 /* both unlocked in bgp_clear_node_queue_del */
5545 bgp_table_lock(bgp_dest_table(dest
));
5546 bgp_dest_lock_node(dest
);
5548 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5549 sizeof(struct bgp_clear_node_queue
));
5551 work_queue_add(peer
->clear_node_queue
, cnq
);
5559 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5561 struct bgp_dest
*dest
;
5562 struct bgp_table
*table
;
5564 if (peer
->clear_node_queue
== NULL
)
5565 bgp_clear_node_queue_init(peer
);
5567 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5568 * Idle until it receives a Clearing_Completed event. This protects
5569 * against peers which flap faster than we can we clear, which could
5572 * a) race with routes from the new session being installed before
5573 * clear_route_node visits the node (to delete the route of that
5575 * b) resource exhaustion, clear_route_node likely leads to an entry
5576 * on the process_main queue. Fast-flapping could cause that queue
5580 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5581 * the unlock will happen upon work-queue completion; other wise, the
5582 * unlock happens at the end of this function.
5584 if (!peer
->clear_node_queue
->thread
)
5587 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5588 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5590 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5591 dest
= bgp_route_next(dest
)) {
5592 table
= bgp_dest_get_bgp_table_info(dest
);
5596 bgp_clear_route_table(peer
, afi
, safi
, table
);
5599 /* unlock if no nodes got added to the clear-node-queue. */
5600 if (!peer
->clear_node_queue
->thread
)
5604 void bgp_clear_route_all(struct peer
*peer
)
5609 FOREACH_AFI_SAFI (afi
, safi
)
5610 bgp_clear_route(peer
, afi
, safi
);
5612 #ifdef ENABLE_BGP_VNC
5613 rfapiProcessPeerDown(peer
);
5617 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5619 struct bgp_table
*table
;
5620 struct bgp_dest
*dest
;
5621 struct bgp_adj_in
*ain
;
5622 struct bgp_adj_in
*ain_next
;
5624 table
= peer
->bgp
->rib
[afi
][safi
];
5626 /* It is possible that we have multiple paths for a prefix from a peer
5627 * if that peer is using AddPath.
5629 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5633 ain_next
= ain
->next
;
5635 if (ain
->peer
== peer
)
5636 bgp_adj_in_remove(dest
, ain
);
5643 /* If any of the routes from the peer have been marked with the NO_LLGR
5644 * community, either as sent by the peer, or as the result of a configured
5645 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5646 * operation of [RFC4271].
5648 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5650 struct bgp_dest
*dest
;
5651 struct bgp_path_info
*pi
;
5652 struct bgp_table
*table
;
5654 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5655 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5656 dest
= bgp_route_next(dest
)) {
5657 struct bgp_dest
*rm
;
5659 /* look for neighbor in tables */
5660 table
= bgp_dest_get_bgp_table_info(dest
);
5664 for (rm
= bgp_table_top(table
); rm
;
5665 rm
= bgp_route_next(rm
))
5666 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5668 if (pi
->peer
!= peer
)
5671 peer
->af_sflags
[afi
][safi
],
5672 PEER_STATUS_LLGR_WAIT
) &&
5673 bgp_attr_get_community(pi
->attr
) &&
5675 bgp_attr_get_community(
5679 if (!CHECK_FLAG(pi
->flags
,
5684 * If this is VRF leaked route
5685 * process for withdraw.
5688 BGP_ROUTE_IMPORTED
&&
5689 peer
->bgp
->inst_type
==
5690 BGP_INSTANCE_TYPE_DEFAULT
)
5691 vpn_leak_to_vrf_withdraw(
5694 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5699 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5700 dest
= bgp_route_next(dest
))
5701 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5703 if (pi
->peer
!= peer
)
5705 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5706 PEER_STATUS_LLGR_WAIT
) &&
5707 bgp_attr_get_community(pi
->attr
) &&
5709 bgp_attr_get_community(pi
->attr
),
5712 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5714 if (safi
== SAFI_UNICAST
&&
5715 (peer
->bgp
->inst_type
==
5716 BGP_INSTANCE_TYPE_VRF
||
5717 peer
->bgp
->inst_type
==
5718 BGP_INSTANCE_TYPE_DEFAULT
))
5719 vpn_leak_from_vrf_withdraw(
5720 bgp_get_default(), peer
->bgp
,
5723 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5729 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5731 struct bgp_dest
*dest
, *ndest
;
5732 struct bgp_path_info
*pi
;
5733 struct bgp_table
*table
;
5735 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5736 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5737 dest
= bgp_route_next(dest
)) {
5738 table
= bgp_dest_get_bgp_table_info(dest
);
5742 for (ndest
= bgp_table_top(table
); ndest
;
5743 ndest
= bgp_route_next(ndest
)) {
5744 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5746 if (pi
->peer
!= peer
)
5750 peer
->af_sflags
[afi
][safi
],
5751 PEER_STATUS_ENHANCED_REFRESH
))
5752 && !CHECK_FLAG(pi
->flags
,
5756 BGP_PATH_UNUSEABLE
)) {
5757 if (bgp_debug_neighbor_events(
5760 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5764 bgp_dest_get_prefix(
5767 bgp_path_info_set_flag(
5775 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5776 dest
= bgp_route_next(dest
)) {
5777 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5779 if (pi
->peer
!= peer
)
5782 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5783 PEER_STATUS_ENHANCED_REFRESH
))
5784 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5785 && !CHECK_FLAG(pi
->flags
,
5786 BGP_PATH_UNUSEABLE
)) {
5787 if (bgp_debug_neighbor_events(peer
))
5789 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5792 bgp_dest_get_prefix(
5795 bgp_path_info_set_flag(dest
, pi
,
5803 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5805 if (peer
->sort
== BGP_PEER_IBGP
)
5808 if (peer
->sort
== BGP_PEER_EBGP
5809 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5810 || FILTER_LIST_OUT_NAME(filter
)
5811 || DISTRIBUTE_OUT_NAME(filter
)))
5816 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5818 if (peer
->sort
== BGP_PEER_IBGP
)
5821 if (peer
->sort
== BGP_PEER_EBGP
5822 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5823 || FILTER_LIST_IN_NAME(filter
)
5824 || DISTRIBUTE_IN_NAME(filter
)))
5829 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5832 struct bgp_dest
*dest
;
5833 struct bgp_path_info
*pi
;
5834 struct bgp_path_info
*next
;
5836 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5837 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5838 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5842 /* Unimport EVPN routes from VRFs */
5843 if (safi
== SAFI_EVPN
)
5844 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5847 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5848 && pi
->type
== ZEBRA_ROUTE_BGP
5849 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5850 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5851 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5853 if (bgp_fibupd_safi(safi
))
5854 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5857 bgp_path_info_reap(dest
, pi
);
5861 /* Delete all kernel routes. */
5862 void bgp_cleanup_routes(struct bgp
*bgp
)
5865 struct bgp_dest
*dest
;
5866 struct bgp_table
*table
;
5868 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5869 if (afi
== AFI_L2VPN
)
5871 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5874 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5876 if (afi
!= AFI_L2VPN
) {
5878 safi
= SAFI_MPLS_VPN
;
5879 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5880 dest
= bgp_route_next(dest
)) {
5881 table
= bgp_dest_get_bgp_table_info(dest
);
5882 if (table
!= NULL
) {
5883 bgp_cleanup_table(bgp
, table
, safi
);
5884 bgp_table_finish(&table
);
5885 bgp_dest_set_bgp_table_info(dest
, NULL
);
5886 bgp_dest_unlock_node(dest
);
5890 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5891 dest
= bgp_route_next(dest
)) {
5892 table
= bgp_dest_get_bgp_table_info(dest
);
5893 if (table
!= NULL
) {
5894 bgp_cleanup_table(bgp
, table
, safi
);
5895 bgp_table_finish(&table
);
5896 bgp_dest_set_bgp_table_info(dest
, NULL
);
5897 bgp_dest_unlock_node(dest
);
5902 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5903 dest
= bgp_route_next(dest
)) {
5904 table
= bgp_dest_get_bgp_table_info(dest
);
5905 if (table
!= NULL
) {
5906 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5907 bgp_table_finish(&table
);
5908 bgp_dest_set_bgp_table_info(dest
, NULL
);
5909 bgp_dest_unlock_node(dest
);
5914 void bgp_reset(void)
5917 bgp_zclient_reset();
5918 access_list_reset();
5919 prefix_list_reset();
5922 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5924 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5925 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5926 PEER_CAP_ADDPATH_AF_TX_RCV
));
5929 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5931 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5932 struct bgp_nlri
*packet
)
5940 bool addpath_capable
;
5941 uint32_t addpath_id
;
5944 lim
= pnt
+ packet
->length
;
5946 safi
= packet
->safi
;
5948 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5950 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5951 syntactic validity. If the field is syntactically incorrect,
5952 then the Error Subcode is set to Invalid Network Field. */
5953 for (; pnt
< lim
; pnt
+= psize
) {
5954 /* Clear prefix structure. */
5955 memset(&p
, 0, sizeof(p
));
5957 if (addpath_capable
) {
5959 /* When packet overflow occurs return immediately. */
5960 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5961 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5963 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5964 addpath_id
= ntohl(addpath_id
);
5965 pnt
+= BGP_ADDPATH_ID_LEN
;
5968 /* Fetch prefix length. */
5969 p
.prefixlen
= *pnt
++;
5970 /* afi/safi validity already verified by caller,
5971 * bgp_update_receive */
5972 p
.family
= afi2family(afi
);
5974 /* Prefix length check. */
5975 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5978 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5979 peer
->host
, p
.prefixlen
, packet
->afi
);
5980 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5983 /* Packet size overflow check. */
5984 psize
= PSIZE(p
.prefixlen
);
5986 /* When packet overflow occur return immediately. */
5987 if (pnt
+ psize
> lim
) {
5990 "%s [Error] Update packet error (prefix length %d overflows packet)",
5991 peer
->host
, p
.prefixlen
);
5992 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5995 /* Defensive coding, double-check the psize fits in a struct
5996 * prefix for the v4 and v6 afi's and unicast/multicast */
5997 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6000 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6001 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6002 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6005 /* Fetch prefix from NLRI packet. */
6006 memcpy(p
.u
.val
, pnt
, psize
);
6008 /* Check address. */
6009 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6010 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6011 /* From RFC4271 Section 6.3:
6013 * If a prefix in the NLRI field is semantically
6015 * (e.g., an unexpected multicast IP address),
6017 * be logged locally, and the prefix SHOULD be
6022 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6023 peer
->host
, &p
.u
.prefix4
);
6028 /* Check address. */
6029 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6030 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6033 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6034 peer
->host
, &p
.u
.prefix6
);
6038 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6041 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6042 peer
->host
, &p
.u
.prefix6
);
6048 /* Normal process. */
6050 bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6051 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6054 bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6055 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6058 /* Do not send BGP notification twice when maximum-prefix count
6060 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6061 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6064 /* Packet length consistency check. */
6068 "%s [Error] Update packet error (prefix length mismatch with total length)",
6070 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6073 return BGP_NLRI_PARSE_OK
;
6076 static struct bgp_static
*bgp_static_new(void)
6078 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6081 static void bgp_static_free(struct bgp_static
*bgp_static
)
6083 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6084 route_map_counter_decrement(bgp_static
->rmap
.map
);
6086 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6087 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6090 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6091 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6093 struct bgp_dest
*dest
;
6094 struct bgp_path_info
*pi
;
6095 struct bgp_path_info
*new;
6096 struct bgp_path_info rmap_path
;
6098 struct attr
*attr_new
;
6099 route_map_result_t ret
;
6100 #ifdef ENABLE_BGP_VNC
6101 int vnc_implicit_withdraw
= 0;
6106 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6108 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6110 attr
.nexthop
= bgp_static
->igpnexthop
;
6111 attr
.med
= bgp_static
->igpmetric
;
6112 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6115 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6117 if (bgp_static
->igpmetric
)
6118 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6120 if (bgp_static
->atomic
)
6121 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6123 /* Store label index, if required. */
6124 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6125 attr
.label_index
= bgp_static
->label_index
;
6126 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6129 /* Apply route-map. */
6130 if (bgp_static
->rmap
.name
) {
6131 struct attr attr_tmp
= attr
;
6133 memset(&rmap_path
, 0, sizeof(rmap_path
));
6134 rmap_path
.peer
= bgp
->peer_self
;
6135 rmap_path
.attr
= &attr_tmp
;
6137 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6139 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6141 bgp
->peer_self
->rmap_type
= 0;
6143 if (ret
== RMAP_DENYMATCH
) {
6144 /* Free uninterned attribute. */
6145 bgp_attr_flush(&attr_tmp
);
6147 /* Unintern original. */
6148 aspath_unintern(&attr
.aspath
);
6149 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6150 bgp_dest_unlock_node(dest
);
6154 if (bgp_in_graceful_shutdown(bgp
))
6155 bgp_attr_add_gshut_community(&attr_tmp
);
6157 attr_new
= bgp_attr_intern(&attr_tmp
);
6160 if (bgp_in_graceful_shutdown(bgp
))
6161 bgp_attr_add_gshut_community(&attr
);
6163 attr_new
= bgp_attr_intern(&attr
);
6166 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6167 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6168 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6172 if (attrhash_cmp(pi
->attr
, attr_new
)
6173 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6174 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6175 bgp_dest_unlock_node(dest
);
6176 bgp_attr_unintern(&attr_new
);
6177 aspath_unintern(&attr
.aspath
);
6180 /* The attribute is changed. */
6181 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6183 /* Rewrite BGP route information. */
6184 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6185 bgp_path_info_restore(dest
, pi
);
6187 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6188 #ifdef ENABLE_BGP_VNC
6189 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6190 && (safi
== SAFI_UNICAST
)) {
6191 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6193 * Implicit withdraw case.
6194 * We have to do this before pi is
6197 ++vnc_implicit_withdraw
;
6198 vnc_import_bgp_del_route(bgp
, p
, pi
);
6199 vnc_import_bgp_exterior_del_route(
6204 bgp_attr_unintern(&pi
->attr
);
6205 pi
->attr
= attr_new
;
6206 pi
->uptime
= monotime(NULL
);
6207 #ifdef ENABLE_BGP_VNC
6208 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6209 && (safi
== SAFI_UNICAST
)) {
6210 if (vnc_implicit_withdraw
) {
6211 vnc_import_bgp_add_route(bgp
, p
, pi
);
6212 vnc_import_bgp_exterior_add_route(
6218 /* Nexthop reachability check. */
6219 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6220 && (safi
== SAFI_UNICAST
6221 || safi
== SAFI_LABELED_UNICAST
)) {
6223 struct bgp
*bgp_nexthop
= bgp
;
6225 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6226 bgp_nexthop
= pi
->extra
->bgp_orig
;
6228 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6229 afi
, safi
, pi
, NULL
,
6231 bgp_path_info_set_flag(dest
, pi
,
6234 if (BGP_DEBUG(nht
, NHT
)) {
6235 char buf1
[INET6_ADDRSTRLEN
];
6236 inet_ntop(p
->family
,
6240 "%s(%s): Route not in table, not advertising",
6243 bgp_path_info_unset_flag(
6244 dest
, pi
, BGP_PATH_VALID
);
6247 /* Delete the NHT structure if any, if we're
6249 * enabling/disabling import check. We
6250 * deregister the route
6251 * from NHT to avoid overloading NHT and the
6252 * process interaction
6254 bgp_unlink_nexthop(pi
);
6255 bgp_path_info_set_flag(dest
, pi
,
6258 /* Process change. */
6259 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6260 bgp_process(bgp
, dest
, afi
, safi
);
6262 if (SAFI_UNICAST
== safi
6263 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6265 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6266 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6270 bgp_dest_unlock_node(dest
);
6271 aspath_unintern(&attr
.aspath
);
6276 /* Make new BGP info. */
6277 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6279 /* Nexthop reachability check. */
6280 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6281 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6282 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6284 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6286 if (BGP_DEBUG(nht
, NHT
)) {
6287 char buf1
[INET6_ADDRSTRLEN
];
6289 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6292 "%s(%s): Route not in table, not advertising",
6295 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6298 /* Delete the NHT structure if any, if we're toggling between
6299 * enabling/disabling import check. We deregister the route
6300 * from NHT to avoid overloading NHT and the process interaction
6302 bgp_unlink_nexthop(new);
6304 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6307 /* Aggregate address increment. */
6308 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6310 /* Register new BGP information. */
6311 bgp_path_info_add(dest
, new);
6313 /* route_node_get lock */
6314 bgp_dest_unlock_node(dest
);
6316 /* Process change. */
6317 bgp_process(bgp
, dest
, afi
, safi
);
6319 if (SAFI_UNICAST
== safi
6320 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6321 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6322 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6325 /* Unintern original. */
6326 aspath_unintern(&attr
.aspath
);
6329 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6332 struct bgp_dest
*dest
;
6333 struct bgp_path_info
*pi
;
6335 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6337 /* Check selected route and self inserted route. */
6338 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6339 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6340 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6343 /* Withdraw static BGP route from routing table. */
6345 if (SAFI_UNICAST
== safi
6346 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6347 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6348 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6350 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6351 bgp_unlink_nexthop(pi
);
6352 bgp_path_info_delete(dest
, pi
);
6353 bgp_process(bgp
, dest
, afi
, safi
);
6356 /* Unlock bgp_node_lookup. */
6357 bgp_dest_unlock_node(dest
);
6361 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6363 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6364 afi_t afi
, safi_t safi
,
6365 struct prefix_rd
*prd
)
6367 struct bgp_dest
*dest
;
6368 struct bgp_path_info
*pi
;
6370 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6372 /* Check selected route and self inserted route. */
6373 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6374 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6375 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6378 /* Withdraw static BGP route from routing table. */
6380 #ifdef ENABLE_BGP_VNC
6381 rfapiProcessWithdraw(
6382 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6383 1); /* Kill, since it is an administrative change */
6385 if (SAFI_MPLS_VPN
== safi
6386 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6387 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6389 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6390 bgp_path_info_delete(dest
, pi
);
6391 bgp_process(bgp
, dest
, afi
, safi
);
6394 /* Unlock bgp_node_lookup. */
6395 bgp_dest_unlock_node(dest
);
6398 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6399 struct bgp_static
*bgp_static
, afi_t afi
,
6402 struct bgp_dest
*dest
;
6403 struct bgp_path_info
*new;
6404 struct attr
*attr_new
;
6405 struct attr attr
= {0};
6406 struct bgp_path_info
*pi
;
6407 #ifdef ENABLE_BGP_VNC
6408 mpls_label_t label
= 0;
6410 uint32_t num_labels
= 0;
6414 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6416 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6419 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6421 attr
.nexthop
= bgp_static
->igpnexthop
;
6422 attr
.med
= bgp_static
->igpmetric
;
6423 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6425 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6426 || (safi
== SAFI_ENCAP
)) {
6427 if (afi
== AFI_IP
) {
6428 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6429 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6432 if (afi
== AFI_L2VPN
) {
6433 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6434 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6435 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6436 &bgp_static
->gatewayIp
.u
.prefix4
,
6438 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6439 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6440 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6441 &bgp_static
->gatewayIp
.u
.prefix6
,
6444 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6445 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6446 struct bgp_encap_type_vxlan bet
;
6447 memset(&bet
, 0, sizeof(bet
));
6448 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6449 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6451 if (bgp_static
->router_mac
) {
6452 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6455 /* Apply route-map. */
6456 if (bgp_static
->rmap
.name
) {
6457 struct attr attr_tmp
= attr
;
6458 struct bgp_path_info rmap_path
;
6459 route_map_result_t ret
;
6461 rmap_path
.peer
= bgp
->peer_self
;
6462 rmap_path
.attr
= &attr_tmp
;
6464 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6466 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6468 bgp
->peer_self
->rmap_type
= 0;
6470 if (ret
== RMAP_DENYMATCH
) {
6471 /* Free uninterned attribute. */
6472 bgp_attr_flush(&attr_tmp
);
6474 /* Unintern original. */
6475 aspath_unintern(&attr
.aspath
);
6476 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6478 bgp_dest_unlock_node(dest
);
6482 attr_new
= bgp_attr_intern(&attr_tmp
);
6484 attr_new
= bgp_attr_intern(&attr
);
6487 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6488 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6489 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6493 if (attrhash_cmp(pi
->attr
, attr_new
)
6494 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6495 bgp_dest_unlock_node(dest
);
6496 bgp_attr_unintern(&attr_new
);
6497 aspath_unintern(&attr
.aspath
);
6500 /* The attribute is changed. */
6501 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6503 /* Rewrite BGP route information. */
6504 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6505 bgp_path_info_restore(dest
, pi
);
6507 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6508 bgp_attr_unintern(&pi
->attr
);
6509 pi
->attr
= attr_new
;
6510 pi
->uptime
= monotime(NULL
);
6511 #ifdef ENABLE_BGP_VNC
6513 label
= decode_label(&pi
->extra
->label
[0]);
6516 /* Process change. */
6517 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6518 bgp_process(bgp
, dest
, afi
, safi
);
6520 if (SAFI_MPLS_VPN
== safi
6521 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6522 vpn_leak_to_vrf_update(bgp
, pi
,
6525 #ifdef ENABLE_BGP_VNC
6526 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6527 pi
->attr
, afi
, safi
, pi
->type
,
6528 pi
->sub_type
, &label
);
6530 bgp_dest_unlock_node(dest
);
6531 aspath_unintern(&attr
.aspath
);
6537 /* Make new BGP info. */
6538 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6540 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6541 bgp_path_info_extra_get(new);
6543 new->extra
->label
[0] = bgp_static
->label
;
6544 new->extra
->num_labels
= num_labels
;
6546 #ifdef ENABLE_BGP_VNC
6547 label
= decode_label(&bgp_static
->label
);
6550 /* Aggregate address increment. */
6551 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6553 /* Register new BGP information. */
6554 bgp_path_info_add(dest
, new);
6555 /* route_node_get lock */
6556 bgp_dest_unlock_node(dest
);
6558 /* Process change. */
6559 bgp_process(bgp
, dest
, afi
, safi
);
6561 if (SAFI_MPLS_VPN
== safi
6562 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6563 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6565 #ifdef ENABLE_BGP_VNC
6566 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6567 safi
, new->type
, new->sub_type
, &label
);
6570 /* Unintern original. */
6571 aspath_unintern(&attr
.aspath
);
6574 /* Configure static BGP network. When user don't run zebra, static
6575 route should be installed as valid. */
6576 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6577 const char *ip_str
, afi_t afi
, safi_t safi
,
6578 const char *rmap
, int backdoor
, uint32_t label_index
)
6580 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6583 struct bgp_static
*bgp_static
;
6584 struct bgp_dest
*dest
;
6585 uint8_t need_update
= 0;
6587 /* Convert IP prefix string to struct prefix. */
6588 ret
= str2prefix(ip_str
, &p
);
6590 vty_out(vty
, "%% Malformed prefix\n");
6591 return CMD_WARNING_CONFIG_FAILED
;
6593 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6594 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6595 return CMD_WARNING_CONFIG_FAILED
;
6602 /* Set BGP static route configuration. */
6603 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6606 vty_out(vty
, "%% Can't find static route specified\n");
6607 return CMD_WARNING_CONFIG_FAILED
;
6610 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6612 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6613 && (label_index
!= bgp_static
->label_index
)) {
6615 "%% label-index doesn't match static route\n");
6616 bgp_dest_unlock_node(dest
);
6617 return CMD_WARNING_CONFIG_FAILED
;
6620 if ((rmap
&& bgp_static
->rmap
.name
)
6621 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6623 "%% route-map name doesn't match static route\n");
6624 bgp_dest_unlock_node(dest
);
6625 return CMD_WARNING_CONFIG_FAILED
;
6628 /* Update BGP RIB. */
6629 if (!bgp_static
->backdoor
)
6630 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6632 /* Clear configuration. */
6633 bgp_static_free(bgp_static
);
6634 bgp_dest_set_bgp_static_info(dest
, NULL
);
6635 bgp_dest_unlock_node(dest
);
6636 bgp_dest_unlock_node(dest
);
6639 /* Set BGP static route configuration. */
6640 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6641 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6643 /* Configuration change. */
6644 /* Label index cannot be changed. */
6645 if (bgp_static
->label_index
!= label_index
) {
6646 vty_out(vty
, "%% cannot change label-index\n");
6647 bgp_dest_unlock_node(dest
);
6648 return CMD_WARNING_CONFIG_FAILED
;
6651 /* Check previous routes are installed into BGP. */
6652 if (bgp_static
->valid
6653 && bgp_static
->backdoor
!= backdoor
)
6656 bgp_static
->backdoor
= backdoor
;
6659 XFREE(MTYPE_ROUTE_MAP_NAME
,
6660 bgp_static
->rmap
.name
);
6661 route_map_counter_decrement(
6662 bgp_static
->rmap
.map
);
6663 bgp_static
->rmap
.name
=
6664 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6665 bgp_static
->rmap
.map
=
6666 route_map_lookup_by_name(rmap
);
6667 route_map_counter_increment(
6668 bgp_static
->rmap
.map
);
6670 XFREE(MTYPE_ROUTE_MAP_NAME
,
6671 bgp_static
->rmap
.name
);
6672 route_map_counter_decrement(
6673 bgp_static
->rmap
.map
);
6674 bgp_static
->rmap
.map
= NULL
;
6675 bgp_static
->valid
= 0;
6677 bgp_dest_unlock_node(dest
);
6679 /* New configuration. */
6680 bgp_static
= bgp_static_new();
6681 bgp_static
->backdoor
= backdoor
;
6682 bgp_static
->valid
= 0;
6683 bgp_static
->igpmetric
= 0;
6684 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6685 bgp_static
->label_index
= label_index
;
6688 XFREE(MTYPE_ROUTE_MAP_NAME
,
6689 bgp_static
->rmap
.name
);
6690 route_map_counter_decrement(
6691 bgp_static
->rmap
.map
);
6692 bgp_static
->rmap
.name
=
6693 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6694 bgp_static
->rmap
.map
=
6695 route_map_lookup_by_name(rmap
);
6696 route_map_counter_increment(
6697 bgp_static
->rmap
.map
);
6699 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6702 bgp_static
->valid
= 1;
6704 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6706 if (!bgp_static
->backdoor
)
6707 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6713 void bgp_static_add(struct bgp
*bgp
)
6717 struct bgp_dest
*dest
;
6718 struct bgp_dest
*rm
;
6719 struct bgp_table
*table
;
6720 struct bgp_static
*bgp_static
;
6722 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6723 FOREACH_AFI_SAFI (afi
, safi
)
6724 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6725 dest
= bgp_route_next(dest
)) {
6726 if (!bgp_dest_has_bgp_path_info_data(dest
))
6729 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6730 || (safi
== SAFI_EVPN
)) {
6731 table
= bgp_dest_get_bgp_table_info(dest
);
6733 for (rm
= bgp_table_top(table
); rm
;
6734 rm
= bgp_route_next(rm
)) {
6736 bgp_dest_get_bgp_static_info(
6738 bgp_static_update_safi(
6739 bgp
, bgp_dest_get_prefix(rm
),
6740 bgp_static
, afi
, safi
);
6744 bgp
, bgp_dest_get_prefix(dest
),
6745 bgp_dest_get_bgp_static_info(dest
), afi
,
6749 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6752 /* Called from bgp_delete(). Delete all static routes from the BGP
6754 void bgp_static_delete(struct bgp
*bgp
)
6758 struct bgp_dest
*dest
;
6759 struct bgp_dest
*rm
;
6760 struct bgp_table
*table
;
6761 struct bgp_static
*bgp_static
;
6763 FOREACH_AFI_SAFI (afi
, safi
)
6764 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6765 dest
= bgp_route_next(dest
)) {
6766 if (!bgp_dest_has_bgp_path_info_data(dest
))
6769 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6770 || (safi
== SAFI_EVPN
)) {
6771 table
= bgp_dest_get_bgp_table_info(dest
);
6773 for (rm
= bgp_table_top(table
); rm
;
6774 rm
= bgp_route_next(rm
)) {
6776 bgp_dest_get_bgp_static_info(
6781 bgp_static_withdraw_safi(
6782 bgp
, bgp_dest_get_prefix(rm
),
6784 (struct prefix_rd
*)
6785 bgp_dest_get_prefix(
6787 bgp_static_free(bgp_static
);
6788 bgp_dest_set_bgp_static_info(rm
,
6790 bgp_dest_unlock_node(rm
);
6793 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6794 bgp_static_withdraw(bgp
,
6795 bgp_dest_get_prefix(dest
),
6797 bgp_static_free(bgp_static
);
6798 bgp_dest_set_bgp_static_info(dest
, NULL
);
6799 bgp_dest_unlock_node(dest
);
6804 void bgp_static_redo_import_check(struct bgp
*bgp
)
6808 struct bgp_dest
*dest
;
6809 struct bgp_dest
*rm
;
6810 struct bgp_table
*table
;
6811 struct bgp_static
*bgp_static
;
6813 /* Use this flag to force reprocessing of the route */
6814 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6815 FOREACH_AFI_SAFI (afi
, safi
) {
6816 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6817 dest
= bgp_route_next(dest
)) {
6818 if (!bgp_dest_has_bgp_path_info_data(dest
))
6821 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6822 || (safi
== SAFI_EVPN
)) {
6823 table
= bgp_dest_get_bgp_table_info(dest
);
6825 for (rm
= bgp_table_top(table
); rm
;
6826 rm
= bgp_route_next(rm
)) {
6828 bgp_dest_get_bgp_static_info(
6830 bgp_static_update_safi(
6831 bgp
, bgp_dest_get_prefix(rm
),
6832 bgp_static
, afi
, safi
);
6835 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6836 bgp_static_update(bgp
,
6837 bgp_dest_get_prefix(dest
),
6838 bgp_static
, afi
, safi
);
6842 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6845 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6848 struct bgp_table
*table
;
6849 struct bgp_dest
*dest
;
6850 struct bgp_path_info
*pi
;
6852 /* Do not install the aggregate route if BGP is in the
6853 * process of termination.
6855 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6856 || (bgp
->peer_self
== NULL
))
6859 table
= bgp
->rib
[afi
][safi
];
6860 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6861 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6862 if (pi
->peer
== bgp
->peer_self
6863 && ((pi
->type
== ZEBRA_ROUTE_BGP
6864 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6865 || (pi
->type
!= ZEBRA_ROUTE_BGP
6867 == BGP_ROUTE_REDISTRIBUTE
))) {
6868 bgp_aggregate_decrement(
6869 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6871 bgp_unlink_nexthop(pi
);
6872 bgp_path_info_delete(dest
, pi
);
6873 bgp_process(bgp
, dest
, afi
, safi
);
6880 * Purge all networks and redistributed routes from routing table.
6881 * Invoked upon the instance going down.
6883 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6888 FOREACH_AFI_SAFI (afi
, safi
)
6889 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6894 * Currently this is used to set static routes for VPN and ENCAP.
6895 * I think it can probably be factored with bgp_static_set.
6897 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6898 const char *ip_str
, const char *rd_str
,
6899 const char *label_str
, const char *rmap_str
,
6900 int evpn_type
, const char *esi
, const char *gwip
,
6901 const char *ethtag
, const char *routermac
)
6903 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6906 struct prefix_rd prd
;
6907 struct bgp_dest
*pdest
;
6908 struct bgp_dest
*dest
;
6909 struct bgp_table
*table
;
6910 struct bgp_static
*bgp_static
;
6911 mpls_label_t label
= MPLS_INVALID_LABEL
;
6912 struct prefix gw_ip
;
6914 /* validate ip prefix */
6915 ret
= str2prefix(ip_str
, &p
);
6917 vty_out(vty
, "%% Malformed prefix\n");
6918 return CMD_WARNING_CONFIG_FAILED
;
6921 if ((afi
== AFI_L2VPN
)
6922 && (bgp_build_evpn_prefix(evpn_type
,
6923 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6924 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6925 return CMD_WARNING_CONFIG_FAILED
;
6928 ret
= str2prefix_rd(rd_str
, &prd
);
6930 vty_out(vty
, "%% Malformed rd\n");
6931 return CMD_WARNING_CONFIG_FAILED
;
6935 unsigned long label_val
;
6936 label_val
= strtoul(label_str
, NULL
, 10);
6937 encode_label(label_val
, &label
);
6940 if (safi
== SAFI_EVPN
) {
6941 if (esi
&& str2esi(esi
, NULL
) == 0) {
6942 vty_out(vty
, "%% Malformed ESI\n");
6943 return CMD_WARNING_CONFIG_FAILED
;
6945 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6946 vty_out(vty
, "%% Malformed Router MAC\n");
6947 return CMD_WARNING_CONFIG_FAILED
;
6950 memset(&gw_ip
, 0, sizeof(gw_ip
));
6951 ret
= str2prefix(gwip
, &gw_ip
);
6953 vty_out(vty
, "%% Malformed GatewayIp\n");
6954 return CMD_WARNING_CONFIG_FAILED
;
6956 if ((gw_ip
.family
== AF_INET
6957 && is_evpn_prefix_ipaddr_v6(
6958 (struct prefix_evpn
*)&p
))
6959 || (gw_ip
.family
== AF_INET6
6960 && is_evpn_prefix_ipaddr_v4(
6961 (struct prefix_evpn
*)&p
))) {
6963 "%% GatewayIp family differs with IP prefix\n");
6964 return CMD_WARNING_CONFIG_FAILED
;
6968 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6969 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6970 bgp_dest_set_bgp_table_info(pdest
,
6971 bgp_table_init(bgp
, afi
, safi
));
6972 table
= bgp_dest_get_bgp_table_info(pdest
);
6974 dest
= bgp_node_get(table
, &p
);
6976 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6977 vty_out(vty
, "%% Same network configuration exists\n");
6978 bgp_dest_unlock_node(dest
);
6980 /* New configuration. */
6981 bgp_static
= bgp_static_new();
6982 bgp_static
->backdoor
= 0;
6983 bgp_static
->valid
= 0;
6984 bgp_static
->igpmetric
= 0;
6985 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6986 bgp_static
->label
= label
;
6987 bgp_static
->prd
= prd
;
6990 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6991 route_map_counter_decrement(bgp_static
->rmap
.map
);
6992 bgp_static
->rmap
.name
=
6993 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6994 bgp_static
->rmap
.map
=
6995 route_map_lookup_by_name(rmap_str
);
6996 route_map_counter_increment(bgp_static
->rmap
.map
);
6999 if (safi
== SAFI_EVPN
) {
7001 bgp_static
->eth_s_id
=
7004 str2esi(esi
, bgp_static
->eth_s_id
);
7007 bgp_static
->router_mac
=
7008 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7009 (void)prefix_str2mac(routermac
,
7010 bgp_static
->router_mac
);
7013 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7015 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7017 bgp_static
->valid
= 1;
7018 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7024 /* Configure static BGP network. */
7025 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7026 const char *ip_str
, const char *rd_str
,
7027 const char *label_str
, int evpn_type
, const char *esi
,
7028 const char *gwip
, const char *ethtag
)
7030 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7033 struct prefix_rd prd
;
7034 struct bgp_dest
*pdest
;
7035 struct bgp_dest
*dest
;
7036 struct bgp_table
*table
;
7037 struct bgp_static
*bgp_static
;
7038 mpls_label_t label
= MPLS_INVALID_LABEL
;
7040 /* Convert IP prefix string to struct prefix. */
7041 ret
= str2prefix(ip_str
, &p
);
7043 vty_out(vty
, "%% Malformed prefix\n");
7044 return CMD_WARNING_CONFIG_FAILED
;
7047 if ((afi
== AFI_L2VPN
)
7048 && (bgp_build_evpn_prefix(evpn_type
,
7049 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7050 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7051 return CMD_WARNING_CONFIG_FAILED
;
7053 ret
= str2prefix_rd(rd_str
, &prd
);
7055 vty_out(vty
, "%% Malformed rd\n");
7056 return CMD_WARNING_CONFIG_FAILED
;
7060 unsigned long label_val
;
7061 label_val
= strtoul(label_str
, NULL
, 10);
7062 encode_label(label_val
, &label
);
7065 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7066 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7067 bgp_dest_set_bgp_table_info(pdest
,
7068 bgp_table_init(bgp
, afi
, safi
));
7070 bgp_dest_unlock_node(pdest
);
7071 table
= bgp_dest_get_bgp_table_info(pdest
);
7073 dest
= bgp_node_lookup(table
, &p
);
7076 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7078 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7079 bgp_static_free(bgp_static
);
7080 bgp_dest_set_bgp_static_info(dest
, NULL
);
7081 bgp_dest_unlock_node(dest
);
7082 bgp_dest_unlock_node(dest
);
7084 vty_out(vty
, "%% Can't find the route\n");
7089 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7090 const char *rmap_name
)
7092 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7093 struct bgp_rmap
*rmap
;
7095 rmap
= &bgp
->table_map
[afi
][safi
];
7097 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7098 route_map_counter_decrement(rmap
->map
);
7099 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7100 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7101 route_map_counter_increment(rmap
->map
);
7103 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7104 route_map_counter_decrement(rmap
->map
);
7108 if (bgp_fibupd_safi(safi
))
7109 bgp_zebra_announce_table(bgp
, afi
, safi
);
7114 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7115 const char *rmap_name
)
7117 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7118 struct bgp_rmap
*rmap
;
7120 rmap
= &bgp
->table_map
[afi
][safi
];
7121 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7122 route_map_counter_decrement(rmap
->map
);
7125 if (bgp_fibupd_safi(safi
))
7126 bgp_zebra_announce_table(bgp
, afi
, safi
);
7131 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7134 if (bgp
->table_map
[afi
][safi
].name
) {
7135 vty_out(vty
, " table-map %s\n",
7136 bgp
->table_map
[afi
][safi
].name
);
7140 DEFUN (bgp_table_map
,
7143 "BGP table to RIB route download filter\n"
7144 "Name of the route map\n")
7147 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7148 argv
[idx_word
]->arg
);
7150 DEFUN (no_bgp_table_map
,
7151 no_bgp_table_map_cmd
,
7152 "no table-map WORD",
7154 "BGP table to RIB route download filter\n"
7155 "Name of the route map\n")
7158 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7159 argv
[idx_word
]->arg
);
7165 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7166 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7167 backdoor$backdoor}]",
7169 "Specify a network to announce via BGP\n"
7174 "Route-map to modify the attributes\n"
7175 "Name of the route map\n"
7176 "Label index to associate with the prefix\n"
7177 "Label index value\n"
7178 "Specify a BGP backdoor route\n")
7180 char addr_prefix_str
[BUFSIZ
];
7185 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7187 sizeof(addr_prefix_str
));
7189 vty_out(vty
, "%% Inconsistent address and mask\n");
7190 return CMD_WARNING_CONFIG_FAILED
;
7194 return bgp_static_set(
7195 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7196 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7197 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7200 DEFPY(ipv6_bgp_network
,
7201 ipv6_bgp_network_cmd
,
7202 "[no] network X:X::X:X/M$prefix \
7203 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7205 "Specify a network to announce via BGP\n"
7207 "Route-map to modify the attributes\n"
7208 "Name of the route map\n"
7209 "Label index to associate with the prefix\n"
7210 "Label index value\n")
7212 return bgp_static_set(
7213 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7214 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7217 static struct bgp_aggregate
*bgp_aggregate_new(void)
7219 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7222 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7224 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7225 route_map_counter_decrement(aggregate
->suppress_map
);
7226 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7227 route_map_counter_decrement(aggregate
->rmap
.map
);
7228 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7232 * Helper function to avoid repeated code: prepare variables for a
7233 * `route_map_apply` call.
7235 * \returns `true` on route map match, otherwise `false`.
7237 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7238 struct bgp_aggregate
*aggregate
,
7239 struct bgp_path_info
*pi
)
7241 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7242 route_map_result_t rmr
= RMAP_DENYMATCH
;
7243 struct bgp_path_info rmap_path
= {};
7244 struct attr attr
= {};
7246 /* No route map entries created, just don't match. */
7247 if (aggregate
->suppress_map
== NULL
)
7250 /* Call route map matching and return result. */
7251 attr
.aspath
= aspath_empty();
7252 rmap_path
.peer
= bgp
->peer_self
;
7253 rmap_path
.attr
= &attr
;
7255 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7256 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7257 bgp
->peer_self
->rmap_type
= 0;
7259 bgp_attr_flush(&attr
);
7260 aspath_unintern(&attr
.aspath
);
7262 return rmr
== RMAP_PERMITMATCH
;
7265 /** Test whether the aggregation has suppressed this path or not. */
7266 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7267 struct bgp_path_info
*pi
)
7269 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7272 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7276 * Suppress this path and keep the reference.
7278 * \returns `true` if needs processing otherwise `false`.
7280 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7281 struct bgp_path_info
*pi
)
7283 struct bgp_path_info_extra
*pie
;
7285 /* Path is already suppressed by this aggregation. */
7286 if (aggr_suppress_exists(aggregate
, pi
))
7289 pie
= bgp_path_info_extra_get(pi
);
7291 /* This is the first suppression, allocate memory and list it. */
7292 if (pie
->aggr_suppressors
== NULL
)
7293 pie
->aggr_suppressors
= list_new();
7295 listnode_add(pie
->aggr_suppressors
, aggregate
);
7297 /* Only mark for processing if suppressed. */
7298 if (listcount(pie
->aggr_suppressors
) == 1) {
7299 if (BGP_DEBUG(update
, UPDATE_OUT
))
7300 zlog_debug("aggregate-address suppressing: %pFX",
7301 bgp_dest_get_prefix(pi
->net
));
7303 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7311 * Unsuppress this path and remove the reference.
7313 * \returns `true` if needs processing otherwise `false`.
7315 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7316 struct bgp_path_info
*pi
)
7318 /* Path wasn't suppressed. */
7319 if (!aggr_suppress_exists(aggregate
, pi
))
7322 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7324 /* Unsuppress and free extra memory if last item. */
7325 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7326 if (BGP_DEBUG(update
, UPDATE_OUT
))
7327 zlog_debug("aggregate-address unsuppressing: %pFX",
7328 bgp_dest_get_prefix(pi
->net
));
7330 list_delete(&pi
->extra
->aggr_suppressors
);
7331 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7338 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7339 struct aspath
*aspath
,
7340 struct community
*comm
,
7341 struct ecommunity
*ecomm
,
7342 struct lcommunity
*lcomm
)
7344 static struct aspath
*ae
= NULL
;
7347 ae
= aspath_empty();
7352 if (origin
!= pi
->attr
->origin
)
7355 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7358 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7361 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7364 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7367 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7373 static void bgp_aggregate_install(
7374 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7375 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7376 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7377 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7379 struct bgp_dest
*dest
;
7380 struct bgp_table
*table
;
7381 struct bgp_path_info
*pi
, *orig
, *new;
7384 table
= bgp
->rib
[afi
][safi
];
7386 dest
= bgp_node_get(table
, p
);
7388 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7389 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7390 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7394 * If we have paths with different MEDs, then don't install
7395 * (or uninstall) the aggregate route.
7397 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7398 goto uninstall_aggregate_route
;
7400 if (aggregate
->count
> 0) {
7402 * If the aggregate information has not changed
7403 * no need to re-install it again.
7405 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7406 ecommunity
, lcommunity
)) {
7407 bgp_dest_unlock_node(dest
);
7410 aspath_free(aspath
);
7412 community_free(&community
);
7414 ecommunity_free(&ecommunity
);
7416 lcommunity_free(&lcommunity
);
7422 * Mark the old as unusable
7425 bgp_path_info_delete(dest
, pi
);
7427 attr
= bgp_attr_aggregate_intern(
7428 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7429 aggregate
, atomic_aggregate
, p
);
7432 bgp_dest_unlock_node(dest
);
7433 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7434 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7435 zlog_debug("%s: %pFX null attribute", __func__
,
7440 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7441 bgp
->peer_self
, attr
, dest
);
7443 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7445 bgp_path_info_add(dest
, new);
7446 bgp_process(bgp
, dest
, afi
, safi
);
7448 uninstall_aggregate_route
:
7449 for (pi
= orig
; pi
; pi
= pi
->next
)
7450 if (pi
->peer
== bgp
->peer_self
7451 && pi
->type
== ZEBRA_ROUTE_BGP
7452 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7455 /* Withdraw static BGP route from routing table. */
7457 bgp_path_info_delete(dest
, pi
);
7458 bgp_process(bgp
, dest
, afi
, safi
);
7462 bgp_dest_unlock_node(dest
);
7466 * Check if the current path has different MED than other known paths.
7468 * \returns `true` if the MED matched the others else `false`.
7470 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7471 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7473 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7475 /* This is the first route being analyzed. */
7476 if (!aggregate
->med_initialized
) {
7477 aggregate
->med_initialized
= true;
7478 aggregate
->med_mismatched
= false;
7479 aggregate
->med_matched_value
= cur_med
;
7481 /* Check if routes with different MED showed up. */
7482 if (cur_med
!= aggregate
->med_matched_value
)
7483 aggregate
->med_mismatched
= true;
7486 return !aggregate
->med_mismatched
;
7490 * Initializes and tests all routes in the aggregate address path for MED
7493 * \returns `true` if all MEDs are the same otherwise `false`.
7495 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7496 struct bgp
*bgp
, const struct prefix
*p
,
7497 afi_t afi
, safi_t safi
)
7499 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7500 const struct prefix
*dest_p
;
7501 struct bgp_dest
*dest
, *top
;
7502 struct bgp_path_info
*pi
;
7503 bool med_matched
= true;
7505 aggregate
->med_initialized
= false;
7507 top
= bgp_node_get(table
, p
);
7508 for (dest
= bgp_node_get(table
, p
); dest
;
7509 dest
= bgp_route_next_until(dest
, top
)) {
7510 dest_p
= bgp_dest_get_prefix(dest
);
7511 if (dest_p
->prefixlen
<= p
->prefixlen
)
7514 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7515 if (BGP_PATH_HOLDDOWN(pi
))
7517 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7519 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7520 med_matched
= false;
7527 bgp_dest_unlock_node(top
);
7533 * Toggles the route suppression status for this aggregate address
7536 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7537 struct bgp
*bgp
, const struct prefix
*p
,
7538 afi_t afi
, safi_t safi
, bool suppress
)
7540 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7541 const struct prefix
*dest_p
;
7542 struct bgp_dest
*dest
, *top
;
7543 struct bgp_path_info
*pi
;
7544 bool toggle_suppression
;
7546 /* We've found a different MED we must revert any suppressed routes. */
7547 top
= bgp_node_get(table
, p
);
7548 for (dest
= bgp_node_get(table
, p
); dest
;
7549 dest
= bgp_route_next_until(dest
, top
)) {
7550 dest_p
= bgp_dest_get_prefix(dest
);
7551 if (dest_p
->prefixlen
<= p
->prefixlen
)
7554 toggle_suppression
= false;
7555 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7556 if (BGP_PATH_HOLDDOWN(pi
))
7558 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7561 /* We are toggling suppression back. */
7563 /* Suppress route if not suppressed already. */
7564 if (aggr_suppress_path(aggregate
, pi
))
7565 toggle_suppression
= true;
7569 /* Install route if there is no more suppression. */
7570 if (aggr_unsuppress_path(aggregate
, pi
))
7571 toggle_suppression
= true;
7574 if (toggle_suppression
)
7575 bgp_process(bgp
, dest
, afi
, safi
);
7577 bgp_dest_unlock_node(top
);
7581 * Aggregate address MED matching incremental test: this function is called
7582 * when the initial aggregation occurred and we are only testing a single
7585 * In addition to testing and setting the MED validity it also installs back
7586 * suppressed routes (if summary is configured).
7588 * Must not be called in `bgp_aggregate_route`.
7590 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7591 struct bgp
*bgp
, const struct prefix
*p
,
7592 afi_t afi
, safi_t safi
,
7593 struct bgp_path_info
*pi
)
7595 /* MED matching disabled. */
7596 if (!aggregate
->match_med
)
7599 /* Aggregation with different MED, recheck if we have got equal MEDs
7602 if (aggregate
->med_mismatched
&&
7603 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7604 aggregate
->summary_only
)
7605 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7608 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7610 /* No mismatches, just quit. */
7611 if (!aggregate
->med_mismatched
)
7614 /* Route summarization is disabled. */
7615 if (!aggregate
->summary_only
)
7618 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7621 /* Update an aggregate as routes are added/removed from the BGP table */
7622 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7623 safi_t safi
, struct bgp_aggregate
*aggregate
)
7625 struct bgp_table
*table
;
7626 struct bgp_dest
*top
;
7627 struct bgp_dest
*dest
;
7629 struct aspath
*aspath
= NULL
;
7630 struct community
*community
= NULL
;
7631 struct ecommunity
*ecommunity
= NULL
;
7632 struct lcommunity
*lcommunity
= NULL
;
7633 struct bgp_path_info
*pi
;
7634 unsigned long match
= 0;
7635 uint8_t atomic_aggregate
= 0;
7637 /* If the bgp instance is being deleted or self peer is deleted
7638 * then do not create aggregate route
7640 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7641 || (bgp
->peer_self
== NULL
))
7644 /* Initialize and test routes for MED difference. */
7645 if (aggregate
->match_med
)
7646 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7649 * Reset aggregate count: we might've been called from route map
7650 * update so in that case we must retest all more specific routes.
7652 * \see `bgp_route_map_process_update`.
7654 aggregate
->count
= 0;
7655 aggregate
->incomplete_origin_count
= 0;
7656 aggregate
->incomplete_origin_count
= 0;
7657 aggregate
->egp_origin_count
= 0;
7659 /* ORIGIN attribute: If at least one route among routes that are
7660 aggregated has ORIGIN with the value INCOMPLETE, then the
7661 aggregated route must have the ORIGIN attribute with the value
7662 INCOMPLETE. Otherwise, if at least one route among routes that
7663 are aggregated has ORIGIN with the value EGP, then the aggregated
7664 route must have the origin attribute with the value EGP. In all
7665 other case the value of the ORIGIN attribute of the aggregated
7666 route is INTERNAL. */
7667 origin
= BGP_ORIGIN_IGP
;
7669 table
= bgp
->rib
[afi
][safi
];
7671 top
= bgp_node_get(table
, p
);
7672 for (dest
= bgp_node_get(table
, p
); dest
;
7673 dest
= bgp_route_next_until(dest
, top
)) {
7674 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7676 if (dest_p
->prefixlen
<= p
->prefixlen
)
7679 /* If suppress fib is enabled and route not installed
7680 * in FIB, skip the route
7682 if (!bgp_check_advertise(bgp
, dest
))
7687 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7688 if (BGP_PATH_HOLDDOWN(pi
))
7692 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7693 atomic_aggregate
= 1;
7695 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7699 * summary-only aggregate route suppress
7700 * aggregated route announcements.
7703 * Don't create summaries if MED didn't match
7704 * otherwise neither the specific routes and the
7705 * aggregation will be announced.
7707 if (aggregate
->summary_only
7708 && AGGREGATE_MED_VALID(aggregate
)) {
7709 if (aggr_suppress_path(aggregate
, pi
))
7714 * Suppress more specific routes that match the route
7718 * Don't suppress routes if MED matching is enabled and
7719 * it mismatched otherwise we might end up with no
7720 * routes for this path.
7722 if (aggregate
->suppress_map_name
7723 && AGGREGATE_MED_VALID(aggregate
)
7724 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7725 if (aggr_suppress_path(aggregate
, pi
))
7732 * If at least one route among routes that are
7733 * aggregated has ORIGIN with the value INCOMPLETE,
7734 * then the aggregated route MUST have the ORIGIN
7735 * attribute with the value INCOMPLETE. Otherwise, if
7736 * at least one route among routes that are aggregated
7737 * has ORIGIN with the value EGP, then the aggregated
7738 * route MUST have the ORIGIN attribute with the value
7741 switch (pi
->attr
->origin
) {
7742 case BGP_ORIGIN_INCOMPLETE
:
7743 aggregate
->incomplete_origin_count
++;
7745 case BGP_ORIGIN_EGP
:
7746 aggregate
->egp_origin_count
++;
7754 if (!aggregate
->as_set
)
7758 * as-set aggregate route generate origin, as path,
7759 * and community aggregation.
7761 /* Compute aggregate route's as-path.
7763 bgp_compute_aggregate_aspath_hash(aggregate
,
7766 /* Compute aggregate route's community.
7768 if (bgp_attr_get_community(pi
->attr
))
7769 bgp_compute_aggregate_community_hash(
7771 bgp_attr_get_community(pi
->attr
));
7773 /* Compute aggregate route's extended community.
7775 if (bgp_attr_get_ecommunity(pi
->attr
))
7776 bgp_compute_aggregate_ecommunity_hash(
7778 bgp_attr_get_ecommunity(pi
->attr
));
7780 /* Compute aggregate route's large community.
7782 if (bgp_attr_get_lcommunity(pi
->attr
))
7783 bgp_compute_aggregate_lcommunity_hash(
7785 bgp_attr_get_lcommunity(pi
->attr
));
7788 bgp_process(bgp
, dest
, afi
, safi
);
7790 if (aggregate
->as_set
) {
7791 bgp_compute_aggregate_aspath_val(aggregate
);
7792 bgp_compute_aggregate_community_val(aggregate
);
7793 bgp_compute_aggregate_ecommunity_val(aggregate
);
7794 bgp_compute_aggregate_lcommunity_val(aggregate
);
7798 bgp_dest_unlock_node(top
);
7801 if (aggregate
->incomplete_origin_count
> 0)
7802 origin
= BGP_ORIGIN_INCOMPLETE
;
7803 else if (aggregate
->egp_origin_count
> 0)
7804 origin
= BGP_ORIGIN_EGP
;
7806 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7807 origin
= aggregate
->origin
;
7809 if (aggregate
->as_set
) {
7810 if (aggregate
->aspath
)
7811 /* Retrieve aggregate route's as-path.
7813 aspath
= aspath_dup(aggregate
->aspath
);
7815 if (aggregate
->community
)
7816 /* Retrieve aggregate route's community.
7818 community
= community_dup(aggregate
->community
);
7820 if (aggregate
->ecommunity
)
7821 /* Retrieve aggregate route's ecommunity.
7823 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7825 if (aggregate
->lcommunity
)
7826 /* Retrieve aggregate route's lcommunity.
7828 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7831 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7832 ecommunity
, lcommunity
, atomic_aggregate
,
7836 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7837 safi_t safi
, struct bgp_aggregate
*aggregate
)
7839 struct bgp_table
*table
;
7840 struct bgp_dest
*top
;
7841 struct bgp_dest
*dest
;
7842 struct bgp_path_info
*pi
;
7843 unsigned long match
;
7845 table
= bgp
->rib
[afi
][safi
];
7847 /* If routes exists below this node, generate aggregate routes. */
7848 top
= bgp_node_get(table
, p
);
7849 for (dest
= bgp_node_get(table
, p
); dest
;
7850 dest
= bgp_route_next_until(dest
, top
)) {
7851 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7853 if (dest_p
->prefixlen
<= p
->prefixlen
)
7857 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7858 if (BGP_PATH_HOLDDOWN(pi
))
7861 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7865 * This route is suppressed: attempt to unsuppress it.
7867 * `aggr_unsuppress_path` will fail if this particular
7868 * aggregate route was not the suppressor.
7870 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7871 listcount(pi
->extra
->aggr_suppressors
)) {
7872 if (aggr_unsuppress_path(aggregate
, pi
))
7878 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7879 aggregate
->incomplete_origin_count
--;
7880 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7881 aggregate
->egp_origin_count
--;
7883 if (aggregate
->as_set
) {
7884 /* Remove as-path from aggregate.
7886 bgp_remove_aspath_from_aggregate_hash(
7890 if (bgp_attr_get_community(pi
->attr
))
7891 /* Remove community from aggregate.
7893 bgp_remove_comm_from_aggregate_hash(
7895 bgp_attr_get_community(
7898 if (bgp_attr_get_ecommunity(pi
->attr
))
7899 /* Remove ecommunity from aggregate.
7901 bgp_remove_ecomm_from_aggregate_hash(
7903 bgp_attr_get_ecommunity(
7906 if (bgp_attr_get_lcommunity(pi
->attr
))
7907 /* Remove lcommunity from aggregate.
7909 bgp_remove_lcomm_from_aggregate_hash(
7911 bgp_attr_get_lcommunity(
7916 /* If this node was suppressed, process the change. */
7918 bgp_process(bgp
, dest
, afi
, safi
);
7920 if (aggregate
->as_set
) {
7921 aspath_free(aggregate
->aspath
);
7922 aggregate
->aspath
= NULL
;
7923 if (aggregate
->community
)
7924 community_free(&aggregate
->community
);
7925 if (aggregate
->ecommunity
)
7926 ecommunity_free(&aggregate
->ecommunity
);
7927 if (aggregate
->lcommunity
)
7928 lcommunity_free(&aggregate
->lcommunity
);
7931 bgp_dest_unlock_node(top
);
7934 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7935 const struct prefix
*aggr_p
,
7936 struct bgp_path_info
*pinew
, afi_t afi
,
7938 struct bgp_aggregate
*aggregate
)
7941 struct aspath
*aspath
= NULL
;
7942 uint8_t atomic_aggregate
= 0;
7943 struct community
*community
= NULL
;
7944 struct ecommunity
*ecommunity
= NULL
;
7945 struct lcommunity
*lcommunity
= NULL
;
7947 /* If the bgp instance is being deleted or self peer is deleted
7948 * then do not create aggregate route
7950 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7951 || (bgp
->peer_self
== NULL
))
7954 /* ORIGIN attribute: If at least one route among routes that are
7955 * aggregated has ORIGIN with the value INCOMPLETE, then the
7956 * aggregated route must have the ORIGIN attribute with the value
7957 * INCOMPLETE. Otherwise, if at least one route among routes that
7958 * are aggregated has ORIGIN with the value EGP, then the aggregated
7959 * route must have the origin attribute with the value EGP. In all
7960 * other case the value of the ORIGIN attribute of the aggregated
7961 * route is INTERNAL.
7963 origin
= BGP_ORIGIN_IGP
;
7968 * This must be called before `summary` check to avoid
7969 * "suppressing" twice.
7971 if (aggregate
->match_med
)
7972 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7975 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7976 aggr_suppress_path(aggregate
, pinew
);
7978 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7979 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7980 aggr_suppress_path(aggregate
, pinew
);
7982 switch (pinew
->attr
->origin
) {
7983 case BGP_ORIGIN_INCOMPLETE
:
7984 aggregate
->incomplete_origin_count
++;
7986 case BGP_ORIGIN_EGP
:
7987 aggregate
->egp_origin_count
++;
7995 if (aggregate
->incomplete_origin_count
> 0)
7996 origin
= BGP_ORIGIN_INCOMPLETE
;
7997 else if (aggregate
->egp_origin_count
> 0)
7998 origin
= BGP_ORIGIN_EGP
;
8000 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8001 origin
= aggregate
->origin
;
8003 if (aggregate
->as_set
) {
8004 /* Compute aggregate route's as-path.
8006 bgp_compute_aggregate_aspath(aggregate
,
8007 pinew
->attr
->aspath
);
8009 /* Compute aggregate route's community.
8011 if (bgp_attr_get_community(pinew
->attr
))
8012 bgp_compute_aggregate_community(
8013 aggregate
, bgp_attr_get_community(pinew
->attr
));
8015 /* Compute aggregate route's extended community.
8017 if (bgp_attr_get_ecommunity(pinew
->attr
))
8018 bgp_compute_aggregate_ecommunity(
8020 bgp_attr_get_ecommunity(pinew
->attr
));
8022 /* Compute aggregate route's large community.
8024 if (bgp_attr_get_lcommunity(pinew
->attr
))
8025 bgp_compute_aggregate_lcommunity(
8027 bgp_attr_get_lcommunity(pinew
->attr
));
8029 /* Retrieve aggregate route's as-path.
8031 if (aggregate
->aspath
)
8032 aspath
= aspath_dup(aggregate
->aspath
);
8034 /* Retrieve aggregate route's community.
8036 if (aggregate
->community
)
8037 community
= community_dup(aggregate
->community
);
8039 /* Retrieve aggregate route's ecommunity.
8041 if (aggregate
->ecommunity
)
8042 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8044 /* Retrieve aggregate route's lcommunity.
8046 if (aggregate
->lcommunity
)
8047 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8050 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8051 aspath
, community
, ecommunity
,
8052 lcommunity
, atomic_aggregate
, aggregate
);
8055 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8057 struct bgp_path_info
*pi
,
8058 struct bgp_aggregate
*aggregate
,
8059 const struct prefix
*aggr_p
)
8062 struct aspath
*aspath
= NULL
;
8063 uint8_t atomic_aggregate
= 0;
8064 struct community
*community
= NULL
;
8065 struct ecommunity
*ecommunity
= NULL
;
8066 struct lcommunity
*lcommunity
= NULL
;
8067 unsigned long match
= 0;
8069 /* If the bgp instance is being deleted or self peer is deleted
8070 * then do not create aggregate route
8072 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8073 || (bgp
->peer_self
== NULL
))
8076 if (BGP_PATH_HOLDDOWN(pi
))
8079 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8082 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8083 if (aggr_unsuppress_path(aggregate
, pi
))
8086 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8087 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8088 if (aggr_unsuppress_path(aggregate
, pi
))
8092 * This must be called after `summary`, `suppress-map` check to avoid
8093 * "unsuppressing" twice.
8095 if (aggregate
->match_med
)
8096 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8098 if (aggregate
->count
> 0)
8101 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8102 aggregate
->incomplete_origin_count
--;
8103 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8104 aggregate
->egp_origin_count
--;
8106 if (aggregate
->as_set
) {
8107 /* Remove as-path from aggregate.
8109 bgp_remove_aspath_from_aggregate(aggregate
,
8112 if (bgp_attr_get_community(pi
->attr
))
8113 /* Remove community from aggregate.
8115 bgp_remove_community_from_aggregate(
8116 aggregate
, bgp_attr_get_community(pi
->attr
));
8118 if (bgp_attr_get_ecommunity(pi
->attr
))
8119 /* Remove ecommunity from aggregate.
8121 bgp_remove_ecommunity_from_aggregate(
8122 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8124 if (bgp_attr_get_lcommunity(pi
->attr
))
8125 /* Remove lcommunity from aggregate.
8127 bgp_remove_lcommunity_from_aggregate(
8128 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8131 /* If this node was suppressed, process the change. */
8133 bgp_process(bgp
, pi
->net
, afi
, safi
);
8135 origin
= BGP_ORIGIN_IGP
;
8136 if (aggregate
->incomplete_origin_count
> 0)
8137 origin
= BGP_ORIGIN_INCOMPLETE
;
8138 else if (aggregate
->egp_origin_count
> 0)
8139 origin
= BGP_ORIGIN_EGP
;
8141 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8142 origin
= aggregate
->origin
;
8144 if (aggregate
->as_set
) {
8145 /* Retrieve aggregate route's as-path.
8147 if (aggregate
->aspath
)
8148 aspath
= aspath_dup(aggregate
->aspath
);
8150 /* Retrieve aggregate route's community.
8152 if (aggregate
->community
)
8153 community
= community_dup(aggregate
->community
);
8155 /* Retrieve aggregate route's ecommunity.
8157 if (aggregate
->ecommunity
)
8158 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8160 /* Retrieve aggregate route's lcommunity.
8162 if (aggregate
->lcommunity
)
8163 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8166 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8167 aspath
, community
, ecommunity
,
8168 lcommunity
, atomic_aggregate
, aggregate
);
8171 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8172 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8174 struct bgp_dest
*child
;
8175 struct bgp_dest
*dest
;
8176 struct bgp_aggregate
*aggregate
;
8177 struct bgp_table
*table
;
8179 table
= bgp
->aggregate
[afi
][safi
];
8181 /* No aggregates configured. */
8182 if (bgp_table_top_nolock(table
) == NULL
)
8185 if (p
->prefixlen
== 0)
8188 if (BGP_PATH_HOLDDOWN(pi
))
8191 /* If suppress fib is enabled and route not installed
8192 * in FIB, do not update the aggregate route
8194 if (!bgp_check_advertise(bgp
, pi
->net
))
8197 child
= bgp_node_get(table
, p
);
8199 /* Aggregate address configuration check. */
8200 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8201 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8203 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8204 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8205 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8209 bgp_dest_unlock_node(child
);
8212 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8213 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8215 struct bgp_dest
*child
;
8216 struct bgp_dest
*dest
;
8217 struct bgp_aggregate
*aggregate
;
8218 struct bgp_table
*table
;
8220 table
= bgp
->aggregate
[afi
][safi
];
8222 /* No aggregates configured. */
8223 if (bgp_table_top_nolock(table
) == NULL
)
8226 if (p
->prefixlen
== 0)
8229 child
= bgp_node_get(table
, p
);
8231 /* Aggregate address configuration check. */
8232 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8233 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8235 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8236 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8237 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8241 bgp_dest_unlock_node(child
);
8244 /* Aggregate route attribute. */
8245 #define AGGREGATE_SUMMARY_ONLY 1
8246 #define AGGREGATE_AS_SET 1
8247 #define AGGREGATE_AS_UNSET 0
8249 static const char *bgp_origin2str(uint8_t origin
)
8252 case BGP_ORIGIN_IGP
:
8254 case BGP_ORIGIN_EGP
:
8256 case BGP_ORIGIN_INCOMPLETE
:
8257 return "incomplete";
8262 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8265 case RPKI_NOT_BEING_USED
:
8275 assert(!"We should never get here this is a dev escape");
8279 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8280 afi_t afi
, safi_t safi
)
8282 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8285 struct bgp_dest
*dest
;
8286 struct bgp_aggregate
*aggregate
;
8288 /* Convert string to prefix structure. */
8289 ret
= str2prefix(prefix_str
, &p
);
8291 vty_out(vty
, "Malformed prefix\n");
8292 return CMD_WARNING_CONFIG_FAILED
;
8296 /* Old configuration check. */
8297 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8300 "%% There is no aggregate-address configuration.\n");
8301 return CMD_WARNING_CONFIG_FAILED
;
8304 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8305 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8306 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8307 NULL
, NULL
, 0, aggregate
);
8309 /* Unlock aggregate address configuration. */
8310 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8312 if (aggregate
->community
)
8313 community_free(&aggregate
->community
);
8315 if (aggregate
->community_hash
) {
8316 /* Delete all communities in the hash.
8318 hash_clean(aggregate
->community_hash
,
8319 bgp_aggr_community_remove
);
8320 /* Free up the community_hash.
8322 hash_free(aggregate
->community_hash
);
8325 if (aggregate
->ecommunity
)
8326 ecommunity_free(&aggregate
->ecommunity
);
8328 if (aggregate
->ecommunity_hash
) {
8329 /* Delete all ecommunities in the hash.
8331 hash_clean(aggregate
->ecommunity_hash
,
8332 bgp_aggr_ecommunity_remove
);
8333 /* Free up the ecommunity_hash.
8335 hash_free(aggregate
->ecommunity_hash
);
8338 if (aggregate
->lcommunity
)
8339 lcommunity_free(&aggregate
->lcommunity
);
8341 if (aggregate
->lcommunity_hash
) {
8342 /* Delete all lcommunities in the hash.
8344 hash_clean(aggregate
->lcommunity_hash
,
8345 bgp_aggr_lcommunity_remove
);
8346 /* Free up the lcommunity_hash.
8348 hash_free(aggregate
->lcommunity_hash
);
8351 if (aggregate
->aspath
)
8352 aspath_free(aggregate
->aspath
);
8354 if (aggregate
->aspath_hash
) {
8355 /* Delete all as-paths in the hash.
8357 hash_clean(aggregate
->aspath_hash
,
8358 bgp_aggr_aspath_remove
);
8359 /* Free up the aspath_hash.
8361 hash_free(aggregate
->aspath_hash
);
8364 bgp_aggregate_free(aggregate
);
8365 bgp_dest_unlock_node(dest
);
8366 bgp_dest_unlock_node(dest
);
8371 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8372 safi_t safi
, const char *rmap
,
8373 uint8_t summary_only
, uint8_t as_set
,
8374 uint8_t origin
, bool match_med
,
8375 const char *suppress_map
)
8377 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8380 struct bgp_dest
*dest
;
8381 struct bgp_aggregate
*aggregate
;
8382 uint8_t as_set_new
= as_set
;
8384 if (suppress_map
&& summary_only
) {
8386 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8387 return CMD_WARNING_CONFIG_FAILED
;
8390 /* Convert string to prefix structure. */
8391 ret
= str2prefix(prefix_str
, &p
);
8393 vty_out(vty
, "Malformed prefix\n");
8394 return CMD_WARNING_CONFIG_FAILED
;
8398 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8399 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8400 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8402 return CMD_WARNING_CONFIG_FAILED
;
8405 /* Old configuration check. */
8406 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8407 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8410 vty_out(vty
, "There is already same aggregate network.\n");
8411 /* try to remove the old entry */
8412 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8414 vty_out(vty
, "Error deleting aggregate.\n");
8415 bgp_dest_unlock_node(dest
);
8416 return CMD_WARNING_CONFIG_FAILED
;
8420 /* Make aggregate address structure. */
8421 aggregate
= bgp_aggregate_new();
8422 aggregate
->summary_only
= summary_only
;
8423 aggregate
->match_med
= match_med
;
8425 /* Network operators MUST NOT locally generate any new
8426 * announcements containing AS_SET or AS_CONFED_SET. If they have
8427 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8428 * SHOULD withdraw those routes and re-announce routes for the
8429 * aggregate or component prefixes (i.e., the more-specific routes
8430 * subsumed by the previously aggregated route) without AS_SET
8431 * or AS_CONFED_SET in the updates.
8433 if (bgp
->reject_as_sets
) {
8434 if (as_set
== AGGREGATE_AS_SET
) {
8435 as_set_new
= AGGREGATE_AS_UNSET
;
8437 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8440 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8444 aggregate
->as_set
= as_set_new
;
8445 aggregate
->safi
= safi
;
8446 /* Override ORIGIN attribute if defined.
8447 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8448 * to IGP which is not what rfc4271 says.
8449 * This enables the same behavior, optionally.
8451 aggregate
->origin
= origin
;
8454 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8455 route_map_counter_decrement(aggregate
->rmap
.map
);
8456 aggregate
->rmap
.name
=
8457 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8458 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8459 route_map_counter_increment(aggregate
->rmap
.map
);
8463 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8464 route_map_counter_decrement(aggregate
->suppress_map
);
8466 aggregate
->suppress_map_name
=
8467 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8468 aggregate
->suppress_map
=
8469 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8470 route_map_counter_increment(aggregate
->suppress_map
);
8473 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8475 /* Aggregate address insert into BGP routing table. */
8476 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8481 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8482 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8484 "|summary-only$summary_only"
8485 "|route-map RMAP_NAME$rmap_name"
8486 "|origin <egp|igp|incomplete>$origin_s"
8487 "|matching-MED-only$match_med"
8488 "|suppress-map RMAP_NAME$suppress_map"
8491 "Configure BGP aggregate entries\n"
8492 "Aggregate prefix\n"
8493 "Aggregate address\n"
8495 "Generate AS set path information\n"
8496 "Filter more specific routes from updates\n"
8497 "Apply route map to aggregate network\n"
8502 "Unknown heritage\n"
8503 "Only aggregate routes with matching MED\n"
8504 "Suppress the selected more specific routes\n"
8505 "Route map with the route selectors\n")
8507 const char *prefix_s
= NULL
;
8508 safi_t safi
= bgp_node_safi(vty
);
8509 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8510 int as_set
= AGGREGATE_AS_UNSET
;
8511 char prefix_buf
[PREFIX2STR_BUFFER
];
8514 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8517 vty_out(vty
, "%% Inconsistent address and mask\n");
8518 return CMD_WARNING_CONFIG_FAILED
;
8520 prefix_s
= prefix_buf
;
8522 prefix_s
= prefix_str
;
8525 if (strcmp(origin_s
, "egp") == 0)
8526 origin
= BGP_ORIGIN_EGP
;
8527 else if (strcmp(origin_s
, "igp") == 0)
8528 origin
= BGP_ORIGIN_IGP
;
8529 else if (strcmp(origin_s
, "incomplete") == 0)
8530 origin
= BGP_ORIGIN_INCOMPLETE
;
8534 as_set
= AGGREGATE_AS_SET
;
8536 /* Handle configuration removal, otherwise installation. */
8538 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8540 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8541 summary_only
!= NULL
, as_set
, origin
,
8542 match_med
!= NULL
, suppress_map
);
8545 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8546 "[no] aggregate-address X:X::X:X/M$prefix [{"
8548 "|summary-only$summary_only"
8549 "|route-map RMAP_NAME$rmap_name"
8550 "|origin <egp|igp|incomplete>$origin_s"
8551 "|matching-MED-only$match_med"
8552 "|suppress-map RMAP_NAME$suppress_map"
8555 "Configure BGP aggregate entries\n"
8556 "Aggregate prefix\n"
8557 "Generate AS set path information\n"
8558 "Filter more specific routes from updates\n"
8559 "Apply route map to aggregate network\n"
8564 "Unknown heritage\n"
8565 "Only aggregate routes with matching MED\n"
8566 "Suppress the selected more specific routes\n"
8567 "Route map with the route selectors\n")
8569 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8570 int as_set
= AGGREGATE_AS_UNSET
;
8573 if (strcmp(origin_s
, "egp") == 0)
8574 origin
= BGP_ORIGIN_EGP
;
8575 else if (strcmp(origin_s
, "igp") == 0)
8576 origin
= BGP_ORIGIN_IGP
;
8577 else if (strcmp(origin_s
, "incomplete") == 0)
8578 origin
= BGP_ORIGIN_INCOMPLETE
;
8582 as_set
= AGGREGATE_AS_SET
;
8584 /* Handle configuration removal, otherwise installation. */
8586 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8589 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8590 rmap_name
, summary_only
!= NULL
, as_set
,
8591 origin
, match_med
!= NULL
, suppress_map
);
8594 /* Redistribute route treatment. */
8595 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8596 const union g_addr
*nexthop
, ifindex_t ifindex
,
8597 enum nexthop_types_t nhtype
, uint8_t distance
,
8598 enum blackhole_type bhtype
, uint32_t metric
,
8599 uint8_t type
, unsigned short instance
,
8602 struct bgp_path_info
*new;
8603 struct bgp_path_info
*bpi
;
8604 struct bgp_path_info rmap_path
;
8605 struct bgp_dest
*bn
;
8607 struct attr
*new_attr
;
8609 route_map_result_t ret
;
8610 struct bgp_redist
*red
;
8612 /* Make default attribute. */
8613 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8615 * This must not be NULL to satisfy Coverity SA
8617 assert(attr
.aspath
);
8620 case NEXTHOP_TYPE_IFINDEX
:
8621 switch (p
->family
) {
8623 attr
.nexthop
.s_addr
= INADDR_ANY
;
8624 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8627 memset(&attr
.mp_nexthop_global
, 0,
8628 sizeof(attr
.mp_nexthop_global
));
8629 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8633 case NEXTHOP_TYPE_IPV4
:
8634 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8635 attr
.nexthop
= nexthop
->ipv4
;
8636 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8638 case NEXTHOP_TYPE_IPV6
:
8639 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8640 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8641 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8643 case NEXTHOP_TYPE_BLACKHOLE
:
8644 switch (p
->family
) {
8646 attr
.nexthop
.s_addr
= INADDR_ANY
;
8647 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8650 memset(&attr
.mp_nexthop_global
, 0,
8651 sizeof(attr
.mp_nexthop_global
));
8652 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8655 attr
.bh_type
= bhtype
;
8658 attr
.nh_type
= nhtype
;
8659 attr
.nh_ifindex
= ifindex
;
8662 attr
.distance
= distance
;
8663 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8667 bgp_attr_set_aigp_metric(&attr
, metric
);
8669 afi
= family2afi(p
->family
);
8671 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8673 struct attr attr_new
;
8675 /* Copy attribute for modification. */
8678 if (red
->redist_metric_flag
) {
8679 attr_new
.med
= red
->redist_metric
;
8680 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8683 /* Apply route-map. */
8684 if (red
->rmap
.name
) {
8685 memset(&rmap_path
, 0, sizeof(rmap_path
));
8686 rmap_path
.peer
= bgp
->peer_self
;
8687 rmap_path
.attr
= &attr_new
;
8689 SET_FLAG(bgp
->peer_self
->rmap_type
,
8690 PEER_RMAP_TYPE_REDISTRIBUTE
);
8692 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8694 bgp
->peer_self
->rmap_type
= 0;
8696 if (ret
== RMAP_DENYMATCH
) {
8697 /* Free uninterned attribute. */
8698 bgp_attr_flush(&attr_new
);
8700 /* Unintern original. */
8701 aspath_unintern(&attr
.aspath
);
8702 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8707 if (bgp_in_graceful_shutdown(bgp
))
8708 bgp_attr_add_gshut_community(&attr_new
);
8710 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8711 SAFI_UNICAST
, p
, NULL
);
8713 new_attr
= bgp_attr_intern(&attr_new
);
8715 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8716 if (bpi
->peer
== bgp
->peer_self
8717 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8721 /* Ensure the (source route) type is updated. */
8723 if (attrhash_cmp(bpi
->attr
, new_attr
)
8724 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8725 bgp_attr_unintern(&new_attr
);
8726 aspath_unintern(&attr
.aspath
);
8727 bgp_dest_unlock_node(bn
);
8730 /* The attribute is changed. */
8731 bgp_path_info_set_flag(bn
, bpi
,
8732 BGP_PATH_ATTR_CHANGED
);
8734 /* Rewrite BGP route information. */
8735 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8736 bgp_path_info_restore(bn
, bpi
);
8738 bgp_aggregate_decrement(
8739 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8740 bgp_attr_unintern(&bpi
->attr
);
8741 bpi
->attr
= new_attr
;
8742 bpi
->uptime
= monotime(NULL
);
8744 /* Process change. */
8745 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8747 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8748 bgp_dest_unlock_node(bn
);
8749 aspath_unintern(&attr
.aspath
);
8751 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8753 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8755 vpn_leak_from_vrf_update(
8756 bgp_get_default(), bgp
, bpi
);
8762 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8763 bgp
->peer_self
, new_attr
, bn
);
8764 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8766 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8767 bgp_path_info_add(bn
, new);
8768 bgp_dest_unlock_node(bn
);
8769 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8770 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8772 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8773 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8775 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8779 /* Unintern original. */
8780 aspath_unintern(&attr
.aspath
);
8783 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8784 unsigned short instance
)
8787 struct bgp_dest
*dest
;
8788 struct bgp_path_info
*pi
;
8789 struct bgp_redist
*red
;
8791 afi
= family2afi(p
->family
);
8793 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8795 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8796 SAFI_UNICAST
, p
, NULL
);
8798 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8799 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8803 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8804 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8806 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8809 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8810 bgp_path_info_delete(dest
, pi
);
8811 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8813 bgp_dest_unlock_node(dest
);
8817 /* Withdraw specified route type's route. */
8818 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8819 unsigned short instance
)
8821 struct bgp_dest
*dest
;
8822 struct bgp_path_info
*pi
;
8823 struct bgp_table
*table
;
8825 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8827 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8828 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8829 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8830 && pi
->instance
== instance
)
8834 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8835 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8837 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8840 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8841 pi
, afi
, SAFI_UNICAST
);
8842 bgp_path_info_delete(dest
, pi
);
8843 if (!CHECK_FLAG(bgp
->flags
,
8844 BGP_FLAG_DELETE_IN_PROGRESS
))
8845 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8847 bgp_path_info_reap(dest
, pi
);
8852 /* Static function to display route. */
8853 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8854 struct vty
*vty
, json_object
*json
, bool wide
)
8857 char buf
[INET6_ADDRSTRLEN
];
8859 if (p
->family
== AF_INET
) {
8861 len
= vty_out(vty
, "%pFX", p
);
8863 json_object_string_add(json
, "prefix",
8864 inet_ntop(p
->family
,
8867 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8868 json_object_string_addf(json
, "network", "%pFX", p
);
8869 json_object_int_add(json
, "version", dest
->version
);
8871 } else if (p
->family
== AF_ETHERNET
) {
8872 len
= vty_out(vty
, "%pFX", p
);
8873 } else if (p
->family
== AF_EVPN
) {
8875 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8877 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8878 } else if (p
->family
== AF_FLOWSPEC
) {
8879 route_vty_out_flowspec(vty
, p
, NULL
,
8881 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8882 NLRI_STRING_FORMAT_MIN
, json
);
8885 len
= vty_out(vty
, "%pFX", p
);
8887 json_object_string_add(json
, "prefix",
8888 inet_ntop(p
->family
,
8891 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8892 json_object_string_addf(json
, "network", "%pFX", p
);
8893 json_object_int_add(json
, "version", dest
->version
);
8898 len
= wide
? (45 - len
) : (17 - len
);
8900 vty_out(vty
, "\n%*s", 20, " ");
8902 vty_out(vty
, "%*s", len
, " ");
8906 enum bgp_display_type
{
8910 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8913 case bgp_path_selection_none
:
8914 return "Nothing to Select";
8915 case bgp_path_selection_first
:
8916 return "First path received";
8917 case bgp_path_selection_evpn_sticky_mac
:
8918 return "EVPN Sticky Mac";
8919 case bgp_path_selection_evpn_seq
:
8920 return "EVPN sequence number";
8921 case bgp_path_selection_evpn_lower_ip
:
8922 return "EVPN lower IP";
8923 case bgp_path_selection_evpn_local_path
:
8924 return "EVPN local ES path";
8925 case bgp_path_selection_evpn_non_proxy
:
8926 return "EVPN non proxy";
8927 case bgp_path_selection_weight
:
8929 case bgp_path_selection_local_pref
:
8930 return "Local Pref";
8931 case bgp_path_selection_accept_own
:
8932 return "Accept Own";
8933 case bgp_path_selection_local_route
:
8934 return "Local Route";
8935 case bgp_path_selection_aigp
:
8937 case bgp_path_selection_confed_as_path
:
8938 return "Confederation based AS Path";
8939 case bgp_path_selection_as_path
:
8941 case bgp_path_selection_origin
:
8943 case bgp_path_selection_med
:
8945 case bgp_path_selection_peer
:
8947 case bgp_path_selection_confed
:
8948 return "Confed Peer Type";
8949 case bgp_path_selection_igp_metric
:
8950 return "IGP Metric";
8951 case bgp_path_selection_older
:
8952 return "Older Path";
8953 case bgp_path_selection_router_id
:
8955 case bgp_path_selection_cluster_length
:
8956 return "Cluster length";
8957 case bgp_path_selection_stale
:
8958 return "Path Staleness";
8959 case bgp_path_selection_local_configured
:
8960 return "Locally configured route";
8961 case bgp_path_selection_neighbor_ip
:
8962 return "Neighbor IP";
8963 case bgp_path_selection_default
:
8964 return "Nothing left to compare";
8966 return "Invalid (internal error)";
8969 /* Print the short form route status for a bgp_path_info */
8970 static void route_vty_short_status_out(struct vty
*vty
,
8971 struct bgp_path_info
*path
,
8972 const struct prefix
*p
,
8973 json_object
*json_path
)
8975 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8979 /* Route status display. */
8980 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8981 json_object_boolean_true_add(json_path
, "removed");
8983 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8984 json_object_boolean_true_add(json_path
, "stale");
8986 if (path
->extra
&& bgp_path_suppressed(path
))
8987 json_object_boolean_true_add(json_path
, "suppressed");
8989 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8990 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8991 json_object_boolean_true_add(json_path
, "valid");
8994 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8995 json_object_boolean_true_add(json_path
, "history");
8997 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8998 json_object_boolean_true_add(json_path
, "damped");
9000 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9001 json_object_boolean_true_add(json_path
, "bestpath");
9002 json_object_string_add(json_path
, "selectionReason",
9003 bgp_path_selection_reason2str(
9004 path
->net
->reason
));
9007 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9008 json_object_boolean_true_add(json_path
, "multipath");
9010 /* Internal route. */
9011 if ((path
->peer
->as
)
9012 && (path
->peer
->as
== path
->peer
->local_as
))
9013 json_object_string_add(json_path
, "pathFrom",
9016 json_object_string_add(json_path
, "pathFrom",
9022 /* RPKI validation state */
9024 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9026 if (rpki_state
== RPKI_VALID
)
9028 else if (rpki_state
== RPKI_INVALID
)
9030 else if (rpki_state
== RPKI_NOTFOUND
)
9035 /* Route status display. */
9036 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9038 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9040 else if (bgp_path_suppressed(path
))
9042 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9043 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9049 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9051 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9053 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9055 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9060 /* Internal route. */
9061 if (path
->peer
&& (path
->peer
->as
)
9062 && (path
->peer
->as
== path
->peer
->local_as
))
9068 static char *bgp_nexthop_hostname(struct peer
*peer
,
9069 struct bgp_nexthop_cache
*bnc
)
9072 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9073 return peer
->hostname
;
9077 /* called from terminal list command */
9078 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9079 struct bgp_path_info
*path
, int display
, safi_t safi
,
9080 json_object
*json_paths
, bool wide
)
9083 struct attr
*attr
= path
->attr
;
9084 json_object
*json_path
= NULL
;
9085 json_object
*json_nexthops
= NULL
;
9086 json_object
*json_nexthop_global
= NULL
;
9087 json_object
*json_nexthop_ll
= NULL
;
9088 json_object
*json_ext_community
= NULL
;
9089 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9091 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9092 bool nexthop_othervrf
= false;
9093 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9094 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9095 char *nexthop_hostname
=
9096 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9097 char esi_buf
[ESI_STR_LEN
];
9100 json_path
= json_object_new_object();
9102 /* short status lead text */
9103 route_vty_short_status_out(vty
, path
, p
, json_path
);
9106 /* print prefix and mask */
9108 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9110 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9112 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9116 * If vrf id of nexthop is different from that of prefix,
9117 * set up printable string to append
9119 if (path
->extra
&& path
->extra
->bgp_orig
) {
9120 const char *self
= "";
9125 nexthop_othervrf
= true;
9126 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9128 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9129 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9130 "@%s%s", VRFID_NONE_STR
, self
);
9132 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9133 path
->extra
->bgp_orig
->vrf_id
, self
);
9135 if (path
->extra
->bgp_orig
->inst_type
9136 != BGP_INSTANCE_TYPE_DEFAULT
)
9138 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9140 const char *self
= "";
9145 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9149 * For ENCAP and EVPN routes, nexthop address family is not
9150 * neccessarily the same as the prefix address family.
9151 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9152 * EVPN routes are also exchanged with a MP nexthop. Currently,
9154 * is only IPv4, the value will be present in either
9156 * attr->mp_nexthop_global_in
9158 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9160 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9164 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9165 &attr
->mp_nexthop_global_in
);
9168 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9169 &attr
->mp_nexthop_global
);
9172 snprintf(nexthop
, sizeof(nexthop
), "?");
9177 json_nexthop_global
= json_object_new_object();
9179 json_object_string_add(json_nexthop_global
, "ip",
9182 if (path
->peer
->hostname
)
9183 json_object_string_add(json_nexthop_global
,
9185 path
->peer
->hostname
);
9187 json_object_string_add(json_nexthop_global
, "afi",
9188 (af
== AF_INET
) ? "ipv4"
9190 json_object_boolean_true_add(json_nexthop_global
,
9193 if (nexthop_hostname
)
9194 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9195 nexthop_hostname
, vrf_id_str
);
9197 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9199 len
= wide
? (41 - len
) : (16 - len
);
9201 vty_out(vty
, "\n%*s", 36, " ");
9203 vty_out(vty
, "%*s", len
, " ");
9205 } else if (safi
== SAFI_EVPN
) {
9207 json_nexthop_global
= json_object_new_object();
9209 json_object_string_addf(json_nexthop_global
, "ip",
9211 &attr
->mp_nexthop_global_in
);
9213 if (path
->peer
->hostname
)
9214 json_object_string_add(json_nexthop_global
,
9216 path
->peer
->hostname
);
9218 json_object_string_add(json_nexthop_global
, "afi",
9220 json_object_boolean_true_add(json_nexthop_global
,
9223 if (nexthop_hostname
)
9224 len
= vty_out(vty
, "%pI4(%s)%s",
9225 &attr
->mp_nexthop_global_in
,
9226 nexthop_hostname
, vrf_id_str
);
9228 len
= vty_out(vty
, "%pI4%s",
9229 &attr
->mp_nexthop_global_in
,
9232 len
= wide
? (41 - len
) : (16 - len
);
9234 vty_out(vty
, "\n%*s", 36, " ");
9236 vty_out(vty
, "%*s", len
, " ");
9238 } else if (safi
== SAFI_FLOWSPEC
) {
9239 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9241 json_nexthop_global
= json_object_new_object();
9243 json_object_string_add(json_nexthop_global
,
9245 json_object_string_addf(json_nexthop_global
,
9249 if (path
->peer
->hostname
)
9250 json_object_string_add(
9251 json_nexthop_global
, "hostname",
9252 path
->peer
->hostname
);
9254 json_object_boolean_true_add(
9255 json_nexthop_global
,
9258 if (nexthop_hostname
)
9259 len
= vty_out(vty
, "%pI4(%s)%s",
9264 len
= vty_out(vty
, "%pI4%s",
9268 len
= wide
? (41 - len
) : (16 - len
);
9270 vty_out(vty
, "\n%*s", 36, " ");
9272 vty_out(vty
, "%*s", len
, " ");
9275 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9277 json_nexthop_global
= json_object_new_object();
9279 json_object_string_addf(json_nexthop_global
, "ip",
9280 "%pI4", &attr
->nexthop
);
9282 if (path
->peer
->hostname
)
9283 json_object_string_add(json_nexthop_global
,
9285 path
->peer
->hostname
);
9287 json_object_string_add(json_nexthop_global
, "afi",
9289 json_object_boolean_true_add(json_nexthop_global
,
9292 if (nexthop_hostname
)
9293 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9294 nexthop_hostname
, vrf_id_str
);
9296 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9299 len
= wide
? (41 - len
) : (16 - len
);
9301 vty_out(vty
, "\n%*s", 36, " ");
9303 vty_out(vty
, "%*s", len
, " ");
9308 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9310 json_nexthop_global
= json_object_new_object();
9311 json_object_string_addf(json_nexthop_global
, "ip",
9313 &attr
->mp_nexthop_global
);
9315 if (path
->peer
->hostname
)
9316 json_object_string_add(json_nexthop_global
,
9318 path
->peer
->hostname
);
9320 json_object_string_add(json_nexthop_global
, "afi",
9322 json_object_string_add(json_nexthop_global
, "scope",
9325 /* We display both LL & GL if both have been
9327 if ((attr
->mp_nexthop_len
9328 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9329 || (path
->peer
->conf_if
)) {
9330 json_nexthop_ll
= json_object_new_object();
9331 json_object_string_addf(
9332 json_nexthop_ll
, "ip", "%pI6",
9333 &attr
->mp_nexthop_local
);
9335 if (path
->peer
->hostname
)
9336 json_object_string_add(
9337 json_nexthop_ll
, "hostname",
9338 path
->peer
->hostname
);
9340 json_object_string_add(json_nexthop_ll
, "afi",
9342 json_object_string_add(json_nexthop_ll
, "scope",
9345 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9346 &attr
->mp_nexthop_local
)
9348 && !attr
->mp_nexthop_prefer_global
)
9349 json_object_boolean_true_add(
9350 json_nexthop_ll
, "used");
9352 json_object_boolean_true_add(
9353 json_nexthop_global
, "used");
9355 json_object_boolean_true_add(
9356 json_nexthop_global
, "used");
9358 /* Display LL if LL/Global both in table unless
9359 * prefer-global is set */
9360 if (((attr
->mp_nexthop_len
9361 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9362 && !attr
->mp_nexthop_prefer_global
)
9363 || (path
->peer
->conf_if
)) {
9364 if (path
->peer
->conf_if
) {
9365 len
= vty_out(vty
, "%s",
9366 path
->peer
->conf_if
);
9367 /* len of IPv6 addr + max len of def
9369 len
= wide
? (41 - len
) : (16 - len
);
9372 vty_out(vty
, "\n%*s", 36, " ");
9374 vty_out(vty
, "%*s", len
, " ");
9376 if (nexthop_hostname
)
9379 &attr
->mp_nexthop_local
,
9385 &attr
->mp_nexthop_local
,
9388 len
= wide
? (41 - len
) : (16 - len
);
9391 vty_out(vty
, "\n%*s", 36, " ");
9393 vty_out(vty
, "%*s", len
, " ");
9396 if (nexthop_hostname
)
9397 len
= vty_out(vty
, "%pI6(%s)%s",
9398 &attr
->mp_nexthop_global
,
9402 len
= vty_out(vty
, "%pI6%s",
9403 &attr
->mp_nexthop_global
,
9406 len
= wide
? (41 - len
) : (16 - len
);
9409 vty_out(vty
, "\n%*s", 36, " ");
9411 vty_out(vty
, "%*s", len
, " ");
9417 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9419 json_object_int_add(json_path
, "metric", attr
->med
);
9421 vty_out(vty
, "%7u", attr
->med
);
9423 vty_out(vty
, "%10u", attr
->med
);
9424 else if (!json_paths
) {
9426 vty_out(vty
, "%*s", 7, " ");
9428 vty_out(vty
, "%*s", 10, " ");
9432 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9434 json_object_int_add(json_path
, "locPrf",
9437 vty_out(vty
, "%7u", attr
->local_pref
);
9438 else if (!json_paths
)
9442 json_object_int_add(json_path
, "weight", attr
->weight
);
9444 vty_out(vty
, "%7u ", attr
->weight
);
9447 json_object_string_addf(json_path
, "peerId", "%pSU",
9453 json_object_string_add(json_path
, "path",
9456 aspath_print_vty(vty
, attr
->aspath
);
9461 json_object_string_add(json_path
, "origin",
9462 bgp_origin_long_str
[attr
->origin
]);
9464 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9467 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9468 json_object_string_add(json_path
, "esi",
9469 esi_to_str(&attr
->esi
,
9470 esi_buf
, sizeof(esi_buf
)));
9472 if (safi
== SAFI_EVPN
&&
9473 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9474 json_ext_community
= json_object_new_object();
9475 json_object_string_add(
9476 json_ext_community
, "string",
9477 bgp_attr_get_ecommunity(attr
)->str
);
9478 json_object_object_add(json_path
,
9479 "extendedCommunity",
9480 json_ext_community
);
9484 json_object_boolean_true_add(json_path
,
9485 "announceNexthopSelf");
9486 if (nexthop_othervrf
) {
9487 json_object_string_add(json_path
, "nhVrfName",
9490 json_object_int_add(json_path
, "nhVrfId",
9491 ((nexthop_vrfid
== VRF_UNKNOWN
)
9493 : (int)nexthop_vrfid
));
9498 if (json_nexthop_global
|| json_nexthop_ll
) {
9499 json_nexthops
= json_object_new_array();
9501 if (json_nexthop_global
)
9502 json_object_array_add(json_nexthops
,
9503 json_nexthop_global
);
9505 if (json_nexthop_ll
)
9506 json_object_array_add(json_nexthops
,
9509 json_object_object_add(json_path
, "nexthops",
9513 json_object_array_add(json_paths
, json_path
);
9517 if (safi
== SAFI_EVPN
) {
9518 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9519 /* XXX - add these params to the json out */
9520 vty_out(vty
, "%*s", 20, " ");
9521 vty_out(vty
, "ESI:%s",
9522 esi_to_str(&attr
->esi
, esi_buf
,
9528 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9529 vty_out(vty
, "%*s", 20, " ");
9530 vty_out(vty
, "%s\n",
9531 bgp_attr_get_ecommunity(attr
)->str
);
9535 #ifdef ENABLE_BGP_VNC
9536 /* prints an additional line, indented, with VNC info, if
9538 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9539 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9544 /* called from terminal list command */
9545 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9546 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9547 bool use_json
, json_object
*json_ar
, bool wide
)
9549 json_object
*json_status
= NULL
;
9550 json_object
*json_net
= NULL
;
9554 /* Route status display. */
9556 json_status
= json_object_new_object();
9557 json_net
= json_object_new_object();
9564 /* print prefix and mask */
9566 if (safi
== SAFI_EVPN
)
9567 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9568 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9569 json_object_string_add(
9570 json_net
, "addrPrefix",
9571 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9573 json_object_int_add(json_net
, "prefixLen",
9575 json_object_string_addf(json_net
, "network", "%pFX", p
);
9578 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9580 /* Print attribute */
9583 if (p
->family
== AF_INET
&&
9584 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9585 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9586 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9587 json_object_string_addf(
9588 json_net
, "nextHop", "%pI4",
9589 &attr
->mp_nexthop_global_in
);
9591 json_object_string_addf(
9592 json_net
, "nextHop", "%pI4",
9594 } else if (p
->family
== AF_INET6
||
9595 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9596 json_object_string_addf(
9597 json_net
, "nextHopGlobal", "%pI6",
9598 &attr
->mp_nexthop_global
);
9599 } else if (p
->family
== AF_EVPN
&&
9600 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9601 json_object_string_addf(
9602 json_net
, "nextHop", "%pI4",
9603 &attr
->mp_nexthop_global_in
);
9607 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9608 json_object_int_add(json_net
, "metric",
9611 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9612 json_object_int_add(json_net
, "locPrf",
9615 json_object_int_add(json_net
, "weight", attr
->weight
);
9619 json_object_string_add(json_net
, "path",
9623 #if CONFDATE > 20231208
9624 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9626 json_object_string_add(json_net
, "bgpOriginCode",
9627 bgp_origin_str
[attr
->origin
]);
9628 json_object_string_add(
9630 bgp_origin_long_str
[attr
->origin
]);
9632 if (p
->family
== AF_INET
&&
9633 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9634 safi
== SAFI_EVPN
||
9635 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9636 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9637 || safi
== SAFI_EVPN
)
9638 vty_out(vty
, "%-16pI4",
9639 &attr
->mp_nexthop_global_in
);
9641 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9643 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9644 } else if (p
->family
== AF_INET6
||
9645 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9646 len
= vty_out(vty
, "%pI6",
9647 &attr
->mp_nexthop_global
);
9648 len
= wide
? (41 - len
) : (16 - len
);
9650 vty_out(vty
, "\n%*s", 36, " ");
9652 vty_out(vty
, "%*s", len
, " ");
9655 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9657 vty_out(vty
, "%7u", attr
->med
);
9659 vty_out(vty
, "%10u", attr
->med
);
9665 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9666 vty_out(vty
, "%7u", attr
->local_pref
);
9670 vty_out(vty
, "%7u ", attr
->weight
);
9674 aspath_print_vty(vty
, attr
->aspath
);
9677 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9681 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9683 #if CONFDATE > 20231208
9684 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9686 json_object_boolean_true_add(json_status
, "*");
9687 json_object_boolean_true_add(json_status
, ">");
9688 json_object_boolean_true_add(json_net
, "valid");
9689 json_object_boolean_true_add(json_net
, "best");
9691 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9692 json_object_boolean_true_add(json_status
, "=");
9693 json_object_boolean_true_add(json_net
, "multipath");
9695 json_object_object_add(json_net
, "appliedStatusSymbols",
9697 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9702 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9703 struct bgp_path_info
*path
, int display
, safi_t safi
,
9706 json_object
*json_out
= NULL
;
9708 mpls_label_t label
= MPLS_INVALID_LABEL
;
9714 json_out
= json_object_new_object();
9716 /* short status lead text */
9717 route_vty_short_status_out(vty
, path
, p
, json_out
);
9719 /* print prefix and mask */
9722 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9724 vty_out(vty
, "%*s", 17, " ");
9727 /* Print attribute */
9729 if (((p
->family
== AF_INET
) &&
9730 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9731 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9732 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9733 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9734 || safi
== SAFI_EVPN
) {
9736 json_object_string_addf(
9737 json_out
, "mpNexthopGlobalIn", "%pI4",
9738 &attr
->mp_nexthop_global_in
);
9740 vty_out(vty
, "%-16pI4",
9741 &attr
->mp_nexthop_global_in
);
9744 json_object_string_addf(json_out
, "nexthop",
9745 "%pI4", &attr
->nexthop
);
9747 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9749 } else if (((p
->family
== AF_INET6
) &&
9750 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9751 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9752 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9755 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9757 json_object_string_addf(
9758 json_out
, "mpNexthopGlobalIn", "%pI6",
9759 &attr
->mp_nexthop_global
);
9763 &attr
->mp_nexthop_global
,
9764 buf_a
, sizeof(buf_a
)));
9765 } else if (attr
->mp_nexthop_len
9766 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9767 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9768 &attr
->mp_nexthop_global
,
9769 &attr
->mp_nexthop_local
);
9771 json_object_string_add(json_out
,
9772 "mpNexthopGlobalLocal",
9775 vty_out(vty
, "%s", buf_a
);
9779 label
= decode_label(&path
->extra
->label
[0]);
9781 if (bgp_is_valid_label(&label
)) {
9783 json_object_int_add(json_out
, "notag", label
);
9784 json_object_array_add(json
, json_out
);
9786 vty_out(vty
, "notag/%d", label
);
9793 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9794 struct bgp_path_info
*path
, int display
,
9795 json_object
*json_paths
)
9798 json_object
*json_path
= NULL
;
9799 json_object
*json_nexthop
= NULL
;
9800 json_object
*json_overlay
= NULL
;
9806 json_path
= json_object_new_object();
9807 json_overlay
= json_object_new_object();
9808 json_nexthop
= json_object_new_object();
9811 /* short status lead text */
9812 route_vty_short_status_out(vty
, path
, p
, json_path
);
9814 /* print prefix and mask */
9816 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9818 vty_out(vty
, "%*s", 17, " ");
9820 /* Print attribute */
9822 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9827 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9829 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9830 &attr
->mp_nexthop_global_in
);
9832 json_object_string_add(json_nexthop
, "afi", "ipv4");
9834 json_object_object_add(json_path
, "nexthop",
9840 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9841 &attr
->mp_nexthop_local
);
9843 json_object_string_addf(json_nexthop
, "ipv6Global",
9845 &attr
->mp_nexthop_global
);
9847 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9849 &attr
->mp_nexthop_local
);
9851 json_object_string_add(json_nexthop
, "afi", "ipv6");
9853 json_object_object_add(json_path
, "nexthop",
9861 json_object_string_add(json_nexthop
, "error",
9862 "Unsupported address-family");
9866 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9869 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9871 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9873 if (bgp_attr_get_ecommunity(attr
)) {
9875 struct ecommunity_val
*routermac
= ecommunity_lookup(
9876 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9877 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9880 mac
= ecom_mac2str((char *)routermac
->val
);
9883 vty_out(vty
, "/%s", mac
);
9885 json_object_string_add(json_overlay
, "rmac",
9888 XFREE(MTYPE_TMP
, mac
);
9895 json_object_object_add(json_path
, "overlay", json_overlay
);
9897 json_object_array_add(json_paths
, json_path
);
9901 /* dampening route */
9902 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9903 struct bgp_path_info
*path
, int display
,
9904 afi_t afi
, safi_t safi
, bool use_json
,
9905 json_object
*json_paths
)
9907 struct attr
*attr
= path
->attr
;
9909 char timebuf
[BGP_UPTIME_LEN
];
9910 json_object
*json_path
= NULL
;
9913 json_path
= json_object_new_object();
9915 /* short status lead text */
9916 route_vty_short_status_out(vty
, path
, p
, json_path
);
9918 /* print prefix and mask */
9921 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9923 vty_out(vty
, "%*s", 17, " ");
9925 len
= vty_out(vty
, "%s", path
->peer
->host
);
9929 vty_out(vty
, "\n%*s", 34, " ");
9931 vty_out(vty
, "%*s", len
, " ");
9934 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9935 BGP_UPTIME_LEN
, afi
, safi
,
9939 aspath_print_vty(vty
, attr
->aspath
);
9941 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9945 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9946 safi
, use_json
, json_path
);
9949 json_object_string_add(json_path
, "asPath",
9952 json_object_string_add(json_path
, "origin",
9953 bgp_origin_str
[attr
->origin
]);
9954 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9956 json_object_array_add(json_paths
, json_path
);
9961 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9962 struct bgp_path_info
*path
, int display
,
9963 afi_t afi
, safi_t safi
, bool use_json
,
9964 json_object
*json_paths
)
9966 struct attr
*attr
= path
->attr
;
9967 struct bgp_damp_info
*bdi
;
9968 char timebuf
[BGP_UPTIME_LEN
];
9970 json_object
*json_path
= NULL
;
9976 json_path
= json_object_new_object();
9978 bdi
= path
->extra
->damp_info
;
9980 /* short status lead text */
9981 route_vty_short_status_out(vty
, path
, p
, json_path
);
9985 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9987 vty_out(vty
, "%*s", 17, " ");
9989 len
= vty_out(vty
, "%s", path
->peer
->host
);
9992 vty_out(vty
, "\n%*s", 33, " ");
9994 vty_out(vty
, "%*s", len
, " ");
9996 len
= vty_out(vty
, "%d", bdi
->flap
);
10001 vty_out(vty
, "%*s", len
, " ");
10003 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10004 BGP_UPTIME_LEN
, 0, NULL
));
10006 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10007 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10008 vty_out(vty
, "%s ",
10009 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10010 BGP_UPTIME_LEN
, afi
,
10011 safi
, use_json
, NULL
));
10013 vty_out(vty
, "%*s ", 8, " ");
10016 aspath_print_vty(vty
, attr
->aspath
);
10018 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10020 vty_out(vty
, "\n");
10022 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10023 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10025 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10028 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10029 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10030 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10031 BGP_UPTIME_LEN
, afi
, safi
,
10032 use_json
, json_path
);
10035 json_object_string_add(json_path
, "asPath",
10036 attr
->aspath
->str
);
10038 json_object_string_add(json_path
, "origin",
10039 bgp_origin_str
[attr
->origin
]);
10041 json_object_array_add(json_paths
, json_path
);
10045 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10046 int *first
, const char *header
,
10047 json_object
*json_adv_to
)
10049 json_object
*json_peer
= NULL
;
10052 /* 'advertised-to' is a dictionary of peers we have advertised
10054 * prefix too. The key is the peer's IP or swpX, the value is
10056 * hostname if we know it and "" if not.
10058 json_peer
= json_object_new_object();
10060 if (peer
->hostname
)
10061 json_object_string_add(json_peer
, "hostname",
10065 json_object_object_add(json_adv_to
, peer
->conf_if
,
10068 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10072 vty_out(vty
, "%s", header
);
10077 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10079 vty_out(vty
, " %s(%s)", peer
->hostname
,
10082 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10086 vty_out(vty
, " %s", peer
->conf_if
);
10088 vty_out(vty
, " %pSU", &peer
->su
);
10093 static void route_vty_out_tx_ids(struct vty
*vty
,
10094 struct bgp_addpath_info_data
*d
)
10098 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10099 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10100 d
->addpath_tx_id
[i
],
10101 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10105 static void route_vty_out_detail_es_info(struct vty
*vty
,
10106 struct bgp_path_info
*pi
,
10108 json_object
*json_path
)
10110 char esi_buf
[ESI_STR_LEN
];
10111 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10112 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10113 ATTR_ES_PEER_ROUTER
);
10114 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10115 ATTR_ES_PEER_ACTIVE
);
10116 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10117 ATTR_ES_PEER_PROXY
);
10118 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10120 json_object
*json_es_info
= NULL
;
10122 json_object_string_add(
10125 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10126 json_es_info
= json_object_new_object();
10128 json_object_boolean_true_add(
10129 json_es_info
, "localEs");
10131 json_object_boolean_true_add(
10132 json_es_info
, "peerActive");
10134 json_object_boolean_true_add(
10135 json_es_info
, "peerProxy");
10137 json_object_boolean_true_add(
10138 json_es_info
, "peerRouter");
10139 if (attr
->mm_sync_seqnum
)
10140 json_object_int_add(
10141 json_es_info
, "peerSeq",
10142 attr
->mm_sync_seqnum
);
10143 json_object_object_add(
10144 json_path
, "es_info",
10148 if (bgp_evpn_attr_is_sync(attr
))
10150 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10152 es_local
? "local-es":"",
10153 peer_proxy
? "proxy " : "",
10154 peer_active
? "active ":"",
10155 peer_router
? "router ":"",
10156 attr
->mm_sync_seqnum
);
10158 vty_out(vty
, " ESI %s %s\n",
10160 es_local
? "local-es":"");
10164 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10165 const struct prefix
*p
, struct bgp_path_info
*path
,
10166 afi_t afi
, safi_t safi
,
10167 enum rpki_states rpki_curr_state
,
10168 json_object
*json_paths
)
10170 char buf
[INET6_ADDRSTRLEN
];
10172 struct attr
*attr
= path
->attr
;
10174 json_object
*json_bestpath
= NULL
;
10175 json_object
*json_cluster_list
= NULL
;
10176 json_object
*json_cluster_list_list
= NULL
;
10177 json_object
*json_ext_community
= NULL
;
10178 json_object
*json_last_update
= NULL
;
10179 json_object
*json_pmsi
= NULL
;
10180 json_object
*json_nexthop_global
= NULL
;
10181 json_object
*json_nexthop_ll
= NULL
;
10182 json_object
*json_nexthops
= NULL
;
10183 json_object
*json_path
= NULL
;
10184 json_object
*json_peer
= NULL
;
10185 json_object
*json_string
= NULL
;
10186 json_object
*json_adv_to
= NULL
;
10188 struct listnode
*node
, *nnode
;
10190 bool addpath_capable
;
10192 unsigned int first_as
;
10193 bool nexthop_self
=
10194 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10196 char *nexthop_hostname
=
10197 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10201 mpls_label_t label
= MPLS_INVALID_LABEL
;
10203 struct bgp_path_info
*bpi_ultimate
=
10204 bgp_get_imported_bpi_ultimate(path
);
10207 json_path
= json_object_new_object();
10208 json_peer
= json_object_new_object();
10209 json_nexthop_global
= json_object_new_object();
10212 if (safi
== SAFI_EVPN
) {
10214 vty_out(vty
, " Route %pFX", p
);
10218 if (path
->extra
&& path
->extra
->num_labels
) {
10219 bgp_evpn_label2str(path
->extra
->label
,
10220 path
->extra
->num_labels
, tag_buf
,
10223 if (safi
== SAFI_EVPN
) {
10225 if (tag_buf
[0] != '\0')
10226 vty_out(vty
, " VNI %s", tag_buf
);
10229 json_object_string_add(json_path
, "vni",
10235 if (safi
== SAFI_EVPN
10236 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10237 char gwip_buf
[INET6_ADDRSTRLEN
];
10239 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10243 json_object_string_add(json_path
, "gatewayIP",
10246 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10249 if (safi
== SAFI_EVPN
&& !json_path
)
10250 vty_out(vty
, "\n");
10253 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10254 struct bgp_path_info
*parent_ri
;
10255 struct bgp_dest
*dest
, *pdest
;
10257 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10258 dest
= parent_ri
->net
;
10259 if (dest
&& dest
->pdest
) {
10260 pdest
= dest
->pdest
;
10261 if (is_pi_family_evpn(parent_ri
)) {
10263 " Imported from %pRD:%pFX, VNI %s",
10264 (struct prefix_rd
*)bgp_dest_get_prefix(
10266 (struct prefix_evpn
*)
10267 bgp_dest_get_prefix(dest
),
10269 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10270 vty_out(vty
, ", L3NHG %s",
10273 ATTR_ES_L3_NHG_ACTIVE
)
10276 vty_out(vty
, "\n");
10279 vty_out(vty
, " Imported from %pRD:%pFX\n",
10280 (struct prefix_rd
*)bgp_dest_get_prefix(
10282 (struct prefix_evpn
*)
10283 bgp_dest_get_prefix(dest
));
10287 /* Line1 display AS-path, Aggregator */
10288 if (attr
->aspath
) {
10290 if (!attr
->aspath
->json
)
10291 aspath_str_update(attr
->aspath
, true);
10292 json_object_lock(attr
->aspath
->json
);
10293 json_object_object_add(json_path
, "aspath",
10294 attr
->aspath
->json
);
10296 if (attr
->aspath
->segments
)
10297 vty_out(vty
, " %s", attr
->aspath
->str
);
10299 vty_out(vty
, " Local");
10303 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10305 json_object_boolean_true_add(json_path
, "removed");
10307 vty_out(vty
, ", (removed)");
10310 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10312 json_object_boolean_true_add(json_path
, "stale");
10314 vty_out(vty
, ", (stale)");
10317 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10319 json_object_int_add(json_path
, "aggregatorAs",
10320 attr
->aggregator_as
);
10321 json_object_string_addf(json_path
, "aggregatorId",
10322 "%pI4", &attr
->aggregator_addr
);
10324 vty_out(vty
, ", (aggregated by %u %pI4)",
10325 attr
->aggregator_as
, &attr
->aggregator_addr
);
10329 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10330 PEER_FLAG_REFLECTOR_CLIENT
)) {
10332 json_object_boolean_true_add(json_path
,
10333 "rxedFromRrClient");
10335 vty_out(vty
, ", (Received from a RR-client)");
10338 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10339 PEER_FLAG_RSERVER_CLIENT
)) {
10341 json_object_boolean_true_add(json_path
,
10342 "rxedFromRsClient");
10344 vty_out(vty
, ", (Received from a RS-client)");
10347 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10349 json_object_boolean_true_add(json_path
,
10350 "dampeningHistoryEntry");
10352 vty_out(vty
, ", (history entry)");
10353 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10355 json_object_boolean_true_add(json_path
,
10356 "dampeningSuppressed");
10358 vty_out(vty
, ", (suppressed due to dampening)");
10362 vty_out(vty
, "\n");
10364 /* Line2 display Next-hop, Neighbor, Router-id */
10365 /* Display the nexthop */
10367 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10368 p
->family
== AF_EVPN
) &&
10369 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10370 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10371 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10372 || safi
== SAFI_EVPN
) {
10374 json_object_string_addf(
10375 json_nexthop_global
, "ip", "%pI4",
10376 &attr
->mp_nexthop_global_in
);
10378 if (path
->peer
->hostname
)
10379 json_object_string_add(
10380 json_nexthop_global
, "hostname",
10381 path
->peer
->hostname
);
10383 if (nexthop_hostname
)
10384 vty_out(vty
, " %pI4(%s)",
10385 &attr
->mp_nexthop_global_in
,
10388 vty_out(vty
, " %pI4",
10389 &attr
->mp_nexthop_global_in
);
10393 json_object_string_addf(json_nexthop_global
,
10397 if (path
->peer
->hostname
)
10398 json_object_string_add(
10399 json_nexthop_global
, "hostname",
10400 path
->peer
->hostname
);
10402 if (nexthop_hostname
)
10403 vty_out(vty
, " %pI4(%s)",
10407 vty_out(vty
, " %pI4",
10413 json_object_string_add(json_nexthop_global
, "afi",
10417 json_object_string_addf(json_nexthop_global
, "ip",
10419 &attr
->mp_nexthop_global
);
10421 if (path
->peer
->hostname
)
10422 json_object_string_add(json_nexthop_global
,
10424 path
->peer
->hostname
);
10426 json_object_string_add(json_nexthop_global
, "afi",
10428 json_object_string_add(json_nexthop_global
, "scope",
10431 if (nexthop_hostname
)
10432 vty_out(vty
, " %pI6(%s)",
10433 &attr
->mp_nexthop_global
,
10436 vty_out(vty
, " %pI6",
10437 &attr
->mp_nexthop_global
);
10441 /* Display the IGP cost or 'inaccessible' */
10442 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10443 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10446 json_object_boolean_false_add(json_nexthop_global
,
10448 json_object_boolean_add(json_nexthop_global
,
10449 "importCheckEnabled", import
);
10451 vty_out(vty
, " (inaccessible%s)",
10452 import
? ", import-check enabled" : "");
10455 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10457 json_object_int_add(
10458 json_nexthop_global
, "metric",
10459 bpi_ultimate
->extra
->igpmetric
);
10461 vty_out(vty
, " (metric %u)",
10462 bpi_ultimate
->extra
->igpmetric
);
10465 /* IGP cost is 0, display this only for json */
10468 json_object_int_add(json_nexthop_global
,
10473 json_object_boolean_true_add(json_nexthop_global
,
10477 /* Display peer "from" output */
10478 /* This path was originated locally */
10479 if (path
->peer
== bgp
->peer_self
) {
10481 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10482 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10484 json_object_string_add(json_peer
, "peerId",
10487 vty_out(vty
, " from 0.0.0.0 ");
10490 json_object_string_add(json_peer
, "peerId",
10493 vty_out(vty
, " from :: ");
10497 json_object_string_addf(json_peer
, "routerId", "%pI4",
10500 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10503 /* We RXed this path from one of our peers */
10507 json_object_string_addf(json_peer
, "peerId", "%pSU",
10509 json_object_string_addf(json_peer
, "routerId", "%pI4",
10510 &path
->peer
->remote_id
);
10512 if (path
->peer
->hostname
)
10513 json_object_string_add(json_peer
, "hostname",
10514 path
->peer
->hostname
);
10516 if (path
->peer
->domainname
)
10517 json_object_string_add(json_peer
, "domainname",
10518 path
->peer
->domainname
);
10520 if (path
->peer
->conf_if
)
10521 json_object_string_add(json_peer
, "interface",
10522 path
->peer
->conf_if
);
10524 if (path
->peer
->conf_if
) {
10525 if (path
->peer
->hostname
10526 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10527 BGP_FLAG_SHOW_HOSTNAME
))
10528 vty_out(vty
, " from %s(%s)",
10529 path
->peer
->hostname
,
10530 path
->peer
->conf_if
);
10532 vty_out(vty
, " from %s",
10533 path
->peer
->conf_if
);
10535 if (path
->peer
->hostname
10536 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10537 BGP_FLAG_SHOW_HOSTNAME
))
10538 vty_out(vty
, " from %s(%s)",
10539 path
->peer
->hostname
,
10542 vty_out(vty
, " from %pSU",
10546 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10547 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10549 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10554 * Note when vrfid of nexthop is different from that of prefix
10556 if (path
->extra
&& path
->extra
->bgp_orig
) {
10557 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10562 if (path
->extra
->bgp_orig
->inst_type
10563 == BGP_INSTANCE_TYPE_DEFAULT
)
10564 vn
= VRF_DEFAULT_NAME
;
10566 vn
= path
->extra
->bgp_orig
->name
;
10568 json_object_string_add(json_path
, "nhVrfName", vn
);
10570 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10571 json_object_int_add(json_path
, "nhVrfId", -1);
10573 json_object_int_add(json_path
, "nhVrfId",
10574 (int)nexthop_vrfid
);
10577 if (nexthop_vrfid
== VRF_UNKNOWN
)
10578 vty_out(vty
, " vrf ?");
10582 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10583 vty_out(vty
, " vrf %s(%u)",
10584 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10589 if (nexthop_self
) {
10591 json_object_boolean_true_add(json_path
,
10592 "announceNexthopSelf");
10594 vty_out(vty
, " announce-nh-self");
10599 vty_out(vty
, "\n");
10601 /* display the link-local nexthop */
10602 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10604 json_nexthop_ll
= json_object_new_object();
10605 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10606 &attr
->mp_nexthop_local
);
10608 if (path
->peer
->hostname
)
10609 json_object_string_add(json_nexthop_ll
,
10611 path
->peer
->hostname
);
10613 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10614 json_object_string_add(json_nexthop_ll
, "scope",
10617 json_object_boolean_true_add(json_nexthop_ll
,
10620 if (!attr
->mp_nexthop_prefer_global
)
10621 json_object_boolean_true_add(json_nexthop_ll
,
10624 json_object_boolean_true_add(
10625 json_nexthop_global
, "used");
10627 vty_out(vty
, " (%s) %s\n",
10628 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10629 buf
, INET6_ADDRSTRLEN
),
10630 attr
->mp_nexthop_prefer_global
10631 ? "(prefer-global)"
10635 /* If we do not have a link-local nexthop then we must flag the
10636 global as "used" */
10639 json_object_boolean_true_add(json_nexthop_global
,
10643 if (safi
== SAFI_EVPN
&&
10644 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10645 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10648 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10649 * Int/Ext/Local, Atomic, best */
10651 json_object_string_add(json_path
, "origin",
10652 bgp_origin_long_str
[attr
->origin
]);
10654 vty_out(vty
, " Origin %s",
10655 bgp_origin_long_str
[attr
->origin
]);
10657 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10659 json_object_int_add(json_path
, "metric", attr
->med
);
10661 vty_out(vty
, ", metric %u", attr
->med
);
10664 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10666 json_object_int_add(json_path
, "locPrf",
10669 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10672 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10674 json_object_int_add(json_path
, "aigpMetric",
10675 bgp_attr_get_aigp_metric(attr
));
10677 vty_out(vty
, ", aigp-metric %" PRIu64
,
10678 bgp_attr_get_aigp_metric(attr
));
10681 if (attr
->weight
!= 0) {
10683 json_object_int_add(json_path
, "weight", attr
->weight
);
10685 vty_out(vty
, ", weight %u", attr
->weight
);
10688 if (attr
->tag
!= 0) {
10690 json_object_int_add(json_path
, "tag", attr
->tag
);
10692 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10695 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10697 json_object_boolean_false_add(json_path
, "valid");
10699 vty_out(vty
, ", invalid");
10700 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10702 json_object_boolean_true_add(json_path
, "valid");
10704 vty_out(vty
, ", valid");
10708 json_object_int_add(json_path
, "version", bn
->version
);
10710 if (path
->peer
!= bgp
->peer_self
) {
10711 if (path
->peer
->as
== path
->peer
->local_as
) {
10712 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10714 json_object_string_add(
10716 "confed-internal");
10718 vty_out(vty
, ", confed-internal");
10721 json_object_string_add(
10722 json_peer
, "type", "internal");
10724 vty_out(vty
, ", internal");
10727 if (bgp_confederation_peers_check(bgp
,
10730 json_object_string_add(
10732 "confed-external");
10734 vty_out(vty
, ", confed-external");
10737 json_object_string_add(
10738 json_peer
, "type", "external");
10740 vty_out(vty
, ", external");
10743 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10745 json_object_boolean_true_add(json_path
, "aggregated");
10746 json_object_boolean_true_add(json_path
, "local");
10748 vty_out(vty
, ", aggregated, local");
10750 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10752 json_object_boolean_true_add(json_path
, "sourced");
10754 vty_out(vty
, ", sourced");
10757 json_object_boolean_true_add(json_path
, "sourced");
10758 json_object_boolean_true_add(json_path
, "local");
10760 vty_out(vty
, ", sourced, local");
10764 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10766 json_object_boolean_true_add(json_path
,
10767 "atomicAggregate");
10769 vty_out(vty
, ", atomic-aggregate");
10772 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10774 json_object_int_add(json_path
, "otc", attr
->otc
);
10776 vty_out(vty
, ", otc %u", attr
->otc
);
10779 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10780 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10781 && bgp_path_info_mpath_count(path
))) {
10783 json_object_boolean_true_add(json_path
, "multipath");
10785 vty_out(vty
, ", multipath");
10788 // Mark the bestpath(s)
10789 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10790 first_as
= aspath_get_first_as(attr
->aspath
);
10793 if (!json_bestpath
)
10794 json_bestpath
= json_object_new_object();
10795 json_object_int_add(json_bestpath
, "bestpathFromAs",
10799 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10801 vty_out(vty
, ", bestpath-from-AS Local");
10805 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10807 if (!json_bestpath
)
10808 json_bestpath
= json_object_new_object();
10809 json_object_boolean_true_add(json_bestpath
, "overall");
10810 json_object_string_add(
10811 json_bestpath
, "selectionReason",
10812 bgp_path_selection_reason2str(bn
->reason
));
10814 vty_out(vty
, ", best");
10815 vty_out(vty
, " (%s)",
10816 bgp_path_selection_reason2str(bn
->reason
));
10820 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10822 json_object_string_add(
10823 json_path
, "rpkiValidationState",
10824 bgp_rpki_validation2str(rpki_curr_state
));
10826 vty_out(vty
, ", rpki validation-state: %s",
10827 bgp_rpki_validation2str(rpki_curr_state
));
10831 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10834 vty_out(vty
, "\n");
10836 /* Line 4 display Community */
10837 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10839 if (!bgp_attr_get_community(attr
)->json
)
10840 community_str(bgp_attr_get_community(attr
),
10842 json_object_lock(bgp_attr_get_community(attr
)->json
);
10843 json_object_object_add(
10844 json_path
, "community",
10845 bgp_attr_get_community(attr
)->json
);
10847 vty_out(vty
, " Community: %s\n",
10848 bgp_attr_get_community(attr
)->str
);
10852 /* Line 5 display Extended-community */
10853 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10855 json_ext_community
= json_object_new_object();
10856 json_object_string_add(
10857 json_ext_community
, "string",
10858 bgp_attr_get_ecommunity(attr
)->str
);
10859 json_object_object_add(json_path
, "extendedCommunity",
10860 json_ext_community
);
10862 vty_out(vty
, " Extended Community: %s\n",
10863 bgp_attr_get_ecommunity(attr
)->str
);
10867 /* Line 6 display Large community */
10868 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10870 if (!bgp_attr_get_lcommunity(attr
)->json
)
10871 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10873 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10874 json_object_object_add(
10875 json_path
, "largeCommunity",
10876 bgp_attr_get_lcommunity(attr
)->json
);
10878 vty_out(vty
, " Large Community: %s\n",
10879 bgp_attr_get_lcommunity(attr
)->str
);
10883 /* Line 7 display Originator, Cluster-id */
10884 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10885 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10886 char buf
[BUFSIZ
] = {0};
10888 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10890 json_object_string_addf(json_path
,
10891 "originatorId", "%pI4",
10892 &attr
->originator_id
);
10894 vty_out(vty
, " Originator: %pI4",
10895 &attr
->originator_id
);
10898 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10899 struct cluster_list
*cluster
=
10900 bgp_attr_get_cluster(attr
);
10904 json_cluster_list
= json_object_new_object();
10905 json_cluster_list_list
=
10906 json_object_new_array();
10908 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10909 json_string
= json_object_new_string(
10912 buf
, sizeof(buf
)));
10913 json_object_array_add(
10914 json_cluster_list_list
,
10919 * struct cluster_list does not have
10920 * "str" variable like aspath and community
10921 * do. Add this someday if someone asks
10923 * json_object_string_add(json_cluster_list,
10924 * "string", cluster->str);
10926 json_object_object_add(json_cluster_list
,
10928 json_cluster_list_list
);
10929 json_object_object_add(json_path
, "clusterList",
10930 json_cluster_list
);
10932 vty_out(vty
, ", Cluster list: ");
10934 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10935 vty_out(vty
, "%pI4 ",
10936 &cluster
->list
[i
]);
10942 vty_out(vty
, "\n");
10945 if (path
->extra
&& path
->extra
->damp_info
)
10946 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10949 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10950 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10951 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10955 json_object_int_add(json_path
, "remoteLabel", label
);
10957 vty_out(vty
, " Remote label: %d\n", label
);
10961 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10963 json_object_string_addf(json_path
, "remoteSid", "%pI6",
10964 &path
->extra
->sid
[0].sid
);
10966 vty_out(vty
, " Remote SID: %pI6\n",
10967 &path
->extra
->sid
[0].sid
);
10971 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10973 json_object_int_add(json_path
, "labelIndex",
10974 attr
->label_index
);
10976 vty_out(vty
, " Label Index: %d\n",
10977 attr
->label_index
);
10980 /* Line 8 display Addpath IDs */
10981 if (path
->addpath_rx_id
10982 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10984 json_object_int_add(json_path
, "addpathRxId",
10985 path
->addpath_rx_id
);
10987 /* Keep backwards compatibility with the old API
10988 * by putting TX All's ID in the old field
10990 json_object_int_add(
10991 json_path
, "addpathTxId",
10993 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10995 /* ... but create a specific field for each
10998 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10999 json_object_int_add(
11001 bgp_addpath_names(i
)->id_json_name
,
11002 path
->tx_addpath
.addpath_tx_id
[i
]);
11005 vty_out(vty
, " AddPath ID: RX %u, ",
11006 path
->addpath_rx_id
);
11008 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11012 /* If we used addpath to TX a non-bestpath we need to display
11013 * "Advertised to" on a path-by-path basis
11015 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11018 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11020 bgp_addpath_encode_tx(peer
, afi
, safi
);
11021 has_adj
= bgp_adj_out_lookup(
11023 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11024 &path
->tx_addpath
));
11026 if ((addpath_capable
&& has_adj
)
11027 || (!addpath_capable
&& has_adj
11028 && CHECK_FLAG(path
->flags
,
11029 BGP_PATH_SELECTED
))) {
11030 if (json_path
&& !json_adv_to
)
11031 json_adv_to
= json_object_new_object();
11033 route_vty_out_advertised_to(
11035 " Advertised to:", json_adv_to
);
11041 json_object_object_add(
11042 json_path
, "advertisedTo", json_adv_to
);
11046 vty_out(vty
, "\n");
11051 /* Line 9 display Uptime */
11052 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11054 json_last_update
= json_object_new_object();
11055 json_object_int_add(json_last_update
, "epoch", tbuf
);
11056 json_object_string_add(json_last_update
, "string",
11058 json_object_object_add(json_path
, "lastUpdate",
11061 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11063 /* Line 10 display PMSI tunnel attribute, if present */
11064 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11065 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11066 bgp_attr_get_pmsi_tnl_type(attr
),
11067 PMSI_TNLTYPE_STR_DEFAULT
);
11070 json_pmsi
= json_object_new_object();
11071 json_object_string_add(json_pmsi
, "tunnelType", str
);
11072 json_object_int_add(json_pmsi
, "label",
11073 label2vni(&attr
->label
));
11074 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11076 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11077 str
, label2vni(&attr
->label
));
11080 if (path
->peer
->t_gr_restart
&&
11081 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11082 unsigned long gr_remaining
=
11083 thread_timer_remain_second(path
->peer
->t_gr_restart
);
11086 json_object_int_add(json_path
,
11087 "gracefulRestartSecondsRemaining",
11091 " Time until Graceful Restart stale route deleted: %lu\n",
11095 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11096 bgp_attr_get_community(attr
) &&
11097 community_include(bgp_attr_get_community(attr
),
11098 COMMUNITY_LLGR_STALE
)) {
11099 unsigned long llgr_remaining
= thread_timer_remain_second(
11100 path
->peer
->t_llgr_stale
[afi
][safi
]);
11103 json_object_int_add(json_path
, "llgrSecondsRemaining",
11107 " Time until Long-lived stale route deleted: %lu\n",
11111 /* Output some debug about internal state of the dest flags */
11113 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11114 json_object_boolean_true_add(json_path
, "processScheduled");
11115 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11116 json_object_boolean_true_add(json_path
, "userCleared");
11117 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11118 json_object_boolean_true_add(json_path
, "labelChanged");
11119 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11120 json_object_boolean_true_add(json_path
, "registeredForLabel");
11121 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11122 json_object_boolean_true_add(json_path
, "selectDefered");
11123 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11124 json_object_boolean_true_add(json_path
, "fibInstalled");
11125 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11126 json_object_boolean_true_add(json_path
, "fibPending");
11128 if (json_nexthop_global
|| json_nexthop_ll
) {
11129 json_nexthops
= json_object_new_array();
11131 if (json_nexthop_global
)
11132 json_object_array_add(json_nexthops
,
11133 json_nexthop_global
);
11135 if (json_nexthop_ll
)
11136 json_object_array_add(json_nexthops
,
11139 json_object_object_add(json_path
, "nexthops",
11143 json_object_object_add(json_path
, "peer", json_peer
);
11144 json_object_array_add(json_paths
, json_path
);
11148 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11149 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11150 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11152 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11153 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11155 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11156 const char *comstr
, int exact
, afi_t afi
,
11157 safi_t safi
, uint16_t show_flags
);
11159 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11160 struct bgp_table
*table
, enum bgp_show_type type
,
11161 void *output_arg
, const char *rd
, int is_last
,
11162 unsigned long *output_cum
, unsigned long *total_cum
,
11163 unsigned long *json_header_depth
, uint16_t show_flags
,
11164 enum rpki_states rpki_target_state
)
11166 struct bgp_path_info
*pi
;
11167 struct bgp_dest
*dest
;
11168 bool header
= true;
11169 bool json_detail_header
= false;
11171 unsigned long output_count
= 0;
11172 unsigned long total_count
= 0;
11174 json_object
*json_paths
= NULL
;
11176 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11177 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11178 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11179 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11180 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11182 if (output_cum
&& *output_cum
!= 0)
11185 if (use_json
&& !*json_header_depth
) {
11187 *json_header_depth
= 1;
11189 vty_out(vty
, "{\n");
11190 *json_header_depth
= 2;
11194 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11195 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11196 " \"localAS\": %u,\n \"routes\": { ",
11197 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11198 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11201 table
->version
, &bgp
->router_id
,
11202 bgp
->default_local_pref
, bgp
->as
);
11204 vty_out(vty
, " \"routeDistinguishers\" : {");
11205 ++*json_header_depth
;
11209 if (use_json
&& rd
) {
11210 vty_out(vty
, " \"%s\" : { ", rd
);
11213 /* Check for 'json detail', where we need header output once per dest */
11214 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11215 type
!= bgp_show_type_damp_neighbor
&&
11216 type
!= bgp_show_type_flap_statistics
&&
11217 type
!= bgp_show_type_flap_neighbor
)
11218 json_detail_header
= true;
11220 /* Start processing of routes. */
11221 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11222 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11223 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11224 bool json_detail
= json_detail_header
;
11226 pi
= bgp_dest_get_bgp_path_info(dest
);
11232 json_paths
= json_object_new_array();
11236 for (; pi
; pi
= pi
->next
) {
11237 struct community
*picomm
= NULL
;
11239 picomm
= bgp_attr_get_community(pi
->attr
);
11243 if (type
== bgp_show_type_prefix_version
) {
11245 strtoul(output_arg
, NULL
, 10);
11246 if (dest
->version
< version
)
11250 if (type
== bgp_show_type_community_alias
) {
11251 char *alias
= output_arg
;
11252 char **communities
;
11254 bool found
= false;
11257 frrstr_split(picomm
->str
, " ",
11258 &communities
, &num
);
11259 for (int i
= 0; i
< num
; i
++) {
11260 const char *com2alias
=
11261 bgp_community2alias(
11264 && strcmp(alias
, com2alias
)
11270 XFREE(MTYPE_TMP
, communities
);
11274 bgp_attr_get_lcommunity(pi
->attr
)) {
11275 frrstr_split(bgp_attr_get_lcommunity(
11278 " ", &communities
, &num
);
11279 for (int i
= 0; i
< num
; i
++) {
11280 const char *com2alias
=
11281 bgp_community2alias(
11284 && strcmp(alias
, com2alias
)
11290 XFREE(MTYPE_TMP
, communities
);
11297 if (type
== bgp_show_type_rpki
) {
11298 if (dest_p
->family
== AF_INET
11299 || dest_p
->family
== AF_INET6
)
11300 rpki_curr_state
= hook_call(
11301 bgp_rpki_prefix_status
,
11302 pi
->peer
, pi
->attr
, dest_p
);
11303 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11304 && rpki_curr_state
!= rpki_target_state
)
11308 if (type
== bgp_show_type_flap_statistics
11309 || type
== bgp_show_type_flap_neighbor
11310 || type
== bgp_show_type_dampend_paths
11311 || type
== bgp_show_type_damp_neighbor
) {
11312 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11315 if (type
== bgp_show_type_regexp
) {
11316 regex_t
*regex
= output_arg
;
11318 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11322 if (type
== bgp_show_type_prefix_list
) {
11323 struct prefix_list
*plist
= output_arg
;
11325 if (prefix_list_apply(plist
, dest_p
)
11329 if (type
== bgp_show_type_access_list
) {
11330 struct access_list
*alist
= output_arg
;
11332 if (access_list_apply(alist
, dest_p
) !=
11336 if (type
== bgp_show_type_filter_list
) {
11337 struct as_list
*as_list
= output_arg
;
11339 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11340 != AS_FILTER_PERMIT
)
11343 if (type
== bgp_show_type_route_map
) {
11344 struct route_map
*rmap
= output_arg
;
11345 struct bgp_path_info path
;
11346 struct bgp_path_info_extra extra
;
11347 struct attr dummy_attr
= {};
11348 route_map_result_t ret
;
11350 dummy_attr
= *pi
->attr
;
11352 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11353 pi
->peer
, &dummy_attr
);
11355 ret
= route_map_apply(rmap
, dest_p
, &path
);
11356 bgp_attr_flush(&dummy_attr
);
11357 if (ret
== RMAP_DENYMATCH
)
11360 if (type
== bgp_show_type_neighbor
11361 || type
== bgp_show_type_flap_neighbor
11362 || type
== bgp_show_type_damp_neighbor
) {
11363 union sockunion
*su
= output_arg
;
11365 if (pi
->peer
== NULL
11366 || pi
->peer
->su_remote
== NULL
11367 || !sockunion_same(pi
->peer
->su_remote
, su
))
11370 if (type
== bgp_show_type_cidr_only
) {
11371 uint32_t destination
;
11373 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11374 if (IN_CLASSC(destination
)
11375 && dest_p
->prefixlen
== 24)
11377 if (IN_CLASSB(destination
)
11378 && dest_p
->prefixlen
== 16)
11380 if (IN_CLASSA(destination
)
11381 && dest_p
->prefixlen
== 8)
11384 if (type
== bgp_show_type_prefix_longer
) {
11386 if (!prefix_match(p
, dest_p
))
11389 if (type
== bgp_show_type_community_all
) {
11393 if (type
== bgp_show_type_community
) {
11394 struct community
*com
= output_arg
;
11396 if (!picomm
|| !community_match(picomm
, com
))
11399 if (type
== bgp_show_type_community_exact
) {
11400 struct community
*com
= output_arg
;
11402 if (!picomm
|| !community_cmp(picomm
, com
))
11405 if (type
== bgp_show_type_community_list
) {
11406 struct community_list
*list
= output_arg
;
11408 if (!community_list_match(picomm
, list
))
11411 if (type
== bgp_show_type_community_list_exact
) {
11412 struct community_list
*list
= output_arg
;
11414 if (!community_list_exact_match(picomm
, list
))
11417 if (type
== bgp_show_type_lcommunity
) {
11418 struct lcommunity
*lcom
= output_arg
;
11420 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11422 bgp_attr_get_lcommunity(pi
->attr
),
11427 if (type
== bgp_show_type_lcommunity_exact
) {
11428 struct lcommunity
*lcom
= output_arg
;
11430 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11432 bgp_attr_get_lcommunity(pi
->attr
),
11436 if (type
== bgp_show_type_lcommunity_list
) {
11437 struct community_list
*list
= output_arg
;
11439 if (!lcommunity_list_match(
11440 bgp_attr_get_lcommunity(pi
->attr
),
11445 == bgp_show_type_lcommunity_list_exact
) {
11446 struct community_list
*list
= output_arg
;
11448 if (!lcommunity_list_exact_match(
11449 bgp_attr_get_lcommunity(pi
->attr
),
11453 if (type
== bgp_show_type_lcommunity_all
) {
11454 if (!bgp_attr_get_lcommunity(pi
->attr
))
11457 if (type
== bgp_show_type_dampend_paths
11458 || type
== bgp_show_type_damp_neighbor
) {
11459 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11460 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11464 if (!use_json
&& header
) {
11466 "BGP table version is %" PRIu64
11467 ", local router ID is %pI4, vrf id ",
11468 table
->version
, &bgp
->router_id
);
11469 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11470 vty_out(vty
, "%s", VRFID_NONE_STR
);
11472 vty_out(vty
, "%u", bgp
->vrf_id
);
11473 vty_out(vty
, "\n");
11474 vty_out(vty
, "Default local pref %u, ",
11475 bgp
->default_local_pref
);
11476 vty_out(vty
, "local AS %u\n", bgp
->as
);
11477 if (!detail_routes
) {
11478 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11479 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11480 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11481 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11483 if (type
== bgp_show_type_dampend_paths
11484 || type
== bgp_show_type_damp_neighbor
)
11485 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11486 else if (type
== bgp_show_type_flap_statistics
11487 || type
== bgp_show_type_flap_neighbor
)
11488 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11489 else if (!detail_routes
)
11490 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11491 : BGP_SHOW_HEADER
));
11494 } else if (json_detail
&& json_paths
!= NULL
) {
11495 const struct prefix_rd
*prd
;
11496 json_object
*jtemp
;
11498 /* Use common detail header, for most types;
11499 * need a json 'object'.
11502 jtemp
= json_object_new_object();
11503 prd
= bgp_rd_from_dest(dest
, safi
);
11505 route_vty_out_detail_header(
11507 bgp_dest_get_prefix(dest
), prd
,
11508 table
->afi
, safi
, jtemp
);
11510 json_object_array_add(json_paths
, jtemp
);
11512 json_detail
= false;
11515 if (rd
!= NULL
&& !display
&& !output_count
) {
11518 "Route Distinguisher: %s\n",
11521 if (type
== bgp_show_type_dampend_paths
11522 || type
== bgp_show_type_damp_neighbor
)
11523 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11524 AFI_IP
, safi
, use_json
,
11526 else if (type
== bgp_show_type_flap_statistics
11527 || type
== bgp_show_type_flap_neighbor
)
11528 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11529 AFI_IP
, safi
, use_json
,
11532 if (detail_routes
|| detail_json
) {
11533 const struct prefix_rd
*prd
= NULL
;
11536 prd
= bgp_rd_from_dest(
11537 dest
->pdest
, safi
);
11540 route_vty_out_detail_header(
11542 bgp_dest_get_prefix(
11544 prd
, table
->afi
, safi
,
11547 route_vty_out_detail(
11548 vty
, bgp
, dest
, dest_p
, pi
,
11549 family2afi(dest_p
->family
),
11550 safi
, RPKI_NOT_BEING_USED
,
11553 route_vty_out(vty
, dest_p
, pi
, display
,
11554 safi
, json_paths
, wide
);
11565 /* encode prefix */
11566 if (dest_p
->family
== AF_FLOWSPEC
) {
11567 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11570 bgp_fs_nlri_get_string(
11572 dest_p
->u
.prefix_flowspec
.ptr
,
11573 dest_p
->u
.prefix_flowspec
.prefixlen
,
11574 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11575 family2afi(dest_p
->u
11576 .prefix_flowspec
.family
));
11578 vty_out(vty
, "\"%s/%d\": ", retstr
,
11579 dest_p
->u
.prefix_flowspec
11582 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11583 dest_p
->u
.prefix_flowspec
11587 vty_out(vty
, "\"%pFX\": ", dest_p
);
11589 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11592 * We are using no_pretty here because under
11593 * extremely high settings( say lots and lots of
11594 * routes with lots and lots of ways to reach
11595 * that route via different paths ) this can
11596 * save several minutes of output when FRR
11597 * is run on older cpu's or more underperforming
11598 * routers out there
11600 vty_json_no_pretty(vty
, json_paths
);
11604 json_object_free(json_paths
);
11608 output_count
+= *output_cum
;
11609 *output_cum
= output_count
;
11612 total_count
+= *total_cum
;
11613 *total_cum
= total_count
;
11617 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11621 for (i
= 0; i
< *json_header_depth
; ++i
)
11622 vty_out(vty
, " } ");
11624 vty_out(vty
, "\n");
11628 /* No route is displayed */
11629 if (output_count
== 0) {
11630 if (type
== bgp_show_type_normal
)
11632 "No BGP prefixes displayed, %ld exist\n",
11636 "\nDisplayed %ld routes and %ld total paths\n",
11637 output_count
, total_count
);
11641 return CMD_SUCCESS
;
11644 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11645 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11646 enum bgp_show_type type
, void *output_arg
,
11647 uint16_t show_flags
)
11649 struct bgp_dest
*dest
, *next
;
11650 unsigned long output_cum
= 0;
11651 unsigned long total_cum
= 0;
11652 unsigned long json_header_depth
= 0;
11653 struct bgp_table
*itable
;
11655 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11657 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11659 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11660 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11662 next
= bgp_route_next(dest
);
11663 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11666 itable
= bgp_dest_get_bgp_table_info(dest
);
11667 if (itable
!= NULL
) {
11668 struct prefix_rd prd
;
11669 char rd
[RD_ADDRSTRLEN
];
11671 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11672 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11673 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11674 rd
, next
== NULL
, &output_cum
,
11675 &total_cum
, &json_header_depth
,
11676 show_flags
, RPKI_NOT_BEING_USED
);
11682 if (output_cum
== 0)
11683 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11687 "\nDisplayed %ld routes and %ld total paths\n",
11688 output_cum
, total_cum
);
11690 if (use_json
&& output_cum
== 0)
11691 vty_out(vty
, "{}\n");
11693 return CMD_SUCCESS
;
11696 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11697 enum bgp_show_type type
, void *output_arg
,
11698 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11700 struct bgp_table
*table
;
11701 unsigned long json_header_depth
= 0;
11702 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11705 bgp
= bgp_get_default();
11710 vty_out(vty
, "No BGP process is configured\n");
11712 vty_out(vty
, "{}\n");
11713 return CMD_WARNING
;
11716 /* Labeled-unicast routes live in the unicast table. */
11717 if (safi
== SAFI_LABELED_UNICAST
)
11718 safi
= SAFI_UNICAST
;
11720 table
= bgp
->rib
[afi
][safi
];
11721 /* use MPLS and ENCAP specific shows until they are merged */
11722 if (safi
== SAFI_MPLS_VPN
) {
11723 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11724 output_arg
, show_flags
);
11727 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11728 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11729 output_arg
, use_json
,
11733 if (safi
== SAFI_EVPN
)
11734 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11736 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11737 NULL
, NULL
, &json_header_depth
, show_flags
,
11738 rpki_target_state
);
11741 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11742 safi_t safi
, uint16_t show_flags
)
11744 struct listnode
*node
, *nnode
;
11747 bool route_output
= false;
11748 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11751 vty_out(vty
, "{\n");
11753 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11754 route_output
= true;
11757 vty_out(vty
, ",\n");
11761 vty_out(vty
, "\"%s\":",
11762 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11766 vty_out(vty
, "\nInstance %s:\n",
11767 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11771 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11772 show_flags
, RPKI_NOT_BEING_USED
);
11776 vty_out(vty
, "}\n");
11777 else if (!route_output
)
11778 vty_out(vty
, "%% BGP instance not found\n");
11781 /* Header of detailed BGP route information */
11782 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11783 struct bgp_dest
*dest
, const struct prefix
*p
,
11784 const struct prefix_rd
*prd
, afi_t afi
,
11785 safi_t safi
, json_object
*json
)
11787 struct bgp_path_info
*pi
;
11789 struct listnode
*node
, *nnode
;
11790 char buf1
[RD_ADDRSTRLEN
];
11794 int accept_own
= 0;
11795 int route_filter_translated_v4
= 0;
11796 int route_filter_v4
= 0;
11797 int route_filter_translated_v6
= 0;
11798 int route_filter_v6
= 0;
11799 int llgr_stale
= 0;
11801 int accept_own_nexthop
= 0;
11804 int no_advertise
= 0;
11808 int has_valid_label
= 0;
11809 mpls_label_t label
= 0;
11810 json_object
*json_adv_to
= NULL
;
11815 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11817 has_valid_label
= bgp_is_valid_label(&label
);
11819 if (safi
== SAFI_EVPN
) {
11821 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11822 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11824 prd
? ":" : "", (struct prefix_evpn
*)p
);
11826 json_object_string_add(json
, "rd",
11827 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11829 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11834 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11836 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11837 ? prefix_rd2str(prd
, buf1
,
11840 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11844 json_object_string_addf(json
, "prefix", "%pFX", p
);
11845 json_object_int_add(json
, "version", dest
->version
);
11850 if (has_valid_label
) {
11852 json_object_int_add(json
, "localLabel", label
);
11854 vty_out(vty
, "Local label: %d\n", label
);
11858 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11859 vty_out(vty
, "not allocated\n");
11861 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11862 struct community
*picomm
= NULL
;
11864 picomm
= bgp_attr_get_community(pi
->attr
);
11867 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11869 if (bgp_path_suppressed(pi
))
11875 no_advertise
+= community_include(
11876 picomm
, COMMUNITY_NO_ADVERTISE
);
11878 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11880 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11882 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11883 route_filter_translated_v4
+= community_include(
11884 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11885 route_filter_translated_v6
+= community_include(
11886 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11887 route_filter_v4
+= community_include(
11888 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11889 route_filter_v6
+= community_include(
11890 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11892 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11893 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11894 accept_own_nexthop
+= community_include(
11895 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11897 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11898 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11903 vty_out(vty
, "Paths: (%d available", count
);
11905 vty_out(vty
, ", best #%d", best
);
11906 if (safi
== SAFI_UNICAST
) {
11907 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11908 vty_out(vty
, ", table %s",
11911 vty_out(vty
, ", vrf %s",
11915 vty_out(vty
, ", no best path");
11919 ", accept own local route exported and imported in different VRF");
11920 else if (route_filter_translated_v4
)
11922 ", mark translated RTs for VPNv4 route filtering");
11923 else if (route_filter_v4
)
11925 ", attach RT as-is for VPNv4 route filtering");
11926 else if (route_filter_translated_v6
)
11928 ", mark translated RTs for VPNv6 route filtering");
11929 else if (route_filter_v6
)
11931 ", attach RT as-is for VPNv6 route filtering");
11932 else if (llgr_stale
)
11934 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11937 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11938 else if (accept_own_nexthop
)
11940 ", accept local nexthop");
11941 else if (blackhole
)
11942 vty_out(vty
, ", inform peer to blackhole prefix");
11943 else if (no_export
)
11944 vty_out(vty
, ", not advertised to EBGP peer");
11945 else if (no_advertise
)
11946 vty_out(vty
, ", not advertised to any peer");
11948 vty_out(vty
, ", not advertised outside local AS");
11951 ", inform EBGP peer not to advertise to their EBGP peers");
11955 ", Advertisements suppressed by an aggregate.");
11956 vty_out(vty
, ")\n");
11959 /* If we are not using addpath then we can display Advertised to and
11961 * show what peers we advertised the bestpath to. If we are using
11963 * though then we must display Advertised to on a path-by-path basis. */
11964 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11965 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11966 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11967 if (json
&& !json_adv_to
)
11968 json_adv_to
= json_object_new_object();
11970 route_vty_out_advertised_to(
11972 " Advertised to non peer-group peers:\n ",
11979 json_object_object_add(json
, "advertisedTo",
11984 vty_out(vty
, " Not advertised to any peer");
11985 vty_out(vty
, "\n");
11990 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
11991 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11992 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11993 json_object
*json
, enum bgp_path_type pathtype
,
11994 int *display
, enum rpki_states rpki_target_state
)
11996 struct bgp_path_info
*pi
;
11998 json_object
*json_header
= NULL
;
11999 json_object
*json_paths
= NULL
;
12000 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12002 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12003 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12005 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12006 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12007 pi
->peer
, pi
->attr
, p
);
12009 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12010 && rpki_curr_state
!= rpki_target_state
)
12013 if (json
&& !json_paths
) {
12014 /* Instantiate json_paths only if path is valid */
12015 json_paths
= json_object_new_array();
12017 json_header
= json_object_new_object();
12019 json_header
= json
;
12023 route_vty_out_detail_header(
12024 vty
, bgp
, bgp_node
,
12025 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12026 safi
, json_header
);
12031 if (pathtype
== BGP_PATH_SHOW_ALL
12032 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12033 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12034 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12035 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12036 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12037 route_vty_out_detail(vty
, bgp
, bgp_node
,
12038 bgp_dest_get_prefix(bgp_node
), pi
,
12039 AFI_IP
, safi
, rpki_curr_state
,
12043 if (json
&& json_paths
) {
12044 json_object_object_add(json_header
, "paths", json_paths
);
12047 json_object_object_addf(json
, json_header
, "%pRD",
12053 * Return rd based on safi
12055 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12059 case SAFI_MPLS_VPN
:
12062 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12068 /* Display specified route of BGP table. */
12069 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12070 struct bgp_table
*rib
, const char *ip_str
,
12071 afi_t afi
, safi_t safi
,
12072 enum rpki_states rpki_target_state
,
12073 struct prefix_rd
*prd
, int prefix_check
,
12074 enum bgp_path_type pathtype
, bool use_json
)
12078 struct prefix match
;
12079 struct bgp_dest
*dest
;
12080 struct bgp_dest
*rm
;
12081 struct bgp_table
*table
;
12082 json_object
*json
= NULL
;
12083 json_object
*json_paths
= NULL
;
12085 /* Check IP address argument. */
12086 ret
= str2prefix(ip_str
, &match
);
12088 vty_out(vty
, "address is malformed\n");
12089 return CMD_WARNING
;
12092 match
.family
= afi2family(afi
);
12095 json
= json_object_new_object();
12097 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12098 for (dest
= bgp_table_top(rib
); dest
;
12099 dest
= bgp_route_next(dest
)) {
12100 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12102 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12104 table
= bgp_dest_get_bgp_table_info(dest
);
12108 rm
= bgp_node_match(table
, &match
);
12112 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12114 && rm_p
->prefixlen
!= match
.prefixlen
) {
12115 bgp_dest_unlock_node(rm
);
12119 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12120 bgp
, afi
, safi
, json
, pathtype
,
12121 &display
, rpki_target_state
);
12123 bgp_dest_unlock_node(rm
);
12125 } else if (safi
== SAFI_EVPN
) {
12126 struct bgp_dest
*longest_pfx
;
12127 bool is_exact_pfxlen_match
= false;
12129 for (dest
= bgp_table_top(rib
); dest
;
12130 dest
= bgp_route_next(dest
)) {
12131 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12133 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12135 table
= bgp_dest_get_bgp_table_info(dest
);
12139 longest_pfx
= NULL
;
12140 is_exact_pfxlen_match
= false;
12142 * Search through all the prefixes for a match. The
12143 * pfx's are enumerated in ascending order of pfxlens.
12144 * So, the last pfx match is the longest match. Set
12145 * is_exact_pfxlen_match when we get exact pfxlen match
12147 for (rm
= bgp_table_top(table
); rm
;
12148 rm
= bgp_route_next(rm
)) {
12149 const struct prefix
*rm_p
=
12150 bgp_dest_get_prefix(rm
);
12152 * Get prefixlen of the ip-prefix within type5
12155 if (evpn_type5_prefix_match(rm_p
, &match
)
12159 bgp_evpn_get_type5_prefixlen(
12161 if (type5_pfxlen
== match
.prefixlen
) {
12162 is_exact_pfxlen_match
= true;
12163 bgp_dest_unlock_node(rm
);
12172 if (prefix_check
&& !is_exact_pfxlen_match
)
12176 bgp_dest_lock_node(rm
);
12178 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12179 bgp
, afi
, safi
, json
, pathtype
,
12180 &display
, rpki_target_state
);
12182 bgp_dest_unlock_node(rm
);
12184 } else if (safi
== SAFI_FLOWSPEC
) {
12186 json_paths
= json_object_new_array();
12188 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12189 &match
, prefix_check
,
12195 json_object_object_add(json
, "paths",
12198 json_object_free(json_paths
);
12201 dest
= bgp_node_match(rib
, &match
);
12202 if (dest
!= NULL
) {
12203 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12205 || dest_p
->prefixlen
== match
.prefixlen
) {
12206 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12207 safi
, json
, pathtype
,
12208 &display
, rpki_target_state
);
12211 bgp_dest_unlock_node(dest
);
12216 vty_json(vty
, json
);
12219 vty_out(vty
, "%% Network not in table\n");
12220 return CMD_WARNING
;
12224 return CMD_SUCCESS
;
12227 /* Display specified route of Main RIB */
12228 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12229 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12230 int prefix_check
, enum bgp_path_type pathtype
,
12231 enum rpki_states rpki_target_state
, bool use_json
)
12234 bgp
= bgp_get_default();
12237 vty_out(vty
, "No BGP process is configured\n");
12239 vty_out(vty
, "{}\n");
12240 return CMD_WARNING
;
12244 /* labeled-unicast routes live in the unicast table */
12245 if (safi
== SAFI_LABELED_UNICAST
)
12246 safi
= SAFI_UNICAST
;
12248 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12249 afi
, safi
, rpki_target_state
, prd
,
12250 prefix_check
, pathtype
, use_json
);
12253 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12254 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12255 safi_t safi
, bool uj
)
12257 struct lcommunity
*lcom
;
12262 uint16_t show_flags
= 0;
12266 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12268 b
= buffer_new(1024);
12269 for (i
= 0; i
< argc
; i
++) {
12271 buffer_putc(b
, ' ');
12273 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12275 buffer_putstr(b
, argv
[i
]->arg
);
12279 buffer_putc(b
, '\0');
12281 str
= buffer_getstr(b
);
12284 lcom
= lcommunity_str2com(str
);
12285 XFREE(MTYPE_TMP
, str
);
12287 vty_out(vty
, "%% Large-community malformed\n");
12288 return CMD_WARNING
;
12291 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12292 (exact
? bgp_show_type_lcommunity_exact
12293 : bgp_show_type_lcommunity
),
12294 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12296 lcommunity_free(&lcom
);
12300 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12301 const char *lcom
, bool exact
, afi_t afi
,
12302 safi_t safi
, bool uj
)
12304 struct community_list
*list
;
12305 uint16_t show_flags
= 0;
12308 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12311 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12312 LARGE_COMMUNITY_LIST_MASTER
);
12313 if (list
== NULL
) {
12314 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12316 return CMD_WARNING
;
12319 return bgp_show(vty
, bgp
, afi
, safi
,
12320 (exact
? bgp_show_type_lcommunity_list_exact
12321 : bgp_show_type_lcommunity_list
),
12322 list
, show_flags
, RPKI_NOT_BEING_USED
);
12325 DEFUN (show_ip_bgp_large_community_list
,
12326 show_ip_bgp_large_community_list_cmd
,
12327 "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]",
12331 BGP_INSTANCE_HELP_STR
12333 BGP_SAFI_WITH_LABEL_HELP_STR
12334 "Display routes matching the large-community-list\n"
12335 "large-community-list number\n"
12336 "large-community-list name\n"
12337 "Exact match of the large-communities\n"
12340 afi_t afi
= AFI_IP6
;
12341 safi_t safi
= SAFI_UNICAST
;
12343 bool exact_match
= 0;
12344 struct bgp
*bgp
= NULL
;
12345 bool uj
= use_json(argc
, argv
);
12350 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12353 return CMD_WARNING
;
12355 argv_find(argv
, argc
, "large-community-list", &idx
);
12357 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12359 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12362 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12363 exact_match
, afi
, safi
, uj
);
12365 DEFUN (show_ip_bgp_large_community
,
12366 show_ip_bgp_large_community_cmd
,
12367 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12371 BGP_INSTANCE_HELP_STR
12373 BGP_SAFI_WITH_LABEL_HELP_STR
12374 "Display routes matching the large-communities\n"
12375 "List of large-community numbers\n"
12376 "Exact match of the large-communities\n"
12379 afi_t afi
= AFI_IP6
;
12380 safi_t safi
= SAFI_UNICAST
;
12382 bool exact_match
= 0;
12383 struct bgp
*bgp
= NULL
;
12384 bool uj
= use_json(argc
, argv
);
12385 uint16_t show_flags
= 0;
12389 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12392 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12395 return CMD_WARNING
;
12397 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12398 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12402 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12403 exact_match
, afi
, safi
, uj
);
12405 return bgp_show(vty
, bgp
, afi
, safi
,
12406 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12407 RPKI_NOT_BEING_USED
);
12410 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12411 safi_t safi
, struct json_object
*json_array
);
12412 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12413 safi_t safi
, struct json_object
*json
);
12416 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12417 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12418 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12419 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12421 bool uj
= use_json(argc
, argv
);
12422 struct bgp
*bgp
= NULL
;
12423 safi_t safi
= SAFI_UNICAST
;
12424 afi_t afi
= AFI_IP6
;
12426 struct json_object
*json_all
= NULL
;
12427 struct json_object
*json_afi_safi
= NULL
;
12429 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12432 return CMD_WARNING
;
12435 json_all
= json_object_new_object();
12437 FOREACH_AFI_SAFI (afi
, safi
) {
12439 * So limit output to those afi/safi pairs that
12440 * actually have something interesting in them
12442 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12447 json_afi_safi
= json_object_new_array();
12448 json_object_object_add(
12450 get_afi_safi_str(afi
, safi
, true),
12453 json_afi_safi
= NULL
;
12456 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12460 vty_json(vty
, json_all
);
12462 return CMD_SUCCESS
;
12465 /* BGP route print out function without JSON */
12466 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12467 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12468 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12472 BGP_INSTANCE_HELP_STR
12475 "BGP RIB advertisement statistics\n"
12478 afi_t afi
= AFI_IP6
;
12479 safi_t safi
= SAFI_UNICAST
;
12480 struct bgp
*bgp
= NULL
;
12482 bool uj
= use_json(argc
, argv
);
12483 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12485 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12488 return CMD_WARNING
;
12491 json_afi_safi
= json_object_new_array();
12493 json_afi_safi
= NULL
;
12495 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12498 json
= json_object_new_object();
12499 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12501 vty_json(vty
, json
);
12506 /* BGP route print out function without JSON */
12507 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12508 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12509 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12511 statistics [json]",
12512 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12513 BGP_SAFI_WITH_LABEL_HELP_STR
12514 "BGP RIB advertisement statistics\n" JSON_STR
)
12516 afi_t afi
= AFI_IP6
;
12517 safi_t safi
= SAFI_UNICAST
;
12518 struct bgp
*bgp
= NULL
;
12520 bool uj
= use_json(argc
, argv
);
12521 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12523 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12526 return CMD_WARNING
;
12529 json_afi_safi
= json_object_new_array();
12531 json_afi_safi
= NULL
;
12533 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12536 json
= json_object_new_object();
12537 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12539 vty_json(vty
, json
);
12544 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12545 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12546 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12547 "]] [all$all] dampening parameters [json]",
12548 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12549 BGP_SAFI_WITH_LABEL_HELP_STR
12550 "Display the entries for all address families\n"
12551 "Display detailed information about dampening\n"
12552 "Display detail of configured dampening parameters\n"
12555 afi_t afi
= AFI_IP6
;
12556 safi_t safi
= SAFI_UNICAST
;
12557 struct bgp
*bgp
= NULL
;
12559 uint16_t show_flags
= 0;
12560 bool uj
= use_json(argc
, argv
);
12564 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12567 /* [<ipv4|ipv6> [all]] */
12569 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12570 if (argv_find(argv
, argc
, "ipv4", &idx
))
12571 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12573 if (argv_find(argv
, argc
, "ipv6", &idx
))
12574 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12577 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12580 return CMD_WARNING
;
12582 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12585 /* BGP route print out function */
12586 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12587 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12588 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12592 |dampening <flap-statistics|dampened-paths>\
12593 |community [AA:NN|local-AS|no-advertise|no-export\
12594 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12595 |accept-own|accept-own-nexthop|route-filter-v6\
12596 |route-filter-v4|route-filter-translated-v6\
12597 |route-filter-translated-v4] [exact-match]\
12598 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12599 |filter-list AS_PATH_FILTER_NAME\
12601 |access-list ACCESSLIST_NAME\
12602 |route-map RMAP_NAME\
12603 |rpki <invalid|valid|notfound>\
12604 |version (1-4294967295)\
12606 |A.B.C.D/M longer-prefixes\
12607 |X:X::X:X/M longer-prefixes\
12608 |detail-routes$detail_routes\
12609 ] [json$uj [detail$detail_json] | wide$wide]",
12610 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12611 BGP_SAFI_WITH_LABEL_HELP_STR
12612 "Display the entries for all address families\n"
12613 "Display only routes with non-natural netmasks\n"
12614 "Display detailed information about dampening\n"
12615 "Display flap statistics of routes\n"
12616 "Display paths suppressed due to dampening\n"
12617 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12618 "Do not send outside local AS (well-known community)\n"
12619 "Do not advertise to any peer (well-known community)\n"
12620 "Do not export to next AS (well-known community)\n"
12621 "Graceful shutdown (well-known community)\n"
12622 "Do not export to any peer (well-known community)\n"
12623 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12624 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12625 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12626 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12627 "Should accept VPN route with local nexthop (well-known community)\n"
12628 "RT VPNv6 route filtering (well-known community)\n"
12629 "RT VPNv4 route filtering (well-known community)\n"
12630 "RT translated VPNv6 route filtering (well-known community)\n"
12631 "RT translated VPNv4 route filtering (well-known community)\n"
12632 "Exact match of the communities\n"
12633 "Community-list number\n"
12634 "Community-list name\n"
12635 "Display routes matching the community-list\n"
12636 "Exact match of the communities\n"
12637 "Display routes conforming to the filter-list\n"
12638 "Regular expression access list name\n"
12639 "Display routes conforming to the prefix-list\n"
12640 "Prefix-list name\n"
12641 "Display routes conforming to the access-list\n"
12642 "Access-list name\n"
12643 "Display routes matching the route-map\n"
12644 "A route-map to match on\n"
12645 "RPKI route types\n"
12646 "A valid path as determined by rpki\n"
12647 "A invalid path as determined by rpki\n"
12648 "A path that has no rpki data\n"
12649 "Display prefixes with matching version numbers\n"
12650 "Version number and above\n"
12651 "Display prefixes with matching BGP community alias\n"
12652 "BGP community alias\n"
12654 "Display route and more specific routes\n"
12656 "Display route and more specific routes\n"
12657 "Display detailed version of all routes\n"
12659 "Display detailed version of JSON output\n"
12660 "Increase table width for longer prefixes\n")
12662 afi_t afi
= AFI_IP6
;
12663 safi_t safi
= SAFI_UNICAST
;
12664 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12665 void *output_arg
= NULL
;
12666 struct bgp
*bgp
= NULL
;
12668 int exact_match
= 0;
12669 char *community
= NULL
;
12671 uint16_t show_flags
= 0;
12672 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12677 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12681 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12684 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12686 /* [<ipv4|ipv6> [all]] */
12688 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12690 if (argv_find(argv
, argc
, "ipv4", &idx
))
12691 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12693 if (argv_find(argv
, argc
, "ipv6", &idx
))
12694 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12698 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12700 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12703 return CMD_WARNING
;
12705 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12706 sh_type
= bgp_show_type_cidr_only
;
12708 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12709 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12710 sh_type
= bgp_show_type_dampend_paths
;
12711 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12712 sh_type
= bgp_show_type_flap_statistics
;
12715 if (argv_find(argv
, argc
, "community", &idx
)) {
12716 char *maybecomm
= NULL
;
12718 if (idx
+ 1 < argc
) {
12719 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12720 maybecomm
= argv
[idx
+ 1]->arg
;
12722 maybecomm
= argv
[idx
+ 1]->text
;
12725 if (maybecomm
&& !strmatch(maybecomm
, "json")
12726 && !strmatch(maybecomm
, "exact-match"))
12727 community
= maybecomm
;
12729 if (argv_find(argv
, argc
, "exact-match", &idx
))
12733 sh_type
= bgp_show_type_community_all
;
12736 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12737 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12738 struct community_list
*list
;
12740 if (argv_find(argv
, argc
, "exact-match", &idx
))
12743 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12744 COMMUNITY_LIST_MASTER
);
12745 if (list
== NULL
) {
12746 vty_out(vty
, "%% %s community-list not found\n",
12747 clist_number_or_name
);
12748 return CMD_WARNING
;
12752 sh_type
= bgp_show_type_community_list_exact
;
12754 sh_type
= bgp_show_type_community_list
;
12758 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12759 const char *filter
= argv
[++idx
]->arg
;
12760 struct as_list
*as_list
;
12762 as_list
= as_list_lookup(filter
);
12763 if (as_list
== NULL
) {
12764 vty_out(vty
, "%% %s AS-path access-list not found\n",
12766 return CMD_WARNING
;
12769 sh_type
= bgp_show_type_filter_list
;
12770 output_arg
= as_list
;
12773 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12774 const char *prefix_list_str
= argv
[++idx
]->arg
;
12775 struct prefix_list
*plist
;
12777 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12778 if (plist
== NULL
) {
12779 vty_out(vty
, "%% %s prefix-list not found\n",
12781 return CMD_WARNING
;
12784 sh_type
= bgp_show_type_prefix_list
;
12785 output_arg
= plist
;
12788 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12789 const char *access_list_str
= argv
[++idx
]->arg
;
12790 struct access_list
*alist
;
12792 alist
= access_list_lookup(afi
, access_list_str
);
12794 vty_out(vty
, "%% %s access-list not found\n",
12796 return CMD_WARNING
;
12799 sh_type
= bgp_show_type_access_list
;
12800 output_arg
= alist
;
12803 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12804 const char *rmap_str
= argv
[++idx
]->arg
;
12805 struct route_map
*rmap
;
12807 rmap
= route_map_lookup_by_name(rmap_str
);
12809 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12810 return CMD_WARNING
;
12813 sh_type
= bgp_show_type_route_map
;
12817 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12818 sh_type
= bgp_show_type_rpki
;
12819 if (argv_find(argv
, argc
, "valid", &idx
))
12820 rpki_target_state
= RPKI_VALID
;
12821 else if (argv_find(argv
, argc
, "invalid", &idx
))
12822 rpki_target_state
= RPKI_INVALID
;
12825 /* Display prefixes with matching version numbers */
12826 if (argv_find(argv
, argc
, "version", &idx
)) {
12827 sh_type
= bgp_show_type_prefix_version
;
12828 output_arg
= argv
[idx
+ 1]->arg
;
12831 /* Display prefixes with matching BGP community alias */
12832 if (argv_find(argv
, argc
, "alias", &idx
)) {
12833 sh_type
= bgp_show_type_community_alias
;
12834 output_arg
= argv
[idx
+ 1]->arg
;
12837 /* prefix-longer */
12838 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12839 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12840 const char *prefix_str
= argv
[idx
]->arg
;
12842 if (!str2prefix(prefix_str
, &p
)) {
12843 vty_out(vty
, "%% Malformed Prefix\n");
12844 return CMD_WARNING
;
12847 sh_type
= bgp_show_type_prefix_longer
;
12852 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12854 return bgp_show_community(vty
, bgp
, community
,
12855 exact_match
, afi
, safi
,
12858 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12859 output_arg
, show_flags
,
12860 rpki_target_state
);
12862 struct listnode
*node
;
12864 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12868 vty_out(vty
, "{\n");
12870 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12871 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12872 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12875 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12876 FOREACH_SAFI (safi
) {
12877 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12885 vty_out(vty
, ",\n");
12886 vty_out(vty
, "\"%s\":{\n",
12887 get_afi_safi_str(afi
,
12892 "\nFor address family: %s\n",
12898 bgp_show_community(
12899 vty
, abgp
, community
,
12900 exact_match
, afi
, safi
,
12903 bgp_show(vty
, abgp
, afi
, safi
,
12904 sh_type
, output_arg
,
12906 rpki_target_state
);
12908 vty_out(vty
, "}\n");
12912 /* show <ip> bgp all: for each AFI and SAFI*/
12913 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12914 FOREACH_AFI_SAFI (afi
, safi
) {
12915 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12923 vty_out(vty
, ",\n");
12925 vty_out(vty
, "\"%s\":{\n",
12926 get_afi_safi_str(afi
,
12931 "\nFor address family: %s\n",
12937 bgp_show_community(
12938 vty
, abgp
, community
,
12939 exact_match
, afi
, safi
,
12942 bgp_show(vty
, abgp
, afi
, safi
,
12943 sh_type
, output_arg
,
12945 rpki_target_state
);
12947 vty_out(vty
, "}\n");
12952 vty_out(vty
, "}\n");
12954 return CMD_SUCCESS
;
12957 DEFUN (show_ip_bgp_route
,
12958 show_ip_bgp_route_cmd
,
12959 "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]",
12963 BGP_INSTANCE_HELP_STR
12965 BGP_SAFI_WITH_LABEL_HELP_STR
12966 "Network in the BGP routing table to display\n"
12968 "Network in the BGP routing table to display\n"
12970 "Display only the bestpath\n"
12971 "Display only multipaths\n"
12972 "Display only paths that match the specified rpki state\n"
12973 "A valid path as determined by rpki\n"
12974 "A invalid path as determined by rpki\n"
12975 "A path that has no rpki data\n"
12978 int prefix_check
= 0;
12980 afi_t afi
= AFI_IP6
;
12981 safi_t safi
= SAFI_UNICAST
;
12982 char *prefix
= NULL
;
12983 struct bgp
*bgp
= NULL
;
12984 enum bgp_path_type path_type
;
12985 bool uj
= use_json(argc
, argv
);
12989 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12992 return CMD_WARNING
;
12996 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12997 return CMD_WARNING
;
13000 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13001 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13002 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13004 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13005 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13008 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13009 && afi
!= AFI_IP6
) {
13011 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13012 return CMD_WARNING
;
13014 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13015 && afi
!= AFI_IP
) {
13017 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13018 return CMD_WARNING
;
13021 prefix
= argv
[idx
]->arg
;
13023 /* [<bestpath|multipath>] */
13024 if (argv_find(argv
, argc
, "bestpath", &idx
))
13025 path_type
= BGP_PATH_SHOW_BESTPATH
;
13026 else if (argv_find(argv
, argc
, "multipath", &idx
))
13027 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13029 path_type
= BGP_PATH_SHOW_ALL
;
13031 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13032 path_type
, RPKI_NOT_BEING_USED
, uj
);
13035 DEFUN (show_ip_bgp_regexp
,
13036 show_ip_bgp_regexp_cmd
,
13037 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13041 BGP_INSTANCE_HELP_STR
13043 BGP_SAFI_WITH_LABEL_HELP_STR
13044 "Display routes matching the AS path regular expression\n"
13045 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13048 afi_t afi
= AFI_IP6
;
13049 safi_t safi
= SAFI_UNICAST
;
13050 struct bgp
*bgp
= NULL
;
13051 bool uj
= use_json(argc
, argv
);
13052 char *regstr
= NULL
;
13055 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13058 return CMD_WARNING
;
13060 // get index of regex
13061 if (argv_find(argv
, argc
, "REGEX", &idx
))
13062 regstr
= argv
[idx
]->arg
;
13065 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13066 bgp_show_type_regexp
, uj
);
13069 DEFPY (show_ip_bgp_instance_all
,
13070 show_ip_bgp_instance_all_cmd
,
13071 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13075 BGP_INSTANCE_ALL_HELP_STR
13077 BGP_SAFI_WITH_LABEL_HELP_STR
13079 "Increase table width for longer prefixes\n")
13081 afi_t afi
= AFI_IP6
;
13082 safi_t safi
= SAFI_UNICAST
;
13083 struct bgp
*bgp
= NULL
;
13085 uint16_t show_flags
= 0;
13089 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13093 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13095 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13098 return CMD_WARNING
;
13100 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13101 return CMD_SUCCESS
;
13104 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13105 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13110 uint16_t show_flags
= 0;
13113 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13115 if (!config_bgp_aspath_validate(regstr
)) {
13116 vty_out(vty
, "Invalid character in REGEX %s\n",
13118 return CMD_WARNING_CONFIG_FAILED
;
13121 regex
= bgp_regcomp(regstr
);
13123 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13124 return CMD_WARNING
;
13127 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13128 RPKI_NOT_BEING_USED
);
13129 bgp_regex_free(regex
);
13133 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13134 const char *comstr
, int exact
, afi_t afi
,
13135 safi_t safi
, uint16_t show_flags
)
13137 struct community
*com
;
13140 com
= community_str2com(comstr
);
13142 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13143 return CMD_WARNING
;
13146 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13147 (exact
? bgp_show_type_community_exact
13148 : bgp_show_type_community
),
13149 com
, show_flags
, RPKI_NOT_BEING_USED
);
13150 community_free(&com
);
13156 BGP_STATS_MAXBITLEN
= 0,
13158 BGP_STATS_PREFIXES
,
13160 BGP_STATS_UNAGGREGATEABLE
,
13161 BGP_STATS_MAX_AGGREGATEABLE
,
13162 BGP_STATS_AGGREGATES
,
13164 BGP_STATS_ASPATH_COUNT
,
13165 BGP_STATS_ASPATH_MAXHOPS
,
13166 BGP_STATS_ASPATH_TOTHOPS
,
13167 BGP_STATS_ASPATH_MAXSIZE
,
13168 BGP_STATS_ASPATH_TOTSIZE
,
13169 BGP_STATS_ASN_HIGHEST
,
13173 #define TABLE_STATS_IDX_VTY 0
13174 #define TABLE_STATS_IDX_JSON 1
13176 static const char *table_stats_strs
[][2] = {
13177 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13178 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13179 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13180 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13181 "unaggregateablePrefixes"},
13182 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13183 "maximumAggregateablePrefixes"},
13184 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13185 "bgpAggregateAdvertisements"},
13186 [BGP_STATS_SPACE
] = {"Address space advertised",
13187 "addressSpaceAdvertised"},
13188 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13189 "advertisementsWithPaths"},
13190 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13192 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13194 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13195 "averageAsPathLengthHops"},
13196 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13197 "averageAsPathSizeBytes"},
13198 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13199 [BGP_STATS_MAX
] = {NULL
, NULL
}
13202 struct bgp_table_stats
{
13203 struct bgp_table
*table
;
13204 unsigned long long counts
[BGP_STATS_MAX
];
13207 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13210 double total_space
;
13213 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13214 struct bgp_table_stats
*ts
, unsigned int space
)
13216 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13217 struct bgp_path_info
*pi
;
13218 const struct prefix
*rn_p
;
13220 if (!bgp_dest_has_bgp_path_info_data(dest
))
13223 rn_p
= bgp_dest_get_prefix(dest
);
13224 ts
->counts
[BGP_STATS_PREFIXES
]++;
13225 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13227 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13228 /* check if the prefix is included by any other announcements */
13229 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13230 pdest
= bgp_dest_parent_nolock(pdest
);
13232 if (pdest
== NULL
|| pdest
== top
) {
13233 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13234 /* announced address space */
13236 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13237 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13238 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13241 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13242 ts
->counts
[BGP_STATS_RIB
]++;
13244 if (CHECK_FLAG(pi
->attr
->flag
,
13245 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13246 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13248 /* as-path stats */
13249 if (pi
->attr
->aspath
) {
13250 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13251 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13252 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13254 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13256 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13257 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13259 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13260 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13262 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13263 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13264 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13265 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13270 static void bgp_table_stats_walker(struct thread
*t
)
13272 struct bgp_dest
*dest
, *ndest
;
13273 struct bgp_dest
*top
;
13274 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13275 unsigned int space
= 0;
13277 if (!(top
= bgp_table_top(ts
->table
)))
13280 switch (ts
->table
->afi
) {
13282 space
= IPV4_MAX_BITLEN
;
13285 space
= IPV6_MAX_BITLEN
;
13288 space
= EVPN_ROUTE_PREFIXLEN
;
13294 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13296 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13297 if (ts
->table
->safi
== SAFI_MPLS_VPN
13298 || ts
->table
->safi
== SAFI_ENCAP
13299 || ts
->table
->safi
== SAFI_EVPN
) {
13300 struct bgp_table
*table
;
13302 table
= bgp_dest_get_bgp_table_info(dest
);
13306 top
= bgp_table_top(table
);
13307 for (ndest
= bgp_table_top(table
); ndest
;
13308 ndest
= bgp_route_next(ndest
))
13309 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13311 bgp_table_stats_rn(dest
, top
, ts
, space
);
13316 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13317 struct json_object
*json_array
)
13319 struct listnode
*node
, *nnode
;
13322 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13323 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13326 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13327 safi_t safi
, struct json_object
*json_array
)
13329 struct bgp_table_stats ts
;
13331 int ret
= CMD_SUCCESS
;
13333 struct json_object
*json
= NULL
;
13334 uint32_t bitlen
= 0;
13335 struct json_object
*json_bitlen
;
13338 json
= json_object_new_object();
13340 if (!bgp
->rib
[afi
][safi
]) {
13341 char warning_msg
[50];
13343 snprintf(warning_msg
, sizeof(warning_msg
),
13344 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13348 vty_out(vty
, "%s\n", warning_msg
);
13350 json_object_string_add(json
, "warning", warning_msg
);
13353 goto end_table_stats
;
13357 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13358 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13360 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13362 /* labeled-unicast routes live in the unicast table */
13363 if (safi
== SAFI_LABELED_UNICAST
)
13364 safi
= SAFI_UNICAST
;
13366 memset(&ts
, 0, sizeof(ts
));
13367 ts
.table
= bgp
->rib
[afi
][safi
];
13368 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13370 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13371 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13372 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13376 case BGP_STATS_ASPATH_TOTHOPS
:
13377 case BGP_STATS_ASPATH_TOTSIZE
:
13380 temp_buf
, sizeof(temp_buf
), "%12.2f",
13382 ? (float)ts
.counts
[i
]
13384 [BGP_STATS_ASPATH_COUNT
]
13386 vty_out(vty
, "%-30s: %s",
13387 table_stats_strs
[i
]
13388 [TABLE_STATS_IDX_VTY
],
13391 json_object_double_add(
13393 table_stats_strs
[i
]
13394 [TABLE_STATS_IDX_JSON
],
13396 ? (double)ts
.counts
[i
]
13397 / (double)ts
.counts
13398 [BGP_STATS_ASPATH_COUNT
]
13402 case BGP_STATS_TOTPLEN
:
13405 temp_buf
, sizeof(temp_buf
), "%12.2f",
13407 ? (float)ts
.counts
[i
]
13409 [BGP_STATS_PREFIXES
]
13411 vty_out(vty
, "%-30s: %s",
13412 table_stats_strs
[i
]
13413 [TABLE_STATS_IDX_VTY
],
13416 json_object_double_add(
13418 table_stats_strs
[i
]
13419 [TABLE_STATS_IDX_JSON
],
13421 ? (double)ts
.counts
[i
]
13422 / (double)ts
.counts
13423 [BGP_STATS_PREFIXES
]
13427 case BGP_STATS_SPACE
:
13429 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13431 vty_out(vty
, "%-30s: %s\n",
13432 table_stats_strs
[i
]
13433 [TABLE_STATS_IDX_VTY
],
13436 json_object_double_add(
13438 table_stats_strs
[i
]
13439 [TABLE_STATS_IDX_JSON
],
13440 (double)ts
.total_space
);
13442 if (afi
== AFI_IP6
) {
13444 snprintf(temp_buf
, sizeof(temp_buf
),
13447 * pow(2.0, -128 + 32));
13448 vty_out(vty
, "%30s: %s\n",
13449 "/32 equivalent %s\n",
13452 json_object_double_add(
13453 json
, "/32equivalent",
13454 (double)(ts
.total_space
13459 snprintf(temp_buf
, sizeof(temp_buf
),
13462 * pow(2.0, -128 + 48));
13463 vty_out(vty
, "%30s: %s\n",
13464 "/48 equivalent %s\n",
13467 json_object_double_add(
13468 json
, "/48equivalent",
13469 (double)(ts
.total_space
13475 snprintf(temp_buf
, sizeof(temp_buf
),
13477 ts
.total_space
* 100.
13479 vty_out(vty
, "%30s: %s\n",
13480 "% announced ", temp_buf
);
13482 json_object_double_add(
13483 json
, "%announced",
13484 (double)(ts
.total_space
* 100.
13488 snprintf(temp_buf
, sizeof(temp_buf
),
13491 * pow(2.0, -32 + 8));
13492 vty_out(vty
, "%30s: %s\n",
13493 "/8 equivalent ", temp_buf
);
13495 json_object_double_add(
13496 json
, "/8equivalent",
13497 (double)(ts
.total_space
13498 * pow(2.0, -32 + 8)));
13501 snprintf(temp_buf
, sizeof(temp_buf
),
13504 * pow(2.0, -32 + 24));
13505 vty_out(vty
, "%30s: %s\n",
13506 "/24 equivalent ", temp_buf
);
13508 json_object_double_add(
13509 json
, "/24equivalent",
13510 (double)(ts
.total_space
13511 * pow(2.0, -32 + 24)));
13517 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13519 vty_out(vty
, "%-30s: %s",
13520 table_stats_strs
[i
]
13521 [TABLE_STATS_IDX_VTY
],
13524 json_object_int_add(
13526 table_stats_strs
[i
]
13527 [TABLE_STATS_IDX_JSON
],
13532 vty_out(vty
, "\n");
13537 bitlen
= IPV4_MAX_BITLEN
;
13540 bitlen
= IPV6_MAX_BITLEN
;
13543 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13550 json_bitlen
= json_object_new_array();
13552 for (i
= 0; i
<= bitlen
; i
++) {
13553 struct json_object
*ind_bit
= json_object_new_object();
13555 if (!ts
.prefix_len_count
[i
])
13558 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13559 json_object_int_add(ind_bit
, temp_buf
,
13560 ts
.prefix_len_count
[i
]);
13561 json_object_array_add(json_bitlen
, ind_bit
);
13563 json_object_object_add(json
, "prefixLength", json_bitlen
);
13568 json_object_array_add(json_array
, json
);
13572 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13573 safi_t safi
, struct json_object
*json_array
)
13576 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13577 return CMD_SUCCESS
;
13580 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13592 PCOUNT_BPATH_SELECTED
,
13593 PCOUNT_PFCNT
, /* the figure we display to users */
13597 static const char *const pcount_strs
[] = {
13598 [PCOUNT_ADJ_IN
] = "Adj-in",
13599 [PCOUNT_DAMPED
] = "Damped",
13600 [PCOUNT_REMOVED
] = "Removed",
13601 [PCOUNT_HISTORY
] = "History",
13602 [PCOUNT_STALE
] = "Stale",
13603 [PCOUNT_VALID
] = "Valid",
13604 [PCOUNT_ALL
] = "All RIB",
13605 [PCOUNT_COUNTED
] = "PfxCt counted",
13606 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13607 [PCOUNT_PFCNT
] = "Useable",
13608 [PCOUNT_MAX
] = NULL
,
13611 struct peer_pcounts
{
13612 unsigned int count
[PCOUNT_MAX
];
13613 const struct peer
*peer
;
13614 const struct bgp_table
*table
;
13618 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13620 const struct bgp_adj_in
*ain
;
13621 const struct bgp_path_info
*pi
;
13622 const struct peer
*peer
= pc
->peer
;
13624 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13625 if (ain
->peer
== peer
)
13626 pc
->count
[PCOUNT_ADJ_IN
]++;
13628 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13630 if (pi
->peer
!= peer
)
13633 pc
->count
[PCOUNT_ALL
]++;
13635 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13636 pc
->count
[PCOUNT_DAMPED
]++;
13637 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13638 pc
->count
[PCOUNT_HISTORY
]++;
13639 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13640 pc
->count
[PCOUNT_REMOVED
]++;
13641 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13642 pc
->count
[PCOUNT_STALE
]++;
13643 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13644 pc
->count
[PCOUNT_VALID
]++;
13645 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13646 pc
->count
[PCOUNT_PFCNT
]++;
13647 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13648 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13650 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13651 pc
->count
[PCOUNT_COUNTED
]++;
13652 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13654 EC_LIB_DEVELOPMENT
,
13655 "Attempting to count but flags say it is unusable");
13657 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13659 EC_LIB_DEVELOPMENT
,
13660 "Not counted but flags say we should");
13665 static void bgp_peer_count_walker(struct thread
*t
)
13667 struct bgp_dest
*rn
, *rm
;
13668 const struct bgp_table
*table
;
13669 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13671 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13672 || pc
->safi
== SAFI_EVPN
) {
13673 /* Special handling for 2-level routing tables. */
13674 for (rn
= bgp_table_top(pc
->table
); rn
;
13675 rn
= bgp_route_next(rn
)) {
13676 table
= bgp_dest_get_bgp_table_info(rn
);
13678 for (rm
= bgp_table_top(table
); rm
;
13679 rm
= bgp_route_next(rm
))
13680 bgp_peer_count_proc(rm
, pc
);
13683 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13684 bgp_peer_count_proc(rn
, pc
);
13687 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13688 safi_t safi
, bool use_json
)
13690 struct peer_pcounts pcounts
= {.peer
= peer
};
13692 json_object
*json
= NULL
;
13693 json_object
*json_loop
= NULL
;
13696 json
= json_object_new_object();
13697 json_loop
= json_object_new_object();
13700 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13701 || !peer
->bgp
->rib
[afi
][safi
]) {
13703 json_object_string_add(
13705 "No such neighbor or address family");
13706 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13707 json_object_free(json
);
13708 json_object_free(json_loop
);
13710 vty_out(vty
, "%% No such neighbor or address family\n");
13712 return CMD_WARNING
;
13715 memset(&pcounts
, 0, sizeof(pcounts
));
13716 pcounts
.peer
= peer
;
13717 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13718 pcounts
.safi
= safi
;
13720 /* in-place call via thread subsystem so as to record execution time
13721 * stats for the thread-walk (i.e. ensure this can't be blamed on
13722 * on just vty_read()).
13724 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13727 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13728 json_object_string_add(json
, "multiProtocol",
13729 get_afi_safi_str(afi
, safi
, true));
13730 json_object_int_add(json
, "pfxCounter",
13731 peer
->pcount
[afi
][safi
]);
13733 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13734 json_object_int_add(json_loop
, pcount_strs
[i
],
13737 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13739 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13740 json_object_string_add(json
, "pfxctDriftFor",
13742 json_object_string_add(
13743 json
, "recommended",
13744 "Please report this bug, with the above command output");
13746 vty_json(vty
, json
);
13750 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13751 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13752 peer
->hostname
, peer
->host
,
13753 get_afi_safi_str(afi
, safi
, false));
13755 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13756 get_afi_safi_str(afi
, safi
, false));
13759 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13760 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13762 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13763 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13766 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13767 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13769 "Please report this bug, with the above command output\n");
13773 return CMD_SUCCESS
;
13776 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13777 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13778 "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]",
13782 BGP_INSTANCE_HELP_STR
13785 "Detailed information on TCP and BGP neighbor connections\n"
13786 "Neighbor to display information about\n"
13787 "Neighbor to display information about\n"
13788 "Neighbor on BGP configured interface\n"
13789 "Display detailed prefix count information\n"
13792 afi_t afi
= AFI_IP6
;
13793 safi_t safi
= SAFI_UNICAST
;
13796 struct bgp
*bgp
= NULL
;
13797 bool uj
= use_json(argc
, argv
);
13802 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13805 return CMD_WARNING
;
13807 argv_find(argv
, argc
, "neighbors", &idx
);
13808 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13810 return CMD_WARNING
;
13812 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13815 #ifdef KEEP_OLD_VPN_COMMANDS
13816 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13817 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13818 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13823 "Display information about all VPNv4 NLRIs\n"
13824 "Detailed information on TCP and BGP neighbor connections\n"
13825 "Neighbor to display information about\n"
13826 "Neighbor to display information about\n"
13827 "Neighbor on BGP configured interface\n"
13828 "Display detailed prefix count information\n"
13833 bool uj
= use_json(argc
, argv
);
13835 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13837 return CMD_WARNING
;
13839 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13842 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13843 show_ip_bgp_vpn_all_route_prefix_cmd
,
13844 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13849 "Display information about all VPNv4 NLRIs\n"
13850 "Network in the BGP routing table to display\n"
13851 "Network in the BGP routing table to display\n"
13855 char *network
= NULL
;
13856 struct bgp
*bgp
= bgp_get_default();
13858 vty_out(vty
, "Can't find default instance\n");
13859 return CMD_WARNING
;
13862 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13863 network
= argv
[idx
]->arg
;
13864 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13865 network
= argv
[idx
]->arg
;
13867 vty_out(vty
, "Unable to figure out Network\n");
13868 return CMD_WARNING
;
13871 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13872 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13873 use_json(argc
, argv
));
13875 #endif /* KEEP_OLD_VPN_COMMANDS */
13877 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13878 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13879 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13884 "Network in the BGP routing table to display\n"
13885 "Network in the BGP routing table to display\n"
13886 "Network in the BGP routing table to display\n"
13887 "Network in the BGP routing table to display\n"
13891 char *network
= NULL
;
13892 int prefix_check
= 0;
13894 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13895 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13896 network
= argv
[idx
]->arg
;
13897 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13898 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13899 network
= argv
[idx
]->arg
;
13902 vty_out(vty
, "Unable to figure out Network\n");
13903 return CMD_WARNING
;
13905 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13906 prefix_check
, BGP_PATH_SHOW_ALL
,
13907 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13910 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13911 struct bgp_table
*table
, int *header1
,
13912 int *header2
, json_object
*json
,
13913 json_object
*json_scode
,
13914 json_object
*json_ocode
, bool wide
,
13917 uint64_t version
= table
? table
->version
: 0;
13921 json_object_int_add(json
, "bgpTableVersion", version
);
13922 json_object_string_addf(json
, "bgpLocalRouterId",
13923 "%pI4", &peer
->bgp
->router_id
);
13924 json_object_int_add(json
, "defaultLocPrf",
13925 peer
->bgp
->default_local_pref
);
13926 json_object_int_add(json
, "localAS",
13927 peer
->change_local_as
13928 ? peer
->change_local_as
13930 json_object_object_add(json
, "bgpStatusCodes",
13932 json_object_object_add(json
, "bgpOriginCodes",
13936 "BGP table version is %" PRIu64
13937 ", local router ID is %pI4, vrf id ",
13938 version
, &peer
->bgp
->router_id
);
13939 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
13940 vty_out(vty
, "%s", VRFID_NONE_STR
);
13942 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
13943 vty_out(vty
, "\n");
13944 vty_out(vty
, "Default local pref %u, ",
13945 peer
->bgp
->default_local_pref
);
13946 vty_out(vty
, "local AS %u\n",
13947 peer
->change_local_as
? peer
->change_local_as
13950 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13951 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13952 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13953 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13959 if (!json
&& !detail
)
13960 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13961 : BGP_SHOW_HEADER
));
13967 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13968 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13969 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13970 json_object
*json_scode
, json_object
*json_ocode
,
13971 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13972 unsigned long *output_count
, unsigned long *filtered_count
)
13974 struct bgp_adj_in
*ain
;
13975 struct bgp_adj_out
*adj
;
13976 struct bgp_dest
*dest
;
13980 struct update_subgroup
*subgrp
;
13981 struct peer_af
*paf
;
13982 bool route_filtered
;
13983 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
13984 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13985 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13986 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13987 || (safi
== SAFI_EVPN
))
13991 json_object
*json_net
= NULL
;
13995 subgrp
= peer_subgroup(peer
, afi
, safi
);
13997 if (type
== bgp_show_adj_route_advertised
&& subgrp
13998 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14000 json_object_int_add(json
, "bgpTableVersion",
14002 json_object_string_addf(json
, "bgpLocalRouterId",
14003 "%pI4", &bgp
->router_id
);
14004 json_object_int_add(json
, "defaultLocPrf",
14005 bgp
->default_local_pref
);
14006 json_object_int_add(json
, "localAS",
14007 peer
->change_local_as
14008 ? peer
->change_local_as
14010 json_object_object_add(json
, "bgpStatusCodes",
14012 json_object_object_add(json
, "bgpOriginCodes",
14014 json_object_string_add(
14015 json
, "bgpOriginatingDefaultNetwork",
14016 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14019 "BGP table version is %" PRIu64
14020 ", local router ID is %pI4, vrf id ",
14021 table
->version
, &bgp
->router_id
);
14022 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14023 vty_out(vty
, "%s", VRFID_NONE_STR
);
14025 vty_out(vty
, "%u", bgp
->vrf_id
);
14026 vty_out(vty
, "\n");
14027 vty_out(vty
, "Default local pref %u, ",
14028 bgp
->default_local_pref
);
14029 vty_out(vty
, "local AS %u\n",
14030 peer
->change_local_as
? peer
->change_local_as
14033 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14034 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14035 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14036 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14039 vty_out(vty
, "Originating default network %s\n\n",
14040 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14046 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14047 if (type
== bgp_show_adj_route_received
14048 || type
== bgp_show_adj_route_filtered
) {
14049 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14050 if (ain
->peer
!= peer
)
14053 show_adj_route_header(vty
, peer
, table
, header1
,
14054 header2
, json
, json_scode
,
14055 json_ocode
, wide
, detail
);
14057 if ((safi
== SAFI_MPLS_VPN
)
14058 || (safi
== SAFI_ENCAP
)
14059 || (safi
== SAFI_EVPN
)) {
14061 json_object_string_add(
14062 json_ar
, "rd", rd_str
);
14063 else if (show_rd
&& rd_str
) {
14065 "Route Distinguisher: %s\n",
14072 route_filtered
= false;
14074 /* Filter prefix using distribute list,
14075 * filter list or prefix list
14077 const struct prefix
*rn_p
=
14078 bgp_dest_get_prefix(dest
);
14079 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14082 route_filtered
= true;
14084 /* Filter prefix using route-map */
14085 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14086 safi
, rmap_name
, NULL
,
14089 if (type
== bgp_show_adj_route_filtered
&&
14090 !route_filtered
&& ret
!= RMAP_DENY
) {
14091 bgp_attr_flush(&attr
);
14095 if (type
== bgp_show_adj_route_received
14096 && (route_filtered
|| ret
== RMAP_DENY
))
14097 (*filtered_count
)++;
14102 json_object_new_object();
14103 bgp_show_path_info(
14104 NULL
/* prefix_rd */, dest
, vty
,
14105 bgp
, afi
, safi
, json_net
,
14106 BGP_PATH_SHOW_ALL
, &display
,
14107 RPKI_NOT_BEING_USED
);
14109 json_object_object_addf(
14113 route_vty_out_tmp(vty
, dest
, rn_p
,
14114 &attr
, safi
, use_json
,
14116 bgp_attr_flush(&attr
);
14119 } else if (type
== bgp_show_adj_route_advertised
) {
14120 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14121 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14122 if (paf
->peer
!= peer
|| !adj
->attr
)
14125 show_adj_route_header(
14126 vty
, peer
, table
, header1
,
14127 header2
, json
, json_scode
,
14128 json_ocode
, wide
, detail
);
14130 const struct prefix
*rn_p
=
14131 bgp_dest_get_prefix(dest
);
14134 ret
= bgp_output_modifier(
14135 peer
, rn_p
, &attr
, afi
, safi
,
14138 if (ret
!= RMAP_DENY
) {
14139 if ((safi
== SAFI_MPLS_VPN
)
14140 || (safi
== SAFI_ENCAP
)
14141 || (safi
== SAFI_EVPN
)) {
14143 json_object_string_add(
14150 "Route Distinguisher: %s\n",
14158 json_object_new_object();
14159 bgp_show_path_info(
14168 RPKI_NOT_BEING_USED
);
14170 json_object_object_addf(
14183 (*filtered_count
)++;
14186 bgp_attr_flush(&attr
);
14188 } else if (type
== bgp_show_adj_route_bestpath
) {
14189 struct bgp_path_info
*pi
;
14191 show_adj_route_header(vty
, peer
, table
, header1
,
14192 header2
, json
, json_scode
,
14193 json_ocode
, wide
, detail
);
14195 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14197 if (pi
->peer
!= peer
)
14200 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14203 route_vty_out_tmp(vty
, dest
,
14204 bgp_dest_get_prefix(dest
),
14205 pi
->attr
, safi
, use_json
,
14213 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14214 safi_t safi
, enum bgp_show_adj_route_type type
,
14215 const char *rmap_name
, uint16_t show_flags
)
14218 struct bgp_table
*table
;
14219 json_object
*json
= NULL
;
14220 json_object
*json_scode
= NULL
;
14221 json_object
*json_ocode
= NULL
;
14222 json_object
*json_ar
= NULL
;
14223 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14225 /* Init BGP headers here so they're only displayed once
14226 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14232 * Initialize variables for each RD
14233 * All prefixes under an RD is aggregated within "json_routes"
14235 char rd_str
[BUFSIZ
] = {0};
14236 json_object
*json_routes
= NULL
;
14239 /* For 2-tier tables, prefix counts need to be
14240 * maintained across multiple runs of show_adj_route()
14242 unsigned long output_count_per_rd
;
14243 unsigned long filtered_count_per_rd
;
14244 unsigned long output_count
= 0;
14245 unsigned long filtered_count
= 0;
14248 json
= json_object_new_object();
14249 json_ar
= json_object_new_object();
14250 json_scode
= json_object_new_object();
14251 json_ocode
= json_object_new_object();
14252 #if CONFDATE > 20231208
14253 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14255 json_object_string_add(json_scode
, "suppressed", "s");
14256 json_object_string_add(json_scode
, "damped", "d");
14257 json_object_string_add(json_scode
, "history", "h");
14258 json_object_string_add(json_scode
, "valid", "*");
14259 json_object_string_add(json_scode
, "best", ">");
14260 json_object_string_add(json_scode
, "multipath", "=");
14261 json_object_string_add(json_scode
, "internal", "i");
14262 json_object_string_add(json_scode
, "ribFailure", "r");
14263 json_object_string_add(json_scode
, "stale", "S");
14264 json_object_string_add(json_scode
, "removed", "R");
14266 #if CONFDATE > 20231208
14267 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14269 json_object_string_add(json_ocode
, "igp", "i");
14270 json_object_string_add(json_ocode
, "egp", "e");
14271 json_object_string_add(json_ocode
, "incomplete", "?");
14274 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14276 json_object_string_add(
14278 "No such neighbor or address family");
14279 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14280 json_object_free(json
);
14281 json_object_free(json_ar
);
14282 json_object_free(json_scode
);
14283 json_object_free(json_ocode
);
14285 vty_out(vty
, "%% No such neighbor or address family\n");
14287 return CMD_WARNING
;
14290 if ((type
== bgp_show_adj_route_received
14291 || type
== bgp_show_adj_route_filtered
)
14292 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14293 PEER_FLAG_SOFT_RECONFIG
)) {
14295 json_object_string_add(
14297 "Inbound soft reconfiguration not enabled");
14298 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14299 json_object_free(json
);
14300 json_object_free(json_ar
);
14301 json_object_free(json_scode
);
14302 json_object_free(json_ocode
);
14305 "%% Inbound soft reconfiguration not enabled\n");
14307 return CMD_WARNING
;
14312 /* labeled-unicast routes live in the unicast table */
14313 if (safi
== SAFI_LABELED_UNICAST
)
14314 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14316 table
= bgp
->rib
[afi
][safi
];
14318 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14319 || (safi
== SAFI_EVPN
)) {
14321 struct bgp_dest
*dest
;
14323 for (dest
= bgp_table_top(table
); dest
;
14324 dest
= bgp_route_next(dest
)) {
14325 table
= bgp_dest_get_bgp_table_info(dest
);
14329 output_count_per_rd
= 0;
14330 filtered_count_per_rd
= 0;
14333 json_routes
= json_object_new_object();
14335 const struct prefix_rd
*prd
;
14336 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14339 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
14341 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
14342 rmap_name
, json
, json_routes
, json_scode
,
14343 json_ocode
, show_flags
, &header1
,
14344 &header2
, rd_str
, &output_count_per_rd
,
14345 &filtered_count_per_rd
);
14347 /* Don't include an empty RD in the output! */
14348 if (json_routes
&& (output_count_per_rd
> 0))
14349 json_object_object_add(json_ar
, rd_str
,
14352 output_count
+= output_count_per_rd
;
14353 filtered_count
+= filtered_count_per_rd
;
14356 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14357 json
, json_ar
, json_scode
, json_ocode
,
14358 show_flags
, &header1
, &header2
, rd_str
,
14359 &output_count
, &filtered_count
);
14362 if (type
== bgp_show_adj_route_advertised
)
14363 json_object_object_add(json
, "advertisedRoutes",
14366 json_object_object_add(json
, "receivedRoutes", json_ar
);
14367 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14368 json_object_int_add(json
, "filteredPrefixCounter",
14372 * These fields only give up ownership to `json` when `header1`
14373 * is used (set to zero). See code in `show_adj_route` and
14374 * `show_adj_route_header`.
14376 if (header1
== 1) {
14377 json_object_free(json_scode
);
14378 json_object_free(json_ocode
);
14381 vty_json(vty
, json
);
14382 } else if (output_count
> 0) {
14383 if (filtered_count
> 0)
14385 "\nTotal number of prefixes %ld (%ld filtered)\n",
14386 output_count
, filtered_count
);
14388 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14392 return CMD_SUCCESS
;
14395 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14396 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14397 "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 [json$uj | wide$wide]",
14401 BGP_INSTANCE_HELP_STR
14403 BGP_SAFI_WITH_LABEL_HELP_STR
14404 "Detailed information on TCP and BGP neighbor connections\n"
14405 "Neighbor to display information about\n"
14406 "Neighbor to display information about\n"
14407 "Neighbor on BGP configured interface\n"
14408 "Display the routes selected by best path\n"
14410 "Increase table width for longer prefixes\n")
14412 afi_t afi
= AFI_IP6
;
14413 safi_t safi
= SAFI_UNICAST
;
14414 char *rmap_name
= NULL
;
14415 char *peerstr
= NULL
;
14416 struct bgp
*bgp
= NULL
;
14418 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14420 uint16_t show_flags
= 0;
14423 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14426 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14428 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14432 return CMD_WARNING
;
14434 argv_find(argv
, argc
, "neighbors", &idx
);
14435 peerstr
= argv
[++idx
]->arg
;
14437 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14439 return CMD_WARNING
;
14441 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14445 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14446 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14447 "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] [detail$detail] [json$uj | wide$wide]",
14451 BGP_INSTANCE_HELP_STR
14453 BGP_SAFI_WITH_LABEL_HELP_STR
14454 "Display the entries for all address families\n"
14455 "Detailed information on TCP and BGP neighbor connections\n"
14456 "Neighbor to display information about\n"
14457 "Neighbor to display information about\n"
14458 "Neighbor on BGP configured interface\n"
14459 "Display the routes advertised to a BGP neighbor\n"
14460 "Display the received routes from neighbor\n"
14461 "Display the filtered routes received from neighbor\n"
14462 "Route-map to modify the attributes\n"
14463 "Name of the route map\n"
14464 "Display detailed version of routes\n"
14466 "Increase table width for longer prefixes\n")
14468 afi_t afi
= AFI_IP6
;
14469 safi_t safi
= SAFI_UNICAST
;
14470 char *peerstr
= NULL
;
14471 struct bgp
*bgp
= NULL
;
14473 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14476 uint16_t show_flags
= 0;
14477 struct listnode
*node
;
14481 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14485 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14489 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14490 if (argv_find(argv
, argc
, "ipv4", &idx
))
14491 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14493 if (argv_find(argv
, argc
, "ipv6", &idx
))
14494 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14498 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14500 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14503 return CMD_WARNING
;
14505 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14506 argv_find(argv
, argc
, "neighbors", &idx
);
14507 peerstr
= argv
[++idx
]->arg
;
14509 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14511 return CMD_WARNING
;
14513 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14514 type
= bgp_show_adj_route_advertised
;
14515 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14516 type
= bgp_show_adj_route_received
;
14517 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14518 type
= bgp_show_adj_route_filtered
;
14521 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14524 vty_out(vty
, "{\n");
14526 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14527 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14528 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14530 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14531 FOREACH_SAFI (safi
) {
14532 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14539 vty_out(vty
, ",\n");
14540 vty_out(vty
, "\"%s\":",
14541 get_afi_safi_str(afi
, safi
,
14545 "\nFor address family: %s\n",
14546 get_afi_safi_str(afi
, safi
,
14549 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14550 route_map
, show_flags
);
14554 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14555 FOREACH_AFI_SAFI (afi
, safi
) {
14556 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14563 vty_out(vty
, ",\n");
14564 vty_out(vty
, "\"%s\":",
14565 get_afi_safi_str(afi
, safi
,
14569 "\nFor address family: %s\n",
14570 get_afi_safi_str(afi
, safi
,
14573 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14574 route_map
, show_flags
);
14579 vty_out(vty
, "}\n");
14581 return CMD_SUCCESS
;
14584 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14585 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14586 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14590 BGP_INSTANCE_HELP_STR
14593 BGP_AF_MODIFIER_STR
14594 "Detailed information on TCP and BGP neighbor connections\n"
14595 "Neighbor to display information about\n"
14596 "Neighbor to display information about\n"
14597 "Neighbor on BGP configured interface\n"
14598 "Display information received from a BGP neighbor\n"
14599 "Display the prefixlist filter\n"
14602 afi_t afi
= AFI_IP6
;
14603 safi_t safi
= SAFI_UNICAST
;
14604 char *peerstr
= NULL
;
14609 struct bgp
*bgp
= NULL
;
14610 bool uj
= use_json(argc
, argv
);
14615 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14618 return CMD_WARNING
;
14620 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14621 argv_find(argv
, argc
, "neighbors", &idx
);
14622 peerstr
= argv
[++idx
]->arg
;
14624 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14626 return CMD_WARNING
;
14628 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14629 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14632 vty_out(vty
, "Address Family: %s\n",
14633 get_afi_safi_str(afi
, safi
, false));
14634 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14637 vty_out(vty
, "{}\n");
14639 vty_out(vty
, "No functional output\n");
14642 return CMD_SUCCESS
;
14645 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14646 afi_t afi
, safi_t safi
,
14647 enum bgp_show_type type
, bool use_json
)
14649 uint16_t show_flags
= 0;
14652 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14654 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14656 json_object
*json_no
= NULL
;
14657 json_no
= json_object_new_object();
14658 json_object_string_add(
14659 json_no
, "warning",
14660 "No such neighbor or address family");
14661 vty_out(vty
, "%s\n",
14662 json_object_to_json_string(json_no
));
14663 json_object_free(json_no
);
14665 vty_out(vty
, "%% No such neighbor or address family\n");
14666 return CMD_WARNING
;
14669 /* labeled-unicast routes live in the unicast table */
14670 if (safi
== SAFI_LABELED_UNICAST
)
14671 safi
= SAFI_UNICAST
;
14673 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14674 RPKI_NOT_BEING_USED
);
14677 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14678 show_ip_bgp_flowspec_routes_detailed_cmd
,
14679 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14683 BGP_INSTANCE_HELP_STR
14686 "Detailed information on flowspec entries\n"
14689 afi_t afi
= AFI_IP6
;
14690 safi_t safi
= SAFI_UNICAST
;
14691 struct bgp
*bgp
= NULL
;
14693 bool uj
= use_json(argc
, argv
);
14694 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14698 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14701 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14704 return CMD_WARNING
;
14706 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14707 show_flags
, RPKI_NOT_BEING_USED
);
14710 DEFUN (show_ip_bgp_neighbor_routes
,
14711 show_ip_bgp_neighbor_routes_cmd
,
14712 "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]",
14716 BGP_INSTANCE_HELP_STR
14718 BGP_SAFI_WITH_LABEL_HELP_STR
14719 "Detailed information on TCP and BGP neighbor connections\n"
14720 "Neighbor to display information about\n"
14721 "Neighbor to display information about\n"
14722 "Neighbor on BGP configured interface\n"
14723 "Display flap statistics of the routes learned from neighbor\n"
14724 "Display the dampened routes received from neighbor\n"
14725 "Display routes learned from neighbor\n"
14728 char *peerstr
= NULL
;
14729 struct bgp
*bgp
= NULL
;
14730 afi_t afi
= AFI_IP6
;
14731 safi_t safi
= SAFI_UNICAST
;
14733 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14735 bool uj
= use_json(argc
, argv
);
14740 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14743 return CMD_WARNING
;
14745 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14746 argv_find(argv
, argc
, "neighbors", &idx
);
14747 peerstr
= argv
[++idx
]->arg
;
14749 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14751 return CMD_WARNING
;
14753 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14754 sh_type
= bgp_show_type_flap_neighbor
;
14755 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14756 sh_type
= bgp_show_type_damp_neighbor
;
14757 else if (argv_find(argv
, argc
, "routes", &idx
))
14758 sh_type
= bgp_show_type_neighbor
;
14760 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14763 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14765 struct bgp_distance
{
14766 /* Distance value for the IP source prefix. */
14769 /* Name of the access-list to be matched. */
14773 DEFUN (show_bgp_afi_vpn_rd_route
,
14774 show_bgp_afi_vpn_rd_route_cmd
,
14775 "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]",
14779 BGP_AF_MODIFIER_STR
14780 "Display information for a route distinguisher\n"
14781 "Route Distinguisher\n"
14782 "All Route Distinguishers\n"
14783 "Network in the BGP routing table to display\n"
14784 "Network in the BGP routing table to display\n"
14788 struct prefix_rd prd
;
14789 afi_t afi
= AFI_MAX
;
14792 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14793 vty_out(vty
, "%% Malformed Address Family\n");
14794 return CMD_WARNING
;
14797 if (!strcmp(argv
[5]->arg
, "all"))
14798 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14799 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14800 RPKI_NOT_BEING_USED
,
14801 use_json(argc
, argv
));
14803 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14805 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14806 return CMD_WARNING
;
14809 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14810 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14811 use_json(argc
, argv
));
14814 static struct bgp_distance
*bgp_distance_new(void)
14816 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14819 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14821 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14824 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14825 const char *ip_str
, const char *access_list_str
)
14832 struct bgp_dest
*dest
;
14833 struct bgp_distance
*bdistance
;
14835 afi
= bgp_node_afi(vty
);
14836 safi
= bgp_node_safi(vty
);
14838 ret
= str2prefix(ip_str
, &p
);
14840 vty_out(vty
, "Malformed prefix\n");
14841 return CMD_WARNING_CONFIG_FAILED
;
14844 distance
= atoi(distance_str
);
14846 /* Get BGP distance node. */
14847 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14848 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14850 bgp_dest_unlock_node(dest
);
14852 bdistance
= bgp_distance_new();
14853 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14856 /* Set distance value. */
14857 bdistance
->distance
= distance
;
14859 /* Reset access-list configuration. */
14860 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14861 if (access_list_str
)
14862 bdistance
->access_list
=
14863 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14865 return CMD_SUCCESS
;
14868 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14869 const char *ip_str
, const char *access_list_str
)
14876 struct bgp_dest
*dest
;
14877 struct bgp_distance
*bdistance
;
14879 afi
= bgp_node_afi(vty
);
14880 safi
= bgp_node_safi(vty
);
14882 ret
= str2prefix(ip_str
, &p
);
14884 vty_out(vty
, "Malformed prefix\n");
14885 return CMD_WARNING_CONFIG_FAILED
;
14888 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14890 vty_out(vty
, "Can't find specified prefix\n");
14891 return CMD_WARNING_CONFIG_FAILED
;
14894 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14895 distance
= atoi(distance_str
);
14897 if (bdistance
->distance
!= distance
) {
14898 vty_out(vty
, "Distance does not match configured\n");
14899 bgp_dest_unlock_node(dest
);
14900 return CMD_WARNING_CONFIG_FAILED
;
14903 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14904 bgp_distance_free(bdistance
);
14906 bgp_dest_set_bgp_path_info(dest
, NULL
);
14907 bgp_dest_unlock_node(dest
);
14908 bgp_dest_unlock_node(dest
);
14910 return CMD_SUCCESS
;
14913 /* Apply BGP information to distance method. */
14914 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14915 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14917 struct bgp_dest
*dest
;
14918 struct prefix q
= {0};
14920 struct bgp_distance
*bdistance
;
14921 struct access_list
*alist
;
14922 struct bgp_static
*bgp_static
;
14923 struct bgp_path_info
*bpi_ultimate
;
14928 peer
= pinfo
->peer
;
14930 if (pinfo
->attr
->distance
)
14931 return pinfo
->attr
->distance
;
14933 /* get peer origin to calculate appropriate distance */
14934 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
14935 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
14936 peer
= bpi_ultimate
->peer
;
14939 /* Check source address.
14940 * Note: for aggregate route, peer can have unspec af type.
14942 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14943 && !sockunion2hostprefix(&peer
->su
, &q
))
14946 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14948 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14949 bgp_dest_unlock_node(dest
);
14951 if (bdistance
->access_list
) {
14952 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14954 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14955 return bdistance
->distance
;
14957 return bdistance
->distance
;
14960 /* Backdoor check. */
14961 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14963 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14964 bgp_dest_unlock_node(dest
);
14966 if (bgp_static
->backdoor
) {
14967 if (bgp
->distance_local
[afi
][safi
])
14968 return bgp
->distance_local
[afi
][safi
];
14970 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14974 if (peer
->sort
== BGP_PEER_EBGP
) {
14975 if (bgp
->distance_ebgp
[afi
][safi
])
14976 return bgp
->distance_ebgp
[afi
][safi
];
14977 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14978 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14979 if (bgp
->distance_ibgp
[afi
][safi
])
14980 return bgp
->distance_ibgp
[afi
][safi
];
14981 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14983 if (bgp
->distance_local
[afi
][safi
])
14984 return bgp
->distance_local
[afi
][safi
];
14985 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14989 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14990 * we should tell ZEBRA update the routes for a specific
14991 * AFI/SAFI to reflect changes in RIB.
14993 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
14995 safi_t update_safi
)
15000 FOREACH_AFI_SAFI (afi
, safi
) {
15001 if (!bgp_fibupd_safi(safi
))
15004 if (afi
!= update_afi
&& safi
!= update_safi
)
15007 if (BGP_DEBUG(zebra
, ZEBRA
))
15009 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15010 __func__
, afi
, safi
);
15011 bgp_zebra_announce_table(bgp
, afi
, safi
);
15015 DEFUN (bgp_distance
,
15017 "distance bgp (1-255) (1-255) (1-255)",
15018 "Define an administrative distance\n"
15020 "Distance for routes external to the AS\n"
15021 "Distance for routes internal to the AS\n"
15022 "Distance for local routes\n")
15024 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15025 int idx_number
= 2;
15026 int idx_number_2
= 3;
15027 int idx_number_3
= 4;
15028 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15029 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15030 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15034 afi
= bgp_node_afi(vty
);
15035 safi
= bgp_node_safi(vty
);
15037 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15038 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15039 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15040 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15041 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15042 bgp
->distance_local
[afi
][safi
] = distance_local
;
15043 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15045 return CMD_SUCCESS
;
15048 DEFUN (no_bgp_distance
,
15049 no_bgp_distance_cmd
,
15050 "no distance bgp [(1-255) (1-255) (1-255)]",
15052 "Define an administrative distance\n"
15054 "Distance for routes external to the AS\n"
15055 "Distance for routes internal to the AS\n"
15056 "Distance for local routes\n")
15058 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15062 afi
= bgp_node_afi(vty
);
15063 safi
= bgp_node_safi(vty
);
15065 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15066 || bgp
->distance_ibgp
[afi
][safi
] != 0
15067 || bgp
->distance_local
[afi
][safi
] != 0) {
15068 bgp
->distance_ebgp
[afi
][safi
] = 0;
15069 bgp
->distance_ibgp
[afi
][safi
] = 0;
15070 bgp
->distance_local
[afi
][safi
] = 0;
15071 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15073 return CMD_SUCCESS
;
15077 DEFUN (bgp_distance_source
,
15078 bgp_distance_source_cmd
,
15079 "distance (1-255) A.B.C.D/M",
15080 "Define an administrative distance\n"
15081 "Administrative distance\n"
15082 "IP source prefix\n")
15084 int idx_number
= 1;
15085 int idx_ipv4_prefixlen
= 2;
15086 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15087 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15088 return CMD_SUCCESS
;
15091 DEFUN (no_bgp_distance_source
,
15092 no_bgp_distance_source_cmd
,
15093 "no distance (1-255) A.B.C.D/M",
15095 "Define an administrative distance\n"
15096 "Administrative distance\n"
15097 "IP source prefix\n")
15099 int idx_number
= 2;
15100 int idx_ipv4_prefixlen
= 3;
15101 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15102 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15103 return CMD_SUCCESS
;
15106 DEFUN (bgp_distance_source_access_list
,
15107 bgp_distance_source_access_list_cmd
,
15108 "distance (1-255) A.B.C.D/M WORD",
15109 "Define an administrative distance\n"
15110 "Administrative distance\n"
15111 "IP source prefix\n"
15112 "Access list name\n")
15114 int idx_number
= 1;
15115 int idx_ipv4_prefixlen
= 2;
15117 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15118 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15119 return CMD_SUCCESS
;
15122 DEFUN (no_bgp_distance_source_access_list
,
15123 no_bgp_distance_source_access_list_cmd
,
15124 "no distance (1-255) A.B.C.D/M WORD",
15126 "Define an administrative distance\n"
15127 "Administrative distance\n"
15128 "IP source prefix\n"
15129 "Access list name\n")
15131 int idx_number
= 2;
15132 int idx_ipv4_prefixlen
= 3;
15134 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15135 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15136 return CMD_SUCCESS
;
15139 DEFUN (ipv6_bgp_distance_source
,
15140 ipv6_bgp_distance_source_cmd
,
15141 "distance (1-255) X:X::X:X/M",
15142 "Define an administrative distance\n"
15143 "Administrative distance\n"
15144 "IP source prefix\n")
15146 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15147 return CMD_SUCCESS
;
15150 DEFUN (no_ipv6_bgp_distance_source
,
15151 no_ipv6_bgp_distance_source_cmd
,
15152 "no distance (1-255) X:X::X:X/M",
15154 "Define an administrative distance\n"
15155 "Administrative distance\n"
15156 "IP source prefix\n")
15158 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15159 return CMD_SUCCESS
;
15162 DEFUN (ipv6_bgp_distance_source_access_list
,
15163 ipv6_bgp_distance_source_access_list_cmd
,
15164 "distance (1-255) X:X::X:X/M WORD",
15165 "Define an administrative distance\n"
15166 "Administrative distance\n"
15167 "IP source prefix\n"
15168 "Access list name\n")
15170 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15171 return CMD_SUCCESS
;
15174 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15175 no_ipv6_bgp_distance_source_access_list_cmd
,
15176 "no distance (1-255) X:X::X:X/M WORD",
15178 "Define an administrative distance\n"
15179 "Administrative distance\n"
15180 "IP source prefix\n"
15181 "Access list name\n")
15183 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15184 return CMD_SUCCESS
;
15187 DEFUN (bgp_damp_set
,
15189 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15190 "BGP Specific commands\n"
15191 "Enable route-flap dampening\n"
15192 "Half-life time for the penalty\n"
15193 "Value to start reusing a route\n"
15194 "Value to start suppressing a route\n"
15195 "Maximum duration to suppress a stable route\n")
15197 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15198 int idx_half_life
= 2;
15200 int idx_suppress
= 4;
15201 int idx_max_suppress
= 5;
15202 int half
= DEFAULT_HALF_LIFE
* 60;
15203 int reuse
= DEFAULT_REUSE
;
15204 int suppress
= DEFAULT_SUPPRESS
;
15205 int max
= 4 * half
;
15208 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15209 reuse
= atoi(argv
[idx_reuse
]->arg
);
15210 suppress
= atoi(argv
[idx_suppress
]->arg
);
15211 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15212 } else if (argc
== 3) {
15213 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15218 * These can't be 0 but our SA doesn't understand the
15219 * way our cli is constructed
15223 if (suppress
< reuse
) {
15225 "Suppress value cannot be less than reuse value \n");
15229 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15230 reuse
, suppress
, max
);
15233 DEFUN (bgp_damp_unset
,
15234 bgp_damp_unset_cmd
,
15235 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15237 "BGP Specific commands\n"
15238 "Enable route-flap dampening\n"
15239 "Half-life time for the penalty\n"
15240 "Value to start reusing a route\n"
15241 "Value to start suppressing a route\n"
15242 "Maximum duration to suppress a stable route\n")
15244 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15245 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15248 /* Display specified route of BGP table. */
15249 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15250 const char *ip_str
, afi_t afi
, safi_t safi
,
15251 struct prefix_rd
*prd
, int prefix_check
)
15254 struct prefix match
;
15255 struct bgp_dest
*dest
;
15256 struct bgp_dest
*rm
;
15257 struct bgp_path_info
*pi
;
15258 struct bgp_path_info
*pi_temp
;
15260 struct bgp_table
*table
;
15262 /* BGP structure lookup. */
15264 bgp
= bgp_lookup_by_name(view_name
);
15266 vty_out(vty
, "%% Can't find BGP instance %s\n",
15268 return CMD_WARNING
;
15271 bgp
= bgp_get_default();
15273 vty_out(vty
, "%% No BGP process is configured\n");
15274 return CMD_WARNING
;
15278 /* Check IP address argument. */
15279 ret
= str2prefix(ip_str
, &match
);
15281 vty_out(vty
, "%% address is malformed\n");
15282 return CMD_WARNING
;
15285 match
.family
= afi2family(afi
);
15287 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15288 || (safi
== SAFI_EVPN
)) {
15289 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15290 dest
= bgp_route_next(dest
)) {
15291 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15293 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15295 table
= bgp_dest_get_bgp_table_info(dest
);
15298 rm
= bgp_node_match(table
, &match
);
15302 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15305 || rm_p
->prefixlen
== match
.prefixlen
) {
15306 pi
= bgp_dest_get_bgp_path_info(rm
);
15308 if (pi
->extra
&& pi
->extra
->damp_info
) {
15309 pi_temp
= pi
->next
;
15310 bgp_damp_info_free(
15311 pi
->extra
->damp_info
,
15319 bgp_dest_unlock_node(rm
);
15322 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15323 if (dest
!= NULL
) {
15324 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15327 || dest_p
->prefixlen
== match
.prefixlen
) {
15328 pi
= bgp_dest_get_bgp_path_info(dest
);
15330 if (pi
->extra
&& pi
->extra
->damp_info
) {
15331 pi_temp
= pi
->next
;
15332 bgp_damp_info_free(
15333 pi
->extra
->damp_info
,
15341 bgp_dest_unlock_node(dest
);
15345 return CMD_SUCCESS
;
15348 DEFUN (clear_ip_bgp_dampening
,
15349 clear_ip_bgp_dampening_cmd
,
15350 "clear ip bgp dampening",
15354 "Clear route flap dampening information\n")
15356 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15357 return CMD_SUCCESS
;
15360 DEFUN (clear_ip_bgp_dampening_prefix
,
15361 clear_ip_bgp_dampening_prefix_cmd
,
15362 "clear ip bgp dampening A.B.C.D/M",
15366 "Clear route flap dampening information\n"
15369 int idx_ipv4_prefixlen
= 4;
15370 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15371 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15374 DEFUN (clear_ip_bgp_dampening_address
,
15375 clear_ip_bgp_dampening_address_cmd
,
15376 "clear ip bgp dampening A.B.C.D",
15380 "Clear route flap dampening information\n"
15381 "Network to clear damping information\n")
15384 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15385 SAFI_UNICAST
, NULL
, 0);
15388 DEFUN (clear_ip_bgp_dampening_address_mask
,
15389 clear_ip_bgp_dampening_address_mask_cmd
,
15390 "clear ip bgp dampening A.B.C.D A.B.C.D",
15394 "Clear route flap dampening information\n"
15395 "Network to clear damping information\n"
15399 int idx_ipv4_2
= 5;
15401 char prefix_str
[BUFSIZ
];
15403 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15404 prefix_str
, sizeof(prefix_str
));
15406 vty_out(vty
, "%% Inconsistent address and mask\n");
15407 return CMD_WARNING
;
15410 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15414 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15416 struct vty
*vty
= arg
;
15417 struct peer
*peer
= bucket
->data
;
15419 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15422 DEFUN (show_bgp_listeners
,
15423 show_bgp_listeners_cmd
,
15424 "show bgp listeners",
15427 "Display Listen Sockets and who created them\n")
15429 bgp_dump_listener_info(vty
);
15431 return CMD_SUCCESS
;
15434 DEFUN (show_bgp_peerhash
,
15435 show_bgp_peerhash_cmd
,
15436 "show bgp peerhash",
15439 "Display information about the BGP peerhash\n")
15441 struct list
*instances
= bm
->bgp
;
15442 struct listnode
*node
;
15445 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15446 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15447 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15451 return CMD_SUCCESS
;
15454 /* also used for encap safi */
15455 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15456 afi_t afi
, safi_t safi
)
15458 struct bgp_dest
*pdest
;
15459 struct bgp_dest
*dest
;
15460 struct bgp_table
*table
;
15461 const struct prefix
*p
;
15462 const struct prefix_rd
*prd
;
15463 struct bgp_static
*bgp_static
;
15464 mpls_label_t label
;
15466 /* Network configuration. */
15467 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15468 pdest
= bgp_route_next(pdest
)) {
15469 table
= bgp_dest_get_bgp_table_info(pdest
);
15473 for (dest
= bgp_table_top(table
); dest
;
15474 dest
= bgp_route_next(dest
)) {
15475 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15476 if (bgp_static
== NULL
)
15479 p
= bgp_dest_get_prefix(dest
);
15480 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
15483 /* "network" configuration display. */
15484 label
= decode_label(&bgp_static
->label
);
15486 vty_out(vty
, " network %pFX rd %pRD", p
, prd
);
15487 if (safi
== SAFI_MPLS_VPN
)
15488 vty_out(vty
, " label %u", label
);
15490 if (bgp_static
->rmap
.name
)
15491 vty_out(vty
, " route-map %s",
15492 bgp_static
->rmap
.name
);
15494 if (bgp_static
->backdoor
)
15495 vty_out(vty
, " backdoor");
15497 vty_out(vty
, "\n");
15502 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15503 afi_t afi
, safi_t safi
)
15505 struct bgp_dest
*pdest
;
15506 struct bgp_dest
*dest
;
15507 struct bgp_table
*table
;
15508 const struct prefix
*p
;
15509 const struct prefix_rd
*prd
;
15510 struct bgp_static
*bgp_static
;
15511 char buf
[PREFIX_STRLEN
* 2];
15512 char buf2
[SU_ADDRSTRLEN
];
15513 char esi_buf
[ESI_STR_LEN
];
15515 /* Network configuration. */
15516 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15517 pdest
= bgp_route_next(pdest
)) {
15518 table
= bgp_dest_get_bgp_table_info(pdest
);
15522 for (dest
= bgp_table_top(table
); dest
;
15523 dest
= bgp_route_next(dest
)) {
15524 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15525 if (bgp_static
== NULL
)
15528 char *macrouter
= NULL
;
15530 if (bgp_static
->router_mac
)
15531 macrouter
= prefix_mac2str(
15532 bgp_static
->router_mac
, NULL
, 0);
15533 if (bgp_static
->eth_s_id
)
15534 esi_to_str(bgp_static
->eth_s_id
,
15535 esi_buf
, sizeof(esi_buf
));
15536 p
= bgp_dest_get_prefix(dest
);
15537 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15539 /* "network" configuration display. */
15540 if (p
->u
.prefix_evpn
.route_type
== 5) {
15541 char local_buf
[PREFIX_STRLEN
];
15543 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15544 struct prefix_evpn
*)p
)
15548 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15550 local_buf
, sizeof(local_buf
));
15551 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15552 p
->u
.prefix_evpn
.prefix_addr
15553 .ip_prefix_length
);
15555 prefix2str(p
, buf
, sizeof(buf
));
15558 if (bgp_static
->gatewayIp
.family
== AF_INET
15559 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15560 inet_ntop(bgp_static
->gatewayIp
.family
,
15561 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15564 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15565 buf
, prd
, p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15566 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15569 XFREE(MTYPE_TMP
, macrouter
);
15574 /* Configuration of static route announcement and aggregate
15576 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15579 struct bgp_dest
*dest
;
15580 const struct prefix
*p
;
15581 struct bgp_static
*bgp_static
;
15582 struct bgp_aggregate
*bgp_aggregate
;
15584 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15585 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15589 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15590 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15594 /* Network configuration. */
15595 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15596 dest
= bgp_route_next(dest
)) {
15597 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15598 if (bgp_static
== NULL
)
15601 p
= bgp_dest_get_prefix(dest
);
15603 vty_out(vty
, " network %pFX", p
);
15605 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15606 vty_out(vty
, " label-index %u",
15607 bgp_static
->label_index
);
15609 if (bgp_static
->rmap
.name
)
15610 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15612 if (bgp_static
->backdoor
)
15613 vty_out(vty
, " backdoor");
15615 vty_out(vty
, "\n");
15618 /* Aggregate-address configuration. */
15619 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15620 dest
= bgp_route_next(dest
)) {
15621 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15622 if (bgp_aggregate
== NULL
)
15625 p
= bgp_dest_get_prefix(dest
);
15627 vty_out(vty
, " aggregate-address %pFX", p
);
15629 if (bgp_aggregate
->as_set
)
15630 vty_out(vty
, " as-set");
15632 if (bgp_aggregate
->summary_only
)
15633 vty_out(vty
, " summary-only");
15635 if (bgp_aggregate
->rmap
.name
)
15636 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15638 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15639 vty_out(vty
, " origin %s",
15640 bgp_origin2str(bgp_aggregate
->origin
));
15642 if (bgp_aggregate
->match_med
)
15643 vty_out(vty
, " matching-MED-only");
15645 if (bgp_aggregate
->suppress_map_name
)
15646 vty_out(vty
, " suppress-map %s",
15647 bgp_aggregate
->suppress_map_name
);
15649 vty_out(vty
, "\n");
15653 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15656 struct bgp_dest
*dest
;
15657 struct bgp_distance
*bdistance
;
15659 /* Distance configuration. */
15660 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15661 && bgp
->distance_local
[afi
][safi
]
15662 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15663 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15664 || bgp
->distance_local
[afi
][safi
]
15665 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15666 vty_out(vty
, " distance bgp %d %d %d\n",
15667 bgp
->distance_ebgp
[afi
][safi
],
15668 bgp
->distance_ibgp
[afi
][safi
],
15669 bgp
->distance_local
[afi
][safi
]);
15672 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15673 dest
= bgp_route_next(dest
)) {
15674 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15675 if (bdistance
!= NULL
)
15676 vty_out(vty
, " distance %d %pBD %s\n",
15677 bdistance
->distance
, dest
,
15678 bdistance
->access_list
? bdistance
->access_list
15683 /* Allocate routing table structure and install commands. */
15684 void bgp_route_init(void)
15689 /* Init BGP distance table. */
15690 FOREACH_AFI_SAFI (afi
, safi
)
15691 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15693 /* IPv4 BGP commands. */
15694 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15695 install_element(BGP_NODE
, &bgp_network_cmd
);
15696 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15698 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15700 /* IPv4 unicast configuration. */
15701 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15702 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15703 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15705 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15707 /* IPv4 multicast configuration. */
15708 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15709 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15710 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15711 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15713 /* IPv4 labeled-unicast configuration. */
15714 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15715 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15717 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15718 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15719 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15720 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15721 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15722 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15723 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15724 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15726 install_element(VIEW_NODE
,
15727 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15728 install_element(VIEW_NODE
,
15729 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15730 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15731 install_element(VIEW_NODE
,
15732 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15733 #ifdef KEEP_OLD_VPN_COMMANDS
15734 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15735 #endif /* KEEP_OLD_VPN_COMMANDS */
15736 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15737 install_element(VIEW_NODE
,
15738 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15740 /* BGP dampening clear commands */
15741 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15742 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15744 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15745 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15748 install_element(ENABLE_NODE
,
15749 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15750 #ifdef KEEP_OLD_VPN_COMMANDS
15751 install_element(ENABLE_NODE
,
15752 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15753 #endif /* KEEP_OLD_VPN_COMMANDS */
15755 /* New config IPv6 BGP commands. */
15756 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15757 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15758 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15760 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15762 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15764 /* IPv6 labeled unicast address family. */
15765 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15766 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15768 install_element(BGP_NODE
, &bgp_distance_cmd
);
15769 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15770 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15771 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15772 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15773 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15774 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15775 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15776 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15777 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15778 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15779 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15780 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15781 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15782 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15783 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15784 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15785 install_element(BGP_IPV4M_NODE
,
15786 &no_bgp_distance_source_access_list_cmd
);
15787 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15788 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15789 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15790 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15791 install_element(BGP_IPV6_NODE
,
15792 &ipv6_bgp_distance_source_access_list_cmd
);
15793 install_element(BGP_IPV6_NODE
,
15794 &no_ipv6_bgp_distance_source_access_list_cmd
);
15795 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15796 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15797 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15798 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15799 install_element(BGP_IPV6M_NODE
,
15800 &ipv6_bgp_distance_source_access_list_cmd
);
15801 install_element(BGP_IPV6M_NODE
,
15802 &no_ipv6_bgp_distance_source_access_list_cmd
);
15804 /* BGP dampening */
15805 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15806 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15807 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15808 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15809 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15810 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15811 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15812 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15813 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15814 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15815 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15816 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15817 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15818 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15820 /* Large Communities */
15821 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15822 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15824 /* show bgp ipv4 flowspec detailed */
15825 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15827 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15828 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15831 void bgp_route_finish(void)
15836 FOREACH_AFI_SAFI (afi
, safi
) {
15837 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15838 bgp_distance_table
[afi
][safi
] = NULL
;