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(pi
);
4464 /* Update to new attribute. */
4465 bgp_attr_unintern(&pi
->attr
);
4466 pi
->attr
= attr_new
;
4468 /* Update MPLS label */
4469 if (has_valid_label
) {
4470 extra
= bgp_path_info_extra_get(pi
);
4471 if (extra
->label
!= label
) {
4472 memcpy(&extra
->label
, label
,
4473 num_labels
* sizeof(mpls_label_t
));
4474 extra
->num_labels
= num_labels
;
4476 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4477 bgp_set_valid_label(&extra
->label
[0]);
4480 /* Update SRv6 SID */
4481 if (attr
->srv6_l3vpn
) {
4482 extra
= bgp_path_info_extra_get(pi
);
4483 if (sid_diff(&extra
->sid
[0].sid
,
4484 &attr
->srv6_l3vpn
->sid
)) {
4485 sid_copy(&extra
->sid
[0].sid
,
4486 &attr
->srv6_l3vpn
->sid
);
4487 extra
->num_sids
= 1;
4489 extra
->sid
[0].loc_block_len
= 0;
4490 extra
->sid
[0].loc_node_len
= 0;
4491 extra
->sid
[0].func_len
= 0;
4492 extra
->sid
[0].arg_len
= 0;
4493 extra
->sid
[0].transposition_len
= 0;
4494 extra
->sid
[0].transposition_offset
= 0;
4496 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4497 extra
->sid
[0].loc_block_len
=
4498 attr
->srv6_l3vpn
->loc_block_len
;
4499 extra
->sid
[0].loc_node_len
=
4500 attr
->srv6_l3vpn
->loc_node_len
;
4501 extra
->sid
[0].func_len
=
4502 attr
->srv6_l3vpn
->func_len
;
4503 extra
->sid
[0].arg_len
=
4504 attr
->srv6_l3vpn
->arg_len
;
4505 extra
->sid
[0].transposition_len
=
4507 ->transposition_len
;
4508 extra
->sid
[0].transposition_offset
=
4510 ->transposition_offset
;
4513 } else if (attr
->srv6_vpn
) {
4514 extra
= bgp_path_info_extra_get(pi
);
4515 if (sid_diff(&extra
->sid
[0].sid
,
4516 &attr
->srv6_vpn
->sid
)) {
4517 sid_copy(&extra
->sid
[0].sid
,
4518 &attr
->srv6_vpn
->sid
);
4519 extra
->num_sids
= 1;
4523 #ifdef ENABLE_BGP_VNC
4524 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4525 && (safi
== SAFI_UNICAST
)) {
4526 if (vnc_implicit_withdraw
) {
4528 * Add back the route with its new attributes
4530 * The route is still selected, until the route
4532 * queued by bgp_process actually runs. We have
4534 * update to the VNC side immediately to avoid
4536 * configuration changes (e.g., route-map
4538 * trigger re-importation of the entire RIB.
4540 vnc_import_bgp_add_route(bgp
, p
, pi
);
4541 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4546 /* Update bgp route dampening information. */
4547 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4548 && peer
->sort
== BGP_PEER_EBGP
) {
4549 /* Now we do normal update dampening. */
4550 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4551 if (ret
== BGP_DAMP_SUPPRESSED
) {
4552 bgp_dest_unlock_node(dest
);
4557 /* Nexthop reachability check - for unicast and
4558 * labeled-unicast.. */
4559 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4560 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4561 || (safi
== SAFI_EVPN
&&
4562 bgp_evpn_is_prefix_nht_supported(p
))) {
4563 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4564 && peer
->ttl
== BGP_DEFAULT_TTL
4565 && !CHECK_FLAG(peer
->flags
,
4566 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4567 && !CHECK_FLAG(bgp
->flags
,
4568 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4573 struct bgp
*bgp_nexthop
= bgp
;
4575 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4576 bgp_nexthop
= pi
->extra
->bgp_orig
;
4578 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4580 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4581 safi
, pi
, NULL
, connected
,
4582 bgp_nht_param_prefix
) ||
4583 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4584 bgp_path_info_set_flag(dest
, pi
,
4587 if (BGP_DEBUG(nht
, NHT
)) {
4588 zlog_debug("%s(%pI4): NH unresolved",
4590 (in_addr_t
*)&attr_new
->nexthop
);
4592 bgp_path_info_unset_flag(dest
, pi
,
4597 bgp_path_info_set_flag(dest
, pi
,
4598 BGP_PATH_ACCEPT_OWN
);
4600 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4603 #ifdef ENABLE_BGP_VNC
4604 if (safi
== SAFI_MPLS_VPN
) {
4605 struct bgp_dest
*pdest
= NULL
;
4606 struct bgp_table
*table
= NULL
;
4608 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4609 (struct prefix
*)prd
);
4610 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4611 table
= bgp_dest_get_bgp_table_info(pdest
);
4613 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4614 bgp
, prd
, table
, p
, pi
);
4616 bgp_dest_unlock_node(pdest
);
4620 /* If this is an EVPN route and some attribute has changed,
4621 * or we are explicitly told to perform a route import, process
4622 * route for import. If the extended community has changed, we
4624 * have done the un-import earlier and the import would result
4626 * route getting injected into appropriate L2 VNIs. If it is
4628 * some other attribute change, the import will result in
4630 * the attributes for the route in the VNI(s).
4632 if (safi
== SAFI_EVPN
&&
4633 (!same_attr
|| force_evpn_import
) &&
4634 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4635 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4637 /* Process change. */
4638 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4640 bgp_process(bgp
, dest
, afi
, safi
);
4641 bgp_dest_unlock_node(dest
);
4643 if (SAFI_UNICAST
== safi
4644 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4645 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4647 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4649 if ((SAFI_MPLS_VPN
== safi
)
4650 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4651 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4654 #ifdef ENABLE_BGP_VNC
4655 if (SAFI_MPLS_VPN
== safi
) {
4656 mpls_label_t label_decoded
= decode_label(label
);
4658 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4659 type
, sub_type
, &label_decoded
);
4661 if (SAFI_ENCAP
== safi
) {
4662 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4663 type
, sub_type
, NULL
);
4666 if ((safi
== SAFI_MPLS_VPN
) &&
4667 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4668 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4670 bgp_unlink_nexthop(pi
);
4671 bgp_path_info_delete(dest
, pi
);
4674 } // End of implicit withdraw
4676 /* Received Logging. */
4677 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4678 if (!peer
->rcvd_attr_printed
) {
4679 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4680 peer
->rcvd_attr_str
);
4681 peer
->rcvd_attr_printed
= 1;
4684 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4685 addpath_id
? 1 : 0, addpath_id
, evpn
,
4686 pfx_buf
, sizeof(pfx_buf
));
4687 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4690 /* Make new BGP info. */
4691 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4693 /* Update MPLS label */
4694 if (has_valid_label
) {
4695 extra
= bgp_path_info_extra_get(new);
4696 if (extra
->label
!= label
) {
4697 memcpy(&extra
->label
, label
,
4698 num_labels
* sizeof(mpls_label_t
));
4699 extra
->num_labels
= num_labels
;
4701 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4702 bgp_set_valid_label(&extra
->label
[0]);
4705 /* Update SRv6 SID */
4706 if (safi
== SAFI_MPLS_VPN
) {
4707 extra
= bgp_path_info_extra_get(new);
4708 if (attr
->srv6_l3vpn
) {
4709 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4710 extra
->num_sids
= 1;
4712 extra
->sid
[0].loc_block_len
=
4713 attr
->srv6_l3vpn
->loc_block_len
;
4714 extra
->sid
[0].loc_node_len
=
4715 attr
->srv6_l3vpn
->loc_node_len
;
4716 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4717 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4718 extra
->sid
[0].transposition_len
=
4719 attr
->srv6_l3vpn
->transposition_len
;
4720 extra
->sid
[0].transposition_offset
=
4721 attr
->srv6_l3vpn
->transposition_offset
;
4722 } else if (attr
->srv6_vpn
) {
4723 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4724 extra
->num_sids
= 1;
4728 /* Nexthop reachability check. */
4729 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4730 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4731 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4732 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4733 && peer
->ttl
== BGP_DEFAULT_TTL
4734 && !CHECK_FLAG(peer
->flags
,
4735 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4736 && !CHECK_FLAG(bgp
->flags
,
4737 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4742 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4744 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4745 connected
, bgp_nht_param_prefix
) ||
4746 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4747 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4749 if (BGP_DEBUG(nht
, NHT
))
4750 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4751 &attr_new
->nexthop
);
4752 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4756 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4758 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4761 /* If maximum prefix count is configured and current prefix
4764 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4765 reason
= "maximum-prefix overflow";
4766 bgp_attr_flush(&new_attr
);
4771 new->addpath_rx_id
= addpath_id
;
4773 /* Increment prefix */
4774 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4776 /* Register new BGP information. */
4777 bgp_path_info_add(dest
, new);
4779 /* route_node_get lock */
4780 bgp_dest_unlock_node(dest
);
4782 #ifdef ENABLE_BGP_VNC
4783 if (safi
== SAFI_MPLS_VPN
) {
4784 struct bgp_dest
*pdest
= NULL
;
4785 struct bgp_table
*table
= NULL
;
4787 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4788 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4789 table
= bgp_dest_get_bgp_table_info(pdest
);
4791 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4792 bgp
, prd
, table
, p
, new);
4794 bgp_dest_unlock_node(pdest
);
4798 /* If this is an EVPN route, process for import. */
4799 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4800 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4802 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4804 /* Process change. */
4805 bgp_process(bgp
, dest
, afi
, safi
);
4807 if (SAFI_UNICAST
== safi
4808 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4809 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4810 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4812 if ((SAFI_MPLS_VPN
== safi
)
4813 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4814 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4816 #ifdef ENABLE_BGP_VNC
4817 if (SAFI_MPLS_VPN
== safi
) {
4818 mpls_label_t label_decoded
= decode_label(label
);
4820 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4821 sub_type
, &label_decoded
);
4823 if (SAFI_ENCAP
== safi
) {
4824 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4828 if ((safi
== SAFI_MPLS_VPN
) &&
4829 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4830 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4832 bgp_unlink_nexthop(new);
4833 bgp_path_info_delete(dest
, new);
4838 /* This BGP update is filtered. Log the reason then update BGP
4842 bgp_unlink_nexthop(new);
4843 bgp_path_info_delete(dest
, new);
4844 bgp_path_info_extra_free(&new->extra
);
4845 XFREE(MTYPE_BGP_ROUTE
, new);
4848 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4850 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4851 if (!peer
->rcvd_attr_printed
) {
4852 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4853 peer
->rcvd_attr_str
);
4854 peer
->rcvd_attr_printed
= 1;
4857 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4858 addpath_id
? 1 : 0, addpath_id
, evpn
,
4859 pfx_buf
, sizeof(pfx_buf
));
4860 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4861 peer
, pfx_buf
, reason
);
4865 /* If this is an EVPN route, un-import it as it is now filtered.
4867 if (safi
== SAFI_EVPN
)
4868 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4870 if (SAFI_UNICAST
== safi
4871 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4872 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4874 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4876 if ((SAFI_MPLS_VPN
== safi
)
4877 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4879 vpn_leak_to_vrf_withdraw(pi
);
4882 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4885 bgp_dest_unlock_node(dest
);
4887 #ifdef ENABLE_BGP_VNC
4889 * Filtered update is treated as an implicit withdrawal (see
4891 * a few lines above)
4893 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4894 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4902 void bgp_withdraw(struct peer
*peer
, const struct prefix
*p
,
4903 uint32_t addpath_id
, struct attr
*attr
, afi_t afi
,
4904 safi_t safi
, int type
, int sub_type
, struct prefix_rd
*prd
,
4905 mpls_label_t
*label
, uint32_t num_labels
,
4906 struct bgp_route_evpn
*evpn
)
4909 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4910 struct bgp_dest
*dest
;
4911 struct bgp_path_info
*pi
;
4913 #ifdef ENABLE_BGP_VNC
4914 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4915 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4923 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4925 /* If peer is soft reconfiguration enabled. Record input packet for
4926 * further calculation.
4928 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4929 * routes that are filtered. This tanks out Quagga RS pretty badly due
4931 * the iteration over all RS clients.
4932 * Since we need to remove the entry from adj_in anyway, do that first
4934 * if there was no entry, we don't need to do anything more.
4936 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4937 && peer
!= bgp
->peer_self
)
4938 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4939 peer
->stat_pfx_dup_withdraw
++;
4941 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4942 bgp_debug_rdpfxpath2str(
4943 afi
, safi
, prd
, p
, label
, num_labels
,
4944 addpath_id
? 1 : 0, addpath_id
, NULL
,
4945 pfx_buf
, sizeof(pfx_buf
));
4947 "%s withdrawing route %s not in adj-in",
4948 peer
->host
, pfx_buf
);
4950 bgp_dest_unlock_node(dest
);
4954 /* Lookup withdrawn route. */
4955 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4956 if (pi
->peer
== peer
&& pi
->type
== type
4957 && pi
->sub_type
== sub_type
4958 && pi
->addpath_rx_id
== addpath_id
)
4962 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4963 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4964 addpath_id
? 1 : 0, addpath_id
, NULL
,
4965 pfx_buf
, sizeof(pfx_buf
));
4966 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
4970 /* Withdraw specified route from routing table. */
4971 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4972 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4973 if (SAFI_UNICAST
== safi
4974 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4975 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4976 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4978 if ((SAFI_MPLS_VPN
== safi
)
4979 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4981 vpn_leak_to_vrf_withdraw(pi
);
4983 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4984 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4985 addpath_id
? 1 : 0, addpath_id
, NULL
,
4986 pfx_buf
, sizeof(pfx_buf
));
4987 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4990 /* Unlock bgp_node_get() lock. */
4991 bgp_dest_unlock_node(dest
);
4996 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4999 struct update_subgroup
*subgrp
;
5000 subgrp
= peer_subgroup(peer
, afi
, safi
);
5001 subgroup_default_originate(subgrp
, withdraw
);
5006 * bgp_stop_announce_route_timer
5008 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5010 if (!paf
->t_announce_route
)
5013 THREAD_OFF(paf
->t_announce_route
);
5017 * bgp_announce_route_timer_expired
5019 * Callback that is invoked when the route announcement timer for a
5022 static void bgp_announce_route_timer_expired(struct thread
*t
)
5024 struct peer_af
*paf
;
5027 paf
= THREAD_ARG(t
);
5030 if (!peer_established(peer
))
5033 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5036 peer_af_announce_route(paf
, 1);
5038 /* Notify BGP conditional advertisement scanner percess */
5039 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5043 * bgp_announce_route
5045 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5047 * if force is true we will force an update even if the update
5048 * limiting code is attempted to kick in.
5050 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5052 struct peer_af
*paf
;
5053 struct update_subgroup
*subgrp
;
5055 paf
= peer_af_find(peer
, afi
, safi
);
5058 subgrp
= PAF_SUBGRP(paf
);
5061 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5062 * or a refresh has already been triggered.
5064 if (!subgrp
|| paf
->t_announce_route
)
5068 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5071 * Start a timer to stagger/delay the announce. This serves
5072 * two purposes - announcement can potentially be combined for
5073 * multiple peers and the announcement doesn't happen in the
5076 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5077 (subgrp
->peer_count
== 1)
5078 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5079 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5080 &paf
->t_announce_route
);
5084 * Announce routes from all AF tables to a peer.
5086 * This should ONLY be called when there is a need to refresh the
5087 * routes to the peer based on a policy change for this peer alone
5088 * or a route refresh request received from the peer.
5089 * The operation will result in splitting the peer from its existing
5090 * subgroups and putting it in new subgroups.
5092 void bgp_announce_route_all(struct peer
*peer
)
5097 FOREACH_AFI_SAFI (afi
, safi
)
5098 bgp_announce_route(peer
, afi
, safi
, false);
5101 /* Flag or unflag bgp_dest to determine whether it should be treated by
5102 * bgp_soft_reconfig_table_task.
5103 * Flag if flag is true. Unflag if flag is false.
5105 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5107 struct bgp_dest
*dest
;
5108 struct bgp_adj_in
*ain
;
5113 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5114 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5115 if (ain
->peer
!= NULL
)
5118 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5119 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5121 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5125 static void bgp_soft_reconfig_table_update(struct peer
*peer
,
5126 struct bgp_dest
*dest
,
5127 struct bgp_adj_in
*ain
, afi_t afi
,
5128 safi_t safi
, struct prefix_rd
*prd
)
5130 struct bgp_path_info
*pi
;
5131 uint32_t num_labels
= 0;
5132 mpls_label_t
*label_pnt
= NULL
;
5133 struct bgp_route_evpn evpn
;
5135 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5136 if (pi
->peer
== peer
)
5139 if (pi
&& pi
->extra
)
5140 num_labels
= pi
->extra
->num_labels
;
5142 label_pnt
= &pi
->extra
->label
[0];
5144 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5147 memset(&evpn
, 0, sizeof(evpn
));
5149 bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5150 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, prd
,
5151 label_pnt
, num_labels
, 1, &evpn
);
5154 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5155 struct bgp_table
*table
,
5156 struct prefix_rd
*prd
)
5158 struct bgp_dest
*dest
;
5159 struct bgp_adj_in
*ain
;
5162 table
= peer
->bgp
->rib
[afi
][safi
];
5164 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5165 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5166 if (ain
->peer
!= peer
)
5169 bgp_soft_reconfig_table_update(peer
, dest
, ain
, afi
,
5174 /* Do soft reconfig table per bgp table.
5175 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5176 * when BGP_NODE_SOFT_RECONFIG is set,
5177 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5178 * Schedule a new thread to continue the job.
5179 * Without splitting the full job into several part,
5180 * vtysh waits for the job to finish before responding to a BGP command
5182 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
5184 uint32_t iter
, max_iter
;
5185 struct bgp_dest
*dest
;
5186 struct bgp_adj_in
*ain
;
5188 struct bgp_table
*table
;
5189 struct prefix_rd
*prd
;
5190 struct listnode
*node
, *nnode
;
5192 table
= THREAD_ARG(thread
);
5195 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5196 if (table
->soft_reconfig_init
) {
5197 /* first call of the function with a new srta structure.
5198 * Don't do any treatment this time on nodes
5199 * in order vtysh to respond quickly
5204 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5205 dest
= bgp_route_next(dest
)) {
5206 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5209 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5211 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5212 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5214 if (ain
->peer
!= peer
)
5217 bgp_soft_reconfig_table_update(
5218 peer
, dest
, ain
, table
->afi
,
5225 /* we're either starting the initial iteration,
5226 * or we're going to continue an ongoing iteration
5228 if (dest
|| table
->soft_reconfig_init
) {
5229 table
->soft_reconfig_init
= false;
5230 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
5231 table
, 0, &table
->soft_reconfig_thread
);
5234 /* we're done, clean up the background iteration context info and
5235 schedule route annoucement
5237 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5238 listnode_delete(table
->soft_reconfig_peers
, peer
);
5239 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5242 list_delete(&table
->soft_reconfig_peers
);
5246 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5248 * - bgp cannot be NULL
5249 * - if table and peer are NULL, cancel all threads within the bgp instance
5250 * - if table is NULL and peer is not,
5251 * remove peer in all threads within the bgp instance
5252 * - if peer is NULL, cancel all threads matching table within the bgp instance
5254 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5255 const struct bgp_table
*table
,
5256 const struct peer
*peer
)
5259 struct listnode
*node
, *nnode
;
5261 struct bgp_table
*ntable
;
5266 FOREACH_AFI_SAFI (afi
, safi
) {
5267 ntable
= bgp
->rib
[afi
][safi
];
5270 if (table
&& table
!= ntable
)
5273 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5275 if (peer
&& peer
!= npeer
)
5277 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5280 if (!ntable
->soft_reconfig_peers
5281 || !list_isempty(ntable
->soft_reconfig_peers
))
5284 list_delete(&ntable
->soft_reconfig_peers
);
5285 bgp_soft_reconfig_table_flag(ntable
, false);
5286 THREAD_OFF(ntable
->soft_reconfig_thread
);
5291 * Returns false if the peer is not configured for soft reconfig in
5293 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5295 struct bgp_dest
*dest
;
5296 struct bgp_table
*table
;
5297 struct listnode
*node
, *nnode
;
5299 struct peer_af
*paf
;
5301 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5304 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5305 && (safi
!= SAFI_EVPN
)) {
5306 table
= peer
->bgp
->rib
[afi
][safi
];
5310 table
->soft_reconfig_init
= true;
5312 if (!table
->soft_reconfig_peers
)
5313 table
->soft_reconfig_peers
= list_new();
5315 /* add peer to the table soft_reconfig_peers if not already
5318 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5324 listnode_add(table
->soft_reconfig_peers
, peer
);
5326 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5327 * on table would start back at the beginning.
5329 bgp_soft_reconfig_table_flag(table
, true);
5331 if (!table
->soft_reconfig_thread
)
5332 thread_add_event(bm
->master
,
5333 bgp_soft_reconfig_table_task
, table
, 0,
5334 &table
->soft_reconfig_thread
);
5335 /* Cancel bgp_announce_route_timer_expired threads.
5336 * bgp_announce_route_timer_expired threads have been scheduled
5337 * to announce routes as soon as the soft_reconfigure process
5339 * In this case, soft_reconfigure is also scheduled by using
5340 * a thread but is planned after the
5341 * bgp_announce_route_timer_expired threads. It means that,
5342 * without cancelling the threads, the route announcement task
5343 * would run before the soft reconfiguration one. That would
5344 * useless and would block vtysh during several seconds. Route
5345 * announcements are rescheduled as soon as the soft_reconfigure
5348 paf
= peer_af_find(peer
, afi
, safi
);
5350 bgp_stop_announce_route_timer(paf
);
5352 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5353 dest
= bgp_route_next(dest
)) {
5354 table
= bgp_dest_get_bgp_table_info(dest
);
5359 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5360 struct prefix_rd prd
;
5362 prd
.family
= AF_UNSPEC
;
5364 memcpy(&prd
.val
, p
->u
.val
, 8);
5366 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5373 struct bgp_clear_node_queue
{
5374 struct bgp_dest
*dest
;
5377 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5379 struct bgp_clear_node_queue
*cnq
= data
;
5380 struct bgp_dest
*dest
= cnq
->dest
;
5381 struct peer
*peer
= wq
->spec
.data
;
5382 struct bgp_path_info
*pi
;
5384 afi_t afi
= bgp_dest_table(dest
)->afi
;
5385 safi_t safi
= bgp_dest_table(dest
)->safi
;
5387 assert(dest
&& peer
);
5390 /* It is possible that we have multiple paths for a prefix from a peer
5391 * if that peer is using AddPath.
5393 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5394 if (pi
->peer
!= peer
)
5397 /* graceful restart STALE flag set. */
5398 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5399 && peer
->nsf
[afi
][safi
])
5400 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5401 PEER_STATUS_ENHANCED_REFRESH
))
5402 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5403 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5404 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5406 /* If this is an EVPN route, process for
5408 if (safi
== SAFI_EVPN
)
5409 bgp_evpn_unimport_route(
5411 bgp_dest_get_prefix(dest
), pi
);
5412 /* Handle withdraw for VRF route-leaking and L3VPN */
5413 if (SAFI_UNICAST
== safi
5414 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5415 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5416 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5419 if (SAFI_MPLS_VPN
== safi
&&
5420 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5421 vpn_leak_to_vrf_withdraw(pi
);
5424 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5430 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5432 struct bgp_clear_node_queue
*cnq
= data
;
5433 struct bgp_dest
*dest
= cnq
->dest
;
5434 struct bgp_table
*table
= bgp_dest_table(dest
);
5436 bgp_dest_unlock_node(dest
);
5437 bgp_table_unlock(table
);
5438 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5441 static void bgp_clear_node_complete(struct work_queue
*wq
)
5443 struct peer
*peer
= wq
->spec
.data
;
5445 /* Tickle FSM to start moving again */
5446 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5448 peer_unlock(peer
); /* bgp_clear_route */
5451 static void bgp_clear_node_queue_init(struct peer
*peer
)
5453 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5455 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5456 #undef CLEAR_QUEUE_NAME_LEN
5458 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5459 peer
->clear_node_queue
->spec
.hold
= 10;
5460 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5461 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5462 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5463 peer
->clear_node_queue
->spec
.max_retries
= 0;
5465 /* we only 'lock' this peer reference when the queue is actually active
5467 peer
->clear_node_queue
->spec
.data
= peer
;
5470 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5471 struct bgp_table
*table
)
5473 struct bgp_dest
*dest
;
5474 int force
= peer
->bgp
->process_queue
? 0 : 1;
5477 table
= peer
->bgp
->rib
[afi
][safi
];
5479 /* If still no table => afi/safi isn't configured at all or smth. */
5483 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5484 struct bgp_path_info
*pi
, *next
;
5485 struct bgp_adj_in
*ain
;
5486 struct bgp_adj_in
*ain_next
;
5488 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5489 * queued for every clearing peer, regardless of whether it is
5490 * relevant to the peer at hand.
5492 * Overview: There are 3 different indices which need to be
5493 * scrubbed, potentially, when a peer is removed:
5495 * 1 peer's routes visible via the RIB (ie accepted routes)
5496 * 2 peer's routes visible by the (optional) peer's adj-in index
5497 * 3 other routes visible by the peer's adj-out index
5499 * 3 there is no hurry in scrubbing, once the struct peer is
5500 * removed from bgp->peer, we could just GC such deleted peer's
5501 * adj-outs at our leisure.
5503 * 1 and 2 must be 'scrubbed' in some way, at least made
5504 * invisible via RIB index before peer session is allowed to be
5505 * brought back up. So one needs to know when such a 'search' is
5510 * - there'd be a single global queue or a single RIB walker
5511 * - rather than tracking which route_nodes still need to be
5512 * examined on a peer basis, we'd track which peers still
5515 * Given that our per-peer prefix-counts now should be reliable,
5516 * this may actually be achievable. It doesn't seem to be a huge
5517 * problem at this time,
5519 * It is possible that we have multiple paths for a prefix from
5521 * if that peer is using AddPath.
5525 ain_next
= ain
->next
;
5527 if (ain
->peer
== peer
)
5528 bgp_adj_in_remove(dest
, ain
);
5533 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5535 if (pi
->peer
!= peer
)
5539 bgp_path_info_reap(dest
, pi
);
5541 struct bgp_clear_node_queue
*cnq
;
5543 /* both unlocked in bgp_clear_node_queue_del */
5544 bgp_table_lock(bgp_dest_table(dest
));
5545 bgp_dest_lock_node(dest
);
5547 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5548 sizeof(struct bgp_clear_node_queue
));
5550 work_queue_add(peer
->clear_node_queue
, cnq
);
5558 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5560 struct bgp_dest
*dest
;
5561 struct bgp_table
*table
;
5563 if (peer
->clear_node_queue
== NULL
)
5564 bgp_clear_node_queue_init(peer
);
5566 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5567 * Idle until it receives a Clearing_Completed event. This protects
5568 * against peers which flap faster than we can we clear, which could
5571 * a) race with routes from the new session being installed before
5572 * clear_route_node visits the node (to delete the route of that
5574 * b) resource exhaustion, clear_route_node likely leads to an entry
5575 * on the process_main queue. Fast-flapping could cause that queue
5579 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5580 * the unlock will happen upon work-queue completion; other wise, the
5581 * unlock happens at the end of this function.
5583 if (!peer
->clear_node_queue
->thread
)
5586 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5587 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5589 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5590 dest
= bgp_route_next(dest
)) {
5591 table
= bgp_dest_get_bgp_table_info(dest
);
5595 bgp_clear_route_table(peer
, afi
, safi
, table
);
5598 /* unlock if no nodes got added to the clear-node-queue. */
5599 if (!peer
->clear_node_queue
->thread
)
5603 void bgp_clear_route_all(struct peer
*peer
)
5608 FOREACH_AFI_SAFI (afi
, safi
)
5609 bgp_clear_route(peer
, afi
, safi
);
5611 #ifdef ENABLE_BGP_VNC
5612 rfapiProcessPeerDown(peer
);
5616 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5618 struct bgp_table
*table
;
5619 struct bgp_dest
*dest
;
5620 struct bgp_adj_in
*ain
;
5621 struct bgp_adj_in
*ain_next
;
5623 table
= peer
->bgp
->rib
[afi
][safi
];
5625 /* It is possible that we have multiple paths for a prefix from a peer
5626 * if that peer is using AddPath.
5628 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5632 ain_next
= ain
->next
;
5634 if (ain
->peer
== peer
)
5635 bgp_adj_in_remove(dest
, ain
);
5642 /* If any of the routes from the peer have been marked with the NO_LLGR
5643 * community, either as sent by the peer, or as the result of a configured
5644 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5645 * operation of [RFC4271].
5647 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5649 struct bgp_dest
*dest
;
5650 struct bgp_path_info
*pi
;
5651 struct bgp_table
*table
;
5653 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5654 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5655 dest
= bgp_route_next(dest
)) {
5656 struct bgp_dest
*rm
;
5658 /* look for neighbor in tables */
5659 table
= bgp_dest_get_bgp_table_info(dest
);
5663 for (rm
= bgp_table_top(table
); rm
;
5664 rm
= bgp_route_next(rm
))
5665 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5667 if (pi
->peer
!= peer
)
5670 peer
->af_sflags
[afi
][safi
],
5671 PEER_STATUS_LLGR_WAIT
) &&
5672 bgp_attr_get_community(pi
->attr
) &&
5674 bgp_attr_get_community(
5678 if (!CHECK_FLAG(pi
->flags
,
5683 * If this is VRF leaked route
5684 * process for withdraw.
5687 BGP_ROUTE_IMPORTED
&&
5688 peer
->bgp
->inst_type
==
5689 BGP_INSTANCE_TYPE_DEFAULT
)
5690 vpn_leak_to_vrf_withdraw(pi
);
5692 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5697 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5698 dest
= bgp_route_next(dest
))
5699 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5701 if (pi
->peer
!= peer
)
5703 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5704 PEER_STATUS_LLGR_WAIT
) &&
5705 bgp_attr_get_community(pi
->attr
) &&
5707 bgp_attr_get_community(pi
->attr
),
5710 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5712 if (safi
== SAFI_UNICAST
&&
5713 (peer
->bgp
->inst_type
==
5714 BGP_INSTANCE_TYPE_VRF
||
5715 peer
->bgp
->inst_type
==
5716 BGP_INSTANCE_TYPE_DEFAULT
))
5717 vpn_leak_from_vrf_withdraw(
5718 bgp_get_default(), peer
->bgp
,
5721 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5727 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5729 struct bgp_dest
*dest
, *ndest
;
5730 struct bgp_path_info
*pi
;
5731 struct bgp_table
*table
;
5733 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5734 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5735 dest
= bgp_route_next(dest
)) {
5736 table
= bgp_dest_get_bgp_table_info(dest
);
5740 for (ndest
= bgp_table_top(table
); ndest
;
5741 ndest
= bgp_route_next(ndest
)) {
5742 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5744 if (pi
->peer
!= peer
)
5748 peer
->af_sflags
[afi
][safi
],
5749 PEER_STATUS_ENHANCED_REFRESH
))
5750 && !CHECK_FLAG(pi
->flags
,
5754 BGP_PATH_UNUSEABLE
)) {
5755 if (bgp_debug_neighbor_events(
5758 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5762 bgp_dest_get_prefix(
5765 bgp_path_info_set_flag(
5773 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5774 dest
= bgp_route_next(dest
)) {
5775 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5777 if (pi
->peer
!= peer
)
5780 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5781 PEER_STATUS_ENHANCED_REFRESH
))
5782 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5783 && !CHECK_FLAG(pi
->flags
,
5784 BGP_PATH_UNUSEABLE
)) {
5785 if (bgp_debug_neighbor_events(peer
))
5787 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5790 bgp_dest_get_prefix(
5793 bgp_path_info_set_flag(dest
, pi
,
5801 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5803 if (peer
->sort
== BGP_PEER_IBGP
)
5806 if (peer
->sort
== BGP_PEER_EBGP
5807 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5808 || FILTER_LIST_OUT_NAME(filter
)
5809 || DISTRIBUTE_OUT_NAME(filter
)))
5814 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5816 if (peer
->sort
== BGP_PEER_IBGP
)
5819 if (peer
->sort
== BGP_PEER_EBGP
5820 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5821 || FILTER_LIST_IN_NAME(filter
)
5822 || DISTRIBUTE_IN_NAME(filter
)))
5827 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5830 struct bgp_dest
*dest
;
5831 struct bgp_path_info
*pi
;
5832 struct bgp_path_info
*next
;
5834 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5835 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5836 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5840 /* Unimport EVPN routes from VRFs */
5841 if (safi
== SAFI_EVPN
)
5842 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5845 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5846 && pi
->type
== ZEBRA_ROUTE_BGP
5847 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5848 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5849 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5851 if (bgp_fibupd_safi(safi
))
5852 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5855 bgp_path_info_reap(dest
, pi
);
5859 /* Delete all kernel routes. */
5860 void bgp_cleanup_routes(struct bgp
*bgp
)
5863 struct bgp_dest
*dest
;
5864 struct bgp_table
*table
;
5866 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5867 if (afi
== AFI_L2VPN
)
5869 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5872 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5874 if (afi
!= AFI_L2VPN
) {
5876 safi
= SAFI_MPLS_VPN
;
5877 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5878 dest
= bgp_route_next(dest
)) {
5879 table
= bgp_dest_get_bgp_table_info(dest
);
5880 if (table
!= NULL
) {
5881 bgp_cleanup_table(bgp
, table
, safi
);
5882 bgp_table_finish(&table
);
5883 bgp_dest_set_bgp_table_info(dest
, NULL
);
5884 bgp_dest_unlock_node(dest
);
5888 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5889 dest
= bgp_route_next(dest
)) {
5890 table
= bgp_dest_get_bgp_table_info(dest
);
5891 if (table
!= NULL
) {
5892 bgp_cleanup_table(bgp
, table
, safi
);
5893 bgp_table_finish(&table
);
5894 bgp_dest_set_bgp_table_info(dest
, NULL
);
5895 bgp_dest_unlock_node(dest
);
5900 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5901 dest
= bgp_route_next(dest
)) {
5902 table
= bgp_dest_get_bgp_table_info(dest
);
5903 if (table
!= NULL
) {
5904 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5905 bgp_table_finish(&table
);
5906 bgp_dest_set_bgp_table_info(dest
, NULL
);
5907 bgp_dest_unlock_node(dest
);
5912 void bgp_reset(void)
5915 bgp_zclient_reset();
5916 access_list_reset();
5917 prefix_list_reset();
5920 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5922 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5923 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5924 PEER_CAP_ADDPATH_AF_TX_RCV
));
5927 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5929 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5930 struct bgp_nlri
*packet
)
5938 bool addpath_capable
;
5939 uint32_t addpath_id
;
5942 lim
= pnt
+ packet
->length
;
5944 safi
= packet
->safi
;
5946 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5948 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5949 syntactic validity. If the field is syntactically incorrect,
5950 then the Error Subcode is set to Invalid Network Field. */
5951 for (; pnt
< lim
; pnt
+= psize
) {
5952 /* Clear prefix structure. */
5953 memset(&p
, 0, sizeof(p
));
5955 if (addpath_capable
) {
5957 /* When packet overflow occurs return immediately. */
5958 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5959 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5961 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5962 addpath_id
= ntohl(addpath_id
);
5963 pnt
+= BGP_ADDPATH_ID_LEN
;
5966 /* Fetch prefix length. */
5967 p
.prefixlen
= *pnt
++;
5968 /* afi/safi validity already verified by caller,
5969 * bgp_update_receive */
5970 p
.family
= afi2family(afi
);
5972 /* Prefix length check. */
5973 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5976 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5977 peer
->host
, p
.prefixlen
, packet
->afi
);
5978 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5981 /* Packet size overflow check. */
5982 psize
= PSIZE(p
.prefixlen
);
5984 /* When packet overflow occur return immediately. */
5985 if (pnt
+ psize
> lim
) {
5988 "%s [Error] Update packet error (prefix length %d overflows packet)",
5989 peer
->host
, p
.prefixlen
);
5990 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5993 /* Defensive coding, double-check the psize fits in a struct
5994 * prefix for the v4 and v6 afi's and unicast/multicast */
5995 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
5998 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5999 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6000 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6003 /* Fetch prefix from NLRI packet. */
6004 memcpy(p
.u
.val
, pnt
, psize
);
6006 /* Check address. */
6007 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6008 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6009 /* From RFC4271 Section 6.3:
6011 * If a prefix in the NLRI field is semantically
6013 * (e.g., an unexpected multicast IP address),
6015 * be logged locally, and the prefix SHOULD be
6020 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6021 peer
->host
, &p
.u
.prefix4
);
6026 /* Check address. */
6027 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6028 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6031 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6032 peer
->host
, &p
.u
.prefix6
);
6036 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6039 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6040 peer
->host
, &p
.u
.prefix6
);
6046 /* Normal process. */
6048 bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6049 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6052 bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6053 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6056 /* Do not send BGP notification twice when maximum-prefix count
6058 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6059 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6062 /* Packet length consistency check. */
6066 "%s [Error] Update packet error (prefix length mismatch with total length)",
6068 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6071 return BGP_NLRI_PARSE_OK
;
6074 static struct bgp_static
*bgp_static_new(void)
6076 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6079 static void bgp_static_free(struct bgp_static
*bgp_static
)
6081 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6082 route_map_counter_decrement(bgp_static
->rmap
.map
);
6084 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6085 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6088 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6089 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6091 struct bgp_dest
*dest
;
6092 struct bgp_path_info
*pi
;
6093 struct bgp_path_info
*new;
6094 struct bgp_path_info rmap_path
;
6096 struct attr
*attr_new
;
6097 route_map_result_t ret
;
6098 #ifdef ENABLE_BGP_VNC
6099 int vnc_implicit_withdraw
= 0;
6104 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6106 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6108 attr
.nexthop
= bgp_static
->igpnexthop
;
6109 attr
.med
= bgp_static
->igpmetric
;
6110 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6113 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6115 if (bgp_static
->igpmetric
)
6116 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6118 if (bgp_static
->atomic
)
6119 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6121 /* Store label index, if required. */
6122 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6123 attr
.label_index
= bgp_static
->label_index
;
6124 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6127 /* Apply route-map. */
6128 if (bgp_static
->rmap
.name
) {
6129 struct attr attr_tmp
= attr
;
6131 memset(&rmap_path
, 0, sizeof(rmap_path
));
6132 rmap_path
.peer
= bgp
->peer_self
;
6133 rmap_path
.attr
= &attr_tmp
;
6135 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6137 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6139 bgp
->peer_self
->rmap_type
= 0;
6141 if (ret
== RMAP_DENYMATCH
) {
6142 /* Free uninterned attribute. */
6143 bgp_attr_flush(&attr_tmp
);
6145 /* Unintern original. */
6146 aspath_unintern(&attr
.aspath
);
6147 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6148 bgp_dest_unlock_node(dest
);
6152 if (bgp_in_graceful_shutdown(bgp
))
6153 bgp_attr_add_gshut_community(&attr_tmp
);
6155 attr_new
= bgp_attr_intern(&attr_tmp
);
6158 if (bgp_in_graceful_shutdown(bgp
))
6159 bgp_attr_add_gshut_community(&attr
);
6161 attr_new
= bgp_attr_intern(&attr
);
6164 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6165 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6166 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6170 if (attrhash_cmp(pi
->attr
, attr_new
)
6171 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6172 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6173 bgp_dest_unlock_node(dest
);
6174 bgp_attr_unintern(&attr_new
);
6175 aspath_unintern(&attr
.aspath
);
6178 /* The attribute is changed. */
6179 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6181 /* Rewrite BGP route information. */
6182 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6183 bgp_path_info_restore(dest
, pi
);
6185 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6186 #ifdef ENABLE_BGP_VNC
6187 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6188 && (safi
== SAFI_UNICAST
)) {
6189 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6191 * Implicit withdraw case.
6192 * We have to do this before pi is
6195 ++vnc_implicit_withdraw
;
6196 vnc_import_bgp_del_route(bgp
, p
, pi
);
6197 vnc_import_bgp_exterior_del_route(
6202 bgp_attr_unintern(&pi
->attr
);
6203 pi
->attr
= attr_new
;
6204 pi
->uptime
= monotime(NULL
);
6205 #ifdef ENABLE_BGP_VNC
6206 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6207 && (safi
== SAFI_UNICAST
)) {
6208 if (vnc_implicit_withdraw
) {
6209 vnc_import_bgp_add_route(bgp
, p
, pi
);
6210 vnc_import_bgp_exterior_add_route(
6216 /* Nexthop reachability check. */
6217 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6218 && (safi
== SAFI_UNICAST
6219 || safi
== SAFI_LABELED_UNICAST
)) {
6221 struct bgp
*bgp_nexthop
= bgp
;
6223 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6224 bgp_nexthop
= pi
->extra
->bgp_orig
;
6226 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6227 afi
, safi
, pi
, NULL
,
6229 bgp_path_info_set_flag(dest
, pi
,
6232 if (BGP_DEBUG(nht
, NHT
)) {
6233 char buf1
[INET6_ADDRSTRLEN
];
6234 inet_ntop(p
->family
,
6238 "%s(%s): Route not in table, not advertising",
6241 bgp_path_info_unset_flag(
6242 dest
, pi
, BGP_PATH_VALID
);
6245 /* Delete the NHT structure if any, if we're
6247 * enabling/disabling import check. We
6248 * deregister the route
6249 * from NHT to avoid overloading NHT and the
6250 * process interaction
6252 bgp_unlink_nexthop(pi
);
6253 bgp_path_info_set_flag(dest
, pi
,
6256 /* Process change. */
6257 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6258 bgp_process(bgp
, dest
, afi
, safi
);
6260 if (SAFI_UNICAST
== safi
6261 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6263 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6264 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6268 bgp_dest_unlock_node(dest
);
6269 aspath_unintern(&attr
.aspath
);
6274 /* Make new BGP info. */
6275 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6277 /* Nexthop reachability check. */
6278 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6279 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6280 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6282 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6284 if (BGP_DEBUG(nht
, NHT
)) {
6285 char buf1
[INET6_ADDRSTRLEN
];
6287 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6290 "%s(%s): Route not in table, not advertising",
6293 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6296 /* Delete the NHT structure if any, if we're toggling between
6297 * enabling/disabling import check. We deregister the route
6298 * from NHT to avoid overloading NHT and the process interaction
6300 bgp_unlink_nexthop(new);
6302 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6305 /* Aggregate address increment. */
6306 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6308 /* Register new BGP information. */
6309 bgp_path_info_add(dest
, new);
6311 /* route_node_get lock */
6312 bgp_dest_unlock_node(dest
);
6314 /* Process change. */
6315 bgp_process(bgp
, dest
, afi
, safi
);
6317 if (SAFI_UNICAST
== safi
6318 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6319 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6320 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6323 /* Unintern original. */
6324 aspath_unintern(&attr
.aspath
);
6327 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6330 struct bgp_dest
*dest
;
6331 struct bgp_path_info
*pi
;
6333 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6335 /* Check selected route and self inserted route. */
6336 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6337 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6338 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6341 /* Withdraw static BGP route from routing table. */
6343 if (SAFI_UNICAST
== safi
6344 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6345 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6346 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6348 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6349 bgp_unlink_nexthop(pi
);
6350 bgp_path_info_delete(dest
, pi
);
6351 bgp_process(bgp
, dest
, afi
, safi
);
6354 /* Unlock bgp_node_lookup. */
6355 bgp_dest_unlock_node(dest
);
6359 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6361 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6362 afi_t afi
, safi_t safi
,
6363 struct prefix_rd
*prd
)
6365 struct bgp_dest
*dest
;
6366 struct bgp_path_info
*pi
;
6368 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6370 /* Check selected route and self inserted route. */
6371 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6372 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6373 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6376 /* Withdraw static BGP route from routing table. */
6378 #ifdef ENABLE_BGP_VNC
6379 rfapiProcessWithdraw(
6380 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6381 1); /* Kill, since it is an administrative change */
6383 if (SAFI_MPLS_VPN
== safi
6384 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6385 vpn_leak_to_vrf_withdraw(pi
);
6387 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6388 bgp_path_info_delete(dest
, pi
);
6389 bgp_process(bgp
, dest
, afi
, safi
);
6392 /* Unlock bgp_node_lookup. */
6393 bgp_dest_unlock_node(dest
);
6396 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6397 struct bgp_static
*bgp_static
, afi_t afi
,
6400 struct bgp_dest
*dest
;
6401 struct bgp_path_info
*new;
6402 struct attr
*attr_new
;
6403 struct attr attr
= {0};
6404 struct bgp_path_info
*pi
;
6405 #ifdef ENABLE_BGP_VNC
6406 mpls_label_t label
= 0;
6408 uint32_t num_labels
= 0;
6412 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6414 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6417 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6419 attr
.nexthop
= bgp_static
->igpnexthop
;
6420 attr
.med
= bgp_static
->igpmetric
;
6421 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6423 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6424 || (safi
== SAFI_ENCAP
)) {
6425 if (afi
== AFI_IP
) {
6426 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6427 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6430 if (afi
== AFI_L2VPN
) {
6431 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6432 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6433 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6434 &bgp_static
->gatewayIp
.u
.prefix4
,
6436 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6437 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6438 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6439 &bgp_static
->gatewayIp
.u
.prefix6
,
6442 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6443 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6444 struct bgp_encap_type_vxlan bet
;
6445 memset(&bet
, 0, sizeof(bet
));
6446 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6447 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6449 if (bgp_static
->router_mac
) {
6450 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6453 /* Apply route-map. */
6454 if (bgp_static
->rmap
.name
) {
6455 struct attr attr_tmp
= attr
;
6456 struct bgp_path_info rmap_path
;
6457 route_map_result_t ret
;
6459 rmap_path
.peer
= bgp
->peer_self
;
6460 rmap_path
.attr
= &attr_tmp
;
6462 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6464 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6466 bgp
->peer_self
->rmap_type
= 0;
6468 if (ret
== RMAP_DENYMATCH
) {
6469 /* Free uninterned attribute. */
6470 bgp_attr_flush(&attr_tmp
);
6472 /* Unintern original. */
6473 aspath_unintern(&attr
.aspath
);
6474 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6476 bgp_dest_unlock_node(dest
);
6480 attr_new
= bgp_attr_intern(&attr_tmp
);
6482 attr_new
= bgp_attr_intern(&attr
);
6485 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6486 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6487 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6491 if (attrhash_cmp(pi
->attr
, attr_new
)
6492 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6493 bgp_dest_unlock_node(dest
);
6494 bgp_attr_unintern(&attr_new
);
6495 aspath_unintern(&attr
.aspath
);
6498 /* The attribute is changed. */
6499 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6501 /* Rewrite BGP route information. */
6502 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6503 bgp_path_info_restore(dest
, pi
);
6505 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6506 bgp_attr_unintern(&pi
->attr
);
6507 pi
->attr
= attr_new
;
6508 pi
->uptime
= monotime(NULL
);
6509 #ifdef ENABLE_BGP_VNC
6511 label
= decode_label(&pi
->extra
->label
[0]);
6514 /* Process change. */
6515 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6516 bgp_process(bgp
, dest
, afi
, safi
);
6518 if (SAFI_MPLS_VPN
== safi
6519 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6520 vpn_leak_to_vrf_update(bgp
, pi
,
6523 #ifdef ENABLE_BGP_VNC
6524 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6525 pi
->attr
, afi
, safi
, pi
->type
,
6526 pi
->sub_type
, &label
);
6528 bgp_dest_unlock_node(dest
);
6529 aspath_unintern(&attr
.aspath
);
6535 /* Make new BGP info. */
6536 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6538 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6539 bgp_path_info_extra_get(new);
6541 new->extra
->label
[0] = bgp_static
->label
;
6542 new->extra
->num_labels
= num_labels
;
6544 #ifdef ENABLE_BGP_VNC
6545 label
= decode_label(&bgp_static
->label
);
6548 /* Aggregate address increment. */
6549 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6551 /* Register new BGP information. */
6552 bgp_path_info_add(dest
, new);
6553 /* route_node_get lock */
6554 bgp_dest_unlock_node(dest
);
6556 /* Process change. */
6557 bgp_process(bgp
, dest
, afi
, safi
);
6559 if (SAFI_MPLS_VPN
== safi
6560 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6561 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6563 #ifdef ENABLE_BGP_VNC
6564 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6565 safi
, new->type
, new->sub_type
, &label
);
6568 /* Unintern original. */
6569 aspath_unintern(&attr
.aspath
);
6572 /* Configure static BGP network. When user don't run zebra, static
6573 route should be installed as valid. */
6574 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6575 const char *ip_str
, afi_t afi
, safi_t safi
,
6576 const char *rmap
, int backdoor
, uint32_t label_index
)
6578 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6581 struct bgp_static
*bgp_static
;
6582 struct bgp_dest
*dest
;
6583 uint8_t need_update
= 0;
6585 /* Convert IP prefix string to struct prefix. */
6586 ret
= str2prefix(ip_str
, &p
);
6588 vty_out(vty
, "%% Malformed prefix\n");
6589 return CMD_WARNING_CONFIG_FAILED
;
6591 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6592 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6593 return CMD_WARNING_CONFIG_FAILED
;
6600 /* Set BGP static route configuration. */
6601 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6604 vty_out(vty
, "%% Can't find static route specified\n");
6605 return CMD_WARNING_CONFIG_FAILED
;
6608 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6610 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6611 && (label_index
!= bgp_static
->label_index
)) {
6613 "%% label-index doesn't match static route\n");
6614 bgp_dest_unlock_node(dest
);
6615 return CMD_WARNING_CONFIG_FAILED
;
6618 if ((rmap
&& bgp_static
->rmap
.name
)
6619 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6621 "%% route-map name doesn't match static route\n");
6622 bgp_dest_unlock_node(dest
);
6623 return CMD_WARNING_CONFIG_FAILED
;
6626 /* Update BGP RIB. */
6627 if (!bgp_static
->backdoor
)
6628 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6630 /* Clear configuration. */
6631 bgp_static_free(bgp_static
);
6632 bgp_dest_set_bgp_static_info(dest
, NULL
);
6633 bgp_dest_unlock_node(dest
);
6634 bgp_dest_unlock_node(dest
);
6637 /* Set BGP static route configuration. */
6638 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6639 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6641 /* Configuration change. */
6642 /* Label index cannot be changed. */
6643 if (bgp_static
->label_index
!= label_index
) {
6644 vty_out(vty
, "%% cannot change label-index\n");
6645 bgp_dest_unlock_node(dest
);
6646 return CMD_WARNING_CONFIG_FAILED
;
6649 /* Check previous routes are installed into BGP. */
6650 if (bgp_static
->valid
6651 && bgp_static
->backdoor
!= backdoor
)
6654 bgp_static
->backdoor
= backdoor
;
6657 XFREE(MTYPE_ROUTE_MAP_NAME
,
6658 bgp_static
->rmap
.name
);
6659 route_map_counter_decrement(
6660 bgp_static
->rmap
.map
);
6661 bgp_static
->rmap
.name
=
6662 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6663 bgp_static
->rmap
.map
=
6664 route_map_lookup_by_name(rmap
);
6665 route_map_counter_increment(
6666 bgp_static
->rmap
.map
);
6668 XFREE(MTYPE_ROUTE_MAP_NAME
,
6669 bgp_static
->rmap
.name
);
6670 route_map_counter_decrement(
6671 bgp_static
->rmap
.map
);
6672 bgp_static
->rmap
.map
= NULL
;
6673 bgp_static
->valid
= 0;
6675 bgp_dest_unlock_node(dest
);
6677 /* New configuration. */
6678 bgp_static
= bgp_static_new();
6679 bgp_static
->backdoor
= backdoor
;
6680 bgp_static
->valid
= 0;
6681 bgp_static
->igpmetric
= 0;
6682 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6683 bgp_static
->label_index
= label_index
;
6686 XFREE(MTYPE_ROUTE_MAP_NAME
,
6687 bgp_static
->rmap
.name
);
6688 route_map_counter_decrement(
6689 bgp_static
->rmap
.map
);
6690 bgp_static
->rmap
.name
=
6691 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6692 bgp_static
->rmap
.map
=
6693 route_map_lookup_by_name(rmap
);
6694 route_map_counter_increment(
6695 bgp_static
->rmap
.map
);
6697 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6700 bgp_static
->valid
= 1;
6702 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6704 if (!bgp_static
->backdoor
)
6705 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6711 void bgp_static_add(struct bgp
*bgp
)
6715 struct bgp_dest
*dest
;
6716 struct bgp_dest
*rm
;
6717 struct bgp_table
*table
;
6718 struct bgp_static
*bgp_static
;
6720 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6721 FOREACH_AFI_SAFI (afi
, safi
)
6722 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6723 dest
= bgp_route_next(dest
)) {
6724 if (!bgp_dest_has_bgp_path_info_data(dest
))
6727 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6728 || (safi
== SAFI_EVPN
)) {
6729 table
= bgp_dest_get_bgp_table_info(dest
);
6731 for (rm
= bgp_table_top(table
); rm
;
6732 rm
= bgp_route_next(rm
)) {
6734 bgp_dest_get_bgp_static_info(
6736 bgp_static_update_safi(
6737 bgp
, bgp_dest_get_prefix(rm
),
6738 bgp_static
, afi
, safi
);
6742 bgp
, bgp_dest_get_prefix(dest
),
6743 bgp_dest_get_bgp_static_info(dest
), afi
,
6747 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6750 /* Called from bgp_delete(). Delete all static routes from the BGP
6752 void bgp_static_delete(struct bgp
*bgp
)
6756 struct bgp_dest
*dest
;
6757 struct bgp_dest
*rm
;
6758 struct bgp_table
*table
;
6759 struct bgp_static
*bgp_static
;
6761 FOREACH_AFI_SAFI (afi
, safi
)
6762 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6763 dest
= bgp_route_next(dest
)) {
6764 if (!bgp_dest_has_bgp_path_info_data(dest
))
6767 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6768 || (safi
== SAFI_EVPN
)) {
6769 table
= bgp_dest_get_bgp_table_info(dest
);
6771 for (rm
= bgp_table_top(table
); rm
;
6772 rm
= bgp_route_next(rm
)) {
6774 bgp_dest_get_bgp_static_info(
6779 bgp_static_withdraw_safi(
6780 bgp
, bgp_dest_get_prefix(rm
),
6782 (struct prefix_rd
*)
6783 bgp_dest_get_prefix(
6785 bgp_static_free(bgp_static
);
6786 bgp_dest_set_bgp_static_info(rm
,
6788 bgp_dest_unlock_node(rm
);
6791 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6792 bgp_static_withdraw(bgp
,
6793 bgp_dest_get_prefix(dest
),
6795 bgp_static_free(bgp_static
);
6796 bgp_dest_set_bgp_static_info(dest
, NULL
);
6797 bgp_dest_unlock_node(dest
);
6802 void bgp_static_redo_import_check(struct bgp
*bgp
)
6806 struct bgp_dest
*dest
;
6807 struct bgp_dest
*rm
;
6808 struct bgp_table
*table
;
6809 struct bgp_static
*bgp_static
;
6811 /* Use this flag to force reprocessing of the route */
6812 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6813 FOREACH_AFI_SAFI (afi
, safi
) {
6814 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6815 dest
= bgp_route_next(dest
)) {
6816 if (!bgp_dest_has_bgp_path_info_data(dest
))
6819 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6820 || (safi
== SAFI_EVPN
)) {
6821 table
= bgp_dest_get_bgp_table_info(dest
);
6823 for (rm
= bgp_table_top(table
); rm
;
6824 rm
= bgp_route_next(rm
)) {
6826 bgp_dest_get_bgp_static_info(
6828 bgp_static_update_safi(
6829 bgp
, bgp_dest_get_prefix(rm
),
6830 bgp_static
, afi
, safi
);
6833 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6834 bgp_static_update(bgp
,
6835 bgp_dest_get_prefix(dest
),
6836 bgp_static
, afi
, safi
);
6840 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6843 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6846 struct bgp_table
*table
;
6847 struct bgp_dest
*dest
;
6848 struct bgp_path_info
*pi
;
6850 /* Do not install the aggregate route if BGP is in the
6851 * process of termination.
6853 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6854 || (bgp
->peer_self
== NULL
))
6857 table
= bgp
->rib
[afi
][safi
];
6858 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6859 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6860 if (pi
->peer
== bgp
->peer_self
6861 && ((pi
->type
== ZEBRA_ROUTE_BGP
6862 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6863 || (pi
->type
!= ZEBRA_ROUTE_BGP
6865 == BGP_ROUTE_REDISTRIBUTE
))) {
6866 bgp_aggregate_decrement(
6867 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6869 bgp_unlink_nexthop(pi
);
6870 bgp_path_info_delete(dest
, pi
);
6871 bgp_process(bgp
, dest
, afi
, safi
);
6878 * Purge all networks and redistributed routes from routing table.
6879 * Invoked upon the instance going down.
6881 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6886 FOREACH_AFI_SAFI (afi
, safi
)
6887 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6892 * Currently this is used to set static routes for VPN and ENCAP.
6893 * I think it can probably be factored with bgp_static_set.
6895 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6896 const char *ip_str
, const char *rd_str
,
6897 const char *label_str
, const char *rmap_str
,
6898 int evpn_type
, const char *esi
, const char *gwip
,
6899 const char *ethtag
, const char *routermac
)
6901 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6904 struct prefix_rd prd
;
6905 struct bgp_dest
*pdest
;
6906 struct bgp_dest
*dest
;
6907 struct bgp_table
*table
;
6908 struct bgp_static
*bgp_static
;
6909 mpls_label_t label
= MPLS_INVALID_LABEL
;
6910 struct prefix gw_ip
;
6912 /* validate ip prefix */
6913 ret
= str2prefix(ip_str
, &p
);
6915 vty_out(vty
, "%% Malformed prefix\n");
6916 return CMD_WARNING_CONFIG_FAILED
;
6919 if ((afi
== AFI_L2VPN
)
6920 && (bgp_build_evpn_prefix(evpn_type
,
6921 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6922 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6923 return CMD_WARNING_CONFIG_FAILED
;
6926 ret
= str2prefix_rd(rd_str
, &prd
);
6928 vty_out(vty
, "%% Malformed rd\n");
6929 return CMD_WARNING_CONFIG_FAILED
;
6933 unsigned long label_val
;
6934 label_val
= strtoul(label_str
, NULL
, 10);
6935 encode_label(label_val
, &label
);
6938 if (safi
== SAFI_EVPN
) {
6939 if (esi
&& str2esi(esi
, NULL
) == 0) {
6940 vty_out(vty
, "%% Malformed ESI\n");
6941 return CMD_WARNING_CONFIG_FAILED
;
6943 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6944 vty_out(vty
, "%% Malformed Router MAC\n");
6945 return CMD_WARNING_CONFIG_FAILED
;
6948 memset(&gw_ip
, 0, sizeof(gw_ip
));
6949 ret
= str2prefix(gwip
, &gw_ip
);
6951 vty_out(vty
, "%% Malformed GatewayIp\n");
6952 return CMD_WARNING_CONFIG_FAILED
;
6954 if ((gw_ip
.family
== AF_INET
6955 && is_evpn_prefix_ipaddr_v6(
6956 (struct prefix_evpn
*)&p
))
6957 || (gw_ip
.family
== AF_INET6
6958 && is_evpn_prefix_ipaddr_v4(
6959 (struct prefix_evpn
*)&p
))) {
6961 "%% GatewayIp family differs with IP prefix\n");
6962 return CMD_WARNING_CONFIG_FAILED
;
6966 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6967 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6968 bgp_dest_set_bgp_table_info(pdest
,
6969 bgp_table_init(bgp
, afi
, safi
));
6970 table
= bgp_dest_get_bgp_table_info(pdest
);
6972 dest
= bgp_node_get(table
, &p
);
6974 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6975 vty_out(vty
, "%% Same network configuration exists\n");
6976 bgp_dest_unlock_node(dest
);
6978 /* New configuration. */
6979 bgp_static
= bgp_static_new();
6980 bgp_static
->backdoor
= 0;
6981 bgp_static
->valid
= 0;
6982 bgp_static
->igpmetric
= 0;
6983 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6984 bgp_static
->label
= label
;
6985 bgp_static
->prd
= prd
;
6988 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6989 route_map_counter_decrement(bgp_static
->rmap
.map
);
6990 bgp_static
->rmap
.name
=
6991 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6992 bgp_static
->rmap
.map
=
6993 route_map_lookup_by_name(rmap_str
);
6994 route_map_counter_increment(bgp_static
->rmap
.map
);
6997 if (safi
== SAFI_EVPN
) {
6999 bgp_static
->eth_s_id
=
7002 str2esi(esi
, bgp_static
->eth_s_id
);
7005 bgp_static
->router_mac
=
7006 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7007 (void)prefix_str2mac(routermac
,
7008 bgp_static
->router_mac
);
7011 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7013 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7015 bgp_static
->valid
= 1;
7016 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7022 /* Configure static BGP network. */
7023 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7024 const char *ip_str
, const char *rd_str
,
7025 const char *label_str
, int evpn_type
, const char *esi
,
7026 const char *gwip
, const char *ethtag
)
7028 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7031 struct prefix_rd prd
;
7032 struct bgp_dest
*pdest
;
7033 struct bgp_dest
*dest
;
7034 struct bgp_table
*table
;
7035 struct bgp_static
*bgp_static
;
7036 mpls_label_t label
= MPLS_INVALID_LABEL
;
7038 /* Convert IP prefix string to struct prefix. */
7039 ret
= str2prefix(ip_str
, &p
);
7041 vty_out(vty
, "%% Malformed prefix\n");
7042 return CMD_WARNING_CONFIG_FAILED
;
7045 if ((afi
== AFI_L2VPN
)
7046 && (bgp_build_evpn_prefix(evpn_type
,
7047 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7048 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7049 return CMD_WARNING_CONFIG_FAILED
;
7051 ret
= str2prefix_rd(rd_str
, &prd
);
7053 vty_out(vty
, "%% Malformed rd\n");
7054 return CMD_WARNING_CONFIG_FAILED
;
7058 unsigned long label_val
;
7059 label_val
= strtoul(label_str
, NULL
, 10);
7060 encode_label(label_val
, &label
);
7063 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7064 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7065 bgp_dest_set_bgp_table_info(pdest
,
7066 bgp_table_init(bgp
, afi
, safi
));
7068 bgp_dest_unlock_node(pdest
);
7069 table
= bgp_dest_get_bgp_table_info(pdest
);
7071 dest
= bgp_node_lookup(table
, &p
);
7074 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7076 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7077 bgp_static_free(bgp_static
);
7078 bgp_dest_set_bgp_static_info(dest
, NULL
);
7079 bgp_dest_unlock_node(dest
);
7080 bgp_dest_unlock_node(dest
);
7082 vty_out(vty
, "%% Can't find the route\n");
7087 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7088 const char *rmap_name
)
7090 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7091 struct bgp_rmap
*rmap
;
7093 rmap
= &bgp
->table_map
[afi
][safi
];
7095 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7096 route_map_counter_decrement(rmap
->map
);
7097 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7098 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7099 route_map_counter_increment(rmap
->map
);
7101 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7102 route_map_counter_decrement(rmap
->map
);
7106 if (bgp_fibupd_safi(safi
))
7107 bgp_zebra_announce_table(bgp
, afi
, safi
);
7112 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7113 const char *rmap_name
)
7115 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7116 struct bgp_rmap
*rmap
;
7118 rmap
= &bgp
->table_map
[afi
][safi
];
7119 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7120 route_map_counter_decrement(rmap
->map
);
7123 if (bgp_fibupd_safi(safi
))
7124 bgp_zebra_announce_table(bgp
, afi
, safi
);
7129 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7132 if (bgp
->table_map
[afi
][safi
].name
) {
7133 vty_out(vty
, " table-map %s\n",
7134 bgp
->table_map
[afi
][safi
].name
);
7138 DEFUN (bgp_table_map
,
7141 "BGP table to RIB route download filter\n"
7142 "Name of the route map\n")
7145 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7146 argv
[idx_word
]->arg
);
7148 DEFUN (no_bgp_table_map
,
7149 no_bgp_table_map_cmd
,
7150 "no table-map WORD",
7152 "BGP table to RIB route download filter\n"
7153 "Name of the route map\n")
7156 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7157 argv
[idx_word
]->arg
);
7163 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7164 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7165 backdoor$backdoor}]",
7167 "Specify a network to announce via BGP\n"
7172 "Route-map to modify the attributes\n"
7173 "Name of the route map\n"
7174 "Label index to associate with the prefix\n"
7175 "Label index value\n"
7176 "Specify a BGP backdoor route\n")
7178 char addr_prefix_str
[BUFSIZ
];
7183 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7185 sizeof(addr_prefix_str
));
7187 vty_out(vty
, "%% Inconsistent address and mask\n");
7188 return CMD_WARNING_CONFIG_FAILED
;
7192 return bgp_static_set(
7193 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7194 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7195 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7198 DEFPY(ipv6_bgp_network
,
7199 ipv6_bgp_network_cmd
,
7200 "[no] network X:X::X:X/M$prefix \
7201 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7203 "Specify a network to announce via BGP\n"
7205 "Route-map to modify the attributes\n"
7206 "Name of the route map\n"
7207 "Label index to associate with the prefix\n"
7208 "Label index value\n")
7210 return bgp_static_set(
7211 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7212 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7215 static struct bgp_aggregate
*bgp_aggregate_new(void)
7217 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7220 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7222 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7223 route_map_counter_decrement(aggregate
->suppress_map
);
7224 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7225 route_map_counter_decrement(aggregate
->rmap
.map
);
7226 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7230 * Helper function to avoid repeated code: prepare variables for a
7231 * `route_map_apply` call.
7233 * \returns `true` on route map match, otherwise `false`.
7235 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7236 struct bgp_aggregate
*aggregate
,
7237 struct bgp_path_info
*pi
)
7239 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7240 route_map_result_t rmr
= RMAP_DENYMATCH
;
7241 struct bgp_path_info rmap_path
= {};
7242 struct attr attr
= {};
7244 /* No route map entries created, just don't match. */
7245 if (aggregate
->suppress_map
== NULL
)
7248 /* Call route map matching and return result. */
7249 attr
.aspath
= aspath_empty();
7250 rmap_path
.peer
= bgp
->peer_self
;
7251 rmap_path
.attr
= &attr
;
7253 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7254 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7255 bgp
->peer_self
->rmap_type
= 0;
7257 bgp_attr_flush(&attr
);
7258 aspath_unintern(&attr
.aspath
);
7260 return rmr
== RMAP_PERMITMATCH
;
7263 /** Test whether the aggregation has suppressed this path or not. */
7264 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7265 struct bgp_path_info
*pi
)
7267 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7270 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7274 * Suppress this path and keep the reference.
7276 * \returns `true` if needs processing otherwise `false`.
7278 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7279 struct bgp_path_info
*pi
)
7281 struct bgp_path_info_extra
*pie
;
7283 /* Path is already suppressed by this aggregation. */
7284 if (aggr_suppress_exists(aggregate
, pi
))
7287 pie
= bgp_path_info_extra_get(pi
);
7289 /* This is the first suppression, allocate memory and list it. */
7290 if (pie
->aggr_suppressors
== NULL
)
7291 pie
->aggr_suppressors
= list_new();
7293 listnode_add(pie
->aggr_suppressors
, aggregate
);
7295 /* Only mark for processing if suppressed. */
7296 if (listcount(pie
->aggr_suppressors
) == 1) {
7297 if (BGP_DEBUG(update
, UPDATE_OUT
))
7298 zlog_debug("aggregate-address suppressing: %pFX",
7299 bgp_dest_get_prefix(pi
->net
));
7301 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7309 * Unsuppress this path and remove the reference.
7311 * \returns `true` if needs processing otherwise `false`.
7313 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7314 struct bgp_path_info
*pi
)
7316 /* Path wasn't suppressed. */
7317 if (!aggr_suppress_exists(aggregate
, pi
))
7320 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7322 /* Unsuppress and free extra memory if last item. */
7323 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7324 if (BGP_DEBUG(update
, UPDATE_OUT
))
7325 zlog_debug("aggregate-address unsuppressing: %pFX",
7326 bgp_dest_get_prefix(pi
->net
));
7328 list_delete(&pi
->extra
->aggr_suppressors
);
7329 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7336 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7337 struct aspath
*aspath
,
7338 struct community
*comm
,
7339 struct ecommunity
*ecomm
,
7340 struct lcommunity
*lcomm
)
7342 static struct aspath
*ae
= NULL
;
7345 ae
= aspath_empty();
7350 if (origin
!= pi
->attr
->origin
)
7353 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7356 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7359 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7362 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7365 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7371 static void bgp_aggregate_install(
7372 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7373 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7374 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7375 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7377 struct bgp_dest
*dest
;
7378 struct bgp_table
*table
;
7379 struct bgp_path_info
*pi
, *orig
, *new;
7382 table
= bgp
->rib
[afi
][safi
];
7384 dest
= bgp_node_get(table
, p
);
7386 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7387 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7388 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7392 * If we have paths with different MEDs, then don't install
7393 * (or uninstall) the aggregate route.
7395 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7396 goto uninstall_aggregate_route
;
7398 if (aggregate
->count
> 0) {
7400 * If the aggregate information has not changed
7401 * no need to re-install it again.
7403 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7404 ecommunity
, lcommunity
)) {
7405 bgp_dest_unlock_node(dest
);
7408 aspath_free(aspath
);
7410 community_free(&community
);
7412 ecommunity_free(&ecommunity
);
7414 lcommunity_free(&lcommunity
);
7420 * Mark the old as unusable
7423 bgp_path_info_delete(dest
, pi
);
7425 attr
= bgp_attr_aggregate_intern(
7426 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7427 aggregate
, atomic_aggregate
, p
);
7430 bgp_dest_unlock_node(dest
);
7431 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7432 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7433 zlog_debug("%s: %pFX null attribute", __func__
,
7438 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7439 bgp
->peer_self
, attr
, dest
);
7441 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7443 bgp_path_info_add(dest
, new);
7444 bgp_process(bgp
, dest
, afi
, safi
);
7446 uninstall_aggregate_route
:
7447 for (pi
= orig
; pi
; pi
= pi
->next
)
7448 if (pi
->peer
== bgp
->peer_self
7449 && pi
->type
== ZEBRA_ROUTE_BGP
7450 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7453 /* Withdraw static BGP route from routing table. */
7455 bgp_path_info_delete(dest
, pi
);
7456 bgp_process(bgp
, dest
, afi
, safi
);
7460 bgp_dest_unlock_node(dest
);
7464 * Check if the current path has different MED than other known paths.
7466 * \returns `true` if the MED matched the others else `false`.
7468 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7469 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7471 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7473 /* This is the first route being analyzed. */
7474 if (!aggregate
->med_initialized
) {
7475 aggregate
->med_initialized
= true;
7476 aggregate
->med_mismatched
= false;
7477 aggregate
->med_matched_value
= cur_med
;
7479 /* Check if routes with different MED showed up. */
7480 if (cur_med
!= aggregate
->med_matched_value
)
7481 aggregate
->med_mismatched
= true;
7484 return !aggregate
->med_mismatched
;
7488 * Initializes and tests all routes in the aggregate address path for MED
7491 * \returns `true` if all MEDs are the same otherwise `false`.
7493 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7494 struct bgp
*bgp
, const struct prefix
*p
,
7495 afi_t afi
, safi_t safi
)
7497 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7498 const struct prefix
*dest_p
;
7499 struct bgp_dest
*dest
, *top
;
7500 struct bgp_path_info
*pi
;
7501 bool med_matched
= true;
7503 aggregate
->med_initialized
= false;
7505 top
= bgp_node_get(table
, p
);
7506 for (dest
= bgp_node_get(table
, p
); dest
;
7507 dest
= bgp_route_next_until(dest
, top
)) {
7508 dest_p
= bgp_dest_get_prefix(dest
);
7509 if (dest_p
->prefixlen
<= p
->prefixlen
)
7512 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7513 if (BGP_PATH_HOLDDOWN(pi
))
7515 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7517 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7518 med_matched
= false;
7525 bgp_dest_unlock_node(top
);
7531 * Toggles the route suppression status for this aggregate address
7534 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7535 struct bgp
*bgp
, const struct prefix
*p
,
7536 afi_t afi
, safi_t safi
, bool suppress
)
7538 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7539 const struct prefix
*dest_p
;
7540 struct bgp_dest
*dest
, *top
;
7541 struct bgp_path_info
*pi
;
7542 bool toggle_suppression
;
7544 /* We've found a different MED we must revert any suppressed routes. */
7545 top
= bgp_node_get(table
, p
);
7546 for (dest
= bgp_node_get(table
, p
); dest
;
7547 dest
= bgp_route_next_until(dest
, top
)) {
7548 dest_p
= bgp_dest_get_prefix(dest
);
7549 if (dest_p
->prefixlen
<= p
->prefixlen
)
7552 toggle_suppression
= false;
7553 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7554 if (BGP_PATH_HOLDDOWN(pi
))
7556 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7559 /* We are toggling suppression back. */
7561 /* Suppress route if not suppressed already. */
7562 if (aggr_suppress_path(aggregate
, pi
))
7563 toggle_suppression
= true;
7567 /* Install route if there is no more suppression. */
7568 if (aggr_unsuppress_path(aggregate
, pi
))
7569 toggle_suppression
= true;
7572 if (toggle_suppression
)
7573 bgp_process(bgp
, dest
, afi
, safi
);
7575 bgp_dest_unlock_node(top
);
7579 * Aggregate address MED matching incremental test: this function is called
7580 * when the initial aggregation occurred and we are only testing a single
7583 * In addition to testing and setting the MED validity it also installs back
7584 * suppressed routes (if summary is configured).
7586 * Must not be called in `bgp_aggregate_route`.
7588 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7589 struct bgp
*bgp
, const struct prefix
*p
,
7590 afi_t afi
, safi_t safi
,
7591 struct bgp_path_info
*pi
)
7593 /* MED matching disabled. */
7594 if (!aggregate
->match_med
)
7597 /* Aggregation with different MED, recheck if we have got equal MEDs
7600 if (aggregate
->med_mismatched
&&
7601 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7602 aggregate
->summary_only
)
7603 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7606 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7608 /* No mismatches, just quit. */
7609 if (!aggregate
->med_mismatched
)
7612 /* Route summarization is disabled. */
7613 if (!aggregate
->summary_only
)
7616 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7619 /* Update an aggregate as routes are added/removed from the BGP table */
7620 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7621 safi_t safi
, struct bgp_aggregate
*aggregate
)
7623 struct bgp_table
*table
;
7624 struct bgp_dest
*top
;
7625 struct bgp_dest
*dest
;
7627 struct aspath
*aspath
= NULL
;
7628 struct community
*community
= NULL
;
7629 struct ecommunity
*ecommunity
= NULL
;
7630 struct lcommunity
*lcommunity
= NULL
;
7631 struct bgp_path_info
*pi
;
7632 unsigned long match
= 0;
7633 uint8_t atomic_aggregate
= 0;
7635 /* If the bgp instance is being deleted or self peer is deleted
7636 * then do not create aggregate route
7638 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7639 || (bgp
->peer_self
== NULL
))
7642 /* Initialize and test routes for MED difference. */
7643 if (aggregate
->match_med
)
7644 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7647 * Reset aggregate count: we might've been called from route map
7648 * update so in that case we must retest all more specific routes.
7650 * \see `bgp_route_map_process_update`.
7652 aggregate
->count
= 0;
7653 aggregate
->incomplete_origin_count
= 0;
7654 aggregate
->incomplete_origin_count
= 0;
7655 aggregate
->egp_origin_count
= 0;
7657 /* ORIGIN attribute: If at least one route among routes that are
7658 aggregated has ORIGIN with the value INCOMPLETE, then the
7659 aggregated route must have the ORIGIN attribute with the value
7660 INCOMPLETE. Otherwise, if at least one route among routes that
7661 are aggregated has ORIGIN with the value EGP, then the aggregated
7662 route must have the origin attribute with the value EGP. In all
7663 other case the value of the ORIGIN attribute of the aggregated
7664 route is INTERNAL. */
7665 origin
= BGP_ORIGIN_IGP
;
7667 table
= bgp
->rib
[afi
][safi
];
7669 top
= bgp_node_get(table
, p
);
7670 for (dest
= bgp_node_get(table
, p
); dest
;
7671 dest
= bgp_route_next_until(dest
, top
)) {
7672 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7674 if (dest_p
->prefixlen
<= p
->prefixlen
)
7677 /* If suppress fib is enabled and route not installed
7678 * in FIB, skip the route
7680 if (!bgp_check_advertise(bgp
, dest
))
7685 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7686 if (BGP_PATH_HOLDDOWN(pi
))
7690 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7691 atomic_aggregate
= 1;
7693 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7697 * summary-only aggregate route suppress
7698 * aggregated route announcements.
7701 * Don't create summaries if MED didn't match
7702 * otherwise neither the specific routes and the
7703 * aggregation will be announced.
7705 if (aggregate
->summary_only
7706 && AGGREGATE_MED_VALID(aggregate
)) {
7707 if (aggr_suppress_path(aggregate
, pi
))
7712 * Suppress more specific routes that match the route
7716 * Don't suppress routes if MED matching is enabled and
7717 * it mismatched otherwise we might end up with no
7718 * routes for this path.
7720 if (aggregate
->suppress_map_name
7721 && AGGREGATE_MED_VALID(aggregate
)
7722 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7723 if (aggr_suppress_path(aggregate
, pi
))
7730 * If at least one route among routes that are
7731 * aggregated has ORIGIN with the value INCOMPLETE,
7732 * then the aggregated route MUST have the ORIGIN
7733 * attribute with the value INCOMPLETE. Otherwise, if
7734 * at least one route among routes that are aggregated
7735 * has ORIGIN with the value EGP, then the aggregated
7736 * route MUST have the ORIGIN attribute with the value
7739 switch (pi
->attr
->origin
) {
7740 case BGP_ORIGIN_INCOMPLETE
:
7741 aggregate
->incomplete_origin_count
++;
7743 case BGP_ORIGIN_EGP
:
7744 aggregate
->egp_origin_count
++;
7752 if (!aggregate
->as_set
)
7756 * as-set aggregate route generate origin, as path,
7757 * and community aggregation.
7759 /* Compute aggregate route's as-path.
7761 bgp_compute_aggregate_aspath_hash(aggregate
,
7764 /* Compute aggregate route's community.
7766 if (bgp_attr_get_community(pi
->attr
))
7767 bgp_compute_aggregate_community_hash(
7769 bgp_attr_get_community(pi
->attr
));
7771 /* Compute aggregate route's extended community.
7773 if (bgp_attr_get_ecommunity(pi
->attr
))
7774 bgp_compute_aggregate_ecommunity_hash(
7776 bgp_attr_get_ecommunity(pi
->attr
));
7778 /* Compute aggregate route's large community.
7780 if (bgp_attr_get_lcommunity(pi
->attr
))
7781 bgp_compute_aggregate_lcommunity_hash(
7783 bgp_attr_get_lcommunity(pi
->attr
));
7786 bgp_process(bgp
, dest
, afi
, safi
);
7788 if (aggregate
->as_set
) {
7789 bgp_compute_aggregate_aspath_val(aggregate
);
7790 bgp_compute_aggregate_community_val(aggregate
);
7791 bgp_compute_aggregate_ecommunity_val(aggregate
);
7792 bgp_compute_aggregate_lcommunity_val(aggregate
);
7796 bgp_dest_unlock_node(top
);
7799 if (aggregate
->incomplete_origin_count
> 0)
7800 origin
= BGP_ORIGIN_INCOMPLETE
;
7801 else if (aggregate
->egp_origin_count
> 0)
7802 origin
= BGP_ORIGIN_EGP
;
7804 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7805 origin
= aggregate
->origin
;
7807 if (aggregate
->as_set
) {
7808 if (aggregate
->aspath
)
7809 /* Retrieve aggregate route's as-path.
7811 aspath
= aspath_dup(aggregate
->aspath
);
7813 if (aggregate
->community
)
7814 /* Retrieve aggregate route's community.
7816 community
= community_dup(aggregate
->community
);
7818 if (aggregate
->ecommunity
)
7819 /* Retrieve aggregate route's ecommunity.
7821 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7823 if (aggregate
->lcommunity
)
7824 /* Retrieve aggregate route's lcommunity.
7826 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7829 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7830 ecommunity
, lcommunity
, atomic_aggregate
,
7834 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7835 safi_t safi
, struct bgp_aggregate
*aggregate
)
7837 struct bgp_table
*table
;
7838 struct bgp_dest
*top
;
7839 struct bgp_dest
*dest
;
7840 struct bgp_path_info
*pi
;
7841 unsigned long match
;
7843 table
= bgp
->rib
[afi
][safi
];
7845 /* If routes exists below this node, generate aggregate routes. */
7846 top
= bgp_node_get(table
, p
);
7847 for (dest
= bgp_node_get(table
, p
); dest
;
7848 dest
= bgp_route_next_until(dest
, top
)) {
7849 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7851 if (dest_p
->prefixlen
<= p
->prefixlen
)
7855 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7856 if (BGP_PATH_HOLDDOWN(pi
))
7859 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7863 * This route is suppressed: attempt to unsuppress it.
7865 * `aggr_unsuppress_path` will fail if this particular
7866 * aggregate route was not the suppressor.
7868 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7869 listcount(pi
->extra
->aggr_suppressors
)) {
7870 if (aggr_unsuppress_path(aggregate
, pi
))
7876 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7877 aggregate
->incomplete_origin_count
--;
7878 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7879 aggregate
->egp_origin_count
--;
7881 if (aggregate
->as_set
) {
7882 /* Remove as-path from aggregate.
7884 bgp_remove_aspath_from_aggregate_hash(
7888 if (bgp_attr_get_community(pi
->attr
))
7889 /* Remove community from aggregate.
7891 bgp_remove_comm_from_aggregate_hash(
7893 bgp_attr_get_community(
7896 if (bgp_attr_get_ecommunity(pi
->attr
))
7897 /* Remove ecommunity from aggregate.
7899 bgp_remove_ecomm_from_aggregate_hash(
7901 bgp_attr_get_ecommunity(
7904 if (bgp_attr_get_lcommunity(pi
->attr
))
7905 /* Remove lcommunity from aggregate.
7907 bgp_remove_lcomm_from_aggregate_hash(
7909 bgp_attr_get_lcommunity(
7914 /* If this node was suppressed, process the change. */
7916 bgp_process(bgp
, dest
, afi
, safi
);
7918 if (aggregate
->as_set
) {
7919 aspath_free(aggregate
->aspath
);
7920 aggregate
->aspath
= NULL
;
7921 if (aggregate
->community
)
7922 community_free(&aggregate
->community
);
7923 if (aggregate
->ecommunity
)
7924 ecommunity_free(&aggregate
->ecommunity
);
7925 if (aggregate
->lcommunity
)
7926 lcommunity_free(&aggregate
->lcommunity
);
7929 bgp_dest_unlock_node(top
);
7932 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7933 const struct prefix
*aggr_p
,
7934 struct bgp_path_info
*pinew
, afi_t afi
,
7936 struct bgp_aggregate
*aggregate
)
7939 struct aspath
*aspath
= NULL
;
7940 uint8_t atomic_aggregate
= 0;
7941 struct community
*community
= NULL
;
7942 struct ecommunity
*ecommunity
= NULL
;
7943 struct lcommunity
*lcommunity
= NULL
;
7945 /* If the bgp instance is being deleted or self peer is deleted
7946 * then do not create aggregate route
7948 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7949 || (bgp
->peer_self
== NULL
))
7952 /* ORIGIN attribute: If at least one route among routes that are
7953 * aggregated has ORIGIN with the value INCOMPLETE, then the
7954 * aggregated route must have the ORIGIN attribute with the value
7955 * INCOMPLETE. Otherwise, if at least one route among routes that
7956 * are aggregated has ORIGIN with the value EGP, then the aggregated
7957 * route must have the origin attribute with the value EGP. In all
7958 * other case the value of the ORIGIN attribute of the aggregated
7959 * route is INTERNAL.
7961 origin
= BGP_ORIGIN_IGP
;
7966 * This must be called before `summary` check to avoid
7967 * "suppressing" twice.
7969 if (aggregate
->match_med
)
7970 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7973 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7974 aggr_suppress_path(aggregate
, pinew
);
7976 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7977 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7978 aggr_suppress_path(aggregate
, pinew
);
7980 switch (pinew
->attr
->origin
) {
7981 case BGP_ORIGIN_INCOMPLETE
:
7982 aggregate
->incomplete_origin_count
++;
7984 case BGP_ORIGIN_EGP
:
7985 aggregate
->egp_origin_count
++;
7993 if (aggregate
->incomplete_origin_count
> 0)
7994 origin
= BGP_ORIGIN_INCOMPLETE
;
7995 else if (aggregate
->egp_origin_count
> 0)
7996 origin
= BGP_ORIGIN_EGP
;
7998 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7999 origin
= aggregate
->origin
;
8001 if (aggregate
->as_set
) {
8002 /* Compute aggregate route's as-path.
8004 bgp_compute_aggregate_aspath(aggregate
,
8005 pinew
->attr
->aspath
);
8007 /* Compute aggregate route's community.
8009 if (bgp_attr_get_community(pinew
->attr
))
8010 bgp_compute_aggregate_community(
8011 aggregate
, bgp_attr_get_community(pinew
->attr
));
8013 /* Compute aggregate route's extended community.
8015 if (bgp_attr_get_ecommunity(pinew
->attr
))
8016 bgp_compute_aggregate_ecommunity(
8018 bgp_attr_get_ecommunity(pinew
->attr
));
8020 /* Compute aggregate route's large community.
8022 if (bgp_attr_get_lcommunity(pinew
->attr
))
8023 bgp_compute_aggregate_lcommunity(
8025 bgp_attr_get_lcommunity(pinew
->attr
));
8027 /* Retrieve aggregate route's as-path.
8029 if (aggregate
->aspath
)
8030 aspath
= aspath_dup(aggregate
->aspath
);
8032 /* Retrieve aggregate route's community.
8034 if (aggregate
->community
)
8035 community
= community_dup(aggregate
->community
);
8037 /* Retrieve aggregate route's ecommunity.
8039 if (aggregate
->ecommunity
)
8040 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8042 /* Retrieve aggregate route's lcommunity.
8044 if (aggregate
->lcommunity
)
8045 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8048 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8049 aspath
, community
, ecommunity
,
8050 lcommunity
, atomic_aggregate
, aggregate
);
8053 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8055 struct bgp_path_info
*pi
,
8056 struct bgp_aggregate
*aggregate
,
8057 const struct prefix
*aggr_p
)
8060 struct aspath
*aspath
= NULL
;
8061 uint8_t atomic_aggregate
= 0;
8062 struct community
*community
= NULL
;
8063 struct ecommunity
*ecommunity
= NULL
;
8064 struct lcommunity
*lcommunity
= NULL
;
8065 unsigned long match
= 0;
8067 /* If the bgp instance is being deleted or self peer is deleted
8068 * then do not create aggregate route
8070 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8071 || (bgp
->peer_self
== NULL
))
8074 if (BGP_PATH_HOLDDOWN(pi
))
8077 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8080 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8081 if (aggr_unsuppress_path(aggregate
, pi
))
8084 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8085 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8086 if (aggr_unsuppress_path(aggregate
, pi
))
8090 * This must be called after `summary`, `suppress-map` check to avoid
8091 * "unsuppressing" twice.
8093 if (aggregate
->match_med
)
8094 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8096 if (aggregate
->count
> 0)
8099 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8100 aggregate
->incomplete_origin_count
--;
8101 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8102 aggregate
->egp_origin_count
--;
8104 if (aggregate
->as_set
) {
8105 /* Remove as-path from aggregate.
8107 bgp_remove_aspath_from_aggregate(aggregate
,
8110 if (bgp_attr_get_community(pi
->attr
))
8111 /* Remove community from aggregate.
8113 bgp_remove_community_from_aggregate(
8114 aggregate
, bgp_attr_get_community(pi
->attr
));
8116 if (bgp_attr_get_ecommunity(pi
->attr
))
8117 /* Remove ecommunity from aggregate.
8119 bgp_remove_ecommunity_from_aggregate(
8120 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8122 if (bgp_attr_get_lcommunity(pi
->attr
))
8123 /* Remove lcommunity from aggregate.
8125 bgp_remove_lcommunity_from_aggregate(
8126 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8129 /* If this node was suppressed, process the change. */
8131 bgp_process(bgp
, pi
->net
, afi
, safi
);
8133 origin
= BGP_ORIGIN_IGP
;
8134 if (aggregate
->incomplete_origin_count
> 0)
8135 origin
= BGP_ORIGIN_INCOMPLETE
;
8136 else if (aggregate
->egp_origin_count
> 0)
8137 origin
= BGP_ORIGIN_EGP
;
8139 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8140 origin
= aggregate
->origin
;
8142 if (aggregate
->as_set
) {
8143 /* Retrieve aggregate route's as-path.
8145 if (aggregate
->aspath
)
8146 aspath
= aspath_dup(aggregate
->aspath
);
8148 /* Retrieve aggregate route's community.
8150 if (aggregate
->community
)
8151 community
= community_dup(aggregate
->community
);
8153 /* Retrieve aggregate route's ecommunity.
8155 if (aggregate
->ecommunity
)
8156 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8158 /* Retrieve aggregate route's lcommunity.
8160 if (aggregate
->lcommunity
)
8161 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8164 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8165 aspath
, community
, ecommunity
,
8166 lcommunity
, atomic_aggregate
, aggregate
);
8169 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8170 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8172 struct bgp_dest
*child
;
8173 struct bgp_dest
*dest
;
8174 struct bgp_aggregate
*aggregate
;
8175 struct bgp_table
*table
;
8177 table
= bgp
->aggregate
[afi
][safi
];
8179 /* No aggregates configured. */
8180 if (bgp_table_top_nolock(table
) == NULL
)
8183 if (p
->prefixlen
== 0)
8186 if (BGP_PATH_HOLDDOWN(pi
))
8189 /* If suppress fib is enabled and route not installed
8190 * in FIB, do not update the aggregate route
8192 if (!bgp_check_advertise(bgp
, pi
->net
))
8195 child
= bgp_node_get(table
, p
);
8197 /* Aggregate address configuration check. */
8198 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8199 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8201 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8202 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8203 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8207 bgp_dest_unlock_node(child
);
8210 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8211 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8213 struct bgp_dest
*child
;
8214 struct bgp_dest
*dest
;
8215 struct bgp_aggregate
*aggregate
;
8216 struct bgp_table
*table
;
8218 table
= bgp
->aggregate
[afi
][safi
];
8220 /* No aggregates configured. */
8221 if (bgp_table_top_nolock(table
) == NULL
)
8224 if (p
->prefixlen
== 0)
8227 child
= bgp_node_get(table
, p
);
8229 /* Aggregate address configuration check. */
8230 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8231 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8233 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8234 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8235 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8239 bgp_dest_unlock_node(child
);
8242 /* Aggregate route attribute. */
8243 #define AGGREGATE_SUMMARY_ONLY 1
8244 #define AGGREGATE_AS_SET 1
8245 #define AGGREGATE_AS_UNSET 0
8247 static const char *bgp_origin2str(uint8_t origin
)
8250 case BGP_ORIGIN_IGP
:
8252 case BGP_ORIGIN_EGP
:
8254 case BGP_ORIGIN_INCOMPLETE
:
8255 return "incomplete";
8260 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8263 case RPKI_NOT_BEING_USED
:
8273 assert(!"We should never get here this is a dev escape");
8277 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8278 afi_t afi
, safi_t safi
)
8280 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8283 struct bgp_dest
*dest
;
8284 struct bgp_aggregate
*aggregate
;
8286 /* Convert string to prefix structure. */
8287 ret
= str2prefix(prefix_str
, &p
);
8289 vty_out(vty
, "Malformed prefix\n");
8290 return CMD_WARNING_CONFIG_FAILED
;
8294 /* Old configuration check. */
8295 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8298 "%% There is no aggregate-address configuration.\n");
8299 return CMD_WARNING_CONFIG_FAILED
;
8302 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8303 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8304 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8305 NULL
, NULL
, 0, aggregate
);
8307 /* Unlock aggregate address configuration. */
8308 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8310 if (aggregate
->community
)
8311 community_free(&aggregate
->community
);
8313 if (aggregate
->community_hash
) {
8314 /* Delete all communities in the hash.
8316 hash_clean(aggregate
->community_hash
,
8317 bgp_aggr_community_remove
);
8318 /* Free up the community_hash.
8320 hash_free(aggregate
->community_hash
);
8323 if (aggregate
->ecommunity
)
8324 ecommunity_free(&aggregate
->ecommunity
);
8326 if (aggregate
->ecommunity_hash
) {
8327 /* Delete all ecommunities in the hash.
8329 hash_clean(aggregate
->ecommunity_hash
,
8330 bgp_aggr_ecommunity_remove
);
8331 /* Free up the ecommunity_hash.
8333 hash_free(aggregate
->ecommunity_hash
);
8336 if (aggregate
->lcommunity
)
8337 lcommunity_free(&aggregate
->lcommunity
);
8339 if (aggregate
->lcommunity_hash
) {
8340 /* Delete all lcommunities in the hash.
8342 hash_clean(aggregate
->lcommunity_hash
,
8343 bgp_aggr_lcommunity_remove
);
8344 /* Free up the lcommunity_hash.
8346 hash_free(aggregate
->lcommunity_hash
);
8349 if (aggregate
->aspath
)
8350 aspath_free(aggregate
->aspath
);
8352 if (aggregate
->aspath_hash
) {
8353 /* Delete all as-paths in the hash.
8355 hash_clean(aggregate
->aspath_hash
,
8356 bgp_aggr_aspath_remove
);
8357 /* Free up the aspath_hash.
8359 hash_free(aggregate
->aspath_hash
);
8362 bgp_aggregate_free(aggregate
);
8363 bgp_dest_unlock_node(dest
);
8364 bgp_dest_unlock_node(dest
);
8369 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8370 safi_t safi
, const char *rmap
,
8371 uint8_t summary_only
, uint8_t as_set
,
8372 uint8_t origin
, bool match_med
,
8373 const char *suppress_map
)
8375 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8378 struct bgp_dest
*dest
;
8379 struct bgp_aggregate
*aggregate
;
8380 uint8_t as_set_new
= as_set
;
8382 if (suppress_map
&& summary_only
) {
8384 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8385 return CMD_WARNING_CONFIG_FAILED
;
8388 /* Convert string to prefix structure. */
8389 ret
= str2prefix(prefix_str
, &p
);
8391 vty_out(vty
, "Malformed prefix\n");
8392 return CMD_WARNING_CONFIG_FAILED
;
8396 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8397 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8398 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8400 return CMD_WARNING_CONFIG_FAILED
;
8403 /* Old configuration check. */
8404 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8405 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8408 vty_out(vty
, "There is already same aggregate network.\n");
8409 /* try to remove the old entry */
8410 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8412 vty_out(vty
, "Error deleting aggregate.\n");
8413 bgp_dest_unlock_node(dest
);
8414 return CMD_WARNING_CONFIG_FAILED
;
8418 /* Make aggregate address structure. */
8419 aggregate
= bgp_aggregate_new();
8420 aggregate
->summary_only
= summary_only
;
8421 aggregate
->match_med
= match_med
;
8423 /* Network operators MUST NOT locally generate any new
8424 * announcements containing AS_SET or AS_CONFED_SET. If they have
8425 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8426 * SHOULD withdraw those routes and re-announce routes for the
8427 * aggregate or component prefixes (i.e., the more-specific routes
8428 * subsumed by the previously aggregated route) without AS_SET
8429 * or AS_CONFED_SET in the updates.
8431 if (bgp
->reject_as_sets
) {
8432 if (as_set
== AGGREGATE_AS_SET
) {
8433 as_set_new
= AGGREGATE_AS_UNSET
;
8435 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8438 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8442 aggregate
->as_set
= as_set_new
;
8443 aggregate
->safi
= safi
;
8444 /* Override ORIGIN attribute if defined.
8445 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8446 * to IGP which is not what rfc4271 says.
8447 * This enables the same behavior, optionally.
8449 aggregate
->origin
= origin
;
8452 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8453 route_map_counter_decrement(aggregate
->rmap
.map
);
8454 aggregate
->rmap
.name
=
8455 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8456 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8457 route_map_counter_increment(aggregate
->rmap
.map
);
8461 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8462 route_map_counter_decrement(aggregate
->suppress_map
);
8464 aggregate
->suppress_map_name
=
8465 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8466 aggregate
->suppress_map
=
8467 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8468 route_map_counter_increment(aggregate
->suppress_map
);
8471 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8473 /* Aggregate address insert into BGP routing table. */
8474 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8479 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8480 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8482 "|summary-only$summary_only"
8483 "|route-map RMAP_NAME$rmap_name"
8484 "|origin <egp|igp|incomplete>$origin_s"
8485 "|matching-MED-only$match_med"
8486 "|suppress-map RMAP_NAME$suppress_map"
8489 "Configure BGP aggregate entries\n"
8490 "Aggregate prefix\n"
8491 "Aggregate address\n"
8493 "Generate AS set path information\n"
8494 "Filter more specific routes from updates\n"
8495 "Apply route map to aggregate network\n"
8500 "Unknown heritage\n"
8501 "Only aggregate routes with matching MED\n"
8502 "Suppress the selected more specific routes\n"
8503 "Route map with the route selectors\n")
8505 const char *prefix_s
= NULL
;
8506 safi_t safi
= bgp_node_safi(vty
);
8507 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8508 int as_set
= AGGREGATE_AS_UNSET
;
8509 char prefix_buf
[PREFIX2STR_BUFFER
];
8512 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8515 vty_out(vty
, "%% Inconsistent address and mask\n");
8516 return CMD_WARNING_CONFIG_FAILED
;
8518 prefix_s
= prefix_buf
;
8520 prefix_s
= prefix_str
;
8523 if (strcmp(origin_s
, "egp") == 0)
8524 origin
= BGP_ORIGIN_EGP
;
8525 else if (strcmp(origin_s
, "igp") == 0)
8526 origin
= BGP_ORIGIN_IGP
;
8527 else if (strcmp(origin_s
, "incomplete") == 0)
8528 origin
= BGP_ORIGIN_INCOMPLETE
;
8532 as_set
= AGGREGATE_AS_SET
;
8534 /* Handle configuration removal, otherwise installation. */
8536 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8538 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8539 summary_only
!= NULL
, as_set
, origin
,
8540 match_med
!= NULL
, suppress_map
);
8543 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8544 "[no] aggregate-address X:X::X:X/M$prefix [{"
8546 "|summary-only$summary_only"
8547 "|route-map RMAP_NAME$rmap_name"
8548 "|origin <egp|igp|incomplete>$origin_s"
8549 "|matching-MED-only$match_med"
8550 "|suppress-map RMAP_NAME$suppress_map"
8553 "Configure BGP aggregate entries\n"
8554 "Aggregate prefix\n"
8555 "Generate AS set path information\n"
8556 "Filter more specific routes from updates\n"
8557 "Apply route map to aggregate network\n"
8562 "Unknown heritage\n"
8563 "Only aggregate routes with matching MED\n"
8564 "Suppress the selected more specific routes\n"
8565 "Route map with the route selectors\n")
8567 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8568 int as_set
= AGGREGATE_AS_UNSET
;
8571 if (strcmp(origin_s
, "egp") == 0)
8572 origin
= BGP_ORIGIN_EGP
;
8573 else if (strcmp(origin_s
, "igp") == 0)
8574 origin
= BGP_ORIGIN_IGP
;
8575 else if (strcmp(origin_s
, "incomplete") == 0)
8576 origin
= BGP_ORIGIN_INCOMPLETE
;
8580 as_set
= AGGREGATE_AS_SET
;
8582 /* Handle configuration removal, otherwise installation. */
8584 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8587 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8588 rmap_name
, summary_only
!= NULL
, as_set
,
8589 origin
, match_med
!= NULL
, suppress_map
);
8592 /* Redistribute route treatment. */
8593 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8594 const union g_addr
*nexthop
, ifindex_t ifindex
,
8595 enum nexthop_types_t nhtype
, uint8_t distance
,
8596 enum blackhole_type bhtype
, uint32_t metric
,
8597 uint8_t type
, unsigned short instance
,
8600 struct bgp_path_info
*new;
8601 struct bgp_path_info
*bpi
;
8602 struct bgp_path_info rmap_path
;
8603 struct bgp_dest
*bn
;
8605 struct attr
*new_attr
;
8607 route_map_result_t ret
;
8608 struct bgp_redist
*red
;
8610 /* Make default attribute. */
8611 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8613 * This must not be NULL to satisfy Coverity SA
8615 assert(attr
.aspath
);
8618 case NEXTHOP_TYPE_IFINDEX
:
8619 switch (p
->family
) {
8621 attr
.nexthop
.s_addr
= INADDR_ANY
;
8622 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8625 memset(&attr
.mp_nexthop_global
, 0,
8626 sizeof(attr
.mp_nexthop_global
));
8627 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8631 case NEXTHOP_TYPE_IPV4
:
8632 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8633 attr
.nexthop
= nexthop
->ipv4
;
8634 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8636 case NEXTHOP_TYPE_IPV6
:
8637 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8638 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8639 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8641 case NEXTHOP_TYPE_BLACKHOLE
:
8642 switch (p
->family
) {
8644 attr
.nexthop
.s_addr
= INADDR_ANY
;
8645 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8648 memset(&attr
.mp_nexthop_global
, 0,
8649 sizeof(attr
.mp_nexthop_global
));
8650 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8653 attr
.bh_type
= bhtype
;
8656 attr
.nh_type
= nhtype
;
8657 attr
.nh_ifindex
= ifindex
;
8660 attr
.distance
= distance
;
8661 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8665 bgp_attr_set_aigp_metric(&attr
, metric
);
8667 afi
= family2afi(p
->family
);
8669 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8671 struct attr attr_new
;
8673 /* Copy attribute for modification. */
8676 if (red
->redist_metric_flag
) {
8677 attr_new
.med
= red
->redist_metric
;
8678 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8681 /* Apply route-map. */
8682 if (red
->rmap
.name
) {
8683 memset(&rmap_path
, 0, sizeof(rmap_path
));
8684 rmap_path
.peer
= bgp
->peer_self
;
8685 rmap_path
.attr
= &attr_new
;
8687 SET_FLAG(bgp
->peer_self
->rmap_type
,
8688 PEER_RMAP_TYPE_REDISTRIBUTE
);
8690 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8692 bgp
->peer_self
->rmap_type
= 0;
8694 if (ret
== RMAP_DENYMATCH
) {
8695 /* Free uninterned attribute. */
8696 bgp_attr_flush(&attr_new
);
8698 /* Unintern original. */
8699 aspath_unintern(&attr
.aspath
);
8700 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8705 if (bgp_in_graceful_shutdown(bgp
))
8706 bgp_attr_add_gshut_community(&attr_new
);
8708 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8709 SAFI_UNICAST
, p
, NULL
);
8711 new_attr
= bgp_attr_intern(&attr_new
);
8713 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8714 if (bpi
->peer
== bgp
->peer_self
8715 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8719 /* Ensure the (source route) type is updated. */
8721 if (attrhash_cmp(bpi
->attr
, new_attr
)
8722 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8723 bgp_attr_unintern(&new_attr
);
8724 aspath_unintern(&attr
.aspath
);
8725 bgp_dest_unlock_node(bn
);
8728 /* The attribute is changed. */
8729 bgp_path_info_set_flag(bn
, bpi
,
8730 BGP_PATH_ATTR_CHANGED
);
8732 /* Rewrite BGP route information. */
8733 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8734 bgp_path_info_restore(bn
, bpi
);
8736 bgp_aggregate_decrement(
8737 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8738 bgp_attr_unintern(&bpi
->attr
);
8739 bpi
->attr
= new_attr
;
8740 bpi
->uptime
= monotime(NULL
);
8742 /* Process change. */
8743 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8745 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8746 bgp_dest_unlock_node(bn
);
8747 aspath_unintern(&attr
.aspath
);
8749 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8751 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8753 vpn_leak_from_vrf_update(
8754 bgp_get_default(), bgp
, bpi
);
8760 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8761 bgp
->peer_self
, new_attr
, bn
);
8762 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8764 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8765 bgp_path_info_add(bn
, new);
8766 bgp_dest_unlock_node(bn
);
8767 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8768 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8770 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8771 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8773 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8777 /* Unintern original. */
8778 aspath_unintern(&attr
.aspath
);
8781 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8782 unsigned short instance
)
8785 struct bgp_dest
*dest
;
8786 struct bgp_path_info
*pi
;
8787 struct bgp_redist
*red
;
8789 afi
= family2afi(p
->family
);
8791 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8793 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8794 SAFI_UNICAST
, p
, NULL
);
8796 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8797 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8801 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8802 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8804 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8807 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8808 bgp_path_info_delete(dest
, pi
);
8809 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8811 bgp_dest_unlock_node(dest
);
8815 /* Withdraw specified route type's route. */
8816 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8817 unsigned short instance
)
8819 struct bgp_dest
*dest
;
8820 struct bgp_path_info
*pi
;
8821 struct bgp_table
*table
;
8823 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8825 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8826 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8827 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8828 && pi
->instance
== instance
)
8832 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8833 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8835 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8838 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8839 pi
, afi
, SAFI_UNICAST
);
8840 bgp_path_info_delete(dest
, pi
);
8841 if (!CHECK_FLAG(bgp
->flags
,
8842 BGP_FLAG_DELETE_IN_PROGRESS
))
8843 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8845 bgp_path_info_reap(dest
, pi
);
8850 /* Static function to display route. */
8851 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8852 struct vty
*vty
, json_object
*json
, bool wide
)
8855 char buf
[INET6_ADDRSTRLEN
];
8857 if (p
->family
== AF_INET
) {
8859 len
= vty_out(vty
, "%pFX", p
);
8861 json_object_string_add(json
, "prefix",
8862 inet_ntop(p
->family
,
8865 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8866 json_object_string_addf(json
, "network", "%pFX", p
);
8867 json_object_int_add(json
, "version", dest
->version
);
8869 } else if (p
->family
== AF_ETHERNET
) {
8870 len
= vty_out(vty
, "%pFX", p
);
8871 } else if (p
->family
== AF_EVPN
) {
8873 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8875 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8876 } else if (p
->family
== AF_FLOWSPEC
) {
8877 route_vty_out_flowspec(vty
, p
, NULL
,
8879 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8880 NLRI_STRING_FORMAT_MIN
, json
);
8883 len
= vty_out(vty
, "%pFX", p
);
8885 json_object_string_add(json
, "prefix",
8886 inet_ntop(p
->family
,
8889 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8890 json_object_string_addf(json
, "network", "%pFX", p
);
8891 json_object_int_add(json
, "version", dest
->version
);
8896 len
= wide
? (45 - len
) : (17 - len
);
8898 vty_out(vty
, "\n%*s", 20, " ");
8900 vty_out(vty
, "%*s", len
, " ");
8904 enum bgp_display_type
{
8908 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8911 case bgp_path_selection_none
:
8912 return "Nothing to Select";
8913 case bgp_path_selection_first
:
8914 return "First path received";
8915 case bgp_path_selection_evpn_sticky_mac
:
8916 return "EVPN Sticky Mac";
8917 case bgp_path_selection_evpn_seq
:
8918 return "EVPN sequence number";
8919 case bgp_path_selection_evpn_lower_ip
:
8920 return "EVPN lower IP";
8921 case bgp_path_selection_evpn_local_path
:
8922 return "EVPN local ES path";
8923 case bgp_path_selection_evpn_non_proxy
:
8924 return "EVPN non proxy";
8925 case bgp_path_selection_weight
:
8927 case bgp_path_selection_local_pref
:
8928 return "Local Pref";
8929 case bgp_path_selection_accept_own
:
8930 return "Accept Own";
8931 case bgp_path_selection_local_route
:
8932 return "Local Route";
8933 case bgp_path_selection_aigp
:
8935 case bgp_path_selection_confed_as_path
:
8936 return "Confederation based AS Path";
8937 case bgp_path_selection_as_path
:
8939 case bgp_path_selection_origin
:
8941 case bgp_path_selection_med
:
8943 case bgp_path_selection_peer
:
8945 case bgp_path_selection_confed
:
8946 return "Confed Peer Type";
8947 case bgp_path_selection_igp_metric
:
8948 return "IGP Metric";
8949 case bgp_path_selection_older
:
8950 return "Older Path";
8951 case bgp_path_selection_router_id
:
8953 case bgp_path_selection_cluster_length
:
8954 return "Cluster length";
8955 case bgp_path_selection_stale
:
8956 return "Path Staleness";
8957 case bgp_path_selection_local_configured
:
8958 return "Locally configured route";
8959 case bgp_path_selection_neighbor_ip
:
8960 return "Neighbor IP";
8961 case bgp_path_selection_default
:
8962 return "Nothing left to compare";
8964 return "Invalid (internal error)";
8967 /* Print the short form route status for a bgp_path_info */
8968 static void route_vty_short_status_out(struct vty
*vty
,
8969 struct bgp_path_info
*path
,
8970 const struct prefix
*p
,
8971 json_object
*json_path
)
8973 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8977 /* Route status display. */
8978 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8979 json_object_boolean_true_add(json_path
, "removed");
8981 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8982 json_object_boolean_true_add(json_path
, "stale");
8984 if (path
->extra
&& bgp_path_suppressed(path
))
8985 json_object_boolean_true_add(json_path
, "suppressed");
8987 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8988 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8989 json_object_boolean_true_add(json_path
, "valid");
8992 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8993 json_object_boolean_true_add(json_path
, "history");
8995 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8996 json_object_boolean_true_add(json_path
, "damped");
8998 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8999 json_object_boolean_true_add(json_path
, "bestpath");
9000 json_object_string_add(json_path
, "selectionReason",
9001 bgp_path_selection_reason2str(
9002 path
->net
->reason
));
9005 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9006 json_object_boolean_true_add(json_path
, "multipath");
9008 /* Internal route. */
9009 if ((path
->peer
->as
)
9010 && (path
->peer
->as
== path
->peer
->local_as
))
9011 json_object_string_add(json_path
, "pathFrom",
9014 json_object_string_add(json_path
, "pathFrom",
9020 /* RPKI validation state */
9022 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9024 if (rpki_state
== RPKI_VALID
)
9026 else if (rpki_state
== RPKI_INVALID
)
9028 else if (rpki_state
== RPKI_NOTFOUND
)
9033 /* Route status display. */
9034 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9036 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9038 else if (bgp_path_suppressed(path
))
9040 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9041 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9047 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9049 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9051 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9053 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9058 /* Internal route. */
9059 if (path
->peer
&& (path
->peer
->as
)
9060 && (path
->peer
->as
== path
->peer
->local_as
))
9066 static char *bgp_nexthop_hostname(struct peer
*peer
,
9067 struct bgp_nexthop_cache
*bnc
)
9070 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9071 return peer
->hostname
;
9075 /* called from terminal list command */
9076 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9077 struct bgp_path_info
*path
, int display
, safi_t safi
,
9078 json_object
*json_paths
, bool wide
)
9081 struct attr
*attr
= path
->attr
;
9082 json_object
*json_path
= NULL
;
9083 json_object
*json_nexthops
= NULL
;
9084 json_object
*json_nexthop_global
= NULL
;
9085 json_object
*json_nexthop_ll
= NULL
;
9086 json_object
*json_ext_community
= NULL
;
9087 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9089 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9090 bool nexthop_othervrf
= false;
9091 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9092 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9093 char *nexthop_hostname
=
9094 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9095 char esi_buf
[ESI_STR_LEN
];
9098 json_path
= json_object_new_object();
9100 /* short status lead text */
9101 route_vty_short_status_out(vty
, path
, p
, json_path
);
9104 /* print prefix and mask */
9106 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9108 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9110 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9114 * If vrf id of nexthop is different from that of prefix,
9115 * set up printable string to append
9117 if (path
->extra
&& path
->extra
->bgp_orig
) {
9118 const char *self
= "";
9123 nexthop_othervrf
= true;
9124 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9126 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9127 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9128 "@%s%s", VRFID_NONE_STR
, self
);
9130 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9131 path
->extra
->bgp_orig
->vrf_id
, self
);
9133 if (path
->extra
->bgp_orig
->inst_type
9134 != BGP_INSTANCE_TYPE_DEFAULT
)
9136 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9138 const char *self
= "";
9143 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9147 * For ENCAP and EVPN routes, nexthop address family is not
9148 * neccessarily the same as the prefix address family.
9149 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9150 * EVPN routes are also exchanged with a MP nexthop. Currently,
9152 * is only IPv4, the value will be present in either
9154 * attr->mp_nexthop_global_in
9156 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9158 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9162 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9163 &attr
->mp_nexthop_global_in
);
9166 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9167 &attr
->mp_nexthop_global
);
9170 snprintf(nexthop
, sizeof(nexthop
), "?");
9175 json_nexthop_global
= json_object_new_object();
9177 json_object_string_add(json_nexthop_global
, "ip",
9180 if (path
->peer
->hostname
)
9181 json_object_string_add(json_nexthop_global
,
9183 path
->peer
->hostname
);
9185 json_object_string_add(json_nexthop_global
, "afi",
9186 (af
== AF_INET
) ? "ipv4"
9188 json_object_boolean_true_add(json_nexthop_global
,
9191 if (nexthop_hostname
)
9192 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9193 nexthop_hostname
, vrf_id_str
);
9195 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9197 len
= wide
? (41 - len
) : (16 - len
);
9199 vty_out(vty
, "\n%*s", 36, " ");
9201 vty_out(vty
, "%*s", len
, " ");
9203 } else if (safi
== SAFI_EVPN
) {
9205 json_nexthop_global
= json_object_new_object();
9207 json_object_string_addf(json_nexthop_global
, "ip",
9209 &attr
->mp_nexthop_global_in
);
9211 if (path
->peer
->hostname
)
9212 json_object_string_add(json_nexthop_global
,
9214 path
->peer
->hostname
);
9216 json_object_string_add(json_nexthop_global
, "afi",
9218 json_object_boolean_true_add(json_nexthop_global
,
9221 if (nexthop_hostname
)
9222 len
= vty_out(vty
, "%pI4(%s)%s",
9223 &attr
->mp_nexthop_global_in
,
9224 nexthop_hostname
, vrf_id_str
);
9226 len
= vty_out(vty
, "%pI4%s",
9227 &attr
->mp_nexthop_global_in
,
9230 len
= wide
? (41 - len
) : (16 - len
);
9232 vty_out(vty
, "\n%*s", 36, " ");
9234 vty_out(vty
, "%*s", len
, " ");
9236 } else if (safi
== SAFI_FLOWSPEC
) {
9237 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9239 json_nexthop_global
= json_object_new_object();
9241 json_object_string_add(json_nexthop_global
,
9243 json_object_string_addf(json_nexthop_global
,
9247 if (path
->peer
->hostname
)
9248 json_object_string_add(
9249 json_nexthop_global
, "hostname",
9250 path
->peer
->hostname
);
9252 json_object_boolean_true_add(
9253 json_nexthop_global
,
9256 if (nexthop_hostname
)
9257 len
= vty_out(vty
, "%pI4(%s)%s",
9262 len
= vty_out(vty
, "%pI4%s",
9266 len
= wide
? (41 - len
) : (16 - len
);
9268 vty_out(vty
, "\n%*s", 36, " ");
9270 vty_out(vty
, "%*s", len
, " ");
9273 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9275 json_nexthop_global
= json_object_new_object();
9277 json_object_string_addf(json_nexthop_global
, "ip",
9278 "%pI4", &attr
->nexthop
);
9280 if (path
->peer
->hostname
)
9281 json_object_string_add(json_nexthop_global
,
9283 path
->peer
->hostname
);
9285 json_object_string_add(json_nexthop_global
, "afi",
9287 json_object_boolean_true_add(json_nexthop_global
,
9290 if (nexthop_hostname
)
9291 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9292 nexthop_hostname
, vrf_id_str
);
9294 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9297 len
= wide
? (41 - len
) : (16 - len
);
9299 vty_out(vty
, "\n%*s", 36, " ");
9301 vty_out(vty
, "%*s", len
, " ");
9306 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9308 json_nexthop_global
= json_object_new_object();
9309 json_object_string_addf(json_nexthop_global
, "ip",
9311 &attr
->mp_nexthop_global
);
9313 if (path
->peer
->hostname
)
9314 json_object_string_add(json_nexthop_global
,
9316 path
->peer
->hostname
);
9318 json_object_string_add(json_nexthop_global
, "afi",
9320 json_object_string_add(json_nexthop_global
, "scope",
9323 /* We display both LL & GL if both have been
9325 if ((attr
->mp_nexthop_len
9326 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9327 || (path
->peer
->conf_if
)) {
9328 json_nexthop_ll
= json_object_new_object();
9329 json_object_string_addf(
9330 json_nexthop_ll
, "ip", "%pI6",
9331 &attr
->mp_nexthop_local
);
9333 if (path
->peer
->hostname
)
9334 json_object_string_add(
9335 json_nexthop_ll
, "hostname",
9336 path
->peer
->hostname
);
9338 json_object_string_add(json_nexthop_ll
, "afi",
9340 json_object_string_add(json_nexthop_ll
, "scope",
9343 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9344 &attr
->mp_nexthop_local
)
9346 && !attr
->mp_nexthop_prefer_global
)
9347 json_object_boolean_true_add(
9348 json_nexthop_ll
, "used");
9350 json_object_boolean_true_add(
9351 json_nexthop_global
, "used");
9353 json_object_boolean_true_add(
9354 json_nexthop_global
, "used");
9356 /* Display LL if LL/Global both in table unless
9357 * prefer-global is set */
9358 if (((attr
->mp_nexthop_len
9359 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9360 && !attr
->mp_nexthop_prefer_global
)
9361 || (path
->peer
->conf_if
)) {
9362 if (path
->peer
->conf_if
) {
9363 len
= vty_out(vty
, "%s",
9364 path
->peer
->conf_if
);
9365 /* len of IPv6 addr + max len of def
9367 len
= wide
? (41 - len
) : (16 - len
);
9370 vty_out(vty
, "\n%*s", 36, " ");
9372 vty_out(vty
, "%*s", len
, " ");
9374 if (nexthop_hostname
)
9377 &attr
->mp_nexthop_local
,
9383 &attr
->mp_nexthop_local
,
9386 len
= wide
? (41 - len
) : (16 - len
);
9389 vty_out(vty
, "\n%*s", 36, " ");
9391 vty_out(vty
, "%*s", len
, " ");
9394 if (nexthop_hostname
)
9395 len
= vty_out(vty
, "%pI6(%s)%s",
9396 &attr
->mp_nexthop_global
,
9400 len
= vty_out(vty
, "%pI6%s",
9401 &attr
->mp_nexthop_global
,
9404 len
= wide
? (41 - len
) : (16 - len
);
9407 vty_out(vty
, "\n%*s", 36, " ");
9409 vty_out(vty
, "%*s", len
, " ");
9415 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9417 json_object_int_add(json_path
, "metric", attr
->med
);
9419 vty_out(vty
, "%7u", attr
->med
);
9421 vty_out(vty
, "%10u", attr
->med
);
9422 else if (!json_paths
) {
9424 vty_out(vty
, "%*s", 7, " ");
9426 vty_out(vty
, "%*s", 10, " ");
9430 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9432 json_object_int_add(json_path
, "locPrf",
9435 vty_out(vty
, "%7u", attr
->local_pref
);
9436 else if (!json_paths
)
9440 json_object_int_add(json_path
, "weight", attr
->weight
);
9442 vty_out(vty
, "%7u ", attr
->weight
);
9445 json_object_string_addf(json_path
, "peerId", "%pSU",
9451 json_object_string_add(json_path
, "path",
9454 aspath_print_vty(vty
, attr
->aspath
);
9459 json_object_string_add(json_path
, "origin",
9460 bgp_origin_long_str
[attr
->origin
]);
9462 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9465 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9466 json_object_string_add(json_path
, "esi",
9467 esi_to_str(&attr
->esi
,
9468 esi_buf
, sizeof(esi_buf
)));
9470 if (safi
== SAFI_EVPN
&&
9471 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9472 json_ext_community
= json_object_new_object();
9473 json_object_string_add(
9474 json_ext_community
, "string",
9475 bgp_attr_get_ecommunity(attr
)->str
);
9476 json_object_object_add(json_path
,
9477 "extendedCommunity",
9478 json_ext_community
);
9482 json_object_boolean_true_add(json_path
,
9483 "announceNexthopSelf");
9484 if (nexthop_othervrf
) {
9485 json_object_string_add(json_path
, "nhVrfName",
9488 json_object_int_add(json_path
, "nhVrfId",
9489 ((nexthop_vrfid
== VRF_UNKNOWN
)
9491 : (int)nexthop_vrfid
));
9496 if (json_nexthop_global
|| json_nexthop_ll
) {
9497 json_nexthops
= json_object_new_array();
9499 if (json_nexthop_global
)
9500 json_object_array_add(json_nexthops
,
9501 json_nexthop_global
);
9503 if (json_nexthop_ll
)
9504 json_object_array_add(json_nexthops
,
9507 json_object_object_add(json_path
, "nexthops",
9511 json_object_array_add(json_paths
, json_path
);
9515 if (safi
== SAFI_EVPN
) {
9516 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9517 /* XXX - add these params to the json out */
9518 vty_out(vty
, "%*s", 20, " ");
9519 vty_out(vty
, "ESI:%s",
9520 esi_to_str(&attr
->esi
, esi_buf
,
9526 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9527 vty_out(vty
, "%*s", 20, " ");
9528 vty_out(vty
, "%s\n",
9529 bgp_attr_get_ecommunity(attr
)->str
);
9533 #ifdef ENABLE_BGP_VNC
9534 /* prints an additional line, indented, with VNC info, if
9536 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9537 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9542 /* called from terminal list command */
9543 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9544 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9545 bool use_json
, json_object
*json_ar
, bool wide
)
9547 json_object
*json_status
= NULL
;
9548 json_object
*json_net
= NULL
;
9552 /* Route status display. */
9554 json_status
= json_object_new_object();
9555 json_net
= json_object_new_object();
9562 /* print prefix and mask */
9564 if (safi
== SAFI_EVPN
)
9565 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9566 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9567 json_object_string_add(
9568 json_net
, "addrPrefix",
9569 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9571 json_object_int_add(json_net
, "prefixLen",
9573 json_object_string_addf(json_net
, "network", "%pFX", p
);
9576 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9578 /* Print attribute */
9581 if (p
->family
== AF_INET
&&
9582 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9583 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9584 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9585 json_object_string_addf(
9586 json_net
, "nextHop", "%pI4",
9587 &attr
->mp_nexthop_global_in
);
9589 json_object_string_addf(
9590 json_net
, "nextHop", "%pI4",
9592 } else if (p
->family
== AF_INET6
||
9593 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9594 json_object_string_addf(
9595 json_net
, "nextHopGlobal", "%pI6",
9596 &attr
->mp_nexthop_global
);
9597 } else if (p
->family
== AF_EVPN
&&
9598 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9599 json_object_string_addf(
9600 json_net
, "nextHop", "%pI4",
9601 &attr
->mp_nexthop_global_in
);
9605 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9606 json_object_int_add(json_net
, "metric",
9609 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9610 json_object_int_add(json_net
, "locPrf",
9613 json_object_int_add(json_net
, "weight", attr
->weight
);
9617 json_object_string_add(json_net
, "path",
9621 #if CONFDATE > 20231208
9622 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9624 json_object_string_add(json_net
, "bgpOriginCode",
9625 bgp_origin_str
[attr
->origin
]);
9626 json_object_string_add(
9628 bgp_origin_long_str
[attr
->origin
]);
9630 if (p
->family
== AF_INET
&&
9631 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9632 safi
== SAFI_EVPN
||
9633 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9634 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9635 || safi
== SAFI_EVPN
)
9636 vty_out(vty
, "%-16pI4",
9637 &attr
->mp_nexthop_global_in
);
9639 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9641 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9642 } else if (p
->family
== AF_INET6
||
9643 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9644 len
= vty_out(vty
, "%pI6",
9645 &attr
->mp_nexthop_global
);
9646 len
= wide
? (41 - len
) : (16 - len
);
9648 vty_out(vty
, "\n%*s", 36, " ");
9650 vty_out(vty
, "%*s", len
, " ");
9653 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9655 vty_out(vty
, "%7u", attr
->med
);
9657 vty_out(vty
, "%10u", attr
->med
);
9663 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9664 vty_out(vty
, "%7u", attr
->local_pref
);
9668 vty_out(vty
, "%7u ", attr
->weight
);
9672 aspath_print_vty(vty
, attr
->aspath
);
9675 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9679 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9681 #if CONFDATE > 20231208
9682 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9684 json_object_boolean_true_add(json_status
, "*");
9685 json_object_boolean_true_add(json_status
, ">");
9686 json_object_boolean_true_add(json_net
, "valid");
9687 json_object_boolean_true_add(json_net
, "best");
9689 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9690 json_object_boolean_true_add(json_status
, "=");
9691 json_object_boolean_true_add(json_net
, "multipath");
9693 json_object_object_add(json_net
, "appliedStatusSymbols",
9695 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9700 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9701 struct bgp_path_info
*path
, int display
, safi_t safi
,
9704 json_object
*json_out
= NULL
;
9706 mpls_label_t label
= MPLS_INVALID_LABEL
;
9712 json_out
= json_object_new_object();
9714 /* short status lead text */
9715 route_vty_short_status_out(vty
, path
, p
, json_out
);
9717 /* print prefix and mask */
9720 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9722 vty_out(vty
, "%*s", 17, " ");
9725 /* Print attribute */
9727 if (((p
->family
== AF_INET
) &&
9728 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9729 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9730 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9731 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9732 || safi
== SAFI_EVPN
) {
9734 json_object_string_addf(
9735 json_out
, "mpNexthopGlobalIn", "%pI4",
9736 &attr
->mp_nexthop_global_in
);
9738 vty_out(vty
, "%-16pI4",
9739 &attr
->mp_nexthop_global_in
);
9742 json_object_string_addf(json_out
, "nexthop",
9743 "%pI4", &attr
->nexthop
);
9745 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9747 } else if (((p
->family
== AF_INET6
) &&
9748 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9749 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9750 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9753 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9755 json_object_string_addf(
9756 json_out
, "mpNexthopGlobalIn", "%pI6",
9757 &attr
->mp_nexthop_global
);
9761 &attr
->mp_nexthop_global
,
9762 buf_a
, sizeof(buf_a
)));
9763 } else if (attr
->mp_nexthop_len
9764 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9765 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9766 &attr
->mp_nexthop_global
,
9767 &attr
->mp_nexthop_local
);
9769 json_object_string_add(json_out
,
9770 "mpNexthopGlobalLocal",
9773 vty_out(vty
, "%s", buf_a
);
9777 label
= decode_label(&path
->extra
->label
[0]);
9779 if (bgp_is_valid_label(&label
)) {
9781 json_object_int_add(json_out
, "notag", label
);
9782 json_object_array_add(json
, json_out
);
9784 vty_out(vty
, "notag/%d", label
);
9791 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9792 struct bgp_path_info
*path
, int display
,
9793 json_object
*json_paths
)
9796 json_object
*json_path
= NULL
;
9797 json_object
*json_nexthop
= NULL
;
9798 json_object
*json_overlay
= NULL
;
9804 json_path
= json_object_new_object();
9805 json_overlay
= json_object_new_object();
9806 json_nexthop
= json_object_new_object();
9809 /* short status lead text */
9810 route_vty_short_status_out(vty
, path
, p
, json_path
);
9812 /* print prefix and mask */
9814 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9816 vty_out(vty
, "%*s", 17, " ");
9818 /* Print attribute */
9820 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9825 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9827 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9828 &attr
->mp_nexthop_global_in
);
9830 json_object_string_add(json_nexthop
, "afi", "ipv4");
9832 json_object_object_add(json_path
, "nexthop",
9838 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9839 &attr
->mp_nexthop_local
);
9841 json_object_string_addf(json_nexthop
, "ipv6Global",
9843 &attr
->mp_nexthop_global
);
9845 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9847 &attr
->mp_nexthop_local
);
9849 json_object_string_add(json_nexthop
, "afi", "ipv6");
9851 json_object_object_add(json_path
, "nexthop",
9859 json_object_string_add(json_nexthop
, "error",
9860 "Unsupported address-family");
9864 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9867 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9869 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9871 if (bgp_attr_get_ecommunity(attr
)) {
9873 struct ecommunity_val
*routermac
= ecommunity_lookup(
9874 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9875 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9878 mac
= ecom_mac2str((char *)routermac
->val
);
9881 vty_out(vty
, "/%s", mac
);
9883 json_object_string_add(json_overlay
, "rmac",
9886 XFREE(MTYPE_TMP
, mac
);
9893 json_object_object_add(json_path
, "overlay", json_overlay
);
9895 json_object_array_add(json_paths
, json_path
);
9899 /* dampening route */
9900 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9901 struct bgp_path_info
*path
, int display
,
9902 afi_t afi
, safi_t safi
, bool use_json
,
9903 json_object
*json_paths
)
9905 struct attr
*attr
= path
->attr
;
9907 char timebuf
[BGP_UPTIME_LEN
];
9908 json_object
*json_path
= NULL
;
9911 json_path
= json_object_new_object();
9913 /* short status lead text */
9914 route_vty_short_status_out(vty
, path
, p
, json_path
);
9916 /* print prefix and mask */
9919 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9921 vty_out(vty
, "%*s", 17, " ");
9923 len
= vty_out(vty
, "%s", path
->peer
->host
);
9927 vty_out(vty
, "\n%*s", 34, " ");
9929 vty_out(vty
, "%*s", len
, " ");
9932 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9933 BGP_UPTIME_LEN
, afi
, safi
,
9937 aspath_print_vty(vty
, attr
->aspath
);
9939 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9943 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9944 safi
, use_json
, json_path
);
9947 json_object_string_add(json_path
, "asPath",
9950 json_object_string_add(json_path
, "origin",
9951 bgp_origin_str
[attr
->origin
]);
9952 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9954 json_object_array_add(json_paths
, json_path
);
9959 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9960 struct bgp_path_info
*path
, int display
,
9961 afi_t afi
, safi_t safi
, bool use_json
,
9962 json_object
*json_paths
)
9964 struct attr
*attr
= path
->attr
;
9965 struct bgp_damp_info
*bdi
;
9966 char timebuf
[BGP_UPTIME_LEN
];
9968 json_object
*json_path
= NULL
;
9974 json_path
= json_object_new_object();
9976 bdi
= path
->extra
->damp_info
;
9978 /* short status lead text */
9979 route_vty_short_status_out(vty
, path
, p
, json_path
);
9983 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9985 vty_out(vty
, "%*s", 17, " ");
9987 len
= vty_out(vty
, "%s", path
->peer
->host
);
9990 vty_out(vty
, "\n%*s", 33, " ");
9992 vty_out(vty
, "%*s", len
, " ");
9994 len
= vty_out(vty
, "%d", bdi
->flap
);
9999 vty_out(vty
, "%*s", len
, " ");
10001 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10002 BGP_UPTIME_LEN
, 0, NULL
));
10004 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10005 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10006 vty_out(vty
, "%s ",
10007 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10008 BGP_UPTIME_LEN
, afi
,
10009 safi
, use_json
, NULL
));
10011 vty_out(vty
, "%*s ", 8, " ");
10014 aspath_print_vty(vty
, attr
->aspath
);
10016 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10018 vty_out(vty
, "\n");
10020 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10021 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10023 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10026 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10027 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10028 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10029 BGP_UPTIME_LEN
, afi
, safi
,
10030 use_json
, json_path
);
10033 json_object_string_add(json_path
, "asPath",
10034 attr
->aspath
->str
);
10036 json_object_string_add(json_path
, "origin",
10037 bgp_origin_str
[attr
->origin
]);
10039 json_object_array_add(json_paths
, json_path
);
10043 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10044 int *first
, const char *header
,
10045 json_object
*json_adv_to
)
10047 json_object
*json_peer
= NULL
;
10050 /* 'advertised-to' is a dictionary of peers we have advertised
10052 * prefix too. The key is the peer's IP or swpX, the value is
10054 * hostname if we know it and "" if not.
10056 json_peer
= json_object_new_object();
10058 if (peer
->hostname
)
10059 json_object_string_add(json_peer
, "hostname",
10063 json_object_object_add(json_adv_to
, peer
->conf_if
,
10066 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10070 vty_out(vty
, "%s", header
);
10075 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10077 vty_out(vty
, " %s(%s)", peer
->hostname
,
10080 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10084 vty_out(vty
, " %s", peer
->conf_if
);
10086 vty_out(vty
, " %pSU", &peer
->su
);
10091 static void route_vty_out_tx_ids(struct vty
*vty
,
10092 struct bgp_addpath_info_data
*d
)
10096 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10097 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10098 d
->addpath_tx_id
[i
],
10099 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10103 static void route_vty_out_detail_es_info(struct vty
*vty
,
10104 struct bgp_path_info
*pi
,
10106 json_object
*json_path
)
10108 char esi_buf
[ESI_STR_LEN
];
10109 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10110 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10111 ATTR_ES_PEER_ROUTER
);
10112 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10113 ATTR_ES_PEER_ACTIVE
);
10114 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10115 ATTR_ES_PEER_PROXY
);
10116 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10118 json_object
*json_es_info
= NULL
;
10120 json_object_string_add(
10123 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10124 json_es_info
= json_object_new_object();
10126 json_object_boolean_true_add(
10127 json_es_info
, "localEs");
10129 json_object_boolean_true_add(
10130 json_es_info
, "peerActive");
10132 json_object_boolean_true_add(
10133 json_es_info
, "peerProxy");
10135 json_object_boolean_true_add(
10136 json_es_info
, "peerRouter");
10137 if (attr
->mm_sync_seqnum
)
10138 json_object_int_add(
10139 json_es_info
, "peerSeq",
10140 attr
->mm_sync_seqnum
);
10141 json_object_object_add(
10142 json_path
, "es_info",
10146 if (bgp_evpn_attr_is_sync(attr
))
10148 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10150 es_local
? "local-es":"",
10151 peer_proxy
? "proxy " : "",
10152 peer_active
? "active ":"",
10153 peer_router
? "router ":"",
10154 attr
->mm_sync_seqnum
);
10156 vty_out(vty
, " ESI %s %s\n",
10158 es_local
? "local-es":"");
10162 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10163 const struct prefix
*p
, struct bgp_path_info
*path
,
10164 afi_t afi
, safi_t safi
,
10165 enum rpki_states rpki_curr_state
,
10166 json_object
*json_paths
)
10168 char buf
[INET6_ADDRSTRLEN
];
10170 struct attr
*attr
= path
->attr
;
10172 json_object
*json_bestpath
= NULL
;
10173 json_object
*json_cluster_list
= NULL
;
10174 json_object
*json_cluster_list_list
= NULL
;
10175 json_object
*json_ext_community
= NULL
;
10176 json_object
*json_last_update
= NULL
;
10177 json_object
*json_pmsi
= NULL
;
10178 json_object
*json_nexthop_global
= NULL
;
10179 json_object
*json_nexthop_ll
= NULL
;
10180 json_object
*json_nexthops
= NULL
;
10181 json_object
*json_path
= NULL
;
10182 json_object
*json_peer
= NULL
;
10183 json_object
*json_string
= NULL
;
10184 json_object
*json_adv_to
= NULL
;
10186 struct listnode
*node
, *nnode
;
10188 bool addpath_capable
;
10190 unsigned int first_as
;
10191 bool nexthop_self
=
10192 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10194 char *nexthop_hostname
=
10195 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10199 mpls_label_t label
= MPLS_INVALID_LABEL
;
10201 struct bgp_path_info
*bpi_ultimate
=
10202 bgp_get_imported_bpi_ultimate(path
);
10205 json_path
= json_object_new_object();
10206 json_peer
= json_object_new_object();
10207 json_nexthop_global
= json_object_new_object();
10210 if (safi
== SAFI_EVPN
) {
10212 vty_out(vty
, " Route %pFX", p
);
10216 if (path
->extra
&& path
->extra
->num_labels
) {
10217 bgp_evpn_label2str(path
->extra
->label
,
10218 path
->extra
->num_labels
, tag_buf
,
10221 if (safi
== SAFI_EVPN
) {
10223 if (tag_buf
[0] != '\0')
10224 vty_out(vty
, " VNI %s", tag_buf
);
10227 json_object_string_add(json_path
, "vni",
10233 if (safi
== SAFI_EVPN
10234 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10235 char gwip_buf
[INET6_ADDRSTRLEN
];
10237 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10241 json_object_string_add(json_path
, "gatewayIP",
10244 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10247 if (safi
== SAFI_EVPN
&& !json_path
)
10248 vty_out(vty
, "\n");
10251 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10252 struct bgp_path_info
*parent_ri
;
10253 struct bgp_dest
*dest
, *pdest
;
10255 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10256 dest
= parent_ri
->net
;
10257 if (dest
&& dest
->pdest
) {
10258 pdest
= dest
->pdest
;
10259 if (is_pi_family_evpn(parent_ri
)) {
10261 " Imported from %pRD:%pFX, VNI %s",
10262 (struct prefix_rd
*)bgp_dest_get_prefix(
10264 (struct prefix_evpn
*)
10265 bgp_dest_get_prefix(dest
),
10267 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10268 vty_out(vty
, ", L3NHG %s",
10271 ATTR_ES_L3_NHG_ACTIVE
)
10274 vty_out(vty
, "\n");
10277 vty_out(vty
, " Imported from %pRD:%pFX\n",
10278 (struct prefix_rd
*)bgp_dest_get_prefix(
10280 (struct prefix_evpn
*)
10281 bgp_dest_get_prefix(dest
));
10285 /* Line1 display AS-path, Aggregator */
10286 if (attr
->aspath
) {
10288 if (!attr
->aspath
->json
)
10289 aspath_str_update(attr
->aspath
, true);
10290 json_object_lock(attr
->aspath
->json
);
10291 json_object_object_add(json_path
, "aspath",
10292 attr
->aspath
->json
);
10294 if (attr
->aspath
->segments
)
10295 vty_out(vty
, " %s", attr
->aspath
->str
);
10297 vty_out(vty
, " Local");
10301 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10303 json_object_boolean_true_add(json_path
, "removed");
10305 vty_out(vty
, ", (removed)");
10308 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10310 json_object_boolean_true_add(json_path
, "stale");
10312 vty_out(vty
, ", (stale)");
10315 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10317 json_object_int_add(json_path
, "aggregatorAs",
10318 attr
->aggregator_as
);
10319 json_object_string_addf(json_path
, "aggregatorId",
10320 "%pI4", &attr
->aggregator_addr
);
10322 vty_out(vty
, ", (aggregated by %u %pI4)",
10323 attr
->aggregator_as
, &attr
->aggregator_addr
);
10327 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10328 PEER_FLAG_REFLECTOR_CLIENT
)) {
10330 json_object_boolean_true_add(json_path
,
10331 "rxedFromRrClient");
10333 vty_out(vty
, ", (Received from a RR-client)");
10336 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10337 PEER_FLAG_RSERVER_CLIENT
)) {
10339 json_object_boolean_true_add(json_path
,
10340 "rxedFromRsClient");
10342 vty_out(vty
, ", (Received from a RS-client)");
10345 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10347 json_object_boolean_true_add(json_path
,
10348 "dampeningHistoryEntry");
10350 vty_out(vty
, ", (history entry)");
10351 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10353 json_object_boolean_true_add(json_path
,
10354 "dampeningSuppressed");
10356 vty_out(vty
, ", (suppressed due to dampening)");
10360 vty_out(vty
, "\n");
10362 /* Line2 display Next-hop, Neighbor, Router-id */
10363 /* Display the nexthop */
10365 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10366 p
->family
== AF_EVPN
) &&
10367 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10368 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10369 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10370 || safi
== SAFI_EVPN
) {
10372 json_object_string_addf(
10373 json_nexthop_global
, "ip", "%pI4",
10374 &attr
->mp_nexthop_global_in
);
10376 if (path
->peer
->hostname
)
10377 json_object_string_add(
10378 json_nexthop_global
, "hostname",
10379 path
->peer
->hostname
);
10381 if (nexthop_hostname
)
10382 vty_out(vty
, " %pI4(%s)",
10383 &attr
->mp_nexthop_global_in
,
10386 vty_out(vty
, " %pI4",
10387 &attr
->mp_nexthop_global_in
);
10391 json_object_string_addf(json_nexthop_global
,
10395 if (path
->peer
->hostname
)
10396 json_object_string_add(
10397 json_nexthop_global
, "hostname",
10398 path
->peer
->hostname
);
10400 if (nexthop_hostname
)
10401 vty_out(vty
, " %pI4(%s)",
10405 vty_out(vty
, " %pI4",
10411 json_object_string_add(json_nexthop_global
, "afi",
10415 json_object_string_addf(json_nexthop_global
, "ip",
10417 &attr
->mp_nexthop_global
);
10419 if (path
->peer
->hostname
)
10420 json_object_string_add(json_nexthop_global
,
10422 path
->peer
->hostname
);
10424 json_object_string_add(json_nexthop_global
, "afi",
10426 json_object_string_add(json_nexthop_global
, "scope",
10429 if (nexthop_hostname
)
10430 vty_out(vty
, " %pI6(%s)",
10431 &attr
->mp_nexthop_global
,
10434 vty_out(vty
, " %pI6",
10435 &attr
->mp_nexthop_global
);
10439 /* Display the IGP cost or 'inaccessible' */
10440 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10441 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10444 json_object_boolean_false_add(json_nexthop_global
,
10446 json_object_boolean_add(json_nexthop_global
,
10447 "importCheckEnabled", import
);
10449 vty_out(vty
, " (inaccessible%s)",
10450 import
? ", import-check enabled" : "");
10453 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10455 json_object_int_add(
10456 json_nexthop_global
, "metric",
10457 bpi_ultimate
->extra
->igpmetric
);
10459 vty_out(vty
, " (metric %u)",
10460 bpi_ultimate
->extra
->igpmetric
);
10463 /* IGP cost is 0, display this only for json */
10466 json_object_int_add(json_nexthop_global
,
10471 json_object_boolean_true_add(json_nexthop_global
,
10475 /* Display peer "from" output */
10476 /* This path was originated locally */
10477 if (path
->peer
== bgp
->peer_self
) {
10479 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10480 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10482 json_object_string_add(json_peer
, "peerId",
10485 vty_out(vty
, " from 0.0.0.0 ");
10488 json_object_string_add(json_peer
, "peerId",
10491 vty_out(vty
, " from :: ");
10495 json_object_string_addf(json_peer
, "routerId", "%pI4",
10498 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10501 /* We RXed this path from one of our peers */
10505 json_object_string_addf(json_peer
, "peerId", "%pSU",
10507 json_object_string_addf(json_peer
, "routerId", "%pI4",
10508 &path
->peer
->remote_id
);
10510 if (path
->peer
->hostname
)
10511 json_object_string_add(json_peer
, "hostname",
10512 path
->peer
->hostname
);
10514 if (path
->peer
->domainname
)
10515 json_object_string_add(json_peer
, "domainname",
10516 path
->peer
->domainname
);
10518 if (path
->peer
->conf_if
)
10519 json_object_string_add(json_peer
, "interface",
10520 path
->peer
->conf_if
);
10522 if (path
->peer
->conf_if
) {
10523 if (path
->peer
->hostname
10524 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10525 BGP_FLAG_SHOW_HOSTNAME
))
10526 vty_out(vty
, " from %s(%s)",
10527 path
->peer
->hostname
,
10528 path
->peer
->conf_if
);
10530 vty_out(vty
, " from %s",
10531 path
->peer
->conf_if
);
10533 if (path
->peer
->hostname
10534 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10535 BGP_FLAG_SHOW_HOSTNAME
))
10536 vty_out(vty
, " from %s(%s)",
10537 path
->peer
->hostname
,
10540 vty_out(vty
, " from %pSU",
10544 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10545 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10547 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10552 * Note when vrfid of nexthop is different from that of prefix
10554 if (path
->extra
&& path
->extra
->bgp_orig
) {
10555 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10560 if (path
->extra
->bgp_orig
->inst_type
10561 == BGP_INSTANCE_TYPE_DEFAULT
)
10562 vn
= VRF_DEFAULT_NAME
;
10564 vn
= path
->extra
->bgp_orig
->name
;
10566 json_object_string_add(json_path
, "nhVrfName", vn
);
10568 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10569 json_object_int_add(json_path
, "nhVrfId", -1);
10571 json_object_int_add(json_path
, "nhVrfId",
10572 (int)nexthop_vrfid
);
10575 if (nexthop_vrfid
== VRF_UNKNOWN
)
10576 vty_out(vty
, " vrf ?");
10580 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10581 vty_out(vty
, " vrf %s(%u)",
10582 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10587 if (nexthop_self
) {
10589 json_object_boolean_true_add(json_path
,
10590 "announceNexthopSelf");
10592 vty_out(vty
, " announce-nh-self");
10597 vty_out(vty
, "\n");
10599 /* display the link-local nexthop */
10600 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10602 json_nexthop_ll
= json_object_new_object();
10603 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10604 &attr
->mp_nexthop_local
);
10606 if (path
->peer
->hostname
)
10607 json_object_string_add(json_nexthop_ll
,
10609 path
->peer
->hostname
);
10611 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10612 json_object_string_add(json_nexthop_ll
, "scope",
10615 json_object_boolean_true_add(json_nexthop_ll
,
10618 if (!attr
->mp_nexthop_prefer_global
)
10619 json_object_boolean_true_add(json_nexthop_ll
,
10622 json_object_boolean_true_add(
10623 json_nexthop_global
, "used");
10625 vty_out(vty
, " (%s) %s\n",
10626 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10627 buf
, INET6_ADDRSTRLEN
),
10628 attr
->mp_nexthop_prefer_global
10629 ? "(prefer-global)"
10633 /* If we do not have a link-local nexthop then we must flag the
10634 global as "used" */
10637 json_object_boolean_true_add(json_nexthop_global
,
10641 if (safi
== SAFI_EVPN
&&
10642 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10643 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10646 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10647 * Int/Ext/Local, Atomic, best */
10649 json_object_string_add(json_path
, "origin",
10650 bgp_origin_long_str
[attr
->origin
]);
10652 vty_out(vty
, " Origin %s",
10653 bgp_origin_long_str
[attr
->origin
]);
10655 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10657 json_object_int_add(json_path
, "metric", attr
->med
);
10659 vty_out(vty
, ", metric %u", attr
->med
);
10662 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10664 json_object_int_add(json_path
, "locPrf",
10667 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10670 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10672 json_object_int_add(json_path
, "aigpMetric",
10673 bgp_attr_get_aigp_metric(attr
));
10675 vty_out(vty
, ", aigp-metric %" PRIu64
,
10676 bgp_attr_get_aigp_metric(attr
));
10679 if (attr
->weight
!= 0) {
10681 json_object_int_add(json_path
, "weight", attr
->weight
);
10683 vty_out(vty
, ", weight %u", attr
->weight
);
10686 if (attr
->tag
!= 0) {
10688 json_object_int_add(json_path
, "tag", attr
->tag
);
10690 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10693 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10695 json_object_boolean_false_add(json_path
, "valid");
10697 vty_out(vty
, ", invalid");
10698 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10700 json_object_boolean_true_add(json_path
, "valid");
10702 vty_out(vty
, ", valid");
10706 json_object_int_add(json_path
, "version", bn
->version
);
10708 if (path
->peer
!= bgp
->peer_self
) {
10709 if (path
->peer
->as
== path
->peer
->local_as
) {
10710 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10712 json_object_string_add(
10714 "confed-internal");
10716 vty_out(vty
, ", confed-internal");
10719 json_object_string_add(
10720 json_peer
, "type", "internal");
10722 vty_out(vty
, ", internal");
10725 if (bgp_confederation_peers_check(bgp
,
10728 json_object_string_add(
10730 "confed-external");
10732 vty_out(vty
, ", confed-external");
10735 json_object_string_add(
10736 json_peer
, "type", "external");
10738 vty_out(vty
, ", external");
10741 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10743 json_object_boolean_true_add(json_path
, "aggregated");
10744 json_object_boolean_true_add(json_path
, "local");
10746 vty_out(vty
, ", aggregated, local");
10748 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10750 json_object_boolean_true_add(json_path
, "sourced");
10752 vty_out(vty
, ", sourced");
10755 json_object_boolean_true_add(json_path
, "sourced");
10756 json_object_boolean_true_add(json_path
, "local");
10758 vty_out(vty
, ", sourced, local");
10762 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10764 json_object_boolean_true_add(json_path
,
10765 "atomicAggregate");
10767 vty_out(vty
, ", atomic-aggregate");
10770 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10772 json_object_int_add(json_path
, "otc", attr
->otc
);
10774 vty_out(vty
, ", otc %u", attr
->otc
);
10777 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10778 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10779 && bgp_path_info_mpath_count(path
))) {
10781 json_object_boolean_true_add(json_path
, "multipath");
10783 vty_out(vty
, ", multipath");
10786 // Mark the bestpath(s)
10787 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10788 first_as
= aspath_get_first_as(attr
->aspath
);
10791 if (!json_bestpath
)
10792 json_bestpath
= json_object_new_object();
10793 json_object_int_add(json_bestpath
, "bestpathFromAs",
10797 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10799 vty_out(vty
, ", bestpath-from-AS Local");
10803 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10805 if (!json_bestpath
)
10806 json_bestpath
= json_object_new_object();
10807 json_object_boolean_true_add(json_bestpath
, "overall");
10808 json_object_string_add(
10809 json_bestpath
, "selectionReason",
10810 bgp_path_selection_reason2str(bn
->reason
));
10812 vty_out(vty
, ", best");
10813 vty_out(vty
, " (%s)",
10814 bgp_path_selection_reason2str(bn
->reason
));
10818 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10820 json_object_string_add(
10821 json_path
, "rpkiValidationState",
10822 bgp_rpki_validation2str(rpki_curr_state
));
10824 vty_out(vty
, ", rpki validation-state: %s",
10825 bgp_rpki_validation2str(rpki_curr_state
));
10829 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10832 vty_out(vty
, "\n");
10834 /* Line 4 display Community */
10835 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10837 if (!bgp_attr_get_community(attr
)->json
)
10838 community_str(bgp_attr_get_community(attr
),
10840 json_object_lock(bgp_attr_get_community(attr
)->json
);
10841 json_object_object_add(
10842 json_path
, "community",
10843 bgp_attr_get_community(attr
)->json
);
10845 vty_out(vty
, " Community: %s\n",
10846 bgp_attr_get_community(attr
)->str
);
10850 /* Line 5 display Extended-community */
10851 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10853 json_ext_community
= json_object_new_object();
10854 json_object_string_add(
10855 json_ext_community
, "string",
10856 bgp_attr_get_ecommunity(attr
)->str
);
10857 json_object_object_add(json_path
, "extendedCommunity",
10858 json_ext_community
);
10860 vty_out(vty
, " Extended Community: %s\n",
10861 bgp_attr_get_ecommunity(attr
)->str
);
10865 /* Line 6 display Large community */
10866 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10868 if (!bgp_attr_get_lcommunity(attr
)->json
)
10869 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10871 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10872 json_object_object_add(
10873 json_path
, "largeCommunity",
10874 bgp_attr_get_lcommunity(attr
)->json
);
10876 vty_out(vty
, " Large Community: %s\n",
10877 bgp_attr_get_lcommunity(attr
)->str
);
10881 /* Line 7 display Originator, Cluster-id */
10882 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10883 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10884 char buf
[BUFSIZ
] = {0};
10886 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10888 json_object_string_addf(json_path
,
10889 "originatorId", "%pI4",
10890 &attr
->originator_id
);
10892 vty_out(vty
, " Originator: %pI4",
10893 &attr
->originator_id
);
10896 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10897 struct cluster_list
*cluster
=
10898 bgp_attr_get_cluster(attr
);
10902 json_cluster_list
= json_object_new_object();
10903 json_cluster_list_list
=
10904 json_object_new_array();
10906 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10907 json_string
= json_object_new_string(
10910 buf
, sizeof(buf
)));
10911 json_object_array_add(
10912 json_cluster_list_list
,
10917 * struct cluster_list does not have
10918 * "str" variable like aspath and community
10919 * do. Add this someday if someone asks
10921 * json_object_string_add(json_cluster_list,
10922 * "string", cluster->str);
10924 json_object_object_add(json_cluster_list
,
10926 json_cluster_list_list
);
10927 json_object_object_add(json_path
, "clusterList",
10928 json_cluster_list
);
10930 vty_out(vty
, ", Cluster list: ");
10932 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10933 vty_out(vty
, "%pI4 ",
10934 &cluster
->list
[i
]);
10940 vty_out(vty
, "\n");
10943 if (path
->extra
&& path
->extra
->damp_info
)
10944 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10947 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10948 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10949 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10953 json_object_int_add(json_path
, "remoteLabel", label
);
10955 vty_out(vty
, " Remote label: %d\n", label
);
10959 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10961 json_object_string_addf(json_path
, "remoteSid", "%pI6",
10962 &path
->extra
->sid
[0].sid
);
10964 vty_out(vty
, " Remote SID: %pI6\n",
10965 &path
->extra
->sid
[0].sid
);
10969 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10971 json_object_int_add(json_path
, "labelIndex",
10972 attr
->label_index
);
10974 vty_out(vty
, " Label Index: %d\n",
10975 attr
->label_index
);
10978 /* Line 8 display Addpath IDs */
10979 if (path
->addpath_rx_id
10980 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10982 json_object_int_add(json_path
, "addpathRxId",
10983 path
->addpath_rx_id
);
10985 /* Keep backwards compatibility with the old API
10986 * by putting TX All's ID in the old field
10988 json_object_int_add(
10989 json_path
, "addpathTxId",
10991 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10993 /* ... but create a specific field for each
10996 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10997 json_object_int_add(
10999 bgp_addpath_names(i
)->id_json_name
,
11000 path
->tx_addpath
.addpath_tx_id
[i
]);
11003 vty_out(vty
, " AddPath ID: RX %u, ",
11004 path
->addpath_rx_id
);
11006 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11010 /* If we used addpath to TX a non-bestpath we need to display
11011 * "Advertised to" on a path-by-path basis
11013 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11016 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11018 bgp_addpath_encode_tx(peer
, afi
, safi
);
11019 has_adj
= bgp_adj_out_lookup(
11021 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11022 &path
->tx_addpath
));
11024 if ((addpath_capable
&& has_adj
)
11025 || (!addpath_capable
&& has_adj
11026 && CHECK_FLAG(path
->flags
,
11027 BGP_PATH_SELECTED
))) {
11028 if (json_path
&& !json_adv_to
)
11029 json_adv_to
= json_object_new_object();
11031 route_vty_out_advertised_to(
11033 " Advertised to:", json_adv_to
);
11039 json_object_object_add(
11040 json_path
, "advertisedTo", json_adv_to
);
11044 vty_out(vty
, "\n");
11049 /* Line 9 display Uptime */
11050 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11052 json_last_update
= json_object_new_object();
11053 json_object_int_add(json_last_update
, "epoch", tbuf
);
11054 json_object_string_add(json_last_update
, "string",
11056 json_object_object_add(json_path
, "lastUpdate",
11059 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11061 /* Line 10 display PMSI tunnel attribute, if present */
11062 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11063 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11064 bgp_attr_get_pmsi_tnl_type(attr
),
11065 PMSI_TNLTYPE_STR_DEFAULT
);
11068 json_pmsi
= json_object_new_object();
11069 json_object_string_add(json_pmsi
, "tunnelType", str
);
11070 json_object_int_add(json_pmsi
, "label",
11071 label2vni(&attr
->label
));
11072 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11074 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11075 str
, label2vni(&attr
->label
));
11078 if (path
->peer
->t_gr_restart
&&
11079 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11080 unsigned long gr_remaining
=
11081 thread_timer_remain_second(path
->peer
->t_gr_restart
);
11084 json_object_int_add(json_path
,
11085 "gracefulRestartSecondsRemaining",
11089 " Time until Graceful Restart stale route deleted: %lu\n",
11093 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11094 bgp_attr_get_community(attr
) &&
11095 community_include(bgp_attr_get_community(attr
),
11096 COMMUNITY_LLGR_STALE
)) {
11097 unsigned long llgr_remaining
= thread_timer_remain_second(
11098 path
->peer
->t_llgr_stale
[afi
][safi
]);
11101 json_object_int_add(json_path
, "llgrSecondsRemaining",
11105 " Time until Long-lived stale route deleted: %lu\n",
11109 /* Output some debug about internal state of the dest flags */
11111 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11112 json_object_boolean_true_add(json_path
, "processScheduled");
11113 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11114 json_object_boolean_true_add(json_path
, "userCleared");
11115 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11116 json_object_boolean_true_add(json_path
, "labelChanged");
11117 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11118 json_object_boolean_true_add(json_path
, "registeredForLabel");
11119 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11120 json_object_boolean_true_add(json_path
, "selectDefered");
11121 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11122 json_object_boolean_true_add(json_path
, "fibInstalled");
11123 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11124 json_object_boolean_true_add(json_path
, "fibPending");
11126 if (json_nexthop_global
|| json_nexthop_ll
) {
11127 json_nexthops
= json_object_new_array();
11129 if (json_nexthop_global
)
11130 json_object_array_add(json_nexthops
,
11131 json_nexthop_global
);
11133 if (json_nexthop_ll
)
11134 json_object_array_add(json_nexthops
,
11137 json_object_object_add(json_path
, "nexthops",
11141 json_object_object_add(json_path
, "peer", json_peer
);
11142 json_object_array_add(json_paths
, json_path
);
11146 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11147 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11148 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11150 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11151 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11153 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11154 const char *comstr
, int exact
, afi_t afi
,
11155 safi_t safi
, uint16_t show_flags
);
11157 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11158 struct bgp_table
*table
, enum bgp_show_type type
,
11159 void *output_arg
, const char *rd
, int is_last
,
11160 unsigned long *output_cum
, unsigned long *total_cum
,
11161 unsigned long *json_header_depth
, uint16_t show_flags
,
11162 enum rpki_states rpki_target_state
)
11164 struct bgp_path_info
*pi
;
11165 struct bgp_dest
*dest
;
11166 bool header
= true;
11167 bool json_detail_header
= false;
11169 unsigned long output_count
= 0;
11170 unsigned long total_count
= 0;
11172 json_object
*json_paths
= NULL
;
11174 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11175 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11176 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11177 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11178 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11180 if (output_cum
&& *output_cum
!= 0)
11183 if (use_json
&& !*json_header_depth
) {
11185 *json_header_depth
= 1;
11187 vty_out(vty
, "{\n");
11188 *json_header_depth
= 2;
11192 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11193 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11194 " \"localAS\": %u,\n \"routes\": { ",
11195 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11196 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11199 table
->version
, &bgp
->router_id
,
11200 bgp
->default_local_pref
, bgp
->as
);
11202 vty_out(vty
, " \"routeDistinguishers\" : {");
11203 ++*json_header_depth
;
11207 if (use_json
&& rd
) {
11208 vty_out(vty
, " \"%s\" : { ", rd
);
11211 /* Check for 'json detail', where we need header output once per dest */
11212 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11213 type
!= bgp_show_type_damp_neighbor
&&
11214 type
!= bgp_show_type_flap_statistics
&&
11215 type
!= bgp_show_type_flap_neighbor
)
11216 json_detail_header
= true;
11218 /* Start processing of routes. */
11219 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11220 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11221 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11222 bool json_detail
= json_detail_header
;
11224 pi
= bgp_dest_get_bgp_path_info(dest
);
11230 json_paths
= json_object_new_array();
11234 for (; pi
; pi
= pi
->next
) {
11235 struct community
*picomm
= NULL
;
11237 picomm
= bgp_attr_get_community(pi
->attr
);
11241 if (type
== bgp_show_type_prefix_version
) {
11243 strtoul(output_arg
, NULL
, 10);
11244 if (dest
->version
< version
)
11248 if (type
== bgp_show_type_community_alias
) {
11249 char *alias
= output_arg
;
11250 char **communities
;
11252 bool found
= false;
11255 frrstr_split(picomm
->str
, " ",
11256 &communities
, &num
);
11257 for (int i
= 0; i
< num
; i
++) {
11258 const char *com2alias
=
11259 bgp_community2alias(
11262 && strcmp(alias
, com2alias
)
11268 XFREE(MTYPE_TMP
, communities
);
11272 bgp_attr_get_lcommunity(pi
->attr
)) {
11273 frrstr_split(bgp_attr_get_lcommunity(
11276 " ", &communities
, &num
);
11277 for (int i
= 0; i
< num
; i
++) {
11278 const char *com2alias
=
11279 bgp_community2alias(
11282 && strcmp(alias
, com2alias
)
11288 XFREE(MTYPE_TMP
, communities
);
11295 if (type
== bgp_show_type_rpki
) {
11296 if (dest_p
->family
== AF_INET
11297 || dest_p
->family
== AF_INET6
)
11298 rpki_curr_state
= hook_call(
11299 bgp_rpki_prefix_status
,
11300 pi
->peer
, pi
->attr
, dest_p
);
11301 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11302 && rpki_curr_state
!= rpki_target_state
)
11306 if (type
== bgp_show_type_flap_statistics
11307 || type
== bgp_show_type_flap_neighbor
11308 || type
== bgp_show_type_dampend_paths
11309 || type
== bgp_show_type_damp_neighbor
) {
11310 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11313 if (type
== bgp_show_type_regexp
) {
11314 regex_t
*regex
= output_arg
;
11316 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11320 if (type
== bgp_show_type_prefix_list
) {
11321 struct prefix_list
*plist
= output_arg
;
11323 if (prefix_list_apply(plist
, dest_p
)
11327 if (type
== bgp_show_type_access_list
) {
11328 struct access_list
*alist
= output_arg
;
11330 if (access_list_apply(alist
, dest_p
) !=
11334 if (type
== bgp_show_type_filter_list
) {
11335 struct as_list
*as_list
= output_arg
;
11337 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11338 != AS_FILTER_PERMIT
)
11341 if (type
== bgp_show_type_route_map
) {
11342 struct route_map
*rmap
= output_arg
;
11343 struct bgp_path_info path
;
11344 struct bgp_path_info_extra extra
;
11345 struct attr dummy_attr
= {};
11346 route_map_result_t ret
;
11348 dummy_attr
= *pi
->attr
;
11350 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11351 pi
->peer
, &dummy_attr
);
11353 ret
= route_map_apply(rmap
, dest_p
, &path
);
11354 bgp_attr_flush(&dummy_attr
);
11355 if (ret
== RMAP_DENYMATCH
)
11358 if (type
== bgp_show_type_neighbor
11359 || type
== bgp_show_type_flap_neighbor
11360 || type
== bgp_show_type_damp_neighbor
) {
11361 union sockunion
*su
= output_arg
;
11363 if (pi
->peer
== NULL
11364 || pi
->peer
->su_remote
== NULL
11365 || !sockunion_same(pi
->peer
->su_remote
, su
))
11368 if (type
== bgp_show_type_cidr_only
) {
11369 uint32_t destination
;
11371 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11372 if (IN_CLASSC(destination
)
11373 && dest_p
->prefixlen
== 24)
11375 if (IN_CLASSB(destination
)
11376 && dest_p
->prefixlen
== 16)
11378 if (IN_CLASSA(destination
)
11379 && dest_p
->prefixlen
== 8)
11382 if (type
== bgp_show_type_prefix_longer
) {
11384 if (!prefix_match(p
, dest_p
))
11387 if (type
== bgp_show_type_community_all
) {
11391 if (type
== bgp_show_type_community
) {
11392 struct community
*com
= output_arg
;
11394 if (!picomm
|| !community_match(picomm
, com
))
11397 if (type
== bgp_show_type_community_exact
) {
11398 struct community
*com
= output_arg
;
11400 if (!picomm
|| !community_cmp(picomm
, com
))
11403 if (type
== bgp_show_type_community_list
) {
11404 struct community_list
*list
= output_arg
;
11406 if (!community_list_match(picomm
, list
))
11409 if (type
== bgp_show_type_community_list_exact
) {
11410 struct community_list
*list
= output_arg
;
11412 if (!community_list_exact_match(picomm
, list
))
11415 if (type
== bgp_show_type_lcommunity
) {
11416 struct lcommunity
*lcom
= output_arg
;
11418 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11420 bgp_attr_get_lcommunity(pi
->attr
),
11425 if (type
== bgp_show_type_lcommunity_exact
) {
11426 struct lcommunity
*lcom
= output_arg
;
11428 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11430 bgp_attr_get_lcommunity(pi
->attr
),
11434 if (type
== bgp_show_type_lcommunity_list
) {
11435 struct community_list
*list
= output_arg
;
11437 if (!lcommunity_list_match(
11438 bgp_attr_get_lcommunity(pi
->attr
),
11443 == bgp_show_type_lcommunity_list_exact
) {
11444 struct community_list
*list
= output_arg
;
11446 if (!lcommunity_list_exact_match(
11447 bgp_attr_get_lcommunity(pi
->attr
),
11451 if (type
== bgp_show_type_lcommunity_all
) {
11452 if (!bgp_attr_get_lcommunity(pi
->attr
))
11455 if (type
== bgp_show_type_dampend_paths
11456 || type
== bgp_show_type_damp_neighbor
) {
11457 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11458 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11462 if (!use_json
&& header
) {
11464 "BGP table version is %" PRIu64
11465 ", local router ID is %pI4, vrf id ",
11466 table
->version
, &bgp
->router_id
);
11467 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11468 vty_out(vty
, "%s", VRFID_NONE_STR
);
11470 vty_out(vty
, "%u", bgp
->vrf_id
);
11471 vty_out(vty
, "\n");
11472 vty_out(vty
, "Default local pref %u, ",
11473 bgp
->default_local_pref
);
11474 vty_out(vty
, "local AS %u\n", bgp
->as
);
11475 if (!detail_routes
) {
11476 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11477 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11478 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11479 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11481 if (type
== bgp_show_type_dampend_paths
11482 || type
== bgp_show_type_damp_neighbor
)
11483 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11484 else if (type
== bgp_show_type_flap_statistics
11485 || type
== bgp_show_type_flap_neighbor
)
11486 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11487 else if (!detail_routes
)
11488 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11489 : BGP_SHOW_HEADER
));
11492 } else if (json_detail
&& json_paths
!= NULL
) {
11493 const struct prefix_rd
*prd
;
11494 json_object
*jtemp
;
11496 /* Use common detail header, for most types;
11497 * need a json 'object'.
11500 jtemp
= json_object_new_object();
11501 prd
= bgp_rd_from_dest(dest
, safi
);
11503 route_vty_out_detail_header(
11505 bgp_dest_get_prefix(dest
), prd
,
11506 table
->afi
, safi
, jtemp
);
11508 json_object_array_add(json_paths
, jtemp
);
11510 json_detail
= false;
11513 if (rd
!= NULL
&& !display
&& !output_count
) {
11516 "Route Distinguisher: %s\n",
11519 if (type
== bgp_show_type_dampend_paths
11520 || type
== bgp_show_type_damp_neighbor
)
11521 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11522 AFI_IP
, safi
, use_json
,
11524 else if (type
== bgp_show_type_flap_statistics
11525 || type
== bgp_show_type_flap_neighbor
)
11526 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11527 AFI_IP
, safi
, use_json
,
11530 if (detail_routes
|| detail_json
) {
11531 const struct prefix_rd
*prd
= NULL
;
11534 prd
= bgp_rd_from_dest(
11535 dest
->pdest
, safi
);
11538 route_vty_out_detail_header(
11540 bgp_dest_get_prefix(
11542 prd
, table
->afi
, safi
,
11545 route_vty_out_detail(
11546 vty
, bgp
, dest
, dest_p
, pi
,
11547 family2afi(dest_p
->family
),
11548 safi
, RPKI_NOT_BEING_USED
,
11551 route_vty_out(vty
, dest_p
, pi
, display
,
11552 safi
, json_paths
, wide
);
11563 /* encode prefix */
11564 if (dest_p
->family
== AF_FLOWSPEC
) {
11565 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11568 bgp_fs_nlri_get_string(
11570 dest_p
->u
.prefix_flowspec
.ptr
,
11571 dest_p
->u
.prefix_flowspec
.prefixlen
,
11572 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11573 family2afi(dest_p
->u
11574 .prefix_flowspec
.family
));
11576 vty_out(vty
, "\"%s/%d\": ", retstr
,
11577 dest_p
->u
.prefix_flowspec
11580 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11581 dest_p
->u
.prefix_flowspec
11585 vty_out(vty
, "\"%pFX\": ", dest_p
);
11587 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11590 * We are using no_pretty here because under
11591 * extremely high settings( say lots and lots of
11592 * routes with lots and lots of ways to reach
11593 * that route via different paths ) this can
11594 * save several minutes of output when FRR
11595 * is run on older cpu's or more underperforming
11596 * routers out there
11598 vty_json_no_pretty(vty
, json_paths
);
11602 json_object_free(json_paths
);
11606 output_count
+= *output_cum
;
11607 *output_cum
= output_count
;
11610 total_count
+= *total_cum
;
11611 *total_cum
= total_count
;
11615 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11619 for (i
= 0; i
< *json_header_depth
; ++i
)
11620 vty_out(vty
, " } ");
11622 vty_out(vty
, "\n");
11626 /* No route is displayed */
11627 if (output_count
== 0) {
11628 if (type
== bgp_show_type_normal
)
11630 "No BGP prefixes displayed, %ld exist\n",
11634 "\nDisplayed %ld routes and %ld total paths\n",
11635 output_count
, total_count
);
11639 return CMD_SUCCESS
;
11642 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11643 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11644 enum bgp_show_type type
, void *output_arg
,
11645 uint16_t show_flags
)
11647 struct bgp_dest
*dest
, *next
;
11648 unsigned long output_cum
= 0;
11649 unsigned long total_cum
= 0;
11650 unsigned long json_header_depth
= 0;
11651 struct bgp_table
*itable
;
11653 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11655 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11657 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11658 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11660 next
= bgp_route_next(dest
);
11661 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11664 itable
= bgp_dest_get_bgp_table_info(dest
);
11665 if (itable
!= NULL
) {
11666 struct prefix_rd prd
;
11667 char rd
[RD_ADDRSTRLEN
];
11669 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11670 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11671 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11672 rd
, next
== NULL
, &output_cum
,
11673 &total_cum
, &json_header_depth
,
11674 show_flags
, RPKI_NOT_BEING_USED
);
11680 if (output_cum
== 0)
11681 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11685 "\nDisplayed %ld routes and %ld total paths\n",
11686 output_cum
, total_cum
);
11688 if (use_json
&& output_cum
== 0)
11689 vty_out(vty
, "{}\n");
11691 return CMD_SUCCESS
;
11694 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11695 enum bgp_show_type type
, void *output_arg
,
11696 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11698 struct bgp_table
*table
;
11699 unsigned long json_header_depth
= 0;
11700 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11703 bgp
= bgp_get_default();
11708 vty_out(vty
, "No BGP process is configured\n");
11710 vty_out(vty
, "{}\n");
11711 return CMD_WARNING
;
11714 /* Labeled-unicast routes live in the unicast table. */
11715 if (safi
== SAFI_LABELED_UNICAST
)
11716 safi
= SAFI_UNICAST
;
11718 table
= bgp
->rib
[afi
][safi
];
11719 /* use MPLS and ENCAP specific shows until they are merged */
11720 if (safi
== SAFI_MPLS_VPN
) {
11721 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11722 output_arg
, show_flags
);
11725 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11726 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11727 output_arg
, use_json
,
11731 if (safi
== SAFI_EVPN
)
11732 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11734 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11735 NULL
, NULL
, &json_header_depth
, show_flags
,
11736 rpki_target_state
);
11739 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11740 safi_t safi
, uint16_t show_flags
)
11742 struct listnode
*node
, *nnode
;
11745 bool route_output
= false;
11746 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11749 vty_out(vty
, "{\n");
11751 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11752 route_output
= true;
11755 vty_out(vty
, ",\n");
11759 vty_out(vty
, "\"%s\":",
11760 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11764 vty_out(vty
, "\nInstance %s:\n",
11765 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11769 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11770 show_flags
, RPKI_NOT_BEING_USED
);
11774 vty_out(vty
, "}\n");
11775 else if (!route_output
)
11776 vty_out(vty
, "%% BGP instance not found\n");
11779 /* Header of detailed BGP route information */
11780 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11781 struct bgp_dest
*dest
, const struct prefix
*p
,
11782 const struct prefix_rd
*prd
, afi_t afi
,
11783 safi_t safi
, json_object
*json
)
11785 struct bgp_path_info
*pi
;
11787 struct listnode
*node
, *nnode
;
11788 char buf1
[RD_ADDRSTRLEN
];
11792 int accept_own
= 0;
11793 int route_filter_translated_v4
= 0;
11794 int route_filter_v4
= 0;
11795 int route_filter_translated_v6
= 0;
11796 int route_filter_v6
= 0;
11797 int llgr_stale
= 0;
11799 int accept_own_nexthop
= 0;
11802 int no_advertise
= 0;
11806 int has_valid_label
= 0;
11807 mpls_label_t label
= 0;
11808 json_object
*json_adv_to
= NULL
;
11813 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11815 has_valid_label
= bgp_is_valid_label(&label
);
11817 if (safi
== SAFI_EVPN
) {
11819 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11820 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11822 prd
? ":" : "", (struct prefix_evpn
*)p
);
11824 json_object_string_add(json
, "rd",
11825 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11827 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11832 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11834 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11835 ? prefix_rd2str(prd
, buf1
,
11838 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11842 json_object_string_addf(json
, "prefix", "%pFX", p
);
11843 json_object_int_add(json
, "version", dest
->version
);
11848 if (has_valid_label
) {
11850 json_object_int_add(json
, "localLabel", label
);
11852 vty_out(vty
, "Local label: %d\n", label
);
11856 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11857 vty_out(vty
, "not allocated\n");
11859 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11860 struct community
*picomm
= NULL
;
11862 picomm
= bgp_attr_get_community(pi
->attr
);
11865 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11867 if (bgp_path_suppressed(pi
))
11873 no_advertise
+= community_include(
11874 picomm
, COMMUNITY_NO_ADVERTISE
);
11876 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11878 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11880 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11881 route_filter_translated_v4
+= community_include(
11882 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11883 route_filter_translated_v6
+= community_include(
11884 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11885 route_filter_v4
+= community_include(
11886 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11887 route_filter_v6
+= community_include(
11888 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11890 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11891 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11892 accept_own_nexthop
+= community_include(
11893 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11895 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11896 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11901 vty_out(vty
, "Paths: (%d available", count
);
11903 vty_out(vty
, ", best #%d", best
);
11904 if (safi
== SAFI_UNICAST
) {
11905 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11906 vty_out(vty
, ", table %s",
11909 vty_out(vty
, ", vrf %s",
11913 vty_out(vty
, ", no best path");
11917 ", accept own local route exported and imported in different VRF");
11918 else if (route_filter_translated_v4
)
11920 ", mark translated RTs for VPNv4 route filtering");
11921 else if (route_filter_v4
)
11923 ", attach RT as-is for VPNv4 route filtering");
11924 else if (route_filter_translated_v6
)
11926 ", mark translated RTs for VPNv6 route filtering");
11927 else if (route_filter_v6
)
11929 ", attach RT as-is for VPNv6 route filtering");
11930 else if (llgr_stale
)
11932 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11935 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11936 else if (accept_own_nexthop
)
11938 ", accept local nexthop");
11939 else if (blackhole
)
11940 vty_out(vty
, ", inform peer to blackhole prefix");
11941 else if (no_export
)
11942 vty_out(vty
, ", not advertised to EBGP peer");
11943 else if (no_advertise
)
11944 vty_out(vty
, ", not advertised to any peer");
11946 vty_out(vty
, ", not advertised outside local AS");
11949 ", inform EBGP peer not to advertise to their EBGP peers");
11953 ", Advertisements suppressed by an aggregate.");
11954 vty_out(vty
, ")\n");
11957 /* If we are not using addpath then we can display Advertised to and
11959 * show what peers we advertised the bestpath to. If we are using
11961 * though then we must display Advertised to on a path-by-path basis. */
11962 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11963 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11964 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11965 if (json
&& !json_adv_to
)
11966 json_adv_to
= json_object_new_object();
11968 route_vty_out_advertised_to(
11970 " Advertised to non peer-group peers:\n ",
11977 json_object_object_add(json
, "advertisedTo",
11982 vty_out(vty
, " Not advertised to any peer");
11983 vty_out(vty
, "\n");
11988 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
11989 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11990 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11991 json_object
*json
, enum bgp_path_type pathtype
,
11992 int *display
, enum rpki_states rpki_target_state
)
11994 struct bgp_path_info
*pi
;
11996 json_object
*json_header
= NULL
;
11997 json_object
*json_paths
= NULL
;
11998 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12000 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12001 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12003 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12004 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12005 pi
->peer
, pi
->attr
, p
);
12007 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12008 && rpki_curr_state
!= rpki_target_state
)
12011 if (json
&& !json_paths
) {
12012 /* Instantiate json_paths only if path is valid */
12013 json_paths
= json_object_new_array();
12015 json_header
= json_object_new_object();
12017 json_header
= json
;
12021 route_vty_out_detail_header(
12022 vty
, bgp
, bgp_node
,
12023 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12024 safi
, json_header
);
12029 if (pathtype
== BGP_PATH_SHOW_ALL
12030 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12031 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12032 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12033 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12034 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12035 route_vty_out_detail(vty
, bgp
, bgp_node
,
12036 bgp_dest_get_prefix(bgp_node
), pi
,
12037 AFI_IP
, safi
, rpki_curr_state
,
12041 if (json
&& json_paths
) {
12042 json_object_object_add(json_header
, "paths", json_paths
);
12045 json_object_object_addf(json
, json_header
, "%pRD",
12051 * Return rd based on safi
12053 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12057 case SAFI_MPLS_VPN
:
12060 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12063 case SAFI_MULTICAST
:
12064 case SAFI_LABELED_UNICAST
:
12065 case SAFI_FLOWSPEC
:
12070 assert(!"Reached end of function when we were not expecting it");
12073 /* Display specified route of BGP table. */
12074 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12075 struct bgp_table
*rib
, const char *ip_str
,
12076 afi_t afi
, safi_t safi
,
12077 enum rpki_states rpki_target_state
,
12078 struct prefix_rd
*prd
, int prefix_check
,
12079 enum bgp_path_type pathtype
, bool use_json
)
12083 struct prefix match
;
12084 struct bgp_dest
*dest
;
12085 struct bgp_dest
*rm
;
12086 struct bgp_table
*table
;
12087 json_object
*json
= NULL
;
12088 json_object
*json_paths
= NULL
;
12090 /* Check IP address argument. */
12091 ret
= str2prefix(ip_str
, &match
);
12093 vty_out(vty
, "address is malformed\n");
12094 return CMD_WARNING
;
12097 match
.family
= afi2family(afi
);
12100 json
= json_object_new_object();
12102 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12103 for (dest
= bgp_table_top(rib
); dest
;
12104 dest
= bgp_route_next(dest
)) {
12105 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12107 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12109 table
= bgp_dest_get_bgp_table_info(dest
);
12113 rm
= bgp_node_match(table
, &match
);
12117 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12119 && rm_p
->prefixlen
!= match
.prefixlen
) {
12120 bgp_dest_unlock_node(rm
);
12124 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12125 bgp
, afi
, safi
, json
, pathtype
,
12126 &display
, rpki_target_state
);
12128 bgp_dest_unlock_node(rm
);
12130 } else if (safi
== SAFI_EVPN
) {
12131 struct bgp_dest
*longest_pfx
;
12132 bool is_exact_pfxlen_match
= false;
12134 for (dest
= bgp_table_top(rib
); dest
;
12135 dest
= bgp_route_next(dest
)) {
12136 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12138 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12140 table
= bgp_dest_get_bgp_table_info(dest
);
12144 longest_pfx
= NULL
;
12145 is_exact_pfxlen_match
= false;
12147 * Search through all the prefixes for a match. The
12148 * pfx's are enumerated in ascending order of pfxlens.
12149 * So, the last pfx match is the longest match. Set
12150 * is_exact_pfxlen_match when we get exact pfxlen match
12152 for (rm
= bgp_table_top(table
); rm
;
12153 rm
= bgp_route_next(rm
)) {
12154 const struct prefix
*rm_p
=
12155 bgp_dest_get_prefix(rm
);
12157 * Get prefixlen of the ip-prefix within type5
12160 if (evpn_type5_prefix_match(rm_p
, &match
)
12164 bgp_evpn_get_type5_prefixlen(
12166 if (type5_pfxlen
== match
.prefixlen
) {
12167 is_exact_pfxlen_match
= true;
12168 bgp_dest_unlock_node(rm
);
12177 if (prefix_check
&& !is_exact_pfxlen_match
)
12181 bgp_dest_lock_node(rm
);
12183 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12184 bgp
, afi
, safi
, json
, pathtype
,
12185 &display
, rpki_target_state
);
12187 bgp_dest_unlock_node(rm
);
12189 } else if (safi
== SAFI_FLOWSPEC
) {
12191 json_paths
= json_object_new_array();
12193 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12194 &match
, prefix_check
,
12200 json_object_object_add(json
, "paths",
12203 json_object_free(json_paths
);
12206 dest
= bgp_node_match(rib
, &match
);
12207 if (dest
!= NULL
) {
12208 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12210 || dest_p
->prefixlen
== match
.prefixlen
) {
12211 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12212 safi
, json
, pathtype
,
12213 &display
, rpki_target_state
);
12216 bgp_dest_unlock_node(dest
);
12221 vty_json(vty
, json
);
12224 vty_out(vty
, "%% Network not in table\n");
12225 return CMD_WARNING
;
12229 return CMD_SUCCESS
;
12232 /* Display specified route of Main RIB */
12233 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12234 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12235 int prefix_check
, enum bgp_path_type pathtype
,
12236 enum rpki_states rpki_target_state
, bool use_json
)
12239 bgp
= bgp_get_default();
12242 vty_out(vty
, "No BGP process is configured\n");
12244 vty_out(vty
, "{}\n");
12245 return CMD_WARNING
;
12249 /* labeled-unicast routes live in the unicast table */
12250 if (safi
== SAFI_LABELED_UNICAST
)
12251 safi
= SAFI_UNICAST
;
12253 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12254 afi
, safi
, rpki_target_state
, prd
,
12255 prefix_check
, pathtype
, use_json
);
12258 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12259 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12260 safi_t safi
, bool uj
)
12262 struct lcommunity
*lcom
;
12267 uint16_t show_flags
= 0;
12271 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12273 b
= buffer_new(1024);
12274 for (i
= 0; i
< argc
; i
++) {
12276 buffer_putc(b
, ' ');
12278 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12280 buffer_putstr(b
, argv
[i
]->arg
);
12284 buffer_putc(b
, '\0');
12286 str
= buffer_getstr(b
);
12289 lcom
= lcommunity_str2com(str
);
12290 XFREE(MTYPE_TMP
, str
);
12292 vty_out(vty
, "%% Large-community malformed\n");
12293 return CMD_WARNING
;
12296 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12297 (exact
? bgp_show_type_lcommunity_exact
12298 : bgp_show_type_lcommunity
),
12299 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12301 lcommunity_free(&lcom
);
12305 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12306 const char *lcom
, bool exact
, afi_t afi
,
12307 safi_t safi
, bool uj
)
12309 struct community_list
*list
;
12310 uint16_t show_flags
= 0;
12313 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12316 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12317 LARGE_COMMUNITY_LIST_MASTER
);
12318 if (list
== NULL
) {
12319 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12321 return CMD_WARNING
;
12324 return bgp_show(vty
, bgp
, afi
, safi
,
12325 (exact
? bgp_show_type_lcommunity_list_exact
12326 : bgp_show_type_lcommunity_list
),
12327 list
, show_flags
, RPKI_NOT_BEING_USED
);
12330 DEFUN (show_ip_bgp_large_community_list
,
12331 show_ip_bgp_large_community_list_cmd
,
12332 "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]",
12336 BGP_INSTANCE_HELP_STR
12338 BGP_SAFI_WITH_LABEL_HELP_STR
12339 "Display routes matching the large-community-list\n"
12340 "large-community-list number\n"
12341 "large-community-list name\n"
12342 "Exact match of the large-communities\n"
12345 afi_t afi
= AFI_IP6
;
12346 safi_t safi
= SAFI_UNICAST
;
12348 bool exact_match
= 0;
12349 struct bgp
*bgp
= NULL
;
12350 bool uj
= use_json(argc
, argv
);
12355 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12358 return CMD_WARNING
;
12360 argv_find(argv
, argc
, "large-community-list", &idx
);
12362 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12364 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12367 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12368 exact_match
, afi
, safi
, uj
);
12370 DEFUN (show_ip_bgp_large_community
,
12371 show_ip_bgp_large_community_cmd
,
12372 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12376 BGP_INSTANCE_HELP_STR
12378 BGP_SAFI_WITH_LABEL_HELP_STR
12379 "Display routes matching the large-communities\n"
12380 "List of large-community numbers\n"
12381 "Exact match of the large-communities\n"
12384 afi_t afi
= AFI_IP6
;
12385 safi_t safi
= SAFI_UNICAST
;
12387 bool exact_match
= 0;
12388 struct bgp
*bgp
= NULL
;
12389 bool uj
= use_json(argc
, argv
);
12390 uint16_t show_flags
= 0;
12394 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12397 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12400 return CMD_WARNING
;
12402 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12403 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12407 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12408 exact_match
, afi
, safi
, uj
);
12410 return bgp_show(vty
, bgp
, afi
, safi
,
12411 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12412 RPKI_NOT_BEING_USED
);
12415 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12416 safi_t safi
, struct json_object
*json_array
);
12417 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12418 safi_t safi
, struct json_object
*json
);
12421 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12422 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12423 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12424 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12426 bool uj
= use_json(argc
, argv
);
12427 struct bgp
*bgp
= NULL
;
12428 safi_t safi
= SAFI_UNICAST
;
12429 afi_t afi
= AFI_IP6
;
12431 struct json_object
*json_all
= NULL
;
12432 struct json_object
*json_afi_safi
= NULL
;
12434 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12437 return CMD_WARNING
;
12440 json_all
= json_object_new_object();
12442 FOREACH_AFI_SAFI (afi
, safi
) {
12444 * So limit output to those afi/safi pairs that
12445 * actually have something interesting in them
12447 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12452 json_afi_safi
= json_object_new_array();
12453 json_object_object_add(
12455 get_afi_safi_str(afi
, safi
, true),
12458 json_afi_safi
= NULL
;
12461 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12465 vty_json(vty
, json_all
);
12467 return CMD_SUCCESS
;
12470 /* BGP route print out function without JSON */
12471 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12472 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12473 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12477 BGP_INSTANCE_HELP_STR
12480 "BGP RIB advertisement statistics\n"
12483 afi_t afi
= AFI_IP6
;
12484 safi_t safi
= SAFI_UNICAST
;
12485 struct bgp
*bgp
= NULL
;
12487 bool uj
= use_json(argc
, argv
);
12488 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12490 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12493 return CMD_WARNING
;
12496 json_afi_safi
= json_object_new_array();
12498 json_afi_safi
= NULL
;
12500 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12503 json
= json_object_new_object();
12504 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12506 vty_json(vty
, json
);
12511 /* BGP route print out function without JSON */
12512 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12513 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12514 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12516 statistics [json]",
12517 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12518 BGP_SAFI_WITH_LABEL_HELP_STR
12519 "BGP RIB advertisement statistics\n" JSON_STR
)
12521 afi_t afi
= AFI_IP6
;
12522 safi_t safi
= SAFI_UNICAST
;
12523 struct bgp
*bgp
= NULL
;
12525 bool uj
= use_json(argc
, argv
);
12526 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12528 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12531 return CMD_WARNING
;
12534 json_afi_safi
= json_object_new_array();
12536 json_afi_safi
= NULL
;
12538 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12541 json
= json_object_new_object();
12542 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12544 vty_json(vty
, json
);
12549 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12550 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12551 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12552 "]] [all$all] dampening parameters [json]",
12553 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12554 BGP_SAFI_WITH_LABEL_HELP_STR
12555 "Display the entries for all address families\n"
12556 "Display detailed information about dampening\n"
12557 "Display detail of configured dampening parameters\n"
12560 afi_t afi
= AFI_IP6
;
12561 safi_t safi
= SAFI_UNICAST
;
12562 struct bgp
*bgp
= NULL
;
12564 uint16_t show_flags
= 0;
12565 bool uj
= use_json(argc
, argv
);
12569 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12572 /* [<ipv4|ipv6> [all]] */
12574 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12575 if (argv_find(argv
, argc
, "ipv4", &idx
))
12576 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12578 if (argv_find(argv
, argc
, "ipv6", &idx
))
12579 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12582 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12585 return CMD_WARNING
;
12587 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12590 /* BGP route print out function */
12591 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12592 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12593 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12597 |dampening <flap-statistics|dampened-paths>\
12598 |community [AA:NN|local-AS|no-advertise|no-export\
12599 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12600 |accept-own|accept-own-nexthop|route-filter-v6\
12601 |route-filter-v4|route-filter-translated-v6\
12602 |route-filter-translated-v4] [exact-match]\
12603 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12604 |filter-list AS_PATH_FILTER_NAME\
12606 |access-list ACCESSLIST_NAME\
12607 |route-map RMAP_NAME\
12608 |rpki <invalid|valid|notfound>\
12609 |version (1-4294967295)\
12611 |A.B.C.D/M longer-prefixes\
12612 |X:X::X:X/M longer-prefixes\
12613 |detail-routes$detail_routes\
12614 ] [json$uj [detail$detail_json] | wide$wide]",
12615 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12616 BGP_SAFI_WITH_LABEL_HELP_STR
12617 "Display the entries for all address families\n"
12618 "Display only routes with non-natural netmasks\n"
12619 "Display detailed information about dampening\n"
12620 "Display flap statistics of routes\n"
12621 "Display paths suppressed due to dampening\n"
12622 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12623 "Do not send outside local AS (well-known community)\n"
12624 "Do not advertise to any peer (well-known community)\n"
12625 "Do not export to next AS (well-known community)\n"
12626 "Graceful shutdown (well-known community)\n"
12627 "Do not export to any peer (well-known community)\n"
12628 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12629 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12630 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12631 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12632 "Should accept VPN route with local nexthop (well-known community)\n"
12633 "RT VPNv6 route filtering (well-known community)\n"
12634 "RT VPNv4 route filtering (well-known community)\n"
12635 "RT translated VPNv6 route filtering (well-known community)\n"
12636 "RT translated VPNv4 route filtering (well-known community)\n"
12637 "Exact match of the communities\n"
12638 "Community-list number\n"
12639 "Community-list name\n"
12640 "Display routes matching the community-list\n"
12641 "Exact match of the communities\n"
12642 "Display routes conforming to the filter-list\n"
12643 "Regular expression access list name\n"
12644 "Display routes conforming to the prefix-list\n"
12645 "Prefix-list name\n"
12646 "Display routes conforming to the access-list\n"
12647 "Access-list name\n"
12648 "Display routes matching the route-map\n"
12649 "A route-map to match on\n"
12650 "RPKI route types\n"
12651 "A valid path as determined by rpki\n"
12652 "A invalid path as determined by rpki\n"
12653 "A path that has no rpki data\n"
12654 "Display prefixes with matching version numbers\n"
12655 "Version number and above\n"
12656 "Display prefixes with matching BGP community alias\n"
12657 "BGP community alias\n"
12659 "Display route and more specific routes\n"
12661 "Display route and more specific routes\n"
12662 "Display detailed version of all routes\n"
12664 "Display detailed version of JSON output\n"
12665 "Increase table width for longer prefixes\n")
12667 afi_t afi
= AFI_IP6
;
12668 safi_t safi
= SAFI_UNICAST
;
12669 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12670 void *output_arg
= NULL
;
12671 struct bgp
*bgp
= NULL
;
12673 int exact_match
= 0;
12674 char *community
= NULL
;
12676 uint16_t show_flags
= 0;
12677 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12682 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12686 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12689 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12691 /* [<ipv4|ipv6> [all]] */
12693 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12695 if (argv_find(argv
, argc
, "ipv4", &idx
))
12696 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12698 if (argv_find(argv
, argc
, "ipv6", &idx
))
12699 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12703 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12705 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12708 return CMD_WARNING
;
12710 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12711 sh_type
= bgp_show_type_cidr_only
;
12713 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12714 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12715 sh_type
= bgp_show_type_dampend_paths
;
12716 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12717 sh_type
= bgp_show_type_flap_statistics
;
12720 if (argv_find(argv
, argc
, "community", &idx
)) {
12721 char *maybecomm
= NULL
;
12723 if (idx
+ 1 < argc
) {
12724 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12725 maybecomm
= argv
[idx
+ 1]->arg
;
12727 maybecomm
= argv
[idx
+ 1]->text
;
12730 if (maybecomm
&& !strmatch(maybecomm
, "json")
12731 && !strmatch(maybecomm
, "exact-match"))
12732 community
= maybecomm
;
12734 if (argv_find(argv
, argc
, "exact-match", &idx
))
12738 sh_type
= bgp_show_type_community_all
;
12741 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12742 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12743 struct community_list
*list
;
12745 if (argv_find(argv
, argc
, "exact-match", &idx
))
12748 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12749 COMMUNITY_LIST_MASTER
);
12750 if (list
== NULL
) {
12751 vty_out(vty
, "%% %s community-list not found\n",
12752 clist_number_or_name
);
12753 return CMD_WARNING
;
12757 sh_type
= bgp_show_type_community_list_exact
;
12759 sh_type
= bgp_show_type_community_list
;
12763 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12764 const char *filter
= argv
[++idx
]->arg
;
12765 struct as_list
*as_list
;
12767 as_list
= as_list_lookup(filter
);
12768 if (as_list
== NULL
) {
12769 vty_out(vty
, "%% %s AS-path access-list not found\n",
12771 return CMD_WARNING
;
12774 sh_type
= bgp_show_type_filter_list
;
12775 output_arg
= as_list
;
12778 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12779 const char *prefix_list_str
= argv
[++idx
]->arg
;
12780 struct prefix_list
*plist
;
12782 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12783 if (plist
== NULL
) {
12784 vty_out(vty
, "%% %s prefix-list not found\n",
12786 return CMD_WARNING
;
12789 sh_type
= bgp_show_type_prefix_list
;
12790 output_arg
= plist
;
12793 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12794 const char *access_list_str
= argv
[++idx
]->arg
;
12795 struct access_list
*alist
;
12797 alist
= access_list_lookup(afi
, access_list_str
);
12799 vty_out(vty
, "%% %s access-list not found\n",
12801 return CMD_WARNING
;
12804 sh_type
= bgp_show_type_access_list
;
12805 output_arg
= alist
;
12808 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12809 const char *rmap_str
= argv
[++idx
]->arg
;
12810 struct route_map
*rmap
;
12812 rmap
= route_map_lookup_by_name(rmap_str
);
12814 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12815 return CMD_WARNING
;
12818 sh_type
= bgp_show_type_route_map
;
12822 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12823 sh_type
= bgp_show_type_rpki
;
12824 if (argv_find(argv
, argc
, "valid", &idx
))
12825 rpki_target_state
= RPKI_VALID
;
12826 else if (argv_find(argv
, argc
, "invalid", &idx
))
12827 rpki_target_state
= RPKI_INVALID
;
12830 /* Display prefixes with matching version numbers */
12831 if (argv_find(argv
, argc
, "version", &idx
)) {
12832 sh_type
= bgp_show_type_prefix_version
;
12833 output_arg
= argv
[idx
+ 1]->arg
;
12836 /* Display prefixes with matching BGP community alias */
12837 if (argv_find(argv
, argc
, "alias", &idx
)) {
12838 sh_type
= bgp_show_type_community_alias
;
12839 output_arg
= argv
[idx
+ 1]->arg
;
12842 /* prefix-longer */
12843 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12844 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12845 const char *prefix_str
= argv
[idx
]->arg
;
12847 if (!str2prefix(prefix_str
, &p
)) {
12848 vty_out(vty
, "%% Malformed Prefix\n");
12849 return CMD_WARNING
;
12852 sh_type
= bgp_show_type_prefix_longer
;
12857 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12859 return bgp_show_community(vty
, bgp
, community
,
12860 exact_match
, afi
, safi
,
12863 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12864 output_arg
, show_flags
,
12865 rpki_target_state
);
12867 struct listnode
*node
;
12869 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12873 vty_out(vty
, "{\n");
12875 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12876 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12877 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12880 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12881 FOREACH_SAFI (safi
) {
12882 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12890 vty_out(vty
, ",\n");
12891 vty_out(vty
, "\"%s\":{\n",
12892 get_afi_safi_str(afi
,
12897 "\nFor address family: %s\n",
12903 bgp_show_community(
12904 vty
, abgp
, community
,
12905 exact_match
, afi
, safi
,
12908 bgp_show(vty
, abgp
, afi
, safi
,
12909 sh_type
, output_arg
,
12911 rpki_target_state
);
12913 vty_out(vty
, "}\n");
12917 /* show <ip> bgp all: for each AFI and SAFI*/
12918 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12919 FOREACH_AFI_SAFI (afi
, safi
) {
12920 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12928 vty_out(vty
, ",\n");
12930 vty_out(vty
, "\"%s\":{\n",
12931 get_afi_safi_str(afi
,
12936 "\nFor address family: %s\n",
12942 bgp_show_community(
12943 vty
, abgp
, community
,
12944 exact_match
, afi
, safi
,
12947 bgp_show(vty
, abgp
, afi
, safi
,
12948 sh_type
, output_arg
,
12950 rpki_target_state
);
12952 vty_out(vty
, "}\n");
12957 vty_out(vty
, "}\n");
12959 return CMD_SUCCESS
;
12962 DEFUN (show_ip_bgp_route
,
12963 show_ip_bgp_route_cmd
,
12964 "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]",
12968 BGP_INSTANCE_HELP_STR
12970 BGP_SAFI_WITH_LABEL_HELP_STR
12971 "Network in the BGP routing table to display\n"
12973 "Network in the BGP routing table to display\n"
12975 "Display only the bestpath\n"
12976 "Display only multipaths\n"
12977 "Display only paths that match the specified rpki state\n"
12978 "A valid path as determined by rpki\n"
12979 "A invalid path as determined by rpki\n"
12980 "A path that has no rpki data\n"
12983 int prefix_check
= 0;
12985 afi_t afi
= AFI_IP6
;
12986 safi_t safi
= SAFI_UNICAST
;
12987 char *prefix
= NULL
;
12988 struct bgp
*bgp
= NULL
;
12989 enum bgp_path_type path_type
;
12990 bool uj
= use_json(argc
, argv
);
12994 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12997 return CMD_WARNING
;
13001 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13002 return CMD_WARNING
;
13005 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13006 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13007 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13009 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13010 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13013 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13014 && afi
!= AFI_IP6
) {
13016 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13017 return CMD_WARNING
;
13019 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13020 && afi
!= AFI_IP
) {
13022 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13023 return CMD_WARNING
;
13026 prefix
= argv
[idx
]->arg
;
13028 /* [<bestpath|multipath>] */
13029 if (argv_find(argv
, argc
, "bestpath", &idx
))
13030 path_type
= BGP_PATH_SHOW_BESTPATH
;
13031 else if (argv_find(argv
, argc
, "multipath", &idx
))
13032 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13034 path_type
= BGP_PATH_SHOW_ALL
;
13036 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13037 path_type
, RPKI_NOT_BEING_USED
, uj
);
13040 DEFUN (show_ip_bgp_regexp
,
13041 show_ip_bgp_regexp_cmd
,
13042 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13046 BGP_INSTANCE_HELP_STR
13048 BGP_SAFI_WITH_LABEL_HELP_STR
13049 "Display routes matching the AS path regular expression\n"
13050 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13053 afi_t afi
= AFI_IP6
;
13054 safi_t safi
= SAFI_UNICAST
;
13055 struct bgp
*bgp
= NULL
;
13056 bool uj
= use_json(argc
, argv
);
13057 char *regstr
= NULL
;
13060 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13063 return CMD_WARNING
;
13065 // get index of regex
13066 if (argv_find(argv
, argc
, "REGEX", &idx
))
13067 regstr
= argv
[idx
]->arg
;
13070 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13071 bgp_show_type_regexp
, uj
);
13074 DEFPY (show_ip_bgp_instance_all
,
13075 show_ip_bgp_instance_all_cmd
,
13076 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13080 BGP_INSTANCE_ALL_HELP_STR
13082 BGP_SAFI_WITH_LABEL_HELP_STR
13084 "Increase table width for longer prefixes\n")
13086 afi_t afi
= AFI_IP6
;
13087 safi_t safi
= SAFI_UNICAST
;
13088 struct bgp
*bgp
= NULL
;
13090 uint16_t show_flags
= 0;
13094 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13098 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13100 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13103 return CMD_WARNING
;
13105 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13106 return CMD_SUCCESS
;
13109 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13110 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13115 uint16_t show_flags
= 0;
13118 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13120 if (!config_bgp_aspath_validate(regstr
)) {
13121 vty_out(vty
, "Invalid character in REGEX %s\n",
13123 return CMD_WARNING_CONFIG_FAILED
;
13126 regex
= bgp_regcomp(regstr
);
13128 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13129 return CMD_WARNING
;
13132 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13133 RPKI_NOT_BEING_USED
);
13134 bgp_regex_free(regex
);
13138 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13139 const char *comstr
, int exact
, afi_t afi
,
13140 safi_t safi
, uint16_t show_flags
)
13142 struct community
*com
;
13145 com
= community_str2com(comstr
);
13147 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13148 return CMD_WARNING
;
13151 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13152 (exact
? bgp_show_type_community_exact
13153 : bgp_show_type_community
),
13154 com
, show_flags
, RPKI_NOT_BEING_USED
);
13155 community_free(&com
);
13161 BGP_STATS_MAXBITLEN
= 0,
13163 BGP_STATS_PREFIXES
,
13165 BGP_STATS_UNAGGREGATEABLE
,
13166 BGP_STATS_MAX_AGGREGATEABLE
,
13167 BGP_STATS_AGGREGATES
,
13169 BGP_STATS_ASPATH_COUNT
,
13170 BGP_STATS_ASPATH_MAXHOPS
,
13171 BGP_STATS_ASPATH_TOTHOPS
,
13172 BGP_STATS_ASPATH_MAXSIZE
,
13173 BGP_STATS_ASPATH_TOTSIZE
,
13174 BGP_STATS_ASN_HIGHEST
,
13178 #define TABLE_STATS_IDX_VTY 0
13179 #define TABLE_STATS_IDX_JSON 1
13181 static const char *table_stats_strs
[][2] = {
13182 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13183 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13184 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13185 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13186 "unaggregateablePrefixes"},
13187 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13188 "maximumAggregateablePrefixes"},
13189 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13190 "bgpAggregateAdvertisements"},
13191 [BGP_STATS_SPACE
] = {"Address space advertised",
13192 "addressSpaceAdvertised"},
13193 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13194 "advertisementsWithPaths"},
13195 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13197 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13199 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13200 "averageAsPathLengthHops"},
13201 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13202 "averageAsPathSizeBytes"},
13203 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13204 [BGP_STATS_MAX
] = {NULL
, NULL
}
13207 struct bgp_table_stats
{
13208 struct bgp_table
*table
;
13209 unsigned long long counts
[BGP_STATS_MAX
];
13212 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13215 double total_space
;
13218 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13219 struct bgp_table_stats
*ts
, unsigned int space
)
13221 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13222 struct bgp_path_info
*pi
;
13223 const struct prefix
*rn_p
;
13225 if (!bgp_dest_has_bgp_path_info_data(dest
))
13228 rn_p
= bgp_dest_get_prefix(dest
);
13229 ts
->counts
[BGP_STATS_PREFIXES
]++;
13230 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13232 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13233 /* check if the prefix is included by any other announcements */
13234 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13235 pdest
= bgp_dest_parent_nolock(pdest
);
13237 if (pdest
== NULL
|| pdest
== top
) {
13238 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13239 /* announced address space */
13241 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13242 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13243 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13246 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13247 ts
->counts
[BGP_STATS_RIB
]++;
13249 if (CHECK_FLAG(pi
->attr
->flag
,
13250 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13251 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13253 /* as-path stats */
13254 if (pi
->attr
->aspath
) {
13255 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13256 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13257 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13259 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13261 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13262 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13264 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13265 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13267 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13268 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13269 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13270 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13275 static void bgp_table_stats_walker(struct thread
*t
)
13277 struct bgp_dest
*dest
, *ndest
;
13278 struct bgp_dest
*top
;
13279 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13280 unsigned int space
= 0;
13282 if (!(top
= bgp_table_top(ts
->table
)))
13285 switch (ts
->table
->afi
) {
13287 space
= IPV4_MAX_BITLEN
;
13290 space
= IPV6_MAX_BITLEN
;
13293 space
= EVPN_ROUTE_PREFIXLEN
;
13300 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13302 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13303 if (ts
->table
->safi
== SAFI_MPLS_VPN
13304 || ts
->table
->safi
== SAFI_ENCAP
13305 || ts
->table
->safi
== SAFI_EVPN
) {
13306 struct bgp_table
*table
;
13308 table
= bgp_dest_get_bgp_table_info(dest
);
13312 top
= bgp_table_top(table
);
13313 for (ndest
= bgp_table_top(table
); ndest
;
13314 ndest
= bgp_route_next(ndest
))
13315 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13317 bgp_table_stats_rn(dest
, top
, ts
, space
);
13322 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13323 struct json_object
*json_array
)
13325 struct listnode
*node
, *nnode
;
13328 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13329 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13332 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13333 safi_t safi
, struct json_object
*json_array
)
13335 struct bgp_table_stats ts
;
13337 int ret
= CMD_SUCCESS
;
13339 struct json_object
*json
= NULL
;
13340 uint32_t bitlen
= 0;
13341 struct json_object
*json_bitlen
;
13344 json
= json_object_new_object();
13346 if (!bgp
->rib
[afi
][safi
]) {
13347 char warning_msg
[50];
13349 snprintf(warning_msg
, sizeof(warning_msg
),
13350 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13354 vty_out(vty
, "%s\n", warning_msg
);
13356 json_object_string_add(json
, "warning", warning_msg
);
13359 goto end_table_stats
;
13363 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13364 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13366 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13368 /* labeled-unicast routes live in the unicast table */
13369 if (safi
== SAFI_LABELED_UNICAST
)
13370 safi
= SAFI_UNICAST
;
13372 memset(&ts
, 0, sizeof(ts
));
13373 ts
.table
= bgp
->rib
[afi
][safi
];
13374 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13376 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13377 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13378 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13382 case BGP_STATS_ASPATH_TOTHOPS
:
13383 case BGP_STATS_ASPATH_TOTSIZE
:
13386 temp_buf
, sizeof(temp_buf
), "%12.2f",
13388 ? (float)ts
.counts
[i
]
13390 [BGP_STATS_ASPATH_COUNT
]
13392 vty_out(vty
, "%-30s: %s",
13393 table_stats_strs
[i
]
13394 [TABLE_STATS_IDX_VTY
],
13397 json_object_double_add(
13399 table_stats_strs
[i
]
13400 [TABLE_STATS_IDX_JSON
],
13402 ? (double)ts
.counts
[i
]
13403 / (double)ts
.counts
13404 [BGP_STATS_ASPATH_COUNT
]
13408 case BGP_STATS_TOTPLEN
:
13411 temp_buf
, sizeof(temp_buf
), "%12.2f",
13413 ? (float)ts
.counts
[i
]
13415 [BGP_STATS_PREFIXES
]
13417 vty_out(vty
, "%-30s: %s",
13418 table_stats_strs
[i
]
13419 [TABLE_STATS_IDX_VTY
],
13422 json_object_double_add(
13424 table_stats_strs
[i
]
13425 [TABLE_STATS_IDX_JSON
],
13427 ? (double)ts
.counts
[i
]
13428 / (double)ts
.counts
13429 [BGP_STATS_PREFIXES
]
13433 case BGP_STATS_SPACE
:
13435 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13437 vty_out(vty
, "%-30s: %s\n",
13438 table_stats_strs
[i
]
13439 [TABLE_STATS_IDX_VTY
],
13442 json_object_double_add(
13444 table_stats_strs
[i
]
13445 [TABLE_STATS_IDX_JSON
],
13446 (double)ts
.total_space
);
13448 if (afi
== AFI_IP6
) {
13450 snprintf(temp_buf
, sizeof(temp_buf
),
13453 * pow(2.0, -128 + 32));
13454 vty_out(vty
, "%30s: %s\n",
13455 "/32 equivalent %s\n",
13458 json_object_double_add(
13459 json
, "/32equivalent",
13460 (double)(ts
.total_space
13465 snprintf(temp_buf
, sizeof(temp_buf
),
13468 * pow(2.0, -128 + 48));
13469 vty_out(vty
, "%30s: %s\n",
13470 "/48 equivalent %s\n",
13473 json_object_double_add(
13474 json
, "/48equivalent",
13475 (double)(ts
.total_space
13481 snprintf(temp_buf
, sizeof(temp_buf
),
13483 ts
.total_space
* 100.
13485 vty_out(vty
, "%30s: %s\n",
13486 "% announced ", temp_buf
);
13488 json_object_double_add(
13489 json
, "%announced",
13490 (double)(ts
.total_space
* 100.
13494 snprintf(temp_buf
, sizeof(temp_buf
),
13497 * pow(2.0, -32 + 8));
13498 vty_out(vty
, "%30s: %s\n",
13499 "/8 equivalent ", temp_buf
);
13501 json_object_double_add(
13502 json
, "/8equivalent",
13503 (double)(ts
.total_space
13504 * pow(2.0, -32 + 8)));
13507 snprintf(temp_buf
, sizeof(temp_buf
),
13510 * pow(2.0, -32 + 24));
13511 vty_out(vty
, "%30s: %s\n",
13512 "/24 equivalent ", temp_buf
);
13514 json_object_double_add(
13515 json
, "/24equivalent",
13516 (double)(ts
.total_space
13517 * pow(2.0, -32 + 24)));
13523 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13525 vty_out(vty
, "%-30s: %s",
13526 table_stats_strs
[i
]
13527 [TABLE_STATS_IDX_VTY
],
13530 json_object_int_add(
13532 table_stats_strs
[i
]
13533 [TABLE_STATS_IDX_JSON
],
13538 vty_out(vty
, "\n");
13543 bitlen
= IPV4_MAX_BITLEN
;
13546 bitlen
= IPV6_MAX_BITLEN
;
13549 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13557 json_bitlen
= json_object_new_array();
13559 for (i
= 0; i
<= bitlen
; i
++) {
13560 struct json_object
*ind_bit
= json_object_new_object();
13562 if (!ts
.prefix_len_count
[i
])
13565 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13566 json_object_int_add(ind_bit
, temp_buf
,
13567 ts
.prefix_len_count
[i
]);
13568 json_object_array_add(json_bitlen
, ind_bit
);
13570 json_object_object_add(json
, "prefixLength", json_bitlen
);
13575 json_object_array_add(json_array
, json
);
13579 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13580 safi_t safi
, struct json_object
*json_array
)
13583 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13584 return CMD_SUCCESS
;
13587 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13599 PCOUNT_BPATH_SELECTED
,
13600 PCOUNT_PFCNT
, /* the figure we display to users */
13604 static const char *const pcount_strs
[] = {
13605 [PCOUNT_ADJ_IN
] = "Adj-in",
13606 [PCOUNT_DAMPED
] = "Damped",
13607 [PCOUNT_REMOVED
] = "Removed",
13608 [PCOUNT_HISTORY
] = "History",
13609 [PCOUNT_STALE
] = "Stale",
13610 [PCOUNT_VALID
] = "Valid",
13611 [PCOUNT_ALL
] = "All RIB",
13612 [PCOUNT_COUNTED
] = "PfxCt counted",
13613 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13614 [PCOUNT_PFCNT
] = "Useable",
13615 [PCOUNT_MAX
] = NULL
,
13618 struct peer_pcounts
{
13619 unsigned int count
[PCOUNT_MAX
];
13620 const struct peer
*peer
;
13621 const struct bgp_table
*table
;
13625 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13627 const struct bgp_adj_in
*ain
;
13628 const struct bgp_path_info
*pi
;
13629 const struct peer
*peer
= pc
->peer
;
13631 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13632 if (ain
->peer
== peer
)
13633 pc
->count
[PCOUNT_ADJ_IN
]++;
13635 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13637 if (pi
->peer
!= peer
)
13640 pc
->count
[PCOUNT_ALL
]++;
13642 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13643 pc
->count
[PCOUNT_DAMPED
]++;
13644 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13645 pc
->count
[PCOUNT_HISTORY
]++;
13646 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13647 pc
->count
[PCOUNT_REMOVED
]++;
13648 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13649 pc
->count
[PCOUNT_STALE
]++;
13650 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13651 pc
->count
[PCOUNT_VALID
]++;
13652 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13653 pc
->count
[PCOUNT_PFCNT
]++;
13654 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13655 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13657 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13658 pc
->count
[PCOUNT_COUNTED
]++;
13659 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13661 EC_LIB_DEVELOPMENT
,
13662 "Attempting to count but flags say it is unusable");
13664 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13666 EC_LIB_DEVELOPMENT
,
13667 "Not counted but flags say we should");
13672 static void bgp_peer_count_walker(struct thread
*t
)
13674 struct bgp_dest
*rn
, *rm
;
13675 const struct bgp_table
*table
;
13676 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13678 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13679 || pc
->safi
== SAFI_EVPN
) {
13680 /* Special handling for 2-level routing tables. */
13681 for (rn
= bgp_table_top(pc
->table
); rn
;
13682 rn
= bgp_route_next(rn
)) {
13683 table
= bgp_dest_get_bgp_table_info(rn
);
13685 for (rm
= bgp_table_top(table
); rm
;
13686 rm
= bgp_route_next(rm
))
13687 bgp_peer_count_proc(rm
, pc
);
13690 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13691 bgp_peer_count_proc(rn
, pc
);
13694 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13695 safi_t safi
, bool use_json
)
13697 struct peer_pcounts pcounts
= {.peer
= peer
};
13699 json_object
*json
= NULL
;
13700 json_object
*json_loop
= NULL
;
13703 json
= json_object_new_object();
13704 json_loop
= json_object_new_object();
13707 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13708 || !peer
->bgp
->rib
[afi
][safi
]) {
13710 json_object_string_add(
13712 "No such neighbor or address family");
13713 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13714 json_object_free(json
);
13715 json_object_free(json_loop
);
13717 vty_out(vty
, "%% No such neighbor or address family\n");
13719 return CMD_WARNING
;
13722 memset(&pcounts
, 0, sizeof(pcounts
));
13723 pcounts
.peer
= peer
;
13724 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13725 pcounts
.safi
= safi
;
13727 /* in-place call via thread subsystem so as to record execution time
13728 * stats for the thread-walk (i.e. ensure this can't be blamed on
13729 * on just vty_read()).
13731 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13734 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13735 json_object_string_add(json
, "multiProtocol",
13736 get_afi_safi_str(afi
, safi
, true));
13737 json_object_int_add(json
, "pfxCounter",
13738 peer
->pcount
[afi
][safi
]);
13740 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13741 json_object_int_add(json_loop
, pcount_strs
[i
],
13744 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13746 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13747 json_object_string_add(json
, "pfxctDriftFor",
13749 json_object_string_add(
13750 json
, "recommended",
13751 "Please report this bug, with the above command output");
13753 vty_json(vty
, json
);
13757 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13758 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13759 peer
->hostname
, peer
->host
,
13760 get_afi_safi_str(afi
, safi
, false));
13762 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13763 get_afi_safi_str(afi
, safi
, false));
13766 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13767 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13769 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13770 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13773 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13774 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13776 "Please report this bug, with the above command output\n");
13780 return CMD_SUCCESS
;
13783 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13784 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13785 "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]",
13789 BGP_INSTANCE_HELP_STR
13792 "Detailed information on TCP and BGP neighbor connections\n"
13793 "Neighbor to display information about\n"
13794 "Neighbor to display information about\n"
13795 "Neighbor on BGP configured interface\n"
13796 "Display detailed prefix count information\n"
13799 afi_t afi
= AFI_IP6
;
13800 safi_t safi
= SAFI_UNICAST
;
13803 struct bgp
*bgp
= NULL
;
13804 bool uj
= use_json(argc
, argv
);
13809 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13812 return CMD_WARNING
;
13814 argv_find(argv
, argc
, "neighbors", &idx
);
13815 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13817 return CMD_WARNING
;
13819 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13822 #ifdef KEEP_OLD_VPN_COMMANDS
13823 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13824 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13825 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13830 "Display information about all VPNv4 NLRIs\n"
13831 "Detailed information on TCP and BGP neighbor connections\n"
13832 "Neighbor to display information about\n"
13833 "Neighbor to display information about\n"
13834 "Neighbor on BGP configured interface\n"
13835 "Display detailed prefix count information\n"
13840 bool uj
= use_json(argc
, argv
);
13842 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13844 return CMD_WARNING
;
13846 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13849 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13850 show_ip_bgp_vpn_all_route_prefix_cmd
,
13851 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13856 "Display information about all VPNv4 NLRIs\n"
13857 "Network in the BGP routing table to display\n"
13858 "Network in the BGP routing table to display\n"
13862 char *network
= NULL
;
13863 struct bgp
*bgp
= bgp_get_default();
13865 vty_out(vty
, "Can't find default instance\n");
13866 return CMD_WARNING
;
13869 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13870 network
= argv
[idx
]->arg
;
13871 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13872 network
= argv
[idx
]->arg
;
13874 vty_out(vty
, "Unable to figure out Network\n");
13875 return CMD_WARNING
;
13878 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13879 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13880 use_json(argc
, argv
));
13882 #endif /* KEEP_OLD_VPN_COMMANDS */
13884 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13885 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13886 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13891 "Network in the BGP routing table to display\n"
13892 "Network in the BGP routing table to display\n"
13893 "Network in the BGP routing table to display\n"
13894 "Network in the BGP routing table to display\n"
13898 char *network
= NULL
;
13899 int prefix_check
= 0;
13901 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13902 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13903 network
= argv
[idx
]->arg
;
13904 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13905 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13906 network
= argv
[idx
]->arg
;
13909 vty_out(vty
, "Unable to figure out Network\n");
13910 return CMD_WARNING
;
13912 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13913 prefix_check
, BGP_PATH_SHOW_ALL
,
13914 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13917 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13918 struct bgp_table
*table
, int *header1
,
13919 int *header2
, json_object
*json
,
13920 json_object
*json_scode
,
13921 json_object
*json_ocode
, bool wide
,
13924 uint64_t version
= table
? table
->version
: 0;
13928 json_object_int_add(json
, "bgpTableVersion", version
);
13929 json_object_string_addf(json
, "bgpLocalRouterId",
13930 "%pI4", &peer
->bgp
->router_id
);
13931 json_object_int_add(json
, "defaultLocPrf",
13932 peer
->bgp
->default_local_pref
);
13933 json_object_int_add(json
, "localAS",
13934 peer
->change_local_as
13935 ? peer
->change_local_as
13937 json_object_object_add(json
, "bgpStatusCodes",
13939 json_object_object_add(json
, "bgpOriginCodes",
13943 "BGP table version is %" PRIu64
13944 ", local router ID is %pI4, vrf id ",
13945 version
, &peer
->bgp
->router_id
);
13946 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
13947 vty_out(vty
, "%s", VRFID_NONE_STR
);
13949 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
13950 vty_out(vty
, "\n");
13951 vty_out(vty
, "Default local pref %u, ",
13952 peer
->bgp
->default_local_pref
);
13953 vty_out(vty
, "local AS %u\n",
13954 peer
->change_local_as
? peer
->change_local_as
13957 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13958 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13959 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13960 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13966 if (!json
&& !detail
)
13967 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13968 : BGP_SHOW_HEADER
));
13974 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13975 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13976 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13977 json_object
*json_scode
, json_object
*json_ocode
,
13978 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13979 unsigned long *output_count
, unsigned long *filtered_count
)
13981 struct bgp_adj_in
*ain
;
13982 struct bgp_adj_out
*adj
;
13983 struct bgp_dest
*dest
;
13987 struct update_subgroup
*subgrp
;
13988 struct peer_af
*paf
;
13989 bool route_filtered
;
13990 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
13991 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13992 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13993 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13994 || (safi
== SAFI_EVPN
))
13998 json_object
*json_net
= NULL
;
14002 subgrp
= peer_subgroup(peer
, afi
, safi
);
14004 if (type
== bgp_show_adj_route_advertised
&& subgrp
14005 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14007 json_object_int_add(json
, "bgpTableVersion",
14009 json_object_string_addf(json
, "bgpLocalRouterId",
14010 "%pI4", &bgp
->router_id
);
14011 json_object_int_add(json
, "defaultLocPrf",
14012 bgp
->default_local_pref
);
14013 json_object_int_add(json
, "localAS",
14014 peer
->change_local_as
14015 ? peer
->change_local_as
14017 json_object_object_add(json
, "bgpStatusCodes",
14019 json_object_object_add(json
, "bgpOriginCodes",
14021 json_object_string_add(
14022 json
, "bgpOriginatingDefaultNetwork",
14023 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14026 "BGP table version is %" PRIu64
14027 ", local router ID is %pI4, vrf id ",
14028 table
->version
, &bgp
->router_id
);
14029 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14030 vty_out(vty
, "%s", VRFID_NONE_STR
);
14032 vty_out(vty
, "%u", bgp
->vrf_id
);
14033 vty_out(vty
, "\n");
14034 vty_out(vty
, "Default local pref %u, ",
14035 bgp
->default_local_pref
);
14036 vty_out(vty
, "local AS %u\n",
14037 peer
->change_local_as
? peer
->change_local_as
14040 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14041 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14042 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14043 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14046 vty_out(vty
, "Originating default network %s\n\n",
14047 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14053 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14054 if (type
== bgp_show_adj_route_received
14055 || type
== bgp_show_adj_route_filtered
) {
14056 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14057 if (ain
->peer
!= peer
)
14060 show_adj_route_header(vty
, peer
, table
, header1
,
14061 header2
, json
, json_scode
,
14062 json_ocode
, wide
, detail
);
14064 if ((safi
== SAFI_MPLS_VPN
)
14065 || (safi
== SAFI_ENCAP
)
14066 || (safi
== SAFI_EVPN
)) {
14068 json_object_string_add(
14069 json_ar
, "rd", rd_str
);
14070 else if (show_rd
&& rd_str
) {
14072 "Route Distinguisher: %s\n",
14079 route_filtered
= false;
14081 /* Filter prefix using distribute list,
14082 * filter list or prefix list
14084 const struct prefix
*rn_p
=
14085 bgp_dest_get_prefix(dest
);
14086 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14089 route_filtered
= true;
14091 /* Filter prefix using route-map */
14092 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14093 safi
, rmap_name
, NULL
,
14096 if (type
== bgp_show_adj_route_filtered
&&
14097 !route_filtered
&& ret
!= RMAP_DENY
) {
14098 bgp_attr_flush(&attr
);
14102 if (type
== bgp_show_adj_route_received
14103 && (route_filtered
|| ret
== RMAP_DENY
))
14104 (*filtered_count
)++;
14109 json_object_new_object();
14110 bgp_show_path_info(
14111 NULL
/* prefix_rd */, dest
, vty
,
14112 bgp
, afi
, safi
, json_net
,
14113 BGP_PATH_SHOW_ALL
, &display
,
14114 RPKI_NOT_BEING_USED
);
14116 json_object_object_addf(
14120 route_vty_out_tmp(vty
, dest
, rn_p
,
14121 &attr
, safi
, use_json
,
14123 bgp_attr_flush(&attr
);
14126 } else if (type
== bgp_show_adj_route_advertised
) {
14127 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14128 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14129 if (paf
->peer
!= peer
|| !adj
->attr
)
14132 show_adj_route_header(
14133 vty
, peer
, table
, header1
,
14134 header2
, json
, json_scode
,
14135 json_ocode
, wide
, detail
);
14137 const struct prefix
*rn_p
=
14138 bgp_dest_get_prefix(dest
);
14141 ret
= bgp_output_modifier(
14142 peer
, rn_p
, &attr
, afi
, safi
,
14145 if (ret
!= RMAP_DENY
) {
14146 if ((safi
== SAFI_MPLS_VPN
)
14147 || (safi
== SAFI_ENCAP
)
14148 || (safi
== SAFI_EVPN
)) {
14150 json_object_string_add(
14157 "Route Distinguisher: %s\n",
14165 json_object_new_object();
14166 bgp_show_path_info(
14175 RPKI_NOT_BEING_USED
);
14177 json_object_object_addf(
14190 (*filtered_count
)++;
14193 bgp_attr_flush(&attr
);
14195 } else if (type
== bgp_show_adj_route_bestpath
) {
14196 struct bgp_path_info
*pi
;
14198 show_adj_route_header(vty
, peer
, table
, header1
,
14199 header2
, json
, json_scode
,
14200 json_ocode
, wide
, detail
);
14202 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14204 if (pi
->peer
!= peer
)
14207 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14210 route_vty_out_tmp(vty
, dest
,
14211 bgp_dest_get_prefix(dest
),
14212 pi
->attr
, safi
, use_json
,
14220 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14221 safi_t safi
, enum bgp_show_adj_route_type type
,
14222 const char *rmap_name
, uint16_t show_flags
)
14225 struct bgp_table
*table
;
14226 json_object
*json
= NULL
;
14227 json_object
*json_scode
= NULL
;
14228 json_object
*json_ocode
= NULL
;
14229 json_object
*json_ar
= NULL
;
14230 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14232 /* Init BGP headers here so they're only displayed once
14233 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14239 * Initialize variables for each RD
14240 * All prefixes under an RD is aggregated within "json_routes"
14242 char rd_str
[BUFSIZ
] = {0};
14243 json_object
*json_routes
= NULL
;
14246 /* For 2-tier tables, prefix counts need to be
14247 * maintained across multiple runs of show_adj_route()
14249 unsigned long output_count_per_rd
;
14250 unsigned long filtered_count_per_rd
;
14251 unsigned long output_count
= 0;
14252 unsigned long filtered_count
= 0;
14255 json
= json_object_new_object();
14256 json_ar
= json_object_new_object();
14257 json_scode
= json_object_new_object();
14258 json_ocode
= json_object_new_object();
14259 #if CONFDATE > 20231208
14260 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14262 json_object_string_add(json_scode
, "suppressed", "s");
14263 json_object_string_add(json_scode
, "damped", "d");
14264 json_object_string_add(json_scode
, "history", "h");
14265 json_object_string_add(json_scode
, "valid", "*");
14266 json_object_string_add(json_scode
, "best", ">");
14267 json_object_string_add(json_scode
, "multipath", "=");
14268 json_object_string_add(json_scode
, "internal", "i");
14269 json_object_string_add(json_scode
, "ribFailure", "r");
14270 json_object_string_add(json_scode
, "stale", "S");
14271 json_object_string_add(json_scode
, "removed", "R");
14273 #if CONFDATE > 20231208
14274 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14276 json_object_string_add(json_ocode
, "igp", "i");
14277 json_object_string_add(json_ocode
, "egp", "e");
14278 json_object_string_add(json_ocode
, "incomplete", "?");
14281 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14283 json_object_string_add(
14285 "No such neighbor or address family");
14286 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14287 json_object_free(json
);
14288 json_object_free(json_ar
);
14289 json_object_free(json_scode
);
14290 json_object_free(json_ocode
);
14292 vty_out(vty
, "%% No such neighbor or address family\n");
14294 return CMD_WARNING
;
14297 if ((type
== bgp_show_adj_route_received
14298 || type
== bgp_show_adj_route_filtered
)
14299 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14300 PEER_FLAG_SOFT_RECONFIG
)) {
14302 json_object_string_add(
14304 "Inbound soft reconfiguration not enabled");
14305 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14306 json_object_free(json
);
14307 json_object_free(json_ar
);
14308 json_object_free(json_scode
);
14309 json_object_free(json_ocode
);
14312 "%% Inbound soft reconfiguration not enabled\n");
14314 return CMD_WARNING
;
14319 /* labeled-unicast routes live in the unicast table */
14320 if (safi
== SAFI_LABELED_UNICAST
)
14321 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14323 table
= bgp
->rib
[afi
][safi
];
14325 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14326 || (safi
== SAFI_EVPN
)) {
14328 struct bgp_dest
*dest
;
14330 for (dest
= bgp_table_top(table
); dest
;
14331 dest
= bgp_route_next(dest
)) {
14332 table
= bgp_dest_get_bgp_table_info(dest
);
14336 output_count_per_rd
= 0;
14337 filtered_count_per_rd
= 0;
14340 json_routes
= json_object_new_object();
14342 const struct prefix_rd
*prd
;
14343 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14346 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
14348 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
14349 rmap_name
, json
, json_routes
, json_scode
,
14350 json_ocode
, show_flags
, &header1
,
14351 &header2
, rd_str
, &output_count_per_rd
,
14352 &filtered_count_per_rd
);
14354 /* Don't include an empty RD in the output! */
14355 if (json_routes
&& (output_count_per_rd
> 0))
14356 json_object_object_add(json_ar
, rd_str
,
14359 output_count
+= output_count_per_rd
;
14360 filtered_count
+= filtered_count_per_rd
;
14363 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14364 json
, json_ar
, json_scode
, json_ocode
,
14365 show_flags
, &header1
, &header2
, rd_str
,
14366 &output_count
, &filtered_count
);
14369 if (type
== bgp_show_adj_route_advertised
)
14370 json_object_object_add(json
, "advertisedRoutes",
14373 json_object_object_add(json
, "receivedRoutes", json_ar
);
14374 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14375 json_object_int_add(json
, "filteredPrefixCounter",
14379 * These fields only give up ownership to `json` when `header1`
14380 * is used (set to zero). See code in `show_adj_route` and
14381 * `show_adj_route_header`.
14383 if (header1
== 1) {
14384 json_object_free(json_scode
);
14385 json_object_free(json_ocode
);
14388 vty_json(vty
, json
);
14389 } else if (output_count
> 0) {
14390 if (filtered_count
> 0)
14392 "\nTotal number of prefixes %ld (%ld filtered)\n",
14393 output_count
, filtered_count
);
14395 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14399 return CMD_SUCCESS
;
14402 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14403 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14404 "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]",
14408 BGP_INSTANCE_HELP_STR
14410 BGP_SAFI_WITH_LABEL_HELP_STR
14411 "Detailed information on TCP and BGP neighbor connections\n"
14412 "Neighbor to display information about\n"
14413 "Neighbor to display information about\n"
14414 "Neighbor on BGP configured interface\n"
14415 "Display the routes selected by best path\n"
14417 "Increase table width for longer prefixes\n")
14419 afi_t afi
= AFI_IP6
;
14420 safi_t safi
= SAFI_UNICAST
;
14421 char *rmap_name
= NULL
;
14422 char *peerstr
= NULL
;
14423 struct bgp
*bgp
= NULL
;
14425 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14427 uint16_t show_flags
= 0;
14430 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14433 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14435 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14439 return CMD_WARNING
;
14441 argv_find(argv
, argc
, "neighbors", &idx
);
14442 peerstr
= argv
[++idx
]->arg
;
14444 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14446 return CMD_WARNING
;
14448 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14452 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14453 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14454 "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]",
14458 BGP_INSTANCE_HELP_STR
14460 BGP_SAFI_WITH_LABEL_HELP_STR
14461 "Display the entries for all address families\n"
14462 "Detailed information on TCP and BGP neighbor connections\n"
14463 "Neighbor to display information about\n"
14464 "Neighbor to display information about\n"
14465 "Neighbor on BGP configured interface\n"
14466 "Display the routes advertised to a BGP neighbor\n"
14467 "Display the received routes from neighbor\n"
14468 "Display the filtered routes received from neighbor\n"
14469 "Route-map to modify the attributes\n"
14470 "Name of the route map\n"
14471 "Display detailed version of routes\n"
14473 "Increase table width for longer prefixes\n")
14475 afi_t afi
= AFI_IP6
;
14476 safi_t safi
= SAFI_UNICAST
;
14477 char *peerstr
= NULL
;
14478 struct bgp
*bgp
= NULL
;
14480 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14483 uint16_t show_flags
= 0;
14484 struct listnode
*node
;
14488 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14492 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14496 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14497 if (argv_find(argv
, argc
, "ipv4", &idx
))
14498 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14500 if (argv_find(argv
, argc
, "ipv6", &idx
))
14501 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14505 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14507 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14510 return CMD_WARNING
;
14512 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14513 argv_find(argv
, argc
, "neighbors", &idx
);
14514 peerstr
= argv
[++idx
]->arg
;
14516 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14518 return CMD_WARNING
;
14520 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14521 type
= bgp_show_adj_route_advertised
;
14522 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14523 type
= bgp_show_adj_route_received
;
14524 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14525 type
= bgp_show_adj_route_filtered
;
14528 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14531 vty_out(vty
, "{\n");
14533 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14534 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14535 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14537 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14538 FOREACH_SAFI (safi
) {
14539 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14546 vty_out(vty
, ",\n");
14547 vty_out(vty
, "\"%s\":",
14548 get_afi_safi_str(afi
, safi
,
14552 "\nFor address family: %s\n",
14553 get_afi_safi_str(afi
, safi
,
14556 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14557 route_map
, show_flags
);
14561 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14562 FOREACH_AFI_SAFI (afi
, safi
) {
14563 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14570 vty_out(vty
, ",\n");
14571 vty_out(vty
, "\"%s\":",
14572 get_afi_safi_str(afi
, safi
,
14576 "\nFor address family: %s\n",
14577 get_afi_safi_str(afi
, safi
,
14580 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14581 route_map
, show_flags
);
14586 vty_out(vty
, "}\n");
14588 return CMD_SUCCESS
;
14591 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14592 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14593 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14597 BGP_INSTANCE_HELP_STR
14600 BGP_AF_MODIFIER_STR
14601 "Detailed information on TCP and BGP neighbor connections\n"
14602 "Neighbor to display information about\n"
14603 "Neighbor to display information about\n"
14604 "Neighbor on BGP configured interface\n"
14605 "Display information received from a BGP neighbor\n"
14606 "Display the prefixlist filter\n"
14609 afi_t afi
= AFI_IP6
;
14610 safi_t safi
= SAFI_UNICAST
;
14611 char *peerstr
= NULL
;
14616 struct bgp
*bgp
= NULL
;
14617 bool uj
= use_json(argc
, argv
);
14622 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14625 return CMD_WARNING
;
14627 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14628 argv_find(argv
, argc
, "neighbors", &idx
);
14629 peerstr
= argv
[++idx
]->arg
;
14631 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14633 return CMD_WARNING
;
14635 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14636 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14639 vty_out(vty
, "Address Family: %s\n",
14640 get_afi_safi_str(afi
, safi
, false));
14641 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14644 vty_out(vty
, "{}\n");
14646 vty_out(vty
, "No functional output\n");
14649 return CMD_SUCCESS
;
14652 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14653 afi_t afi
, safi_t safi
,
14654 enum bgp_show_type type
, bool use_json
)
14656 uint16_t show_flags
= 0;
14659 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14661 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14663 json_object
*json_no
= NULL
;
14664 json_no
= json_object_new_object();
14665 json_object_string_add(
14666 json_no
, "warning",
14667 "No such neighbor or address family");
14668 vty_out(vty
, "%s\n",
14669 json_object_to_json_string(json_no
));
14670 json_object_free(json_no
);
14672 vty_out(vty
, "%% No such neighbor or address family\n");
14673 return CMD_WARNING
;
14676 /* labeled-unicast routes live in the unicast table */
14677 if (safi
== SAFI_LABELED_UNICAST
)
14678 safi
= SAFI_UNICAST
;
14680 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14681 RPKI_NOT_BEING_USED
);
14684 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14685 show_ip_bgp_flowspec_routes_detailed_cmd
,
14686 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14690 BGP_INSTANCE_HELP_STR
14693 "Detailed information on flowspec entries\n"
14696 afi_t afi
= AFI_IP6
;
14697 safi_t safi
= SAFI_UNICAST
;
14698 struct bgp
*bgp
= NULL
;
14700 bool uj
= use_json(argc
, argv
);
14701 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14705 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14708 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14711 return CMD_WARNING
;
14713 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14714 show_flags
, RPKI_NOT_BEING_USED
);
14717 DEFUN (show_ip_bgp_neighbor_routes
,
14718 show_ip_bgp_neighbor_routes_cmd
,
14719 "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]",
14723 BGP_INSTANCE_HELP_STR
14725 BGP_SAFI_WITH_LABEL_HELP_STR
14726 "Detailed information on TCP and BGP neighbor connections\n"
14727 "Neighbor to display information about\n"
14728 "Neighbor to display information about\n"
14729 "Neighbor on BGP configured interface\n"
14730 "Display flap statistics of the routes learned from neighbor\n"
14731 "Display the dampened routes received from neighbor\n"
14732 "Display routes learned from neighbor\n"
14735 char *peerstr
= NULL
;
14736 struct bgp
*bgp
= NULL
;
14737 afi_t afi
= AFI_IP6
;
14738 safi_t safi
= SAFI_UNICAST
;
14740 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14742 bool uj
= use_json(argc
, argv
);
14747 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14750 return CMD_WARNING
;
14752 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14753 argv_find(argv
, argc
, "neighbors", &idx
);
14754 peerstr
= argv
[++idx
]->arg
;
14756 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14758 return CMD_WARNING
;
14760 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14761 sh_type
= bgp_show_type_flap_neighbor
;
14762 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14763 sh_type
= bgp_show_type_damp_neighbor
;
14764 else if (argv_find(argv
, argc
, "routes", &idx
))
14765 sh_type
= bgp_show_type_neighbor
;
14767 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14770 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14772 struct bgp_distance
{
14773 /* Distance value for the IP source prefix. */
14776 /* Name of the access-list to be matched. */
14780 DEFUN (show_bgp_afi_vpn_rd_route
,
14781 show_bgp_afi_vpn_rd_route_cmd
,
14782 "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]",
14786 BGP_AF_MODIFIER_STR
14787 "Display information for a route distinguisher\n"
14788 "Route Distinguisher\n"
14789 "All Route Distinguishers\n"
14790 "Network in the BGP routing table to display\n"
14791 "Network in the BGP routing table to display\n"
14795 struct prefix_rd prd
;
14796 afi_t afi
= AFI_MAX
;
14799 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14800 vty_out(vty
, "%% Malformed Address Family\n");
14801 return CMD_WARNING
;
14804 if (!strcmp(argv
[5]->arg
, "all"))
14805 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14806 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14807 RPKI_NOT_BEING_USED
,
14808 use_json(argc
, argv
));
14810 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14812 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14813 return CMD_WARNING
;
14816 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14817 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14818 use_json(argc
, argv
));
14821 static struct bgp_distance
*bgp_distance_new(void)
14823 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14826 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14828 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14831 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14832 const char *ip_str
, const char *access_list_str
)
14839 struct bgp_dest
*dest
;
14840 struct bgp_distance
*bdistance
;
14842 afi
= bgp_node_afi(vty
);
14843 safi
= bgp_node_safi(vty
);
14845 ret
= str2prefix(ip_str
, &p
);
14847 vty_out(vty
, "Malformed prefix\n");
14848 return CMD_WARNING_CONFIG_FAILED
;
14851 distance
= atoi(distance_str
);
14853 /* Get BGP distance node. */
14854 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14855 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14857 bgp_dest_unlock_node(dest
);
14859 bdistance
= bgp_distance_new();
14860 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14863 /* Set distance value. */
14864 bdistance
->distance
= distance
;
14866 /* Reset access-list configuration. */
14867 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14868 if (access_list_str
)
14869 bdistance
->access_list
=
14870 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14872 return CMD_SUCCESS
;
14875 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14876 const char *ip_str
, const char *access_list_str
)
14883 struct bgp_dest
*dest
;
14884 struct bgp_distance
*bdistance
;
14886 afi
= bgp_node_afi(vty
);
14887 safi
= bgp_node_safi(vty
);
14889 ret
= str2prefix(ip_str
, &p
);
14891 vty_out(vty
, "Malformed prefix\n");
14892 return CMD_WARNING_CONFIG_FAILED
;
14895 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14897 vty_out(vty
, "Can't find specified prefix\n");
14898 return CMD_WARNING_CONFIG_FAILED
;
14901 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14902 distance
= atoi(distance_str
);
14904 if (bdistance
->distance
!= distance
) {
14905 vty_out(vty
, "Distance does not match configured\n");
14906 bgp_dest_unlock_node(dest
);
14907 return CMD_WARNING_CONFIG_FAILED
;
14910 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14911 bgp_distance_free(bdistance
);
14913 bgp_dest_set_bgp_path_info(dest
, NULL
);
14914 bgp_dest_unlock_node(dest
);
14915 bgp_dest_unlock_node(dest
);
14917 return CMD_SUCCESS
;
14920 /* Apply BGP information to distance method. */
14921 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14922 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14924 struct bgp_dest
*dest
;
14925 struct prefix q
= {0};
14927 struct bgp_distance
*bdistance
;
14928 struct access_list
*alist
;
14929 struct bgp_static
*bgp_static
;
14930 struct bgp_path_info
*bpi_ultimate
;
14935 peer
= pinfo
->peer
;
14937 if (pinfo
->attr
->distance
)
14938 return pinfo
->attr
->distance
;
14940 /* get peer origin to calculate appropriate distance */
14941 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
14942 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
14943 peer
= bpi_ultimate
->peer
;
14946 /* Check source address.
14947 * Note: for aggregate route, peer can have unspec af type.
14949 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14950 && !sockunion2hostprefix(&peer
->su
, &q
))
14953 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14955 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14956 bgp_dest_unlock_node(dest
);
14958 if (bdistance
->access_list
) {
14959 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14961 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14962 return bdistance
->distance
;
14964 return bdistance
->distance
;
14967 /* Backdoor check. */
14968 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14970 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14971 bgp_dest_unlock_node(dest
);
14973 if (bgp_static
->backdoor
) {
14974 if (bgp
->distance_local
[afi
][safi
])
14975 return bgp
->distance_local
[afi
][safi
];
14977 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14981 if (peer
->sort
== BGP_PEER_EBGP
) {
14982 if (bgp
->distance_ebgp
[afi
][safi
])
14983 return bgp
->distance_ebgp
[afi
][safi
];
14984 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14985 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14986 if (bgp
->distance_ibgp
[afi
][safi
])
14987 return bgp
->distance_ibgp
[afi
][safi
];
14988 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14990 if (bgp
->distance_local
[afi
][safi
])
14991 return bgp
->distance_local
[afi
][safi
];
14992 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14996 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14997 * we should tell ZEBRA update the routes for a specific
14998 * AFI/SAFI to reflect changes in RIB.
15000 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15002 safi_t update_safi
)
15007 FOREACH_AFI_SAFI (afi
, safi
) {
15008 if (!bgp_fibupd_safi(safi
))
15011 if (afi
!= update_afi
&& safi
!= update_safi
)
15014 if (BGP_DEBUG(zebra
, ZEBRA
))
15016 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15017 __func__
, afi
, safi
);
15018 bgp_zebra_announce_table(bgp
, afi
, safi
);
15022 DEFUN (bgp_distance
,
15024 "distance bgp (1-255) (1-255) (1-255)",
15025 "Define an administrative distance\n"
15027 "Distance for routes external to the AS\n"
15028 "Distance for routes internal to the AS\n"
15029 "Distance for local routes\n")
15031 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15032 int idx_number
= 2;
15033 int idx_number_2
= 3;
15034 int idx_number_3
= 4;
15035 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15036 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15037 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15041 afi
= bgp_node_afi(vty
);
15042 safi
= bgp_node_safi(vty
);
15044 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15045 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15046 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15047 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15048 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15049 bgp
->distance_local
[afi
][safi
] = distance_local
;
15050 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15052 return CMD_SUCCESS
;
15055 DEFUN (no_bgp_distance
,
15056 no_bgp_distance_cmd
,
15057 "no distance bgp [(1-255) (1-255) (1-255)]",
15059 "Define an administrative distance\n"
15061 "Distance for routes external to the AS\n"
15062 "Distance for routes internal to the AS\n"
15063 "Distance for local routes\n")
15065 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15069 afi
= bgp_node_afi(vty
);
15070 safi
= bgp_node_safi(vty
);
15072 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15073 || bgp
->distance_ibgp
[afi
][safi
] != 0
15074 || bgp
->distance_local
[afi
][safi
] != 0) {
15075 bgp
->distance_ebgp
[afi
][safi
] = 0;
15076 bgp
->distance_ibgp
[afi
][safi
] = 0;
15077 bgp
->distance_local
[afi
][safi
] = 0;
15078 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15080 return CMD_SUCCESS
;
15084 DEFUN (bgp_distance_source
,
15085 bgp_distance_source_cmd
,
15086 "distance (1-255) A.B.C.D/M",
15087 "Define an administrative distance\n"
15088 "Administrative distance\n"
15089 "IP source prefix\n")
15091 int idx_number
= 1;
15092 int idx_ipv4_prefixlen
= 2;
15093 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15094 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15095 return CMD_SUCCESS
;
15098 DEFUN (no_bgp_distance_source
,
15099 no_bgp_distance_source_cmd
,
15100 "no distance (1-255) A.B.C.D/M",
15102 "Define an administrative distance\n"
15103 "Administrative distance\n"
15104 "IP source prefix\n")
15106 int idx_number
= 2;
15107 int idx_ipv4_prefixlen
= 3;
15108 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15109 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15110 return CMD_SUCCESS
;
15113 DEFUN (bgp_distance_source_access_list
,
15114 bgp_distance_source_access_list_cmd
,
15115 "distance (1-255) A.B.C.D/M WORD",
15116 "Define an administrative distance\n"
15117 "Administrative distance\n"
15118 "IP source prefix\n"
15119 "Access list name\n")
15121 int idx_number
= 1;
15122 int idx_ipv4_prefixlen
= 2;
15124 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15125 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15126 return CMD_SUCCESS
;
15129 DEFUN (no_bgp_distance_source_access_list
,
15130 no_bgp_distance_source_access_list_cmd
,
15131 "no distance (1-255) A.B.C.D/M WORD",
15133 "Define an administrative distance\n"
15134 "Administrative distance\n"
15135 "IP source prefix\n"
15136 "Access list name\n")
15138 int idx_number
= 2;
15139 int idx_ipv4_prefixlen
= 3;
15141 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15142 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15143 return CMD_SUCCESS
;
15146 DEFUN (ipv6_bgp_distance_source
,
15147 ipv6_bgp_distance_source_cmd
,
15148 "distance (1-255) X:X::X:X/M",
15149 "Define an administrative distance\n"
15150 "Administrative distance\n"
15151 "IP source prefix\n")
15153 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15154 return CMD_SUCCESS
;
15157 DEFUN (no_ipv6_bgp_distance_source
,
15158 no_ipv6_bgp_distance_source_cmd
,
15159 "no distance (1-255) X:X::X:X/M",
15161 "Define an administrative distance\n"
15162 "Administrative distance\n"
15163 "IP source prefix\n")
15165 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15166 return CMD_SUCCESS
;
15169 DEFUN (ipv6_bgp_distance_source_access_list
,
15170 ipv6_bgp_distance_source_access_list_cmd
,
15171 "distance (1-255) X:X::X:X/M WORD",
15172 "Define an administrative distance\n"
15173 "Administrative distance\n"
15174 "IP source prefix\n"
15175 "Access list name\n")
15177 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15178 return CMD_SUCCESS
;
15181 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15182 no_ipv6_bgp_distance_source_access_list_cmd
,
15183 "no distance (1-255) X:X::X:X/M WORD",
15185 "Define an administrative distance\n"
15186 "Administrative distance\n"
15187 "IP source prefix\n"
15188 "Access list name\n")
15190 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15191 return CMD_SUCCESS
;
15194 DEFUN (bgp_damp_set
,
15196 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15197 "BGP Specific commands\n"
15198 "Enable route-flap dampening\n"
15199 "Half-life time for the penalty\n"
15200 "Value to start reusing a route\n"
15201 "Value to start suppressing a route\n"
15202 "Maximum duration to suppress a stable route\n")
15204 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15205 int idx_half_life
= 2;
15207 int idx_suppress
= 4;
15208 int idx_max_suppress
= 5;
15209 int half
= DEFAULT_HALF_LIFE
* 60;
15210 int reuse
= DEFAULT_REUSE
;
15211 int suppress
= DEFAULT_SUPPRESS
;
15212 int max
= 4 * half
;
15215 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15216 reuse
= atoi(argv
[idx_reuse
]->arg
);
15217 suppress
= atoi(argv
[idx_suppress
]->arg
);
15218 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15219 } else if (argc
== 3) {
15220 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15225 * These can't be 0 but our SA doesn't understand the
15226 * way our cli is constructed
15230 if (suppress
< reuse
) {
15232 "Suppress value cannot be less than reuse value \n");
15236 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15237 reuse
, suppress
, max
);
15240 DEFUN (bgp_damp_unset
,
15241 bgp_damp_unset_cmd
,
15242 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15244 "BGP Specific commands\n"
15245 "Enable route-flap dampening\n"
15246 "Half-life time for the penalty\n"
15247 "Value to start reusing a route\n"
15248 "Value to start suppressing a route\n"
15249 "Maximum duration to suppress a stable route\n")
15251 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15252 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15255 /* Display specified route of BGP table. */
15256 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15257 const char *ip_str
, afi_t afi
, safi_t safi
,
15258 struct prefix_rd
*prd
, int prefix_check
)
15261 struct prefix match
;
15262 struct bgp_dest
*dest
;
15263 struct bgp_dest
*rm
;
15264 struct bgp_path_info
*pi
;
15265 struct bgp_path_info
*pi_temp
;
15267 struct bgp_table
*table
;
15269 /* BGP structure lookup. */
15271 bgp
= bgp_lookup_by_name(view_name
);
15273 vty_out(vty
, "%% Can't find BGP instance %s\n",
15275 return CMD_WARNING
;
15278 bgp
= bgp_get_default();
15280 vty_out(vty
, "%% No BGP process is configured\n");
15281 return CMD_WARNING
;
15285 /* Check IP address argument. */
15286 ret
= str2prefix(ip_str
, &match
);
15288 vty_out(vty
, "%% address is malformed\n");
15289 return CMD_WARNING
;
15292 match
.family
= afi2family(afi
);
15294 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15295 || (safi
== SAFI_EVPN
)) {
15296 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15297 dest
= bgp_route_next(dest
)) {
15298 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15300 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15302 table
= bgp_dest_get_bgp_table_info(dest
);
15305 rm
= bgp_node_match(table
, &match
);
15309 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15312 || rm_p
->prefixlen
== match
.prefixlen
) {
15313 pi
= bgp_dest_get_bgp_path_info(rm
);
15315 if (pi
->extra
&& pi
->extra
->damp_info
) {
15316 pi_temp
= pi
->next
;
15317 bgp_damp_info_free(
15318 pi
->extra
->damp_info
,
15326 bgp_dest_unlock_node(rm
);
15329 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15330 if (dest
!= NULL
) {
15331 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15334 || dest_p
->prefixlen
== match
.prefixlen
) {
15335 pi
= bgp_dest_get_bgp_path_info(dest
);
15337 if (pi
->extra
&& pi
->extra
->damp_info
) {
15338 pi_temp
= pi
->next
;
15339 bgp_damp_info_free(
15340 pi
->extra
->damp_info
,
15348 bgp_dest_unlock_node(dest
);
15352 return CMD_SUCCESS
;
15355 DEFUN (clear_ip_bgp_dampening
,
15356 clear_ip_bgp_dampening_cmd
,
15357 "clear ip bgp dampening",
15361 "Clear route flap dampening information\n")
15363 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15364 return CMD_SUCCESS
;
15367 DEFUN (clear_ip_bgp_dampening_prefix
,
15368 clear_ip_bgp_dampening_prefix_cmd
,
15369 "clear ip bgp dampening A.B.C.D/M",
15373 "Clear route flap dampening information\n"
15376 int idx_ipv4_prefixlen
= 4;
15377 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15378 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15381 DEFUN (clear_ip_bgp_dampening_address
,
15382 clear_ip_bgp_dampening_address_cmd
,
15383 "clear ip bgp dampening A.B.C.D",
15387 "Clear route flap dampening information\n"
15388 "Network to clear damping information\n")
15391 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15392 SAFI_UNICAST
, NULL
, 0);
15395 DEFUN (clear_ip_bgp_dampening_address_mask
,
15396 clear_ip_bgp_dampening_address_mask_cmd
,
15397 "clear ip bgp dampening A.B.C.D A.B.C.D",
15401 "Clear route flap dampening information\n"
15402 "Network to clear damping information\n"
15406 int idx_ipv4_2
= 5;
15408 char prefix_str
[BUFSIZ
];
15410 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15411 prefix_str
, sizeof(prefix_str
));
15413 vty_out(vty
, "%% Inconsistent address and mask\n");
15414 return CMD_WARNING
;
15417 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15421 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15423 struct vty
*vty
= arg
;
15424 struct peer
*peer
= bucket
->data
;
15426 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15429 DEFUN (show_bgp_listeners
,
15430 show_bgp_listeners_cmd
,
15431 "show bgp listeners",
15434 "Display Listen Sockets and who created them\n")
15436 bgp_dump_listener_info(vty
);
15438 return CMD_SUCCESS
;
15441 DEFUN (show_bgp_peerhash
,
15442 show_bgp_peerhash_cmd
,
15443 "show bgp peerhash",
15446 "Display information about the BGP peerhash\n")
15448 struct list
*instances
= bm
->bgp
;
15449 struct listnode
*node
;
15452 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15453 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15454 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15458 return CMD_SUCCESS
;
15461 /* also used for encap safi */
15462 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15463 afi_t afi
, safi_t safi
)
15465 struct bgp_dest
*pdest
;
15466 struct bgp_dest
*dest
;
15467 struct bgp_table
*table
;
15468 const struct prefix
*p
;
15469 const struct prefix_rd
*prd
;
15470 struct bgp_static
*bgp_static
;
15471 mpls_label_t label
;
15473 /* Network configuration. */
15474 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15475 pdest
= bgp_route_next(pdest
)) {
15476 table
= bgp_dest_get_bgp_table_info(pdest
);
15480 for (dest
= bgp_table_top(table
); dest
;
15481 dest
= bgp_route_next(dest
)) {
15482 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15483 if (bgp_static
== NULL
)
15486 p
= bgp_dest_get_prefix(dest
);
15487 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
15490 /* "network" configuration display. */
15491 label
= decode_label(&bgp_static
->label
);
15493 vty_out(vty
, " network %pFX rd %pRD", p
, prd
);
15494 if (safi
== SAFI_MPLS_VPN
)
15495 vty_out(vty
, " label %u", label
);
15497 if (bgp_static
->rmap
.name
)
15498 vty_out(vty
, " route-map %s",
15499 bgp_static
->rmap
.name
);
15501 if (bgp_static
->backdoor
)
15502 vty_out(vty
, " backdoor");
15504 vty_out(vty
, "\n");
15509 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15510 afi_t afi
, safi_t safi
)
15512 struct bgp_dest
*pdest
;
15513 struct bgp_dest
*dest
;
15514 struct bgp_table
*table
;
15515 const struct prefix
*p
;
15516 const struct prefix_rd
*prd
;
15517 struct bgp_static
*bgp_static
;
15518 char buf
[PREFIX_STRLEN
* 2];
15519 char buf2
[SU_ADDRSTRLEN
];
15520 char esi_buf
[ESI_STR_LEN
];
15522 /* Network configuration. */
15523 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15524 pdest
= bgp_route_next(pdest
)) {
15525 table
= bgp_dest_get_bgp_table_info(pdest
);
15529 for (dest
= bgp_table_top(table
); dest
;
15530 dest
= bgp_route_next(dest
)) {
15531 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15532 if (bgp_static
== NULL
)
15535 char *macrouter
= NULL
;
15537 if (bgp_static
->router_mac
)
15538 macrouter
= prefix_mac2str(
15539 bgp_static
->router_mac
, NULL
, 0);
15540 if (bgp_static
->eth_s_id
)
15541 esi_to_str(bgp_static
->eth_s_id
,
15542 esi_buf
, sizeof(esi_buf
));
15543 p
= bgp_dest_get_prefix(dest
);
15544 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15546 /* "network" configuration display. */
15547 if (p
->u
.prefix_evpn
.route_type
== 5) {
15548 char local_buf
[PREFIX_STRLEN
];
15550 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15551 struct prefix_evpn
*)p
)
15555 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15557 local_buf
, sizeof(local_buf
));
15558 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15559 p
->u
.prefix_evpn
.prefix_addr
15560 .ip_prefix_length
);
15562 prefix2str(p
, buf
, sizeof(buf
));
15565 if (bgp_static
->gatewayIp
.family
== AF_INET
15566 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15567 inet_ntop(bgp_static
->gatewayIp
.family
,
15568 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15571 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15572 buf
, prd
, p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15573 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15576 XFREE(MTYPE_TMP
, macrouter
);
15581 /* Configuration of static route announcement and aggregate
15583 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15586 struct bgp_dest
*dest
;
15587 const struct prefix
*p
;
15588 struct bgp_static
*bgp_static
;
15589 struct bgp_aggregate
*bgp_aggregate
;
15591 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15592 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15596 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15597 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15601 /* Network configuration. */
15602 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15603 dest
= bgp_route_next(dest
)) {
15604 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15605 if (bgp_static
== NULL
)
15608 p
= bgp_dest_get_prefix(dest
);
15610 vty_out(vty
, " network %pFX", p
);
15612 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15613 vty_out(vty
, " label-index %u",
15614 bgp_static
->label_index
);
15616 if (bgp_static
->rmap
.name
)
15617 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15619 if (bgp_static
->backdoor
)
15620 vty_out(vty
, " backdoor");
15622 vty_out(vty
, "\n");
15625 /* Aggregate-address configuration. */
15626 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15627 dest
= bgp_route_next(dest
)) {
15628 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15629 if (bgp_aggregate
== NULL
)
15632 p
= bgp_dest_get_prefix(dest
);
15634 vty_out(vty
, " aggregate-address %pFX", p
);
15636 if (bgp_aggregate
->as_set
)
15637 vty_out(vty
, " as-set");
15639 if (bgp_aggregate
->summary_only
)
15640 vty_out(vty
, " summary-only");
15642 if (bgp_aggregate
->rmap
.name
)
15643 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15645 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15646 vty_out(vty
, " origin %s",
15647 bgp_origin2str(bgp_aggregate
->origin
));
15649 if (bgp_aggregate
->match_med
)
15650 vty_out(vty
, " matching-MED-only");
15652 if (bgp_aggregate
->suppress_map_name
)
15653 vty_out(vty
, " suppress-map %s",
15654 bgp_aggregate
->suppress_map_name
);
15656 vty_out(vty
, "\n");
15660 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15663 struct bgp_dest
*dest
;
15664 struct bgp_distance
*bdistance
;
15666 /* Distance configuration. */
15667 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15668 && bgp
->distance_local
[afi
][safi
]
15669 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15670 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15671 || bgp
->distance_local
[afi
][safi
]
15672 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15673 vty_out(vty
, " distance bgp %d %d %d\n",
15674 bgp
->distance_ebgp
[afi
][safi
],
15675 bgp
->distance_ibgp
[afi
][safi
],
15676 bgp
->distance_local
[afi
][safi
]);
15679 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15680 dest
= bgp_route_next(dest
)) {
15681 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15682 if (bdistance
!= NULL
)
15683 vty_out(vty
, " distance %d %pBD %s\n",
15684 bdistance
->distance
, dest
,
15685 bdistance
->access_list
? bdistance
->access_list
15690 /* Allocate routing table structure and install commands. */
15691 void bgp_route_init(void)
15696 /* Init BGP distance table. */
15697 FOREACH_AFI_SAFI (afi
, safi
)
15698 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15700 /* IPv4 BGP commands. */
15701 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15702 install_element(BGP_NODE
, &bgp_network_cmd
);
15703 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15705 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15707 /* IPv4 unicast configuration. */
15708 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15709 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15710 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15712 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15714 /* IPv4 multicast configuration. */
15715 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15716 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15717 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15718 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15720 /* IPv4 labeled-unicast configuration. */
15721 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15722 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15724 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15725 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15726 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15727 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15728 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15729 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15730 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15731 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15733 install_element(VIEW_NODE
,
15734 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15735 install_element(VIEW_NODE
,
15736 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15737 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15738 install_element(VIEW_NODE
,
15739 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15740 #ifdef KEEP_OLD_VPN_COMMANDS
15741 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15742 #endif /* KEEP_OLD_VPN_COMMANDS */
15743 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15744 install_element(VIEW_NODE
,
15745 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15747 /* BGP dampening clear commands */
15748 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15749 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15751 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15752 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15755 install_element(ENABLE_NODE
,
15756 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15757 #ifdef KEEP_OLD_VPN_COMMANDS
15758 install_element(ENABLE_NODE
,
15759 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15760 #endif /* KEEP_OLD_VPN_COMMANDS */
15762 /* New config IPv6 BGP commands. */
15763 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15764 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15765 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15767 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15769 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15771 /* IPv6 labeled unicast address family. */
15772 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15773 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15775 install_element(BGP_NODE
, &bgp_distance_cmd
);
15776 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15777 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15778 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15779 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15780 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15781 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15782 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15783 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15784 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15785 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15786 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15787 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15788 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15789 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15790 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15791 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15792 install_element(BGP_IPV4M_NODE
,
15793 &no_bgp_distance_source_access_list_cmd
);
15794 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15795 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15796 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15797 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15798 install_element(BGP_IPV6_NODE
,
15799 &ipv6_bgp_distance_source_access_list_cmd
);
15800 install_element(BGP_IPV6_NODE
,
15801 &no_ipv6_bgp_distance_source_access_list_cmd
);
15802 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15803 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15804 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15805 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15806 install_element(BGP_IPV6M_NODE
,
15807 &ipv6_bgp_distance_source_access_list_cmd
);
15808 install_element(BGP_IPV6M_NODE
,
15809 &no_ipv6_bgp_distance_source_access_list_cmd
);
15811 /* BGP dampening */
15812 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15813 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15814 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15815 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15816 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15817 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15818 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15819 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15820 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15821 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15822 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15823 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15824 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15825 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15827 /* Large Communities */
15828 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15829 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15831 /* show bgp ipv4 flowspec detailed */
15832 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15834 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15835 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15838 void bgp_route_finish(void)
15843 FOREACH_AFI_SAFI (afi
, safi
) {
15844 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15845 bgp_distance_table
[afi
][safi
] = NULL
;