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 attr
->mp_nexthop_len
=
2277 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2280 /* Clear off link-local nexthop in source, whenever it is not
2282 * ensure more prefixes share the same attribute for
2285 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2286 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2287 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2290 if (bgp_check_role_applicability(afi
, safi
) &&
2291 bgp_otc_egress(peer
, attr
))
2294 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2295 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2297 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2298 filter
->advmap
.aname
&&
2299 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2300 struct bgp_path_info rmap_path
= {0};
2301 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2302 struct attr dummy_attr
= *attr
;
2304 /* Fill temp path_info */
2305 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2306 pi
, peer
, &dummy_attr
);
2308 struct route_map
*amap
=
2309 route_map_lookup_by_name(filter
->advmap
.aname
);
2311 ret
= route_map_apply(amap
, p
, &rmap_path
);
2313 bgp_attr_flush(&dummy_attr
);
2316 * The conditional advertisement mode is Withdraw and this
2317 * prefix is a conditional prefix. Don't advertise it
2319 if (ret
== RMAP_PERMITMATCH
)
2323 /* Route map & unsuppress-map apply. */
2325 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2326 struct bgp_path_info rmap_path
= {0};
2327 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2328 struct attr dummy_attr
= {0};
2330 /* Fill temp path_info */
2331 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2334 /* don't confuse inbound and outbound setting */
2335 RESET_FLAG(attr
->rmap_change_flags
);
2338 * The route reflector is not allowed to modify the attributes
2339 * of the reflected IBGP routes unless explicitly allowed.
2341 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2342 && !CHECK_FLAG(bgp
->flags
,
2343 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2345 rmap_path
.attr
= &dummy_attr
;
2348 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2350 if (bgp_path_suppressed(pi
))
2351 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2354 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2357 bgp_attr_flush(&dummy_attr
);
2358 peer
->rmap_type
= 0;
2360 if (ret
== RMAP_DENYMATCH
) {
2361 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2363 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2364 peer
, p
, ROUTE_MAP_OUT_NAME(filter
));
2365 bgp_attr_flush(rmap_path
.attr
);
2370 /* RFC 8212 to prevent route leaks.
2371 * This specification intends to improve this situation by requiring the
2372 * explicit configuration of both BGP Import and Export Policies for any
2373 * External BGP (EBGP) session such as customers, peers, or
2374 * confederation boundaries for all enabled address families. Through
2375 * codification of the aforementioned requirement, operators will
2376 * benefit from consistent behavior across different BGP
2379 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2380 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2381 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2382 NULL
) > FIFTEENMINUTE2USEC
||
2383 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2385 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2386 monotime(&bgp
->ebgprequirespolicywarning
);
2391 /* draft-ietf-idr-deprecate-as-set-confed-set
2392 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2393 * Eventually, This document (if approved) updates RFC 4271
2394 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2395 * and obsoletes RFC 6472.
2397 if (peer
->bgp
->reject_as_sets
)
2398 if (aspath_check_as_sets(attr
->aspath
))
2401 /* If neighbor soo is configured, then check if the route has
2402 * SoO extended community and validate against the configured
2403 * one. If they match, do not announce, to prevent routing
2406 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2407 peer
->soo
[afi
][safi
]) {
2408 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2409 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2411 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2412 ECOMMUNITY_SITE_ORIGIN
) ||
2413 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2414 ECOMMUNITY_SITE_ORIGIN
) ||
2415 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2416 ECOMMUNITY_SITE_ORIGIN
)) &&
2417 ecommunity_include(ecomm
, ecomm_soo
)) {
2418 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2420 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2421 peer
, p
, ecommunity_str(ecomm_soo
));
2426 /* Codification of AS 0 Processing */
2427 if (aspath_check_as_zero(attr
->aspath
))
2430 if (bgp_in_graceful_shutdown(bgp
)) {
2431 if (peer
->sort
== BGP_PEER_IBGP
2432 || peer
->sort
== BGP_PEER_CONFED
) {
2433 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2434 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2436 bgp_attr_add_gshut_community(attr
);
2440 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2441 * Capability" to a neighbor MUST perform the following upon receiving
2442 * a route from that neighbor with the "LLGR_STALE" community, or upon
2443 * attaching the "LLGR_STALE" community itself per Section 4.2:
2445 * The route SHOULD NOT be advertised to any neighbor from which the
2446 * Long-lived Graceful Restart Capability has not been received.
2448 if (bgp_attr_get_community(attr
) &&
2449 community_include(bgp_attr_get_community(attr
),
2450 COMMUNITY_LLGR_STALE
) &&
2451 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2452 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2455 /* After route-map has been applied, we check to see if the nexthop to
2456 * be carried in the attribute (that is used for the announcement) can
2457 * be cleared off or not. We do this in all cases where we would be
2458 * setting the nexthop to "ourselves". For IPv6, we only need to
2460 * the global nexthop here; the link-local nexthop would have been
2462 * already, and if not, it is required by the update formation code.
2463 * Also see earlier comments in this function.
2466 * If route-map has performed some operation on the nexthop or the peer
2467 * configuration says to pass it unchanged, we cannot reset the nexthop
2468 * here, so only attempt to do it if these aren't true. Note that the
2469 * route-map handler itself might have cleared the nexthop, if for
2471 * it is configured as 'peer-address'.
2473 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2474 piattr
->rmap_change_flags
)
2476 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2477 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2478 /* We can reset the nexthop, if setting (or forcing) it to
2480 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2481 PEER_FLAG_NEXTHOP_SELF
)
2482 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2483 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2485 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2486 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2487 subgroup_announce_reset_nhop(
2488 (peer_cap_enhe(peer
, afi
, safi
)
2494 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2495 /* Can also reset the nexthop if announcing to EBGP, but
2497 * no peer in the subgroup is on a shared subnet.
2498 * Note: 3rd party nexthop currently implemented for
2501 if ((p
->family
== AF_INET
) &&
2502 (!bgp_subgrp_multiaccess_check_v4(
2505 subgroup_announce_reset_nhop(
2506 (peer_cap_enhe(peer
, afi
, safi
)
2513 if ((p
->family
== AF_INET6
) &&
2514 (!bgp_subgrp_multiaccess_check_v6(
2515 piattr
->mp_nexthop_global
,
2517 subgroup_announce_reset_nhop(
2518 (peer_cap_enhe(peer
, afi
, safi
)
2527 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2529 * This flag is used for leaked vpn-vrf routes
2531 int family
= p
->family
;
2533 if (peer_cap_enhe(peer
, afi
, safi
))
2536 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2538 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2539 __func__
, p
, family2str(family
));
2540 subgroup_announce_reset_nhop(family
, attr
);
2545 /* If IPv6/MP and nexthop does not have any override and happens
2547 * be a link-local address, reset it so that we don't pass along
2549 * source's link-local IPv6 address to recipients who may not be
2551 * the same interface.
2553 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2554 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2555 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2560 /* If this is an iBGP, send Origin Validation State (OVS)
2561 * extended community (rfc8097).
2563 if (peer
->sort
== BGP_PEER_IBGP
) {
2564 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2566 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2568 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2569 bgp_attr_set_ecommunity(
2570 attr
, ecommunity_add_origin_validation_state(
2572 bgp_attr_get_ecommunity(attr
)));
2576 * When the next hop is set to ourselves, if all multipaths have
2577 * link-bandwidth announce the cumulative bandwidth as that makes
2578 * the most sense. However, don't modify if the link-bandwidth has
2579 * been explicitly set by user policy.
2582 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2583 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2584 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2585 bgp_attr_set_ecommunity(
2587 ecommunity_replace_linkbw(
2588 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2591 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2596 static void bgp_route_select_timer_expire(struct thread
*thread
)
2598 struct afi_safi_info
*info
;
2603 info
= THREAD_ARG(thread
);
2608 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2609 XFREE(MTYPE_TMP
, info
);
2611 /* Best path selection */
2612 bgp_best_path_select_defer(bgp
, afi
, safi
);
2615 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2616 struct bgp_maxpaths_cfg
*mpath_cfg
,
2617 struct bgp_path_info_pair
*result
, afi_t afi
,
2620 struct bgp_path_info
*new_select
;
2621 struct bgp_path_info
*old_select
;
2622 struct bgp_path_info
*pi
;
2623 struct bgp_path_info
*pi1
;
2624 struct bgp_path_info
*pi2
;
2625 struct bgp_path_info
*nextpi
= NULL
;
2626 int paths_eq
, do_mpath
, debug
;
2627 struct list mp_list
;
2628 char pfx_buf
[PREFIX2STR_BUFFER
];
2629 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2631 bgp_mp_list_init(&mp_list
);
2633 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2635 debug
= bgp_debug_bestpath(dest
);
2638 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2640 dest
->reason
= bgp_path_selection_none
;
2641 /* bgp deterministic-med */
2643 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2645 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2646 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2648 bgp_path_info_unset_flag(dest
, pi1
,
2649 BGP_PATH_DMED_SELECTED
);
2651 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2653 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2655 if (BGP_PATH_HOLDDOWN(pi1
))
2657 if (pi1
->peer
!= bgp
->peer_self
)
2658 if (!peer_established(pi1
->peer
))
2663 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2664 if (CHECK_FLAG(pi2
->flags
,
2665 BGP_PATH_DMED_CHECK
))
2667 if (BGP_PATH_HOLDDOWN(pi2
))
2669 if (pi2
->peer
!= bgp
->peer_self
2672 PEER_STATUS_NSF_WAIT
))
2673 if (pi2
->peer
->status
2677 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2679 && !aspath_cmp_left_confed(
2684 if (bgp_path_info_cmp(
2685 bgp
, pi2
, new_select
,
2686 &paths_eq
, mpath_cfg
, debug
,
2689 bgp_path_info_unset_flag(
2691 BGP_PATH_DMED_SELECTED
);
2695 bgp_path_info_set_flag(
2696 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2699 bgp_path_info_set_flag(dest
, new_select
,
2700 BGP_PATH_DMED_CHECK
);
2701 bgp_path_info_set_flag(dest
, new_select
,
2702 BGP_PATH_DMED_SELECTED
);
2705 bgp_path_info_path_with_addpath_rx_str(
2706 new_select
, path_buf
, sizeof(path_buf
));
2708 "%pBD(%s): %s is the bestpath from AS %u",
2709 dest
, bgp
->name_pretty
, path_buf
,
2710 aspath_get_first_as(
2711 new_select
->attr
->aspath
));
2716 /* Check old selected route and new selected route. */
2719 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2720 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2721 enum bgp_path_selection_reason reason
;
2723 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2726 if (BGP_PATH_HOLDDOWN(pi
)) {
2727 /* reap REMOVED routes, if needs be
2728 * selected route must stay for a while longer though
2730 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2731 && (pi
!= old_select
))
2732 bgp_path_info_reap(dest
, pi
);
2735 zlog_debug("%s: pi %p in holddown", __func__
,
2741 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2742 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2743 if (!peer_established(pi
->peer
)) {
2747 "%s: pi %p non self peer %s not estab state",
2748 __func__
, pi
, pi
->peer
->host
);
2753 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2754 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2755 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2757 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2761 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2763 reason
= dest
->reason
;
2764 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2765 debug
, pfx_buf
, afi
, safi
,
2767 if (new_select
== NULL
&&
2768 reason
!= bgp_path_selection_none
)
2769 dest
->reason
= reason
;
2774 /* Now that we know which path is the bestpath see if any of the other
2776 * qualify as multipaths
2780 bgp_path_info_path_with_addpath_rx_str(
2781 new_select
, path_buf
, sizeof(path_buf
));
2783 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2785 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2786 dest
, bgp
->name_pretty
, path_buf
,
2787 old_select
? old_select
->peer
->host
: "NONE");
2790 if (do_mpath
&& new_select
) {
2791 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2792 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2795 bgp_path_info_path_with_addpath_rx_str(
2796 pi
, path_buf
, sizeof(path_buf
));
2798 if (pi
== new_select
) {
2801 "%pBD(%s): %s is the bestpath, add to the multipath list",
2802 dest
, bgp
->name_pretty
,
2804 bgp_mp_list_add(&mp_list
, pi
);
2808 if (BGP_PATH_HOLDDOWN(pi
))
2811 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2812 && !CHECK_FLAG(pi
->peer
->sflags
,
2813 PEER_STATUS_NSF_WAIT
))
2814 if (!peer_established(pi
->peer
))
2817 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2820 "%pBD: %s has the same nexthop as the bestpath, skip it",
2825 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2826 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2832 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2834 bgp_mp_list_add(&mp_list
, pi
);
2839 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2841 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2842 bgp_mp_list_clear(&mp_list
);
2844 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2846 result
->old
= old_select
;
2847 result
->new = new_select
;
2853 * A new route/change in bestpath of an existing route. Evaluate the path
2854 * for advertisement to the subgroup.
2856 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2857 struct bgp_path_info
*selected
,
2858 struct bgp_dest
*dest
,
2859 uint32_t addpath_tx_id
)
2861 const struct prefix
*p
;
2862 struct peer
*onlypeer
;
2869 p
= bgp_dest_get_prefix(dest
);
2870 afi
= SUBGRP_AFI(subgrp
);
2871 safi
= SUBGRP_SAFI(subgrp
);
2872 bgp
= SUBGRP_INST(subgrp
);
2873 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2876 if (BGP_DEBUG(update
, UPDATE_OUT
))
2877 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2879 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2880 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2881 PEER_STATUS_ORF_WAIT_REFRESH
))
2884 memset(&attr
, 0, sizeof(attr
));
2885 /* It's initialized in bgp_announce_check() */
2887 /* Announcement to the subgroup. If the route is filtered withdraw it.
2888 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2889 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2892 advertise
= bgp_check_advertise(bgp
, dest
);
2895 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2897 /* Route is selected, if the route is already installed
2898 * in FIB, then it is advertised
2901 if (!bgp_check_withdrawal(bgp
, dest
))
2902 bgp_adj_out_set_subgroup(
2903 dest
, subgrp
, &attr
, selected
);
2905 bgp_adj_out_unset_subgroup(
2906 dest
, subgrp
, 1, addpath_tx_id
);
2909 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2913 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2915 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2920 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2921 * This is called at the end of route processing.
2923 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2925 struct bgp_path_info
*pi
;
2927 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2928 if (BGP_PATH_HOLDDOWN(pi
))
2930 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2931 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2936 * Has the route changed from the RIB's perspective? This is invoked only
2937 * if the route selection returns the same best route as earlier - to
2938 * determine if we need to update zebra or not.
2940 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2942 struct bgp_path_info
*mpinfo
;
2944 /* If this is multipath, check all selected paths for any nexthop
2945 * change or attribute change. Some attribute changes (e.g., community)
2946 * aren't of relevance to the RIB, but we'll update zebra to ensure
2947 * we handle the case of BGP nexthop change. This is the behavior
2948 * when the best path has an attribute change anyway.
2950 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2951 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2952 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2956 * If this is multipath, check all selected paths for any nexthop change
2958 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2959 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2960 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2961 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2965 /* Nothing has changed from the RIB's perspective. */
2969 struct bgp_process_queue
{
2971 STAILQ_HEAD(, bgp_dest
) pqueue
;
2972 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2974 unsigned int queued
;
2977 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2978 safi_t safi
, struct bgp_dest
*dest
,
2979 struct bgp_path_info
*new_select
,
2980 struct bgp_path_info
*old_select
)
2982 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2984 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2987 if (advertise_type5_routes(bgp
, afi
) && new_select
2988 && is_route_injectable_into_evpn(new_select
)) {
2990 /* apply the route-map */
2991 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2992 route_map_result_t ret
;
2993 struct bgp_path_info rmap_path
;
2994 struct bgp_path_info_extra rmap_path_extra
;
2995 struct attr dummy_attr
;
2997 dummy_attr
= *new_select
->attr
;
2999 /* Fill temp path_info */
3000 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3001 new_select
, new_select
->peer
,
3004 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3006 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3009 if (ret
== RMAP_DENYMATCH
) {
3010 bgp_attr_flush(&dummy_attr
);
3011 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3014 bgp_evpn_advertise_type5_route(
3015 bgp
, p
, &dummy_attr
, afi
, safi
);
3017 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3020 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3021 && is_route_injectable_into_evpn(old_select
))
3022 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3026 * Utility to determine whether a particular path_info should use
3027 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3028 * in a path where we basically _know_ this is a BGP-LU route.
3030 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
3032 /* Certain types get imp null; so do paths where the nexthop is
3035 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3036 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3037 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3039 else if (new_select
->extra
== NULL
||
3040 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
3041 /* TODO -- should be configurable? */
3048 * old_select = The old best path
3049 * new_select = the new best path
3051 * if (!old_select && new_select)
3052 * We are sending new information on.
3054 * if (old_select && new_select) {
3055 * if (new_select != old_select)
3056 * We have a new best path send a change
3058 * We've received a update with new attributes that needs
3062 * if (old_select && !new_select)
3063 * We have no eligible route that we can announce or the rn
3066 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3067 afi_t afi
, safi_t safi
)
3069 struct bgp_path_info
*new_select
;
3070 struct bgp_path_info
*old_select
;
3071 struct bgp_path_info_pair old_and_new
;
3074 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3076 debug
= bgp_debug_bestpath(dest
);
3079 "%s: bgp delete in progress, ignoring event, p=%pBD",
3083 /* Is it end of initial update? (after startup) */
3085 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3086 sizeof(bgp
->update_delay_zebra_resume_time
));
3088 bgp
->main_zebra_update_hold
= 0;
3089 FOREACH_AFI_SAFI (afi
, safi
) {
3090 if (bgp_fibupd_safi(safi
))
3091 bgp_zebra_announce_table(bgp
, afi
, safi
);
3093 bgp
->main_peers_update_hold
= 0;
3095 bgp_start_routeadv(bgp
);
3099 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3101 debug
= bgp_debug_bestpath(dest
);
3103 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__
,
3104 dest
, bgp
->name_pretty
, afi2str(afi
),
3107 /* The best path calculation for the route is deferred if
3108 * BGP_NODE_SELECT_DEFER is set
3110 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3111 if (BGP_DEBUG(update
, UPDATE_OUT
))
3112 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
3116 /* Best path selection. */
3117 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3119 old_select
= old_and_new
.old
;
3120 new_select
= old_and_new
.new;
3122 /* Do we need to allocate or free labels?
3123 * Right now, since we only deal with per-prefix labels, it is not
3124 * necessary to do this upon changes to best path. Exceptions:
3125 * - label index has changed -> recalculate resulting label
3126 * - path_info sub_type changed -> switch to/from implicit-null
3127 * - no valid label (due to removed static label binding) -> get new one
3129 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3132 || bgp_label_index_differs(new_select
, old_select
)
3133 || new_select
->sub_type
!= old_select
->sub_type
3134 || !bgp_is_valid_label(&dest
->local_label
)) {
3135 /* Enforced penultimate hop popping:
3136 * implicit-null for local routes, aggregate
3137 * and redistributed routes
3139 if (bgp_lu_need_imp_null(new_select
)) {
3142 BGP_NODE_REGISTERED_FOR_LABEL
)
3145 BGP_NODE_LABEL_REQUESTED
))
3146 bgp_unregister_for_label(dest
);
3147 dest
->local_label
= mpls_lse_encode(
3148 MPLS_LABEL_IMPLICIT_NULL
, 0, 0,
3150 bgp_set_valid_label(&dest
->local_label
);
3152 bgp_register_for_label(dest
,
3155 } else if (CHECK_FLAG(dest
->flags
,
3156 BGP_NODE_REGISTERED_FOR_LABEL
)
3157 || CHECK_FLAG(dest
->flags
,
3158 BGP_NODE_LABEL_REQUESTED
)) {
3159 bgp_unregister_for_label(dest
);
3161 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3162 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3163 bgp_unregister_for_label(dest
);
3168 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3169 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3170 safi2str(safi
), old_select
, new_select
);
3172 /* If best route remains the same and this is not due to user-initiated
3173 * clear, see exactly what needs to be done.
3175 if (old_select
&& old_select
== new_select
3176 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3177 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3178 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3179 if (bgp_zebra_has_route_changed(old_select
)) {
3180 #ifdef ENABLE_BGP_VNC
3181 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3182 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3184 if (bgp_fibupd_safi(safi
)
3185 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3187 if (BGP_SUPPRESS_FIB_ENABLED(bgp
)
3188 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
3189 SET_FLAG(dest
->flags
,
3190 BGP_NODE_FIB_INSTALL_PENDING
);
3192 if (new_select
->type
== ZEBRA_ROUTE_BGP
3193 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3194 || new_select
->sub_type
3195 == BGP_ROUTE_IMPORTED
))
3197 bgp_zebra_announce(dest
, p
, old_select
,
3202 /* If there is a change of interest to peers, reannounce the
3204 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3205 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3206 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3207 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3209 /* unicast routes must also be annouced to
3210 * labeled-unicast update-groups */
3211 if (safi
== SAFI_UNICAST
)
3212 group_announce_route(bgp
, afi
,
3213 SAFI_LABELED_UNICAST
, dest
,
3216 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3217 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3220 /* advertise/withdraw type-5 routes */
3221 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3222 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3223 bgp_process_evpn_route_injection(
3224 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3226 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3227 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3228 bgp_zebra_clear_route_change_flags(dest
);
3229 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3233 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3235 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3237 /* bestpath has changed; bump version */
3238 if (old_select
|| new_select
) {
3239 bgp_bump_version(dest
);
3241 if (!bgp
->t_rmap_def_originate_eval
) {
3245 update_group_refresh_default_originate_route_map
,
3246 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3247 &bgp
->t_rmap_def_originate_eval
);
3252 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3255 zlog_debug("%s: setting SELECTED flag", __func__
);
3256 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3257 bgp_path_info_unset_flag(dest
, new_select
,
3258 BGP_PATH_ATTR_CHANGED
);
3259 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3260 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3263 #ifdef ENABLE_BGP_VNC
3264 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3265 if (old_select
!= new_select
) {
3267 vnc_import_bgp_exterior_del_route(bgp
, p
,
3269 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3272 vnc_import_bgp_exterior_add_route(bgp
, p
,
3274 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3280 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3282 /* unicast routes must also be annouced to labeled-unicast update-groups
3284 if (safi
== SAFI_UNICAST
)
3285 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3289 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3290 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3292 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3293 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3294 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3295 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3297 if (BGP_SUPPRESS_FIB_ENABLED(bgp
))
3298 SET_FLAG(dest
->flags
,
3299 BGP_NODE_FIB_INSTALL_PENDING
);
3301 /* if this is an evpn imported type-5 prefix,
3302 * we need to withdraw the route first to clear
3303 * the nh neigh and the RMAC entry.
3306 is_route_parent_evpn(old_select
))
3307 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3309 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3311 /* Withdraw the route from the kernel. */
3312 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3313 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3314 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3315 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3317 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3321 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3324 /* Clear any route change flags. */
3325 bgp_zebra_clear_route_change_flags(dest
);
3327 /* Reap old select bgp_path_info, if it has been removed */
3328 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3329 bgp_path_info_reap(dest
, old_select
);
3331 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3335 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3336 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3338 struct bgp_dest
*dest
;
3340 struct afi_safi_info
*thread_info
;
3342 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3343 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3345 thread_info
= THREAD_ARG(t
);
3346 XFREE(MTYPE_TMP
, thread_info
);
3347 THREAD_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3350 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3351 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3352 get_afi_safi_str(afi
, safi
, false),
3353 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3356 /* Process the route list */
3357 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3358 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3359 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3360 dest
= bgp_route_next(dest
)) {
3361 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3364 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3365 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3366 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3369 /* If iteration stopped before the entire table was traversed then the
3370 * node needs to be unlocked.
3373 bgp_dest_unlock_node(dest
);
3377 /* Send EOR message when all routes are processed */
3378 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3379 bgp_send_delayed_eor(bgp
);
3380 /* Send route processing complete message to RIB */
3381 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3382 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3386 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3388 thread_info
->afi
= afi
;
3389 thread_info
->safi
= safi
;
3390 thread_info
->bgp
= bgp
;
3392 /* If there are more routes to be processed, start the
3395 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3396 BGP_ROUTE_SELECT_DELAY
,
3397 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3400 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3402 struct bgp_process_queue
*pqnode
= data
;
3403 struct bgp
*bgp
= pqnode
->bgp
;
3404 struct bgp_table
*table
;
3405 struct bgp_dest
*dest
;
3408 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3409 bgp_process_main_one(bgp
, NULL
, 0, 0);
3410 /* should always have dedicated wq call */
3411 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3415 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3416 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3417 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3418 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3419 table
= bgp_dest_table(dest
);
3420 /* note, new DESTs may be added as part of processing */
3421 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3423 bgp_dest_unlock_node(dest
);
3424 bgp_table_unlock(table
);
3430 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3432 struct bgp_process_queue
*pqnode
= data
;
3434 bgp_unlock(pqnode
->bgp
);
3436 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3439 void bgp_process_queue_init(struct bgp
*bgp
)
3441 if (!bgp
->process_queue
) {
3444 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3445 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3448 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3449 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3450 bgp
->process_queue
->spec
.max_retries
= 0;
3451 bgp
->process_queue
->spec
.hold
= 50;
3452 /* Use a higher yield value of 50ms for main queue processing */
3453 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3456 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3458 struct bgp_process_queue
*pqnode
;
3460 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3461 sizeof(struct bgp_process_queue
));
3463 /* unlocked in bgp_processq_del */
3464 pqnode
->bgp
= bgp_lock(bgp
);
3465 STAILQ_INIT(&pqnode
->pqueue
);
3470 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3472 #define ARBITRARY_PROCESS_QLEN 10000
3473 struct work_queue
*wq
= bgp
->process_queue
;
3474 struct bgp_process_queue
*pqnode
;
3475 int pqnode_reuse
= 0;
3477 /* already scheduled for processing? */
3478 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3481 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3484 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3485 if (BGP_DEBUG(update
, UPDATE_OUT
))
3486 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3491 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3492 if (BGP_DEBUG(update
, UPDATE_OUT
))
3494 "Soft reconfigure table in progress for route %p",
3502 /* Add route nodes to an existing work queue item until reaching the
3503 limit only if is from the same BGP view and it's not an EOIU marker
3505 if (work_queue_item_count(wq
)) {
3506 struct work_queue_item
*item
= work_queue_last_item(wq
);
3507 pqnode
= item
->data
;
3509 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3510 || pqnode
->bgp
!= bgp
3511 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3512 pqnode
= bgp_processq_alloc(bgp
);
3516 pqnode
= bgp_processq_alloc(bgp
);
3517 /* all unlocked in bgp_process_wq */
3518 bgp_table_lock(bgp_dest_table(dest
));
3520 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3521 bgp_dest_lock_node(dest
);
3523 /* can't be enqueued twice */
3524 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3525 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3529 work_queue_add(wq
, pqnode
);
3534 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3536 struct bgp_process_queue
*pqnode
;
3538 if (bgp
->process_queue
== NULL
)
3541 pqnode
= bgp_processq_alloc(bgp
);
3543 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3544 work_queue_add(bgp
->process_queue
, pqnode
);
3547 static void bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3551 peer
= THREAD_ARG(thread
);
3552 peer
->t_pmax_restart
= NULL
;
3554 if (bgp_debug_neighbor_events(peer
))
3556 "%s Maximum-prefix restart timer expired, restore peering",
3559 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3560 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3563 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3567 bool filtered
= false;
3568 struct bgp_dest
*dest
;
3569 struct bgp_adj_in
*ain
;
3570 struct attr attr
= {};
3571 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3573 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3574 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3575 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3579 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3583 if (bgp_input_modifier(
3584 peer
, rn_p
, &attr
, afi
, safi
,
3585 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3593 bgp_attr_flush(&attr
);
3600 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3604 iana_safi_t pkt_safi
;
3605 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3606 PEER_FLAG_MAX_PREFIX_FORCE
))
3607 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3608 + peer
->pcount
[afi
][safi
]
3609 : peer
->pcount
[afi
][safi
];
3611 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3614 if (pcount
> peer
->pmax
[afi
][safi
]) {
3615 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3616 PEER_STATUS_PREFIX_LIMIT
)
3621 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3622 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3623 peer
->pmax
[afi
][safi
]);
3624 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3626 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3627 PEER_FLAG_MAX_PREFIX_WARNING
))
3630 /* Convert AFI, SAFI to values for packet. */
3631 pkt_afi
= afi_int2iana(afi
);
3632 pkt_safi
= safi_int2iana(safi
);
3636 ndata
[0] = (pkt_afi
>> 8);
3638 ndata
[2] = pkt_safi
;
3639 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3640 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3641 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3642 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3644 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3645 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3646 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3650 /* Dynamic peers will just close their connection. */
3651 if (peer_dynamic_neighbor(peer
))
3654 /* restart timer start */
3655 if (peer
->pmax_restart
[afi
][safi
]) {
3656 peer
->v_pmax_restart
=
3657 peer
->pmax_restart
[afi
][safi
] * 60;
3659 if (bgp_debug_neighbor_events(peer
))
3661 "%pBP Maximum-prefix restart timer started for %d secs",
3662 peer
, peer
->v_pmax_restart
);
3664 BGP_TIMER_ON(peer
->t_pmax_restart
,
3665 bgp_maximum_prefix_restart_timer
,
3666 peer
->v_pmax_restart
);
3671 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3672 PEER_STATUS_PREFIX_LIMIT
);
3675 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3676 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3677 PEER_STATUS_PREFIX_THRESHOLD
)
3682 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3683 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3684 peer
->pmax
[afi
][safi
]);
3685 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3686 PEER_STATUS_PREFIX_THRESHOLD
);
3688 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3689 PEER_STATUS_PREFIX_THRESHOLD
);
3693 /* Unconditionally remove the route from the RIB, without taking
3694 * damping into consideration (eg, because the session went down)
3696 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3697 struct peer
*peer
, afi_t afi
, safi_t safi
)
3700 struct bgp
*bgp
= NULL
;
3701 bool delete_route
= false;
3703 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3706 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3707 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3709 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3712 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3713 delete_route
= true;
3714 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3715 delete_route
= true;
3717 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3718 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3719 bgp
= pi
->peer
->bgp
;
3720 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3725 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3726 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3729 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3730 struct peer
*peer
, afi_t afi
, safi_t safi
,
3731 struct prefix_rd
*prd
)
3733 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3735 /* apply dampening, if result is suppressed, we'll be retaining
3736 * the bgp_path_info in the RIB for historical reference.
3738 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3739 && peer
->sort
== BGP_PEER_EBGP
)
3740 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3741 == BGP_DAMP_SUPPRESSED
) {
3742 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3747 #ifdef ENABLE_BGP_VNC
3748 if (safi
== SAFI_MPLS_VPN
) {
3749 struct bgp_dest
*pdest
= NULL
;
3750 struct bgp_table
*table
= NULL
;
3752 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3753 (struct prefix
*)prd
);
3754 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3755 table
= bgp_dest_get_bgp_table_info(pdest
);
3757 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3758 peer
->bgp
, prd
, table
, p
, pi
);
3760 bgp_dest_unlock_node(pdest
);
3762 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3763 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3765 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3766 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3771 /* If this is an EVPN route, process for un-import. */
3772 if (safi
== SAFI_EVPN
)
3773 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3775 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3778 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3779 struct peer
*peer
, struct attr
*attr
,
3780 struct bgp_dest
*dest
)
3782 struct bgp_path_info
*new;
3784 /* Make new BGP info. */
3785 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3787 new->instance
= instance
;
3788 new->sub_type
= sub_type
;
3791 new->uptime
= monotime(NULL
);
3796 /* Check if received nexthop is valid or not. */
3797 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3798 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3799 struct bgp_dest
*dest
)
3802 bool is_bgp_static_route
=
3803 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3807 * Only validated for unicast and multicast currently.
3808 * Also valid for EVPN where the nexthop is an IP address.
3809 * If we are a bgp static route being checked then there is
3810 * no need to check to see if the nexthop is martian as
3811 * that it should be ok.
3813 if (is_bgp_static_route
||
3814 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3817 /* If NEXT_HOP is present, validate it. */
3818 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3819 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3820 !ipv4_unicast_valid(&attr
->nexthop
) ||
3821 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3825 /* If MP_NEXTHOP is present, validate it. */
3826 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3827 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3828 * it is not an IPv6 link-local address.
3830 * If we receive an UPDATE with nexthop length set to 32 bytes
3831 * we shouldn't discard an UPDATE if it's set to (::).
3832 * The link-local (2st) is validated along the code path later.
3834 if (attr
->mp_nexthop_len
) {
3835 switch (attr
->mp_nexthop_len
) {
3836 case BGP_ATTR_NHLEN_IPV4
:
3837 case BGP_ATTR_NHLEN_VPNV4
:
3838 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3840 !ipv4_unicast_valid(
3841 &attr
->mp_nexthop_global_in
) ||
3842 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3846 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3847 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3848 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3849 &attr
->mp_nexthop_global
)
3850 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3851 || IN6_IS_ADDR_MULTICAST(
3852 &attr
->mp_nexthop_global
)
3853 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3856 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3857 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3858 || IN6_IS_ADDR_MULTICAST(
3859 &attr
->mp_nexthop_global
)
3860 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3873 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3875 struct community
*old
;
3876 struct community
*new;
3877 struct community
*merge
;
3878 struct community
*no_export
;
3880 old
= bgp_attr_get_community(attr
);
3881 no_export
= community_str2com("no-export");
3886 merge
= community_merge(community_dup(old
), no_export
);
3889 community_free(&old
);
3891 new = community_uniq_sort(merge
);
3892 community_free(&merge
);
3894 new = community_dup(no_export
);
3897 community_free(&no_export
);
3899 bgp_attr_set_community(attr
, new);
3902 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3903 struct attr
*attr
, const struct prefix
*prefix
,
3906 struct listnode
*node
, *nnode
;
3908 bool accept_own_found
= false;
3910 if (safi
!= SAFI_MPLS_VPN
)
3913 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3914 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3917 /* The route in question carries the ACCEPT_OWN community */
3918 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3919 struct community
*comm
= bgp_attr_get_community(attr
);
3921 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3922 accept_own_found
= true;
3925 /* The route in question is targeted to one or more destination VRFs
3926 * on the router (as determined by inspecting the Route Target(s)).
3928 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3929 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3932 if (accept_own_found
&&
3934 bgp
->vpn_policy
[afi
]
3935 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3936 bgp_attr_get_ecommunity(attr
))) {
3937 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3939 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3942 /* Treat this route as imported, because it's leaked
3943 * already from another VRF, and we got an updated
3944 * version from route-reflector with ACCEPT_OWN
3947 *sub_type
= BGP_ROUTE_IMPORTED
;
3956 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3957 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3958 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3959 uint32_t num_labels
, int soft_reconfig
,
3960 struct bgp_route_evpn
*evpn
)
3963 int aspath_loop_count
= 0;
3964 struct bgp_dest
*dest
;
3966 struct attr new_attr
;
3967 struct attr
*attr_new
;
3968 struct bgp_path_info
*pi
;
3969 struct bgp_path_info
*new = NULL
;
3970 struct bgp_path_info_extra
*extra
;
3972 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3974 int do_loop_check
= 1;
3975 int has_valid_label
= 0;
3977 bool force_evpn_import
= false;
3978 safi_t orig_safi
= safi
;
3979 bool leak_success
= true;
3982 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3983 char pfxprint
[PREFIX2STR_BUFFER
];
3985 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3986 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3990 #ifdef ENABLE_BGP_VNC
3991 int vnc_implicit_withdraw
= 0;
3994 const struct prefix
*bgp_nht_param_prefix
;
3996 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3997 if (orig_safi
== SAFI_LABELED_UNICAST
)
3998 safi
= SAFI_UNICAST
;
4000 memset(&new_attr
, 0, sizeof(new_attr
));
4001 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4002 new_attr
.label
= MPLS_INVALID_LABEL
;
4005 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4006 /* TODO: Check to see if we can get rid of "is_valid_label" */
4007 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4008 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4010 has_valid_label
= bgp_is_valid_label(label
);
4012 if (has_valid_label
)
4013 assert(label
!= NULL
);
4015 /* Update overlay index of the attribute */
4016 if (afi
== AFI_L2VPN
&& evpn
)
4017 memcpy(&attr
->evpn_overlay
, evpn
,
4018 sizeof(struct bgp_route_evpn
));
4020 /* When peer's soft reconfiguration enabled. Record input packet in
4023 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4024 && peer
!= bgp
->peer_self
)
4025 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4027 /* Update permitted loop count */
4028 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4029 allowas_in
= peer
->allowas_in
[afi
][safi
];
4031 /* Check previously received route. */
4032 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4033 if (pi
->peer
== peer
&& pi
->type
== type
4034 && pi
->sub_type
== sub_type
4035 && pi
->addpath_rx_id
== addpath_id
)
4038 /* AS path local-as loop check. */
4039 if (peer
->change_local_as
) {
4041 aspath_loop_count
= allowas_in
;
4042 else if (!CHECK_FLAG(peer
->flags
,
4043 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4044 aspath_loop_count
= 1;
4046 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4047 > aspath_loop_count
) {
4048 peer
->stat_pfx_aspath_loop
++;
4049 reason
= "as-path contains our own AS;";
4054 /* If the peer is configured for "allowas-in origin" and the last ASN in
4056 * as-path is our ASN then we do not need to call aspath_loop_check
4058 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4059 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4062 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4063 bgp_nht_param_prefix
= NULL
;
4065 bgp_nht_param_prefix
= p
;
4067 /* AS path loop check. */
4068 if (do_loop_check
) {
4069 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4070 peer
->allowas_in
[afi
][safi
]) {
4071 peer
->stat_pfx_aspath_loop
++;
4072 reason
= "as-path contains our own AS;";
4077 /* If we're a CONFED we need to loop check the CONFED ID too */
4078 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4079 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4080 peer
->allowas_in
[afi
][safi
]) {
4081 peer
->stat_pfx_aspath_loop
++;
4082 reason
= "as-path contains our own confed AS;";
4086 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4087 * enabled, then take care of that too.
4089 bool accept_own
= false;
4091 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4092 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4094 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4096 peer
->stat_pfx_originator_loop
++;
4097 reason
= "originator is us;";
4102 /* Route reflector cluster ID check. */
4103 if (bgp_cluster_filter(peer
, attr
)) {
4104 peer
->stat_pfx_cluster_loop
++;
4105 reason
= "reflected from the same cluster;";
4109 /* Apply incoming filter. */
4110 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4111 peer
->stat_pfx_filter
++;
4116 /* RFC 8212 to prevent route leaks.
4117 * This specification intends to improve this situation by requiring the
4118 * explicit configuration of both BGP Import and Export Policies for any
4119 * External BGP (EBGP) session such as customers, peers, or
4120 * confederation boundaries for all enabled address families. Through
4121 * codification of the aforementioned requirement, operators will
4122 * benefit from consistent behavior across different BGP
4125 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4126 if (!bgp_inbound_policy_exists(peer
,
4127 &peer
->filter
[afi
][safi
])) {
4128 reason
= "inbound policy missing";
4129 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4130 NULL
) > FIFTEENMINUTE2USEC
||
4131 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4133 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4134 monotime(&bgp
->ebgprequirespolicywarning
);
4139 /* draft-ietf-idr-deprecate-as-set-confed-set
4140 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4141 * Eventually, This document (if approved) updates RFC 4271
4142 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4143 * and obsoletes RFC 6472.
4145 if (peer
->bgp
->reject_as_sets
)
4146 if (aspath_check_as_sets(attr
->aspath
)) {
4148 "as-path contains AS_SET or AS_CONFED_SET type;";
4154 /* Apply incoming route-map.
4155 * NB: new_attr may now contain newly allocated values from route-map
4157 * commands, so we need bgp_attr_flush in the error paths, until we
4159 * the attr (which takes over the memory references) */
4160 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4163 peer
->stat_pfx_filter
++;
4164 reason
= "route-map;";
4165 bgp_attr_flush(&new_attr
);
4169 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4170 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4171 /* remove from RIB previous entry */
4172 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4175 if (peer
->sort
== BGP_PEER_EBGP
) {
4178 * A BGP speaker receiving an announcement tagged with the
4179 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4180 * NO_EXPORT community as defined in RFC1997, or a
4181 * similar community, to prevent propagation of the
4182 * prefix outside the local AS. The community to prevent
4183 * propagation SHOULD be chosen according to the operator's
4186 if (bgp_attr_get_community(&new_attr
) &&
4187 community_include(bgp_attr_get_community(&new_attr
),
4188 COMMUNITY_BLACKHOLE
))
4189 bgp_attr_add_no_export_community(&new_attr
);
4191 /* If we receive the graceful-shutdown community from an eBGP
4192 * peer we must lower local-preference */
4193 if (bgp_attr_get_community(&new_attr
) &&
4194 community_include(bgp_attr_get_community(&new_attr
),
4196 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4197 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4199 /* If graceful-shutdown is configured globally or
4200 * per neighbor, then add the GSHUT community to
4201 * all paths received from eBGP peers. */
4202 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4203 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4204 bgp_attr_add_gshut_community(&new_attr
);
4207 /* next hop check. */
4208 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4209 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4211 peer
->stat_pfx_nh_invalid
++;
4212 reason
= "martian or self next-hop;";
4213 bgp_attr_flush(&new_attr
);
4217 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4218 peer
->stat_pfx_nh_invalid
++;
4219 reason
= "self mac;";
4220 bgp_attr_flush(&new_attr
);
4224 if (bgp_check_role_applicability(afi
, safi
) &&
4225 bgp_otc_filter(peer
, &new_attr
)) {
4226 reason
= "failing otc validation";
4227 bgp_attr_flush(&new_attr
);
4230 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4232 * Suppress fib is enabled
4233 * BGP_OPT_NO_FIB is not enabled
4234 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4235 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4237 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
4238 && (sub_type
== BGP_ROUTE_NORMAL
)
4239 && (!bgp_option_check(BGP_OPT_NO_FIB
))
4240 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
4241 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
4243 /* If neighbor soo is configured, tag all incoming routes with
4244 * this SoO tag and then filter out advertisements in
4245 * subgroup_announce_check() if it matches the configured SoO
4246 * on the other peer.
4248 if (peer
->soo
[afi
][safi
]) {
4249 struct ecommunity
*old_ecomm
=
4250 bgp_attr_get_ecommunity(&new_attr
);
4251 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4252 struct ecommunity
*new_ecomm
;
4255 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4258 if (!old_ecomm
->refcnt
)
4259 ecommunity_free(&old_ecomm
);
4261 new_ecomm
= ecommunity_dup(ecomm_soo
);
4264 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4267 attr_new
= bgp_attr_intern(&new_attr
);
4269 /* If the update is implicit withdraw. */
4271 pi
->uptime
= monotime(NULL
);
4272 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4274 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4276 /* Same attribute comes in. */
4277 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4279 && (!has_valid_label
4280 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4281 num_labels
* sizeof(mpls_label_t
))
4283 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4284 BGP_CONFIG_DAMPENING
)
4285 && peer
->sort
== BGP_PEER_EBGP
4286 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4287 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4288 bgp_debug_rdpfxpath2str(
4289 afi
, safi
, prd
, p
, label
,
4290 num_labels
, addpath_id
? 1 : 0,
4291 addpath_id
, evpn
, pfx_buf
,
4293 zlog_debug("%pBP rcvd %s", peer
,
4297 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4298 != BGP_DAMP_SUPPRESSED
) {
4299 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4301 bgp_process(bgp
, dest
, afi
, safi
);
4303 } else /* Duplicate - odd */
4305 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4306 if (!peer
->rcvd_attr_printed
) {
4308 "%pBP rcvd UPDATE w/ attr: %s",
4310 peer
->rcvd_attr_str
);
4311 peer
->rcvd_attr_printed
= 1;
4314 bgp_debug_rdpfxpath2str(
4315 afi
, safi
, prd
, p
, label
,
4316 num_labels
, addpath_id
? 1 : 0,
4317 addpath_id
, evpn
, pfx_buf
,
4320 "%pBP rcvd %s...duplicate ignored",
4324 /* graceful restart STALE flag unset. */
4325 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4326 bgp_path_info_unset_flag(
4327 dest
, pi
, BGP_PATH_STALE
);
4328 bgp_dest_set_defer_flag(dest
, false);
4329 bgp_process(bgp
, dest
, afi
, safi
);
4333 bgp_dest_unlock_node(dest
);
4334 bgp_attr_unintern(&attr_new
);
4339 /* Withdraw/Announce before we fully processed the withdraw */
4340 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4341 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4342 bgp_debug_rdpfxpath2str(
4343 afi
, safi
, prd
, p
, label
, num_labels
,
4344 addpath_id
? 1 : 0, addpath_id
, evpn
,
4345 pfx_buf
, sizeof(pfx_buf
));
4347 "%pBP rcvd %s, flapped quicker than processing",
4351 bgp_path_info_restore(dest
, pi
);
4354 * If the BGP_PATH_REMOVED flag is set, then EVPN
4355 * routes would have been unimported already when a
4356 * prior BGP withdraw processing happened. Such routes
4357 * need to be imported again, so flag accordingly.
4359 force_evpn_import
= true;
4361 /* implicit withdraw, decrement aggregate and pcount
4362 * here. only if update is accepted, they'll increment
4365 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4368 /* Received Logging. */
4369 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4370 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4371 num_labels
, addpath_id
? 1 : 0,
4372 addpath_id
, evpn
, pfx_buf
,
4374 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4377 /* graceful restart STALE flag unset. */
4378 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4379 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4380 bgp_dest_set_defer_flag(dest
, false);
4383 /* The attribute is changed. */
4384 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4386 /* Update bgp route dampening information. */
4387 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4388 && peer
->sort
== BGP_PEER_EBGP
) {
4389 /* This is implicit withdraw so we should update
4392 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4393 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4395 #ifdef ENABLE_BGP_VNC
4396 if (safi
== SAFI_MPLS_VPN
) {
4397 struct bgp_dest
*pdest
= NULL
;
4398 struct bgp_table
*table
= NULL
;
4400 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4401 (struct prefix
*)prd
);
4402 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4403 table
= bgp_dest_get_bgp_table_info(pdest
);
4405 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4406 bgp
, prd
, table
, p
, pi
);
4408 bgp_dest_unlock_node(pdest
);
4410 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4411 && (safi
== SAFI_UNICAST
)) {
4412 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4414 * Implicit withdraw case.
4416 ++vnc_implicit_withdraw
;
4417 vnc_import_bgp_del_route(bgp
, p
, pi
);
4418 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4423 /* Special handling for EVPN update of an existing route. If the
4424 * extended community attribute has changed, we need to
4426 * the route using its existing extended community. It will be
4427 * subsequently processed for import with the new extended
4430 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4433 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4435 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4438 cmp
= ecommunity_cmp(
4439 bgp_attr_get_ecommunity(pi
->attr
),
4440 bgp_attr_get_ecommunity(attr_new
));
4442 if (bgp_debug_update(peer
, p
, NULL
, 1))
4444 "Change in EXT-COMM, existing %s new %s",
4446 bgp_attr_get_ecommunity(
4449 bgp_attr_get_ecommunity(
4451 if (safi
== SAFI_EVPN
)
4452 bgp_evpn_unimport_route(
4453 bgp
, afi
, safi
, p
, pi
);
4454 else /* SAFI_MPLS_VPN */
4455 vpn_leak_to_vrf_withdraw(bgp
,
4461 /* Update to new attribute. */
4462 bgp_attr_unintern(&pi
->attr
);
4463 pi
->attr
= attr_new
;
4465 /* Update MPLS label */
4466 if (has_valid_label
) {
4467 extra
= bgp_path_info_extra_get(pi
);
4468 if (extra
->label
!= label
) {
4469 memcpy(&extra
->label
, label
,
4470 num_labels
* sizeof(mpls_label_t
));
4471 extra
->num_labels
= num_labels
;
4473 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4474 bgp_set_valid_label(&extra
->label
[0]);
4477 /* Update SRv6 SID */
4478 if (attr
->srv6_l3vpn
) {
4479 extra
= bgp_path_info_extra_get(pi
);
4480 if (sid_diff(&extra
->sid
[0].sid
,
4481 &attr
->srv6_l3vpn
->sid
)) {
4482 sid_copy(&extra
->sid
[0].sid
,
4483 &attr
->srv6_l3vpn
->sid
);
4484 extra
->num_sids
= 1;
4486 extra
->sid
[0].loc_block_len
= 0;
4487 extra
->sid
[0].loc_node_len
= 0;
4488 extra
->sid
[0].func_len
= 0;
4489 extra
->sid
[0].arg_len
= 0;
4490 extra
->sid
[0].transposition_len
= 0;
4491 extra
->sid
[0].transposition_offset
= 0;
4493 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4494 extra
->sid
[0].loc_block_len
=
4495 attr
->srv6_l3vpn
->loc_block_len
;
4496 extra
->sid
[0].loc_node_len
=
4497 attr
->srv6_l3vpn
->loc_node_len
;
4498 extra
->sid
[0].func_len
=
4499 attr
->srv6_l3vpn
->func_len
;
4500 extra
->sid
[0].arg_len
=
4501 attr
->srv6_l3vpn
->arg_len
;
4502 extra
->sid
[0].transposition_len
=
4504 ->transposition_len
;
4505 extra
->sid
[0].transposition_offset
=
4507 ->transposition_offset
;
4510 } else if (attr
->srv6_vpn
) {
4511 extra
= bgp_path_info_extra_get(pi
);
4512 if (sid_diff(&extra
->sid
[0].sid
,
4513 &attr
->srv6_vpn
->sid
)) {
4514 sid_copy(&extra
->sid
[0].sid
,
4515 &attr
->srv6_vpn
->sid
);
4516 extra
->num_sids
= 1;
4520 #ifdef ENABLE_BGP_VNC
4521 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4522 && (safi
== SAFI_UNICAST
)) {
4523 if (vnc_implicit_withdraw
) {
4525 * Add back the route with its new attributes
4527 * The route is still selected, until the route
4529 * queued by bgp_process actually runs. We have
4531 * update to the VNC side immediately to avoid
4533 * configuration changes (e.g., route-map
4535 * trigger re-importation of the entire RIB.
4537 vnc_import_bgp_add_route(bgp
, p
, pi
);
4538 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4543 /* Update bgp route dampening information. */
4544 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4545 && peer
->sort
== BGP_PEER_EBGP
) {
4546 /* Now we do normal update dampening. */
4547 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4548 if (ret
== BGP_DAMP_SUPPRESSED
) {
4549 bgp_dest_unlock_node(dest
);
4554 /* Nexthop reachability check - for unicast and
4555 * labeled-unicast.. */
4556 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4557 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4558 || (safi
== SAFI_EVPN
&&
4559 bgp_evpn_is_prefix_nht_supported(p
))) {
4560 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4561 && peer
->ttl
== BGP_DEFAULT_TTL
4562 && !CHECK_FLAG(peer
->flags
,
4563 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4564 && !CHECK_FLAG(bgp
->flags
,
4565 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4570 struct bgp
*bgp_nexthop
= bgp
;
4572 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4573 bgp_nexthop
= pi
->extra
->bgp_orig
;
4575 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4577 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4578 safi
, pi
, NULL
, connected
,
4579 bgp_nht_param_prefix
) ||
4580 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4581 bgp_path_info_set_flag(dest
, pi
,
4584 if (BGP_DEBUG(nht
, NHT
)) {
4585 zlog_debug("%s(%pI4): NH unresolved",
4587 (in_addr_t
*)&attr_new
->nexthop
);
4589 bgp_path_info_unset_flag(dest
, pi
,
4594 bgp_path_info_set_flag(dest
, pi
,
4595 BGP_PATH_ACCEPT_OWN
);
4597 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4600 #ifdef ENABLE_BGP_VNC
4601 if (safi
== SAFI_MPLS_VPN
) {
4602 struct bgp_dest
*pdest
= NULL
;
4603 struct bgp_table
*table
= NULL
;
4605 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4606 (struct prefix
*)prd
);
4607 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4608 table
= bgp_dest_get_bgp_table_info(pdest
);
4610 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4611 bgp
, prd
, table
, p
, pi
);
4613 bgp_dest_unlock_node(pdest
);
4617 /* If this is an EVPN route and some attribute has changed,
4618 * or we are explicitly told to perform a route import, process
4619 * route for import. If the extended community has changed, we
4621 * have done the un-import earlier and the import would result
4623 * route getting injected into appropriate L2 VNIs. If it is
4625 * some other attribute change, the import will result in
4627 * the attributes for the route in the VNI(s).
4629 if (safi
== SAFI_EVPN
&&
4630 (!same_attr
|| force_evpn_import
) &&
4631 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4632 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4634 /* Process change. */
4635 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4637 bgp_process(bgp
, dest
, afi
, safi
);
4638 bgp_dest_unlock_node(dest
);
4640 if (SAFI_UNICAST
== safi
4641 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4642 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4644 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4646 if ((SAFI_MPLS_VPN
== safi
)
4647 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4648 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4651 #ifdef ENABLE_BGP_VNC
4652 if (SAFI_MPLS_VPN
== safi
) {
4653 mpls_label_t label_decoded
= decode_label(label
);
4655 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4656 type
, sub_type
, &label_decoded
);
4658 if (SAFI_ENCAP
== safi
) {
4659 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4660 type
, sub_type
, NULL
);
4663 if ((safi
== SAFI_MPLS_VPN
) &&
4664 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4665 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4667 bgp_unlink_nexthop(pi
);
4668 bgp_path_info_delete(dest
, pi
);
4671 } // End of implicit withdraw
4673 /* Received Logging. */
4674 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4675 if (!peer
->rcvd_attr_printed
) {
4676 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4677 peer
->rcvd_attr_str
);
4678 peer
->rcvd_attr_printed
= 1;
4681 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4682 addpath_id
? 1 : 0, addpath_id
, evpn
,
4683 pfx_buf
, sizeof(pfx_buf
));
4684 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4687 /* Make new BGP info. */
4688 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4690 /* Update MPLS label */
4691 if (has_valid_label
) {
4692 extra
= bgp_path_info_extra_get(new);
4693 if (extra
->label
!= label
) {
4694 memcpy(&extra
->label
, label
,
4695 num_labels
* sizeof(mpls_label_t
));
4696 extra
->num_labels
= num_labels
;
4698 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4699 bgp_set_valid_label(&extra
->label
[0]);
4702 /* Update SRv6 SID */
4703 if (safi
== SAFI_MPLS_VPN
) {
4704 extra
= bgp_path_info_extra_get(new);
4705 if (attr
->srv6_l3vpn
) {
4706 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4707 extra
->num_sids
= 1;
4709 extra
->sid
[0].loc_block_len
=
4710 attr
->srv6_l3vpn
->loc_block_len
;
4711 extra
->sid
[0].loc_node_len
=
4712 attr
->srv6_l3vpn
->loc_node_len
;
4713 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4714 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4715 extra
->sid
[0].transposition_len
=
4716 attr
->srv6_l3vpn
->transposition_len
;
4717 extra
->sid
[0].transposition_offset
=
4718 attr
->srv6_l3vpn
->transposition_offset
;
4719 } else if (attr
->srv6_vpn
) {
4720 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4721 extra
->num_sids
= 1;
4725 /* Nexthop reachability check. */
4726 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4727 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4728 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4729 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4730 && peer
->ttl
== BGP_DEFAULT_TTL
4731 && !CHECK_FLAG(peer
->flags
,
4732 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4733 && !CHECK_FLAG(bgp
->flags
,
4734 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4739 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4741 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4742 connected
, bgp_nht_param_prefix
) ||
4743 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4744 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4746 if (BGP_DEBUG(nht
, NHT
))
4747 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4748 &attr_new
->nexthop
);
4749 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4753 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4755 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4758 /* If maximum prefix count is configured and current prefix
4761 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4762 reason
= "maximum-prefix overflow";
4763 bgp_attr_flush(&new_attr
);
4768 new->addpath_rx_id
= addpath_id
;
4770 /* Increment prefix */
4771 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4773 /* Register new BGP information. */
4774 bgp_path_info_add(dest
, new);
4776 /* route_node_get lock */
4777 bgp_dest_unlock_node(dest
);
4779 #ifdef ENABLE_BGP_VNC
4780 if (safi
== SAFI_MPLS_VPN
) {
4781 struct bgp_dest
*pdest
= NULL
;
4782 struct bgp_table
*table
= NULL
;
4784 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4785 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4786 table
= bgp_dest_get_bgp_table_info(pdest
);
4788 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4789 bgp
, prd
, table
, p
, new);
4791 bgp_dest_unlock_node(pdest
);
4795 /* If this is an EVPN route, process for import. */
4796 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4797 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4799 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4801 /* Process change. */
4802 bgp_process(bgp
, dest
, afi
, safi
);
4804 if (SAFI_UNICAST
== safi
4805 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4806 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4807 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4809 if ((SAFI_MPLS_VPN
== safi
)
4810 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4811 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4813 #ifdef ENABLE_BGP_VNC
4814 if (SAFI_MPLS_VPN
== safi
) {
4815 mpls_label_t label_decoded
= decode_label(label
);
4817 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4818 sub_type
, &label_decoded
);
4820 if (SAFI_ENCAP
== safi
) {
4821 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4825 if ((safi
== SAFI_MPLS_VPN
) &&
4826 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4827 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4829 bgp_unlink_nexthop(new);
4830 bgp_path_info_delete(dest
, new);
4835 /* This BGP update is filtered. Log the reason then update BGP
4839 bgp_unlink_nexthop(new);
4840 bgp_path_info_delete(dest
, new);
4841 bgp_path_info_extra_free(&new->extra
);
4842 XFREE(MTYPE_BGP_ROUTE
, new);
4845 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4847 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4848 if (!peer
->rcvd_attr_printed
) {
4849 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4850 peer
->rcvd_attr_str
);
4851 peer
->rcvd_attr_printed
= 1;
4854 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4855 addpath_id
? 1 : 0, addpath_id
, evpn
,
4856 pfx_buf
, sizeof(pfx_buf
));
4857 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4858 peer
, pfx_buf
, reason
);
4862 /* If this is an EVPN route, un-import it as it is now filtered.
4864 if (safi
== SAFI_EVPN
)
4865 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4867 if (SAFI_UNICAST
== safi
4868 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4869 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4871 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4873 if ((SAFI_MPLS_VPN
== safi
)
4874 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4876 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4879 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4882 bgp_dest_unlock_node(dest
);
4884 #ifdef ENABLE_BGP_VNC
4886 * Filtered update is treated as an implicit withdrawal (see
4888 * a few lines above)
4890 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4891 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4899 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4900 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4901 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4902 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4905 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4906 struct bgp_dest
*dest
;
4907 struct bgp_path_info
*pi
;
4909 #ifdef ENABLE_BGP_VNC
4910 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4911 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4919 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4921 /* If peer is soft reconfiguration enabled. Record input packet for
4922 * further calculation.
4924 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4925 * routes that are filtered. This tanks out Quagga RS pretty badly due
4927 * the iteration over all RS clients.
4928 * Since we need to remove the entry from adj_in anyway, do that first
4930 * if there was no entry, we don't need to do anything more.
4932 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4933 && peer
!= bgp
->peer_self
)
4934 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4935 peer
->stat_pfx_dup_withdraw
++;
4937 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4938 bgp_debug_rdpfxpath2str(
4939 afi
, safi
, prd
, p
, label
, num_labels
,
4940 addpath_id
? 1 : 0, addpath_id
, NULL
,
4941 pfx_buf
, sizeof(pfx_buf
));
4943 "%s withdrawing route %s not in adj-in",
4944 peer
->host
, pfx_buf
);
4946 bgp_dest_unlock_node(dest
);
4950 /* Lookup withdrawn route. */
4951 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4952 if (pi
->peer
== peer
&& pi
->type
== type
4953 && pi
->sub_type
== sub_type
4954 && pi
->addpath_rx_id
== addpath_id
)
4958 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4959 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4960 addpath_id
? 1 : 0, addpath_id
, NULL
,
4961 pfx_buf
, sizeof(pfx_buf
));
4962 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
4966 /* Withdraw specified route from routing table. */
4967 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4968 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4969 if (SAFI_UNICAST
== safi
4970 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4971 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4972 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4974 if ((SAFI_MPLS_VPN
== safi
)
4975 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4977 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4979 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4980 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4981 addpath_id
? 1 : 0, addpath_id
, NULL
,
4982 pfx_buf
, sizeof(pfx_buf
));
4983 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4986 /* Unlock bgp_node_get() lock. */
4987 bgp_dest_unlock_node(dest
);
4992 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4995 struct update_subgroup
*subgrp
;
4996 subgrp
= peer_subgroup(peer
, afi
, safi
);
4997 subgroup_default_originate(subgrp
, withdraw
);
5002 * bgp_stop_announce_route_timer
5004 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5006 if (!paf
->t_announce_route
)
5009 THREAD_OFF(paf
->t_announce_route
);
5013 * bgp_announce_route_timer_expired
5015 * Callback that is invoked when the route announcement timer for a
5018 static void bgp_announce_route_timer_expired(struct thread
*t
)
5020 struct peer_af
*paf
;
5023 paf
= THREAD_ARG(t
);
5026 if (!peer_established(peer
))
5029 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5032 peer_af_announce_route(paf
, 1);
5034 /* Notify BGP conditional advertisement scanner percess */
5035 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5039 * bgp_announce_route
5041 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5043 * if force is true we will force an update even if the update
5044 * limiting code is attempted to kick in.
5046 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5048 struct peer_af
*paf
;
5049 struct update_subgroup
*subgrp
;
5051 paf
= peer_af_find(peer
, afi
, safi
);
5054 subgrp
= PAF_SUBGRP(paf
);
5057 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5058 * or a refresh has already been triggered.
5060 if (!subgrp
|| paf
->t_announce_route
)
5064 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5067 * Start a timer to stagger/delay the announce. This serves
5068 * two purposes - announcement can potentially be combined for
5069 * multiple peers and the announcement doesn't happen in the
5072 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5073 (subgrp
->peer_count
== 1)
5074 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5075 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5076 &paf
->t_announce_route
);
5080 * Announce routes from all AF tables to a peer.
5082 * This should ONLY be called when there is a need to refresh the
5083 * routes to the peer based on a policy change for this peer alone
5084 * or a route refresh request received from the peer.
5085 * The operation will result in splitting the peer from its existing
5086 * subgroups and putting it in new subgroups.
5088 void bgp_announce_route_all(struct peer
*peer
)
5093 FOREACH_AFI_SAFI (afi
, safi
)
5094 bgp_announce_route(peer
, afi
, safi
, false);
5097 /* Flag or unflag bgp_dest to determine whether it should be treated by
5098 * bgp_soft_reconfig_table_task.
5099 * Flag if flag is true. Unflag if flag is false.
5101 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5103 struct bgp_dest
*dest
;
5104 struct bgp_adj_in
*ain
;
5109 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5110 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5111 if (ain
->peer
!= NULL
)
5114 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5115 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5117 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5121 static int bgp_soft_reconfig_table_update(struct peer
*peer
,
5122 struct bgp_dest
*dest
,
5123 struct bgp_adj_in
*ain
, afi_t afi
,
5124 safi_t safi
, struct prefix_rd
*prd
)
5126 struct bgp_path_info
*pi
;
5127 uint32_t num_labels
= 0;
5128 mpls_label_t
*label_pnt
= NULL
;
5129 struct bgp_route_evpn evpn
;
5131 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5132 if (pi
->peer
== peer
)
5135 if (pi
&& pi
->extra
)
5136 num_labels
= pi
->extra
->num_labels
;
5138 label_pnt
= &pi
->extra
->label
[0];
5140 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5143 memset(&evpn
, 0, sizeof(evpn
));
5145 return bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5146 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
5147 BGP_ROUTE_NORMAL
, prd
, label_pnt
, num_labels
, 1,
5151 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5152 struct bgp_table
*table
,
5153 struct prefix_rd
*prd
)
5156 struct bgp_dest
*dest
;
5157 struct bgp_adj_in
*ain
;
5160 table
= peer
->bgp
->rib
[afi
][safi
];
5162 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5163 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5164 if (ain
->peer
!= peer
)
5167 ret
= bgp_soft_reconfig_table_update(peer
, dest
, ain
,
5171 bgp_dest_unlock_node(dest
);
5177 /* Do soft reconfig table per bgp table.
5178 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5179 * when BGP_NODE_SOFT_RECONFIG is set,
5180 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5181 * Schedule a new thread to continue the job.
5182 * Without splitting the full job into several part,
5183 * vtysh waits for the job to finish before responding to a BGP command
5185 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
5187 uint32_t iter
, max_iter
;
5189 struct bgp_dest
*dest
;
5190 struct bgp_adj_in
*ain
;
5192 struct bgp_table
*table
;
5193 struct prefix_rd
*prd
;
5194 struct listnode
*node
, *nnode
;
5196 table
= THREAD_ARG(thread
);
5199 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5200 if (table
->soft_reconfig_init
) {
5201 /* first call of the function with a new srta structure.
5202 * Don't do any treatment this time on nodes
5203 * in order vtysh to respond quickly
5208 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5209 dest
= bgp_route_next(dest
)) {
5210 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5213 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5215 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5216 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5218 if (ain
->peer
!= peer
)
5221 ret
= bgp_soft_reconfig_table_update(
5222 peer
, dest
, ain
, table
->afi
,
5227 bgp_dest_unlock_node(dest
);
5229 table
->soft_reconfig_peers
,
5231 bgp_announce_route(peer
, table
->afi
,
5232 table
->safi
, false);
5234 table
->soft_reconfig_peers
)) {
5236 &table
->soft_reconfig_peers
);
5237 bgp_soft_reconfig_table_flag(
5246 /* we're either starting the initial iteration,
5247 * or we're going to continue an ongoing iteration
5249 if (dest
|| table
->soft_reconfig_init
) {
5250 table
->soft_reconfig_init
= false;
5251 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
5252 table
, 0, &table
->soft_reconfig_thread
);
5255 /* we're done, clean up the background iteration context info and
5256 schedule route annoucement
5258 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5259 listnode_delete(table
->soft_reconfig_peers
, peer
);
5260 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5263 list_delete(&table
->soft_reconfig_peers
);
5267 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5269 * - bgp cannot be NULL
5270 * - if table and peer are NULL, cancel all threads within the bgp instance
5271 * - if table is NULL and peer is not,
5272 * remove peer in all threads within the bgp instance
5273 * - if peer is NULL, cancel all threads matching table within the bgp instance
5275 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5276 const struct bgp_table
*table
,
5277 const struct peer
*peer
)
5280 struct listnode
*node
, *nnode
;
5282 struct bgp_table
*ntable
;
5287 FOREACH_AFI_SAFI (afi
, safi
) {
5288 ntable
= bgp
->rib
[afi
][safi
];
5291 if (table
&& table
!= ntable
)
5294 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5296 if (peer
&& peer
!= npeer
)
5298 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5301 if (!ntable
->soft_reconfig_peers
5302 || !list_isempty(ntable
->soft_reconfig_peers
))
5305 list_delete(&ntable
->soft_reconfig_peers
);
5306 bgp_soft_reconfig_table_flag(ntable
, false);
5307 THREAD_OFF(ntable
->soft_reconfig_thread
);
5312 * Returns false if the peer is not configured for soft reconfig in
5314 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5316 struct bgp_dest
*dest
;
5317 struct bgp_table
*table
;
5318 struct listnode
*node
, *nnode
;
5320 struct peer_af
*paf
;
5322 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5325 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5326 && (safi
!= SAFI_EVPN
)) {
5327 table
= peer
->bgp
->rib
[afi
][safi
];
5331 table
->soft_reconfig_init
= true;
5333 if (!table
->soft_reconfig_peers
)
5334 table
->soft_reconfig_peers
= list_new();
5336 /* add peer to the table soft_reconfig_peers if not already
5339 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5345 listnode_add(table
->soft_reconfig_peers
, peer
);
5347 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5348 * on table would start back at the beginning.
5350 bgp_soft_reconfig_table_flag(table
, true);
5352 if (!table
->soft_reconfig_thread
)
5353 thread_add_event(bm
->master
,
5354 bgp_soft_reconfig_table_task
, table
, 0,
5355 &table
->soft_reconfig_thread
);
5356 /* Cancel bgp_announce_route_timer_expired threads.
5357 * bgp_announce_route_timer_expired threads have been scheduled
5358 * to announce routes as soon as the soft_reconfigure process
5360 * In this case, soft_reconfigure is also scheduled by using
5361 * a thread but is planned after the
5362 * bgp_announce_route_timer_expired threads. It means that,
5363 * without cancelling the threads, the route announcement task
5364 * would run before the soft reconfiguration one. That would
5365 * useless and would block vtysh during several seconds. Route
5366 * announcements are rescheduled as soon as the soft_reconfigure
5369 paf
= peer_af_find(peer
, afi
, safi
);
5371 bgp_stop_announce_route_timer(paf
);
5373 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5374 dest
= bgp_route_next(dest
)) {
5375 table
= bgp_dest_get_bgp_table_info(dest
);
5380 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5381 struct prefix_rd prd
;
5383 prd
.family
= AF_UNSPEC
;
5385 memcpy(&prd
.val
, p
->u
.val
, 8);
5387 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5394 struct bgp_clear_node_queue
{
5395 struct bgp_dest
*dest
;
5398 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5400 struct bgp_clear_node_queue
*cnq
= data
;
5401 struct bgp_dest
*dest
= cnq
->dest
;
5402 struct peer
*peer
= wq
->spec
.data
;
5403 struct bgp_path_info
*pi
;
5405 afi_t afi
= bgp_dest_table(dest
)->afi
;
5406 safi_t safi
= bgp_dest_table(dest
)->safi
;
5408 assert(dest
&& peer
);
5411 /* It is possible that we have multiple paths for a prefix from a peer
5412 * if that peer is using AddPath.
5414 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5415 if (pi
->peer
!= peer
)
5418 /* graceful restart STALE flag set. */
5419 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5420 && peer
->nsf
[afi
][safi
])
5421 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5422 PEER_STATUS_ENHANCED_REFRESH
))
5423 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5424 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5425 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5427 /* If this is an EVPN route, process for
5429 if (safi
== SAFI_EVPN
)
5430 bgp_evpn_unimport_route(
5432 bgp_dest_get_prefix(dest
), pi
);
5433 /* Handle withdraw for VRF route-leaking and L3VPN */
5434 if (SAFI_UNICAST
== safi
5435 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5436 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5437 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5440 if (SAFI_MPLS_VPN
== safi
&&
5441 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5442 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5445 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5451 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5453 struct bgp_clear_node_queue
*cnq
= data
;
5454 struct bgp_dest
*dest
= cnq
->dest
;
5455 struct bgp_table
*table
= bgp_dest_table(dest
);
5457 bgp_dest_unlock_node(dest
);
5458 bgp_table_unlock(table
);
5459 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5462 static void bgp_clear_node_complete(struct work_queue
*wq
)
5464 struct peer
*peer
= wq
->spec
.data
;
5466 /* Tickle FSM to start moving again */
5467 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5469 peer_unlock(peer
); /* bgp_clear_route */
5472 static void bgp_clear_node_queue_init(struct peer
*peer
)
5474 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5476 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5477 #undef CLEAR_QUEUE_NAME_LEN
5479 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5480 peer
->clear_node_queue
->spec
.hold
= 10;
5481 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5482 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5483 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5484 peer
->clear_node_queue
->spec
.max_retries
= 0;
5486 /* we only 'lock' this peer reference when the queue is actually active
5488 peer
->clear_node_queue
->spec
.data
= peer
;
5491 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5492 struct bgp_table
*table
)
5494 struct bgp_dest
*dest
;
5495 int force
= peer
->bgp
->process_queue
? 0 : 1;
5498 table
= peer
->bgp
->rib
[afi
][safi
];
5500 /* If still no table => afi/safi isn't configured at all or smth. */
5504 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5505 struct bgp_path_info
*pi
, *next
;
5506 struct bgp_adj_in
*ain
;
5507 struct bgp_adj_in
*ain_next
;
5509 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5510 * queued for every clearing peer, regardless of whether it is
5511 * relevant to the peer at hand.
5513 * Overview: There are 3 different indices which need to be
5514 * scrubbed, potentially, when a peer is removed:
5516 * 1 peer's routes visible via the RIB (ie accepted routes)
5517 * 2 peer's routes visible by the (optional) peer's adj-in index
5518 * 3 other routes visible by the peer's adj-out index
5520 * 3 there is no hurry in scrubbing, once the struct peer is
5521 * removed from bgp->peer, we could just GC such deleted peer's
5522 * adj-outs at our leisure.
5524 * 1 and 2 must be 'scrubbed' in some way, at least made
5525 * invisible via RIB index before peer session is allowed to be
5526 * brought back up. So one needs to know when such a 'search' is
5531 * - there'd be a single global queue or a single RIB walker
5532 * - rather than tracking which route_nodes still need to be
5533 * examined on a peer basis, we'd track which peers still
5536 * Given that our per-peer prefix-counts now should be reliable,
5537 * this may actually be achievable. It doesn't seem to be a huge
5538 * problem at this time,
5540 * It is possible that we have multiple paths for a prefix from
5542 * if that peer is using AddPath.
5546 ain_next
= ain
->next
;
5548 if (ain
->peer
== peer
)
5549 bgp_adj_in_remove(dest
, ain
);
5554 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5556 if (pi
->peer
!= peer
)
5560 bgp_path_info_reap(dest
, pi
);
5562 struct bgp_clear_node_queue
*cnq
;
5564 /* both unlocked in bgp_clear_node_queue_del */
5565 bgp_table_lock(bgp_dest_table(dest
));
5566 bgp_dest_lock_node(dest
);
5568 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5569 sizeof(struct bgp_clear_node_queue
));
5571 work_queue_add(peer
->clear_node_queue
, cnq
);
5579 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5581 struct bgp_dest
*dest
;
5582 struct bgp_table
*table
;
5584 if (peer
->clear_node_queue
== NULL
)
5585 bgp_clear_node_queue_init(peer
);
5587 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5588 * Idle until it receives a Clearing_Completed event. This protects
5589 * against peers which flap faster than we can we clear, which could
5592 * a) race with routes from the new session being installed before
5593 * clear_route_node visits the node (to delete the route of that
5595 * b) resource exhaustion, clear_route_node likely leads to an entry
5596 * on the process_main queue. Fast-flapping could cause that queue
5600 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5601 * the unlock will happen upon work-queue completion; other wise, the
5602 * unlock happens at the end of this function.
5604 if (!peer
->clear_node_queue
->thread
)
5607 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5608 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5610 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5611 dest
= bgp_route_next(dest
)) {
5612 table
= bgp_dest_get_bgp_table_info(dest
);
5616 bgp_clear_route_table(peer
, afi
, safi
, table
);
5619 /* unlock if no nodes got added to the clear-node-queue. */
5620 if (!peer
->clear_node_queue
->thread
)
5624 void bgp_clear_route_all(struct peer
*peer
)
5629 FOREACH_AFI_SAFI (afi
, safi
)
5630 bgp_clear_route(peer
, afi
, safi
);
5632 #ifdef ENABLE_BGP_VNC
5633 rfapiProcessPeerDown(peer
);
5637 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5639 struct bgp_table
*table
;
5640 struct bgp_dest
*dest
;
5641 struct bgp_adj_in
*ain
;
5642 struct bgp_adj_in
*ain_next
;
5644 table
= peer
->bgp
->rib
[afi
][safi
];
5646 /* It is possible that we have multiple paths for a prefix from a peer
5647 * if that peer is using AddPath.
5649 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5653 ain_next
= ain
->next
;
5655 if (ain
->peer
== peer
)
5656 bgp_adj_in_remove(dest
, ain
);
5663 /* If any of the routes from the peer have been marked with the NO_LLGR
5664 * community, either as sent by the peer, or as the result of a configured
5665 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5666 * operation of [RFC4271].
5668 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5670 struct bgp_dest
*dest
;
5671 struct bgp_path_info
*pi
;
5672 struct bgp_table
*table
;
5674 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5675 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5676 dest
= bgp_route_next(dest
)) {
5677 struct bgp_dest
*rm
;
5679 /* look for neighbor in tables */
5680 table
= bgp_dest_get_bgp_table_info(dest
);
5684 for (rm
= bgp_table_top(table
); rm
;
5685 rm
= bgp_route_next(rm
))
5686 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5688 if (pi
->peer
!= peer
)
5691 peer
->af_sflags
[afi
][safi
],
5692 PEER_STATUS_LLGR_WAIT
) &&
5693 bgp_attr_get_community(pi
->attr
) &&
5695 bgp_attr_get_community(
5699 if (!CHECK_FLAG(pi
->flags
,
5704 * If this is VRF leaked route
5705 * process for withdraw.
5708 BGP_ROUTE_IMPORTED
&&
5709 peer
->bgp
->inst_type
==
5710 BGP_INSTANCE_TYPE_DEFAULT
)
5711 vpn_leak_to_vrf_withdraw(
5714 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5719 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5720 dest
= bgp_route_next(dest
))
5721 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5723 if (pi
->peer
!= peer
)
5725 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5726 PEER_STATUS_LLGR_WAIT
) &&
5727 bgp_attr_get_community(pi
->attr
) &&
5729 bgp_attr_get_community(pi
->attr
),
5732 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5734 if (safi
== SAFI_UNICAST
&&
5735 (peer
->bgp
->inst_type
==
5736 BGP_INSTANCE_TYPE_VRF
||
5737 peer
->bgp
->inst_type
==
5738 BGP_INSTANCE_TYPE_DEFAULT
))
5739 vpn_leak_from_vrf_withdraw(
5740 bgp_get_default(), peer
->bgp
,
5743 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5749 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5751 struct bgp_dest
*dest
, *ndest
;
5752 struct bgp_path_info
*pi
;
5753 struct bgp_table
*table
;
5755 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5756 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5757 dest
= bgp_route_next(dest
)) {
5758 table
= bgp_dest_get_bgp_table_info(dest
);
5762 for (ndest
= bgp_table_top(table
); ndest
;
5763 ndest
= bgp_route_next(ndest
)) {
5764 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5766 if (pi
->peer
!= peer
)
5770 peer
->af_sflags
[afi
][safi
],
5771 PEER_STATUS_ENHANCED_REFRESH
))
5772 && !CHECK_FLAG(pi
->flags
,
5776 BGP_PATH_UNUSEABLE
)) {
5777 if (bgp_debug_neighbor_events(
5780 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5784 bgp_dest_get_prefix(
5787 bgp_path_info_set_flag(
5795 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5796 dest
= bgp_route_next(dest
)) {
5797 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5799 if (pi
->peer
!= peer
)
5802 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5803 PEER_STATUS_ENHANCED_REFRESH
))
5804 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5805 && !CHECK_FLAG(pi
->flags
,
5806 BGP_PATH_UNUSEABLE
)) {
5807 if (bgp_debug_neighbor_events(peer
))
5809 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5812 bgp_dest_get_prefix(
5815 bgp_path_info_set_flag(dest
, pi
,
5823 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5825 if (peer
->sort
== BGP_PEER_IBGP
)
5828 if (peer
->sort
== BGP_PEER_EBGP
5829 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5830 || FILTER_LIST_OUT_NAME(filter
)
5831 || DISTRIBUTE_OUT_NAME(filter
)))
5836 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5838 if (peer
->sort
== BGP_PEER_IBGP
)
5841 if (peer
->sort
== BGP_PEER_EBGP
5842 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5843 || FILTER_LIST_IN_NAME(filter
)
5844 || DISTRIBUTE_IN_NAME(filter
)))
5849 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5852 struct bgp_dest
*dest
;
5853 struct bgp_path_info
*pi
;
5854 struct bgp_path_info
*next
;
5856 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5857 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5858 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5862 /* Unimport EVPN routes from VRFs */
5863 if (safi
== SAFI_EVPN
)
5864 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5867 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5868 && pi
->type
== ZEBRA_ROUTE_BGP
5869 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5870 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5871 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5873 if (bgp_fibupd_safi(safi
))
5874 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5877 bgp_path_info_reap(dest
, pi
);
5881 /* Delete all kernel routes. */
5882 void bgp_cleanup_routes(struct bgp
*bgp
)
5885 struct bgp_dest
*dest
;
5886 struct bgp_table
*table
;
5888 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5889 if (afi
== AFI_L2VPN
)
5891 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5894 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5896 if (afi
!= AFI_L2VPN
) {
5898 safi
= SAFI_MPLS_VPN
;
5899 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5900 dest
= bgp_route_next(dest
)) {
5901 table
= bgp_dest_get_bgp_table_info(dest
);
5902 if (table
!= NULL
) {
5903 bgp_cleanup_table(bgp
, table
, safi
);
5904 bgp_table_finish(&table
);
5905 bgp_dest_set_bgp_table_info(dest
, NULL
);
5906 bgp_dest_unlock_node(dest
);
5910 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5911 dest
= bgp_route_next(dest
)) {
5912 table
= bgp_dest_get_bgp_table_info(dest
);
5913 if (table
!= NULL
) {
5914 bgp_cleanup_table(bgp
, table
, safi
);
5915 bgp_table_finish(&table
);
5916 bgp_dest_set_bgp_table_info(dest
, NULL
);
5917 bgp_dest_unlock_node(dest
);
5922 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5923 dest
= bgp_route_next(dest
)) {
5924 table
= bgp_dest_get_bgp_table_info(dest
);
5925 if (table
!= NULL
) {
5926 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5927 bgp_table_finish(&table
);
5928 bgp_dest_set_bgp_table_info(dest
, NULL
);
5929 bgp_dest_unlock_node(dest
);
5934 void bgp_reset(void)
5937 bgp_zclient_reset();
5938 access_list_reset();
5939 prefix_list_reset();
5942 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5944 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5945 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5946 PEER_CAP_ADDPATH_AF_TX_RCV
));
5949 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5951 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5952 struct bgp_nlri
*packet
)
5961 bool addpath_capable
;
5962 uint32_t addpath_id
;
5965 lim
= pnt
+ packet
->length
;
5967 safi
= packet
->safi
;
5969 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5971 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5972 syntactic validity. If the field is syntactically incorrect,
5973 then the Error Subcode is set to Invalid Network Field. */
5974 for (; pnt
< lim
; pnt
+= psize
) {
5975 /* Clear prefix structure. */
5976 memset(&p
, 0, sizeof(p
));
5978 if (addpath_capable
) {
5980 /* When packet overflow occurs return immediately. */
5981 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5982 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5984 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5985 addpath_id
= ntohl(addpath_id
);
5986 pnt
+= BGP_ADDPATH_ID_LEN
;
5989 /* Fetch prefix length. */
5990 p
.prefixlen
= *pnt
++;
5991 /* afi/safi validity already verified by caller,
5992 * bgp_update_receive */
5993 p
.family
= afi2family(afi
);
5995 /* Prefix length check. */
5996 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5999 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
6000 peer
->host
, p
.prefixlen
, packet
->afi
);
6001 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
6004 /* Packet size overflow check. */
6005 psize
= PSIZE(p
.prefixlen
);
6007 /* When packet overflow occur return immediately. */
6008 if (pnt
+ psize
> lim
) {
6011 "%s [Error] Update packet error (prefix length %d overflows packet)",
6012 peer
->host
, p
.prefixlen
);
6013 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6016 /* Defensive coding, double-check the psize fits in a struct
6017 * prefix for the v4 and v6 afi's and unicast/multicast */
6018 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6021 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6022 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6023 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6026 /* Fetch prefix from NLRI packet. */
6027 memcpy(p
.u
.val
, pnt
, psize
);
6029 /* Check address. */
6030 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6031 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6032 /* From RFC4271 Section 6.3:
6034 * If a prefix in the NLRI field is semantically
6036 * (e.g., an unexpected multicast IP address),
6038 * be logged locally, and the prefix SHOULD be
6043 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6044 peer
->host
, &p
.u
.prefix4
);
6049 /* Check address. */
6050 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6051 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6054 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6055 peer
->host
, &p
.u
.prefix6
);
6059 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6062 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6063 peer
->host
, &p
.u
.prefix6
);
6069 /* Normal process. */
6071 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6072 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
6073 NULL
, NULL
, 0, 0, NULL
);
6075 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
6076 safi
, ZEBRA_ROUTE_BGP
,
6077 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
6080 /* Do not send BGP notification twice when maximum-prefix count
6082 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6083 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6085 /* Address family configuration mismatch. */
6087 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
6090 /* Packet length consistency check. */
6094 "%s [Error] Update packet error (prefix length mismatch with total length)",
6096 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6099 return BGP_NLRI_PARSE_OK
;
6102 static struct bgp_static
*bgp_static_new(void)
6104 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6107 static void bgp_static_free(struct bgp_static
*bgp_static
)
6109 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6110 route_map_counter_decrement(bgp_static
->rmap
.map
);
6112 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6113 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6116 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6117 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6119 struct bgp_dest
*dest
;
6120 struct bgp_path_info
*pi
;
6121 struct bgp_path_info
*new;
6122 struct bgp_path_info rmap_path
;
6124 struct attr
*attr_new
;
6125 route_map_result_t ret
;
6126 #ifdef ENABLE_BGP_VNC
6127 int vnc_implicit_withdraw
= 0;
6132 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6134 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6136 attr
.nexthop
= bgp_static
->igpnexthop
;
6137 attr
.med
= bgp_static
->igpmetric
;
6138 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6141 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6143 if (bgp_static
->igpmetric
)
6144 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6146 if (bgp_static
->atomic
)
6147 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6149 /* Store label index, if required. */
6150 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6151 attr
.label_index
= bgp_static
->label_index
;
6152 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6155 /* Apply route-map. */
6156 if (bgp_static
->rmap
.name
) {
6157 struct attr attr_tmp
= attr
;
6159 memset(&rmap_path
, 0, sizeof(rmap_path
));
6160 rmap_path
.peer
= bgp
->peer_self
;
6161 rmap_path
.attr
= &attr_tmp
;
6163 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6165 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6167 bgp
->peer_self
->rmap_type
= 0;
6169 if (ret
== RMAP_DENYMATCH
) {
6170 /* Free uninterned attribute. */
6171 bgp_attr_flush(&attr_tmp
);
6173 /* Unintern original. */
6174 aspath_unintern(&attr
.aspath
);
6175 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6176 bgp_dest_unlock_node(dest
);
6180 if (bgp_in_graceful_shutdown(bgp
))
6181 bgp_attr_add_gshut_community(&attr_tmp
);
6183 attr_new
= bgp_attr_intern(&attr_tmp
);
6186 if (bgp_in_graceful_shutdown(bgp
))
6187 bgp_attr_add_gshut_community(&attr
);
6189 attr_new
= bgp_attr_intern(&attr
);
6192 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6193 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6194 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6198 if (attrhash_cmp(pi
->attr
, attr_new
)
6199 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6200 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6201 bgp_dest_unlock_node(dest
);
6202 bgp_attr_unintern(&attr_new
);
6203 aspath_unintern(&attr
.aspath
);
6206 /* The attribute is changed. */
6207 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6209 /* Rewrite BGP route information. */
6210 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6211 bgp_path_info_restore(dest
, pi
);
6213 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6214 #ifdef ENABLE_BGP_VNC
6215 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6216 && (safi
== SAFI_UNICAST
)) {
6217 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6219 * Implicit withdraw case.
6220 * We have to do this before pi is
6223 ++vnc_implicit_withdraw
;
6224 vnc_import_bgp_del_route(bgp
, p
, pi
);
6225 vnc_import_bgp_exterior_del_route(
6230 bgp_attr_unintern(&pi
->attr
);
6231 pi
->attr
= attr_new
;
6232 pi
->uptime
= monotime(NULL
);
6233 #ifdef ENABLE_BGP_VNC
6234 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6235 && (safi
== SAFI_UNICAST
)) {
6236 if (vnc_implicit_withdraw
) {
6237 vnc_import_bgp_add_route(bgp
, p
, pi
);
6238 vnc_import_bgp_exterior_add_route(
6244 /* Nexthop reachability check. */
6245 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6246 && (safi
== SAFI_UNICAST
6247 || safi
== SAFI_LABELED_UNICAST
)) {
6249 struct bgp
*bgp_nexthop
= bgp
;
6251 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6252 bgp_nexthop
= pi
->extra
->bgp_orig
;
6254 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6255 afi
, safi
, pi
, NULL
,
6257 bgp_path_info_set_flag(dest
, pi
,
6260 if (BGP_DEBUG(nht
, NHT
)) {
6261 char buf1
[INET6_ADDRSTRLEN
];
6262 inet_ntop(p
->family
,
6266 "%s(%s): Route not in table, not advertising",
6269 bgp_path_info_unset_flag(
6270 dest
, pi
, BGP_PATH_VALID
);
6273 /* Delete the NHT structure if any, if we're
6275 * enabling/disabling import check. We
6276 * deregister the route
6277 * from NHT to avoid overloading NHT and the
6278 * process interaction
6280 bgp_unlink_nexthop(pi
);
6281 bgp_path_info_set_flag(dest
, pi
,
6284 /* Process change. */
6285 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6286 bgp_process(bgp
, dest
, afi
, safi
);
6288 if (SAFI_UNICAST
== safi
6289 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6291 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6292 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6296 bgp_dest_unlock_node(dest
);
6297 aspath_unintern(&attr
.aspath
);
6302 /* Make new BGP info. */
6303 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6305 /* Nexthop reachability check. */
6306 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6307 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6308 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6310 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6312 if (BGP_DEBUG(nht
, NHT
)) {
6313 char buf1
[INET6_ADDRSTRLEN
];
6315 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6318 "%s(%s): Route not in table, not advertising",
6321 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6324 /* Delete the NHT structure if any, if we're toggling between
6325 * enabling/disabling import check. We deregister the route
6326 * from NHT to avoid overloading NHT and the process interaction
6328 bgp_unlink_nexthop(new);
6330 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6333 /* Aggregate address increment. */
6334 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6336 /* Register new BGP information. */
6337 bgp_path_info_add(dest
, new);
6339 /* route_node_get lock */
6340 bgp_dest_unlock_node(dest
);
6342 /* Process change. */
6343 bgp_process(bgp
, dest
, afi
, safi
);
6345 if (SAFI_UNICAST
== safi
6346 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6347 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6348 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6351 /* Unintern original. */
6352 aspath_unintern(&attr
.aspath
);
6355 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6358 struct bgp_dest
*dest
;
6359 struct bgp_path_info
*pi
;
6361 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6363 /* Check selected route and self inserted route. */
6364 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6365 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6366 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6369 /* Withdraw static BGP route from routing table. */
6371 if (SAFI_UNICAST
== safi
6372 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6373 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6374 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6376 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6377 bgp_unlink_nexthop(pi
);
6378 bgp_path_info_delete(dest
, pi
);
6379 bgp_process(bgp
, dest
, afi
, safi
);
6382 /* Unlock bgp_node_lookup. */
6383 bgp_dest_unlock_node(dest
);
6387 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6389 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6390 afi_t afi
, safi_t safi
,
6391 struct prefix_rd
*prd
)
6393 struct bgp_dest
*dest
;
6394 struct bgp_path_info
*pi
;
6396 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6398 /* Check selected route and self inserted route. */
6399 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6400 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6401 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6404 /* Withdraw static BGP route from routing table. */
6406 #ifdef ENABLE_BGP_VNC
6407 rfapiProcessWithdraw(
6408 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6409 1); /* Kill, since it is an administrative change */
6411 if (SAFI_MPLS_VPN
== safi
6412 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6413 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6415 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6416 bgp_path_info_delete(dest
, pi
);
6417 bgp_process(bgp
, dest
, afi
, safi
);
6420 /* Unlock bgp_node_lookup. */
6421 bgp_dest_unlock_node(dest
);
6424 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6425 struct bgp_static
*bgp_static
, afi_t afi
,
6428 struct bgp_dest
*dest
;
6429 struct bgp_path_info
*new;
6430 struct attr
*attr_new
;
6431 struct attr attr
= {0};
6432 struct bgp_path_info
*pi
;
6433 #ifdef ENABLE_BGP_VNC
6434 mpls_label_t label
= 0;
6436 uint32_t num_labels
= 0;
6440 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6442 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6445 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6447 attr
.nexthop
= bgp_static
->igpnexthop
;
6448 attr
.med
= bgp_static
->igpmetric
;
6449 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6451 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6452 || (safi
== SAFI_ENCAP
)) {
6453 if (afi
== AFI_IP
) {
6454 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6455 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6458 if (afi
== AFI_L2VPN
) {
6459 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6460 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6461 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6462 &bgp_static
->gatewayIp
.u
.prefix4
,
6464 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6465 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6466 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6467 &bgp_static
->gatewayIp
.u
.prefix6
,
6470 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6471 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6472 struct bgp_encap_type_vxlan bet
;
6473 memset(&bet
, 0, sizeof(bet
));
6474 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6475 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6477 if (bgp_static
->router_mac
) {
6478 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6481 /* Apply route-map. */
6482 if (bgp_static
->rmap
.name
) {
6483 struct attr attr_tmp
= attr
;
6484 struct bgp_path_info rmap_path
;
6485 route_map_result_t ret
;
6487 rmap_path
.peer
= bgp
->peer_self
;
6488 rmap_path
.attr
= &attr_tmp
;
6490 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6492 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6494 bgp
->peer_self
->rmap_type
= 0;
6496 if (ret
== RMAP_DENYMATCH
) {
6497 /* Free uninterned attribute. */
6498 bgp_attr_flush(&attr_tmp
);
6500 /* Unintern original. */
6501 aspath_unintern(&attr
.aspath
);
6502 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6504 bgp_dest_unlock_node(dest
);
6508 attr_new
= bgp_attr_intern(&attr_tmp
);
6510 attr_new
= bgp_attr_intern(&attr
);
6513 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6514 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6515 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6519 if (attrhash_cmp(pi
->attr
, attr_new
)
6520 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6521 bgp_dest_unlock_node(dest
);
6522 bgp_attr_unintern(&attr_new
);
6523 aspath_unintern(&attr
.aspath
);
6526 /* The attribute is changed. */
6527 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6529 /* Rewrite BGP route information. */
6530 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6531 bgp_path_info_restore(dest
, pi
);
6533 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6534 bgp_attr_unintern(&pi
->attr
);
6535 pi
->attr
= attr_new
;
6536 pi
->uptime
= monotime(NULL
);
6537 #ifdef ENABLE_BGP_VNC
6539 label
= decode_label(&pi
->extra
->label
[0]);
6542 /* Process change. */
6543 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6544 bgp_process(bgp
, dest
, afi
, safi
);
6546 if (SAFI_MPLS_VPN
== safi
6547 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6548 vpn_leak_to_vrf_update(bgp
, pi
,
6551 #ifdef ENABLE_BGP_VNC
6552 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6553 pi
->attr
, afi
, safi
, pi
->type
,
6554 pi
->sub_type
, &label
);
6556 bgp_dest_unlock_node(dest
);
6557 aspath_unintern(&attr
.aspath
);
6563 /* Make new BGP info. */
6564 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6566 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6567 bgp_path_info_extra_get(new);
6569 new->extra
->label
[0] = bgp_static
->label
;
6570 new->extra
->num_labels
= num_labels
;
6572 #ifdef ENABLE_BGP_VNC
6573 label
= decode_label(&bgp_static
->label
);
6576 /* Aggregate address increment. */
6577 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6579 /* Register new BGP information. */
6580 bgp_path_info_add(dest
, new);
6581 /* route_node_get lock */
6582 bgp_dest_unlock_node(dest
);
6584 /* Process change. */
6585 bgp_process(bgp
, dest
, afi
, safi
);
6587 if (SAFI_MPLS_VPN
== safi
6588 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6589 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6591 #ifdef ENABLE_BGP_VNC
6592 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6593 safi
, new->type
, new->sub_type
, &label
);
6596 /* Unintern original. */
6597 aspath_unintern(&attr
.aspath
);
6600 /* Configure static BGP network. When user don't run zebra, static
6601 route should be installed as valid. */
6602 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6603 const char *ip_str
, afi_t afi
, safi_t safi
,
6604 const char *rmap
, int backdoor
, uint32_t label_index
)
6606 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6609 struct bgp_static
*bgp_static
;
6610 struct bgp_dest
*dest
;
6611 uint8_t need_update
= 0;
6613 /* Convert IP prefix string to struct prefix. */
6614 ret
= str2prefix(ip_str
, &p
);
6616 vty_out(vty
, "%% Malformed prefix\n");
6617 return CMD_WARNING_CONFIG_FAILED
;
6619 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6620 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6621 return CMD_WARNING_CONFIG_FAILED
;
6628 /* Set BGP static route configuration. */
6629 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6632 vty_out(vty
, "%% Can't find static route specified\n");
6633 return CMD_WARNING_CONFIG_FAILED
;
6636 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6638 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6639 && (label_index
!= bgp_static
->label_index
)) {
6641 "%% label-index doesn't match static route\n");
6642 bgp_dest_unlock_node(dest
);
6643 return CMD_WARNING_CONFIG_FAILED
;
6646 if ((rmap
&& bgp_static
->rmap
.name
)
6647 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6649 "%% route-map name doesn't match static route\n");
6650 bgp_dest_unlock_node(dest
);
6651 return CMD_WARNING_CONFIG_FAILED
;
6654 /* Update BGP RIB. */
6655 if (!bgp_static
->backdoor
)
6656 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6658 /* Clear configuration. */
6659 bgp_static_free(bgp_static
);
6660 bgp_dest_set_bgp_static_info(dest
, NULL
);
6661 bgp_dest_unlock_node(dest
);
6662 bgp_dest_unlock_node(dest
);
6665 /* Set BGP static route configuration. */
6666 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6667 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6669 /* Configuration change. */
6670 /* Label index cannot be changed. */
6671 if (bgp_static
->label_index
!= label_index
) {
6672 vty_out(vty
, "%% cannot change label-index\n");
6673 bgp_dest_unlock_node(dest
);
6674 return CMD_WARNING_CONFIG_FAILED
;
6677 /* Check previous routes are installed into BGP. */
6678 if (bgp_static
->valid
6679 && bgp_static
->backdoor
!= backdoor
)
6682 bgp_static
->backdoor
= backdoor
;
6685 XFREE(MTYPE_ROUTE_MAP_NAME
,
6686 bgp_static
->rmap
.name
);
6687 route_map_counter_decrement(
6688 bgp_static
->rmap
.map
);
6689 bgp_static
->rmap
.name
=
6690 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6691 bgp_static
->rmap
.map
=
6692 route_map_lookup_by_name(rmap
);
6693 route_map_counter_increment(
6694 bgp_static
->rmap
.map
);
6696 XFREE(MTYPE_ROUTE_MAP_NAME
,
6697 bgp_static
->rmap
.name
);
6698 route_map_counter_decrement(
6699 bgp_static
->rmap
.map
);
6700 bgp_static
->rmap
.map
= NULL
;
6701 bgp_static
->valid
= 0;
6703 bgp_dest_unlock_node(dest
);
6705 /* New configuration. */
6706 bgp_static
= bgp_static_new();
6707 bgp_static
->backdoor
= backdoor
;
6708 bgp_static
->valid
= 0;
6709 bgp_static
->igpmetric
= 0;
6710 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6711 bgp_static
->label_index
= label_index
;
6714 XFREE(MTYPE_ROUTE_MAP_NAME
,
6715 bgp_static
->rmap
.name
);
6716 route_map_counter_decrement(
6717 bgp_static
->rmap
.map
);
6718 bgp_static
->rmap
.name
=
6719 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6720 bgp_static
->rmap
.map
=
6721 route_map_lookup_by_name(rmap
);
6722 route_map_counter_increment(
6723 bgp_static
->rmap
.map
);
6725 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6728 bgp_static
->valid
= 1;
6730 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6732 if (!bgp_static
->backdoor
)
6733 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6739 void bgp_static_add(struct bgp
*bgp
)
6743 struct bgp_dest
*dest
;
6744 struct bgp_dest
*rm
;
6745 struct bgp_table
*table
;
6746 struct bgp_static
*bgp_static
;
6748 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6749 FOREACH_AFI_SAFI (afi
, safi
)
6750 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6751 dest
= bgp_route_next(dest
)) {
6752 if (!bgp_dest_has_bgp_path_info_data(dest
))
6755 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6756 || (safi
== SAFI_EVPN
)) {
6757 table
= bgp_dest_get_bgp_table_info(dest
);
6759 for (rm
= bgp_table_top(table
); rm
;
6760 rm
= bgp_route_next(rm
)) {
6762 bgp_dest_get_bgp_static_info(
6764 bgp_static_update_safi(
6765 bgp
, bgp_dest_get_prefix(rm
),
6766 bgp_static
, afi
, safi
);
6770 bgp
, bgp_dest_get_prefix(dest
),
6771 bgp_dest_get_bgp_static_info(dest
), afi
,
6775 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6778 /* Called from bgp_delete(). Delete all static routes from the BGP
6780 void bgp_static_delete(struct bgp
*bgp
)
6784 struct bgp_dest
*dest
;
6785 struct bgp_dest
*rm
;
6786 struct bgp_table
*table
;
6787 struct bgp_static
*bgp_static
;
6789 FOREACH_AFI_SAFI (afi
, safi
)
6790 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6791 dest
= bgp_route_next(dest
)) {
6792 if (!bgp_dest_has_bgp_path_info_data(dest
))
6795 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6796 || (safi
== SAFI_EVPN
)) {
6797 table
= bgp_dest_get_bgp_table_info(dest
);
6799 for (rm
= bgp_table_top(table
); rm
;
6800 rm
= bgp_route_next(rm
)) {
6802 bgp_dest_get_bgp_static_info(
6807 bgp_static_withdraw_safi(
6808 bgp
, bgp_dest_get_prefix(rm
),
6810 (struct prefix_rd
*)
6811 bgp_dest_get_prefix(
6813 bgp_static_free(bgp_static
);
6814 bgp_dest_set_bgp_static_info(rm
,
6816 bgp_dest_unlock_node(rm
);
6819 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6820 bgp_static_withdraw(bgp
,
6821 bgp_dest_get_prefix(dest
),
6823 bgp_static_free(bgp_static
);
6824 bgp_dest_set_bgp_static_info(dest
, NULL
);
6825 bgp_dest_unlock_node(dest
);
6830 void bgp_static_redo_import_check(struct bgp
*bgp
)
6834 struct bgp_dest
*dest
;
6835 struct bgp_dest
*rm
;
6836 struct bgp_table
*table
;
6837 struct bgp_static
*bgp_static
;
6839 /* Use this flag to force reprocessing of the route */
6840 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6841 FOREACH_AFI_SAFI (afi
, safi
) {
6842 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6843 dest
= bgp_route_next(dest
)) {
6844 if (!bgp_dest_has_bgp_path_info_data(dest
))
6847 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6848 || (safi
== SAFI_EVPN
)) {
6849 table
= bgp_dest_get_bgp_table_info(dest
);
6851 for (rm
= bgp_table_top(table
); rm
;
6852 rm
= bgp_route_next(rm
)) {
6854 bgp_dest_get_bgp_static_info(
6856 bgp_static_update_safi(
6857 bgp
, bgp_dest_get_prefix(rm
),
6858 bgp_static
, afi
, safi
);
6861 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6862 bgp_static_update(bgp
,
6863 bgp_dest_get_prefix(dest
),
6864 bgp_static
, afi
, safi
);
6868 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6871 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6874 struct bgp_table
*table
;
6875 struct bgp_dest
*dest
;
6876 struct bgp_path_info
*pi
;
6878 /* Do not install the aggregate route if BGP is in the
6879 * process of termination.
6881 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6882 || (bgp
->peer_self
== NULL
))
6885 table
= bgp
->rib
[afi
][safi
];
6886 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6887 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6888 if (pi
->peer
== bgp
->peer_self
6889 && ((pi
->type
== ZEBRA_ROUTE_BGP
6890 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6891 || (pi
->type
!= ZEBRA_ROUTE_BGP
6893 == BGP_ROUTE_REDISTRIBUTE
))) {
6894 bgp_aggregate_decrement(
6895 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6897 bgp_unlink_nexthop(pi
);
6898 bgp_path_info_delete(dest
, pi
);
6899 bgp_process(bgp
, dest
, afi
, safi
);
6906 * Purge all networks and redistributed routes from routing table.
6907 * Invoked upon the instance going down.
6909 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6914 FOREACH_AFI_SAFI (afi
, safi
)
6915 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6920 * Currently this is used to set static routes for VPN and ENCAP.
6921 * I think it can probably be factored with bgp_static_set.
6923 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6924 const char *ip_str
, const char *rd_str
,
6925 const char *label_str
, const char *rmap_str
,
6926 int evpn_type
, const char *esi
, const char *gwip
,
6927 const char *ethtag
, const char *routermac
)
6929 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6932 struct prefix_rd prd
;
6933 struct bgp_dest
*pdest
;
6934 struct bgp_dest
*dest
;
6935 struct bgp_table
*table
;
6936 struct bgp_static
*bgp_static
;
6937 mpls_label_t label
= MPLS_INVALID_LABEL
;
6938 struct prefix gw_ip
;
6940 /* validate ip prefix */
6941 ret
= str2prefix(ip_str
, &p
);
6943 vty_out(vty
, "%% Malformed prefix\n");
6944 return CMD_WARNING_CONFIG_FAILED
;
6947 if ((afi
== AFI_L2VPN
)
6948 && (bgp_build_evpn_prefix(evpn_type
,
6949 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6950 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6951 return CMD_WARNING_CONFIG_FAILED
;
6954 ret
= str2prefix_rd(rd_str
, &prd
);
6956 vty_out(vty
, "%% Malformed rd\n");
6957 return CMD_WARNING_CONFIG_FAILED
;
6961 unsigned long label_val
;
6962 label_val
= strtoul(label_str
, NULL
, 10);
6963 encode_label(label_val
, &label
);
6966 if (safi
== SAFI_EVPN
) {
6967 if (esi
&& str2esi(esi
, NULL
) == 0) {
6968 vty_out(vty
, "%% Malformed ESI\n");
6969 return CMD_WARNING_CONFIG_FAILED
;
6971 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6972 vty_out(vty
, "%% Malformed Router MAC\n");
6973 return CMD_WARNING_CONFIG_FAILED
;
6976 memset(&gw_ip
, 0, sizeof(gw_ip
));
6977 ret
= str2prefix(gwip
, &gw_ip
);
6979 vty_out(vty
, "%% Malformed GatewayIp\n");
6980 return CMD_WARNING_CONFIG_FAILED
;
6982 if ((gw_ip
.family
== AF_INET
6983 && is_evpn_prefix_ipaddr_v6(
6984 (struct prefix_evpn
*)&p
))
6985 || (gw_ip
.family
== AF_INET6
6986 && is_evpn_prefix_ipaddr_v4(
6987 (struct prefix_evpn
*)&p
))) {
6989 "%% GatewayIp family differs with IP prefix\n");
6990 return CMD_WARNING_CONFIG_FAILED
;
6994 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6995 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6996 bgp_dest_set_bgp_table_info(pdest
,
6997 bgp_table_init(bgp
, afi
, safi
));
6998 table
= bgp_dest_get_bgp_table_info(pdest
);
7000 dest
= bgp_node_get(table
, &p
);
7002 if (bgp_dest_has_bgp_path_info_data(dest
)) {
7003 vty_out(vty
, "%% Same network configuration exists\n");
7004 bgp_dest_unlock_node(dest
);
7006 /* New configuration. */
7007 bgp_static
= bgp_static_new();
7008 bgp_static
->backdoor
= 0;
7009 bgp_static
->valid
= 0;
7010 bgp_static
->igpmetric
= 0;
7011 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7012 bgp_static
->label
= label
;
7013 bgp_static
->prd
= prd
;
7016 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7017 route_map_counter_decrement(bgp_static
->rmap
.map
);
7018 bgp_static
->rmap
.name
=
7019 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7020 bgp_static
->rmap
.map
=
7021 route_map_lookup_by_name(rmap_str
);
7022 route_map_counter_increment(bgp_static
->rmap
.map
);
7025 if (safi
== SAFI_EVPN
) {
7027 bgp_static
->eth_s_id
=
7030 str2esi(esi
, bgp_static
->eth_s_id
);
7033 bgp_static
->router_mac
=
7034 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7035 (void)prefix_str2mac(routermac
,
7036 bgp_static
->router_mac
);
7039 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7041 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7043 bgp_static
->valid
= 1;
7044 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7050 /* Configure static BGP network. */
7051 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7052 const char *ip_str
, const char *rd_str
,
7053 const char *label_str
, int evpn_type
, const char *esi
,
7054 const char *gwip
, const char *ethtag
)
7056 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7059 struct prefix_rd prd
;
7060 struct bgp_dest
*pdest
;
7061 struct bgp_dest
*dest
;
7062 struct bgp_table
*table
;
7063 struct bgp_static
*bgp_static
;
7064 mpls_label_t label
= MPLS_INVALID_LABEL
;
7066 /* Convert IP prefix string to struct prefix. */
7067 ret
= str2prefix(ip_str
, &p
);
7069 vty_out(vty
, "%% Malformed prefix\n");
7070 return CMD_WARNING_CONFIG_FAILED
;
7073 if ((afi
== AFI_L2VPN
)
7074 && (bgp_build_evpn_prefix(evpn_type
,
7075 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7076 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7077 return CMD_WARNING_CONFIG_FAILED
;
7079 ret
= str2prefix_rd(rd_str
, &prd
);
7081 vty_out(vty
, "%% Malformed rd\n");
7082 return CMD_WARNING_CONFIG_FAILED
;
7086 unsigned long label_val
;
7087 label_val
= strtoul(label_str
, NULL
, 10);
7088 encode_label(label_val
, &label
);
7091 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7092 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7093 bgp_dest_set_bgp_table_info(pdest
,
7094 bgp_table_init(bgp
, afi
, safi
));
7096 bgp_dest_unlock_node(pdest
);
7097 table
= bgp_dest_get_bgp_table_info(pdest
);
7099 dest
= bgp_node_lookup(table
, &p
);
7102 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7104 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7105 bgp_static_free(bgp_static
);
7106 bgp_dest_set_bgp_static_info(dest
, NULL
);
7107 bgp_dest_unlock_node(dest
);
7108 bgp_dest_unlock_node(dest
);
7110 vty_out(vty
, "%% Can't find the route\n");
7115 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7116 const char *rmap_name
)
7118 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7119 struct bgp_rmap
*rmap
;
7121 rmap
= &bgp
->table_map
[afi
][safi
];
7123 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7124 route_map_counter_decrement(rmap
->map
);
7125 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7126 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7127 route_map_counter_increment(rmap
->map
);
7129 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7130 route_map_counter_decrement(rmap
->map
);
7134 if (bgp_fibupd_safi(safi
))
7135 bgp_zebra_announce_table(bgp
, afi
, safi
);
7140 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7141 const char *rmap_name
)
7143 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7144 struct bgp_rmap
*rmap
;
7146 rmap
= &bgp
->table_map
[afi
][safi
];
7147 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7148 route_map_counter_decrement(rmap
->map
);
7151 if (bgp_fibupd_safi(safi
))
7152 bgp_zebra_announce_table(bgp
, afi
, safi
);
7157 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7160 if (bgp
->table_map
[afi
][safi
].name
) {
7161 vty_out(vty
, " table-map %s\n",
7162 bgp
->table_map
[afi
][safi
].name
);
7166 DEFUN (bgp_table_map
,
7169 "BGP table to RIB route download filter\n"
7170 "Name of the route map\n")
7173 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7174 argv
[idx_word
]->arg
);
7176 DEFUN (no_bgp_table_map
,
7177 no_bgp_table_map_cmd
,
7178 "no table-map WORD",
7180 "BGP table to RIB route download filter\n"
7181 "Name of the route map\n")
7184 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7185 argv
[idx_word
]->arg
);
7191 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7192 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7193 backdoor$backdoor}]",
7195 "Specify a network to announce via BGP\n"
7200 "Route-map to modify the attributes\n"
7201 "Name of the route map\n"
7202 "Label index to associate with the prefix\n"
7203 "Label index value\n"
7204 "Specify a BGP backdoor route\n")
7206 char addr_prefix_str
[BUFSIZ
];
7211 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7213 sizeof(addr_prefix_str
));
7215 vty_out(vty
, "%% Inconsistent address and mask\n");
7216 return CMD_WARNING_CONFIG_FAILED
;
7220 return bgp_static_set(
7221 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7222 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7223 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7226 DEFPY(ipv6_bgp_network
,
7227 ipv6_bgp_network_cmd
,
7228 "[no] network X:X::X:X/M$prefix \
7229 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7231 "Specify a network to announce via BGP\n"
7233 "Route-map to modify the attributes\n"
7234 "Name of the route map\n"
7235 "Label index to associate with the prefix\n"
7236 "Label index value\n")
7238 return bgp_static_set(
7239 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7240 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7243 static struct bgp_aggregate
*bgp_aggregate_new(void)
7245 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7248 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7250 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7251 route_map_counter_decrement(aggregate
->suppress_map
);
7252 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7253 route_map_counter_decrement(aggregate
->rmap
.map
);
7254 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7258 * Helper function to avoid repeated code: prepare variables for a
7259 * `route_map_apply` call.
7261 * \returns `true` on route map match, otherwise `false`.
7263 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7264 struct bgp_aggregate
*aggregate
,
7265 struct bgp_path_info
*pi
)
7267 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7268 route_map_result_t rmr
= RMAP_DENYMATCH
;
7269 struct bgp_path_info rmap_path
= {};
7270 struct attr attr
= {};
7272 /* No route map entries created, just don't match. */
7273 if (aggregate
->suppress_map
== NULL
)
7276 /* Call route map matching and return result. */
7277 attr
.aspath
= aspath_empty();
7278 rmap_path
.peer
= bgp
->peer_self
;
7279 rmap_path
.attr
= &attr
;
7281 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7282 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7283 bgp
->peer_self
->rmap_type
= 0;
7285 bgp_attr_flush(&attr
);
7286 aspath_unintern(&attr
.aspath
);
7288 return rmr
== RMAP_PERMITMATCH
;
7291 /** Test whether the aggregation has suppressed this path or not. */
7292 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7293 struct bgp_path_info
*pi
)
7295 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7298 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7302 * Suppress this path and keep the reference.
7304 * \returns `true` if needs processing otherwise `false`.
7306 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7307 struct bgp_path_info
*pi
)
7309 struct bgp_path_info_extra
*pie
;
7311 /* Path is already suppressed by this aggregation. */
7312 if (aggr_suppress_exists(aggregate
, pi
))
7315 pie
= bgp_path_info_extra_get(pi
);
7317 /* This is the first suppression, allocate memory and list it. */
7318 if (pie
->aggr_suppressors
== NULL
)
7319 pie
->aggr_suppressors
= list_new();
7321 listnode_add(pie
->aggr_suppressors
, aggregate
);
7323 /* Only mark for processing if suppressed. */
7324 if (listcount(pie
->aggr_suppressors
) == 1) {
7325 if (BGP_DEBUG(update
, UPDATE_OUT
))
7326 zlog_debug("aggregate-address suppressing: %pFX",
7327 bgp_dest_get_prefix(pi
->net
));
7329 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7337 * Unsuppress this path and remove the reference.
7339 * \returns `true` if needs processing otherwise `false`.
7341 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7342 struct bgp_path_info
*pi
)
7344 /* Path wasn't suppressed. */
7345 if (!aggr_suppress_exists(aggregate
, pi
))
7348 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7350 /* Unsuppress and free extra memory if last item. */
7351 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7352 if (BGP_DEBUG(update
, UPDATE_OUT
))
7353 zlog_debug("aggregate-address unsuppressing: %pFX",
7354 bgp_dest_get_prefix(pi
->net
));
7356 list_delete(&pi
->extra
->aggr_suppressors
);
7357 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7364 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7365 struct aspath
*aspath
,
7366 struct community
*comm
,
7367 struct ecommunity
*ecomm
,
7368 struct lcommunity
*lcomm
)
7370 static struct aspath
*ae
= NULL
;
7373 ae
= aspath_empty();
7378 if (origin
!= pi
->attr
->origin
)
7381 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7384 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7387 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7390 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7393 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7399 static void bgp_aggregate_install(
7400 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7401 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7402 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7403 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7405 struct bgp_dest
*dest
;
7406 struct bgp_table
*table
;
7407 struct bgp_path_info
*pi
, *orig
, *new;
7410 table
= bgp
->rib
[afi
][safi
];
7412 dest
= bgp_node_get(table
, p
);
7414 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7415 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7416 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7420 * If we have paths with different MEDs, then don't install
7421 * (or uninstall) the aggregate route.
7423 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7424 goto uninstall_aggregate_route
;
7426 if (aggregate
->count
> 0) {
7428 * If the aggregate information has not changed
7429 * no need to re-install it again.
7431 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7432 ecommunity
, lcommunity
)) {
7433 bgp_dest_unlock_node(dest
);
7436 aspath_free(aspath
);
7438 community_free(&community
);
7440 ecommunity_free(&ecommunity
);
7442 lcommunity_free(&lcommunity
);
7448 * Mark the old as unusable
7451 bgp_path_info_delete(dest
, pi
);
7453 attr
= bgp_attr_aggregate_intern(
7454 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7455 aggregate
, atomic_aggregate
, p
);
7458 bgp_dest_unlock_node(dest
);
7459 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7460 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7461 zlog_debug("%s: %pFX null attribute", __func__
,
7466 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7467 bgp
->peer_self
, attr
, dest
);
7469 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7471 bgp_path_info_add(dest
, new);
7472 bgp_process(bgp
, dest
, afi
, safi
);
7474 uninstall_aggregate_route
:
7475 for (pi
= orig
; pi
; pi
= pi
->next
)
7476 if (pi
->peer
== bgp
->peer_self
7477 && pi
->type
== ZEBRA_ROUTE_BGP
7478 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7481 /* Withdraw static BGP route from routing table. */
7483 bgp_path_info_delete(dest
, pi
);
7484 bgp_process(bgp
, dest
, afi
, safi
);
7488 bgp_dest_unlock_node(dest
);
7492 * Check if the current path has different MED than other known paths.
7494 * \returns `true` if the MED matched the others else `false`.
7496 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7497 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7499 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7501 /* This is the first route being analyzed. */
7502 if (!aggregate
->med_initialized
) {
7503 aggregate
->med_initialized
= true;
7504 aggregate
->med_mismatched
= false;
7505 aggregate
->med_matched_value
= cur_med
;
7507 /* Check if routes with different MED showed up. */
7508 if (cur_med
!= aggregate
->med_matched_value
)
7509 aggregate
->med_mismatched
= true;
7512 return !aggregate
->med_mismatched
;
7516 * Initializes and tests all routes in the aggregate address path for MED
7519 * \returns `true` if all MEDs are the same otherwise `false`.
7521 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7522 struct bgp
*bgp
, const struct prefix
*p
,
7523 afi_t afi
, safi_t safi
)
7525 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7526 const struct prefix
*dest_p
;
7527 struct bgp_dest
*dest
, *top
;
7528 struct bgp_path_info
*pi
;
7529 bool med_matched
= true;
7531 aggregate
->med_initialized
= false;
7533 top
= bgp_node_get(table
, p
);
7534 for (dest
= bgp_node_get(table
, p
); dest
;
7535 dest
= bgp_route_next_until(dest
, top
)) {
7536 dest_p
= bgp_dest_get_prefix(dest
);
7537 if (dest_p
->prefixlen
<= p
->prefixlen
)
7540 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7541 if (BGP_PATH_HOLDDOWN(pi
))
7543 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7545 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7546 med_matched
= false;
7553 bgp_dest_unlock_node(top
);
7559 * Toggles the route suppression status for this aggregate address
7562 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7563 struct bgp
*bgp
, const struct prefix
*p
,
7564 afi_t afi
, safi_t safi
, bool suppress
)
7566 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7567 const struct prefix
*dest_p
;
7568 struct bgp_dest
*dest
, *top
;
7569 struct bgp_path_info
*pi
;
7570 bool toggle_suppression
;
7572 /* We've found a different MED we must revert any suppressed routes. */
7573 top
= bgp_node_get(table
, p
);
7574 for (dest
= bgp_node_get(table
, p
); dest
;
7575 dest
= bgp_route_next_until(dest
, top
)) {
7576 dest_p
= bgp_dest_get_prefix(dest
);
7577 if (dest_p
->prefixlen
<= p
->prefixlen
)
7580 toggle_suppression
= false;
7581 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7582 if (BGP_PATH_HOLDDOWN(pi
))
7584 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7587 /* We are toggling suppression back. */
7589 /* Suppress route if not suppressed already. */
7590 if (aggr_suppress_path(aggregate
, pi
))
7591 toggle_suppression
= true;
7595 /* Install route if there is no more suppression. */
7596 if (aggr_unsuppress_path(aggregate
, pi
))
7597 toggle_suppression
= true;
7600 if (toggle_suppression
)
7601 bgp_process(bgp
, dest
, afi
, safi
);
7603 bgp_dest_unlock_node(top
);
7607 * Aggregate address MED matching incremental test: this function is called
7608 * when the initial aggregation occurred and we are only testing a single
7611 * In addition to testing and setting the MED validity it also installs back
7612 * suppressed routes (if summary is configured).
7614 * Must not be called in `bgp_aggregate_route`.
7616 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7617 struct bgp
*bgp
, const struct prefix
*p
,
7618 afi_t afi
, safi_t safi
,
7619 struct bgp_path_info
*pi
)
7621 /* MED matching disabled. */
7622 if (!aggregate
->match_med
)
7625 /* Aggregation with different MED, recheck if we have got equal MEDs
7628 if (aggregate
->med_mismatched
&&
7629 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7630 aggregate
->summary_only
)
7631 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7634 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7636 /* No mismatches, just quit. */
7637 if (!aggregate
->med_mismatched
)
7640 /* Route summarization is disabled. */
7641 if (!aggregate
->summary_only
)
7644 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7647 /* Update an aggregate as routes are added/removed from the BGP table */
7648 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7649 safi_t safi
, struct bgp_aggregate
*aggregate
)
7651 struct bgp_table
*table
;
7652 struct bgp_dest
*top
;
7653 struct bgp_dest
*dest
;
7655 struct aspath
*aspath
= NULL
;
7656 struct community
*community
= NULL
;
7657 struct ecommunity
*ecommunity
= NULL
;
7658 struct lcommunity
*lcommunity
= NULL
;
7659 struct bgp_path_info
*pi
;
7660 unsigned long match
= 0;
7661 uint8_t atomic_aggregate
= 0;
7663 /* If the bgp instance is being deleted or self peer is deleted
7664 * then do not create aggregate route
7666 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7667 || (bgp
->peer_self
== NULL
))
7670 /* Initialize and test routes for MED difference. */
7671 if (aggregate
->match_med
)
7672 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7675 * Reset aggregate count: we might've been called from route map
7676 * update so in that case we must retest all more specific routes.
7678 * \see `bgp_route_map_process_update`.
7680 aggregate
->count
= 0;
7681 aggregate
->incomplete_origin_count
= 0;
7682 aggregate
->incomplete_origin_count
= 0;
7683 aggregate
->egp_origin_count
= 0;
7685 /* ORIGIN attribute: If at least one route among routes that are
7686 aggregated has ORIGIN with the value INCOMPLETE, then the
7687 aggregated route must have the ORIGIN attribute with the value
7688 INCOMPLETE. Otherwise, if at least one route among routes that
7689 are aggregated has ORIGIN with the value EGP, then the aggregated
7690 route must have the origin attribute with the value EGP. In all
7691 other case the value of the ORIGIN attribute of the aggregated
7692 route is INTERNAL. */
7693 origin
= BGP_ORIGIN_IGP
;
7695 table
= bgp
->rib
[afi
][safi
];
7697 top
= bgp_node_get(table
, p
);
7698 for (dest
= bgp_node_get(table
, p
); dest
;
7699 dest
= bgp_route_next_until(dest
, top
)) {
7700 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7702 if (dest_p
->prefixlen
<= p
->prefixlen
)
7705 /* If suppress fib is enabled and route not installed
7706 * in FIB, skip the route
7708 if (!bgp_check_advertise(bgp
, dest
))
7713 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7714 if (BGP_PATH_HOLDDOWN(pi
))
7718 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7719 atomic_aggregate
= 1;
7721 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7725 * summary-only aggregate route suppress
7726 * aggregated route announcements.
7729 * Don't create summaries if MED didn't match
7730 * otherwise neither the specific routes and the
7731 * aggregation will be announced.
7733 if (aggregate
->summary_only
7734 && AGGREGATE_MED_VALID(aggregate
)) {
7735 if (aggr_suppress_path(aggregate
, pi
))
7740 * Suppress more specific routes that match the route
7744 * Don't suppress routes if MED matching is enabled and
7745 * it mismatched otherwise we might end up with no
7746 * routes for this path.
7748 if (aggregate
->suppress_map_name
7749 && AGGREGATE_MED_VALID(aggregate
)
7750 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7751 if (aggr_suppress_path(aggregate
, pi
))
7758 * If at least one route among routes that are
7759 * aggregated has ORIGIN with the value INCOMPLETE,
7760 * then the aggregated route MUST have the ORIGIN
7761 * attribute with the value INCOMPLETE. Otherwise, if
7762 * at least one route among routes that are aggregated
7763 * has ORIGIN with the value EGP, then the aggregated
7764 * route MUST have the ORIGIN attribute with the value
7767 switch (pi
->attr
->origin
) {
7768 case BGP_ORIGIN_INCOMPLETE
:
7769 aggregate
->incomplete_origin_count
++;
7771 case BGP_ORIGIN_EGP
:
7772 aggregate
->egp_origin_count
++;
7780 if (!aggregate
->as_set
)
7784 * as-set aggregate route generate origin, as path,
7785 * and community aggregation.
7787 /* Compute aggregate route's as-path.
7789 bgp_compute_aggregate_aspath_hash(aggregate
,
7792 /* Compute aggregate route's community.
7794 if (bgp_attr_get_community(pi
->attr
))
7795 bgp_compute_aggregate_community_hash(
7797 bgp_attr_get_community(pi
->attr
));
7799 /* Compute aggregate route's extended community.
7801 if (bgp_attr_get_ecommunity(pi
->attr
))
7802 bgp_compute_aggregate_ecommunity_hash(
7804 bgp_attr_get_ecommunity(pi
->attr
));
7806 /* Compute aggregate route's large community.
7808 if (bgp_attr_get_lcommunity(pi
->attr
))
7809 bgp_compute_aggregate_lcommunity_hash(
7811 bgp_attr_get_lcommunity(pi
->attr
));
7814 bgp_process(bgp
, dest
, afi
, safi
);
7816 if (aggregate
->as_set
) {
7817 bgp_compute_aggregate_aspath_val(aggregate
);
7818 bgp_compute_aggregate_community_val(aggregate
);
7819 bgp_compute_aggregate_ecommunity_val(aggregate
);
7820 bgp_compute_aggregate_lcommunity_val(aggregate
);
7824 bgp_dest_unlock_node(top
);
7827 if (aggregate
->incomplete_origin_count
> 0)
7828 origin
= BGP_ORIGIN_INCOMPLETE
;
7829 else if (aggregate
->egp_origin_count
> 0)
7830 origin
= BGP_ORIGIN_EGP
;
7832 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7833 origin
= aggregate
->origin
;
7835 if (aggregate
->as_set
) {
7836 if (aggregate
->aspath
)
7837 /* Retrieve aggregate route's as-path.
7839 aspath
= aspath_dup(aggregate
->aspath
);
7841 if (aggregate
->community
)
7842 /* Retrieve aggregate route's community.
7844 community
= community_dup(aggregate
->community
);
7846 if (aggregate
->ecommunity
)
7847 /* Retrieve aggregate route's ecommunity.
7849 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7851 if (aggregate
->lcommunity
)
7852 /* Retrieve aggregate route's lcommunity.
7854 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7857 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7858 ecommunity
, lcommunity
, atomic_aggregate
,
7862 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7863 safi_t safi
, struct bgp_aggregate
*aggregate
)
7865 struct bgp_table
*table
;
7866 struct bgp_dest
*top
;
7867 struct bgp_dest
*dest
;
7868 struct bgp_path_info
*pi
;
7869 unsigned long match
;
7871 table
= bgp
->rib
[afi
][safi
];
7873 /* If routes exists below this node, generate aggregate routes. */
7874 top
= bgp_node_get(table
, p
);
7875 for (dest
= bgp_node_get(table
, p
); dest
;
7876 dest
= bgp_route_next_until(dest
, top
)) {
7877 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7879 if (dest_p
->prefixlen
<= p
->prefixlen
)
7883 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7884 if (BGP_PATH_HOLDDOWN(pi
))
7887 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7891 * This route is suppressed: attempt to unsuppress it.
7893 * `aggr_unsuppress_path` will fail if this particular
7894 * aggregate route was not the suppressor.
7896 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7897 listcount(pi
->extra
->aggr_suppressors
)) {
7898 if (aggr_unsuppress_path(aggregate
, pi
))
7904 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7905 aggregate
->incomplete_origin_count
--;
7906 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7907 aggregate
->egp_origin_count
--;
7909 if (aggregate
->as_set
) {
7910 /* Remove as-path from aggregate.
7912 bgp_remove_aspath_from_aggregate_hash(
7916 if (bgp_attr_get_community(pi
->attr
))
7917 /* Remove community from aggregate.
7919 bgp_remove_comm_from_aggregate_hash(
7921 bgp_attr_get_community(
7924 if (bgp_attr_get_ecommunity(pi
->attr
))
7925 /* Remove ecommunity from aggregate.
7927 bgp_remove_ecomm_from_aggregate_hash(
7929 bgp_attr_get_ecommunity(
7932 if (bgp_attr_get_lcommunity(pi
->attr
))
7933 /* Remove lcommunity from aggregate.
7935 bgp_remove_lcomm_from_aggregate_hash(
7937 bgp_attr_get_lcommunity(
7942 /* If this node was suppressed, process the change. */
7944 bgp_process(bgp
, dest
, afi
, safi
);
7946 if (aggregate
->as_set
) {
7947 aspath_free(aggregate
->aspath
);
7948 aggregate
->aspath
= NULL
;
7949 if (aggregate
->community
)
7950 community_free(&aggregate
->community
);
7951 if (aggregate
->ecommunity
)
7952 ecommunity_free(&aggregate
->ecommunity
);
7953 if (aggregate
->lcommunity
)
7954 lcommunity_free(&aggregate
->lcommunity
);
7957 bgp_dest_unlock_node(top
);
7960 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7961 const struct prefix
*aggr_p
,
7962 struct bgp_path_info
*pinew
, afi_t afi
,
7964 struct bgp_aggregate
*aggregate
)
7967 struct aspath
*aspath
= NULL
;
7968 uint8_t atomic_aggregate
= 0;
7969 struct community
*community
= NULL
;
7970 struct ecommunity
*ecommunity
= NULL
;
7971 struct lcommunity
*lcommunity
= NULL
;
7973 /* If the bgp instance is being deleted or self peer is deleted
7974 * then do not create aggregate route
7976 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7977 || (bgp
->peer_self
== NULL
))
7980 /* ORIGIN attribute: If at least one route among routes that are
7981 * aggregated has ORIGIN with the value INCOMPLETE, then the
7982 * aggregated route must have the ORIGIN attribute with the value
7983 * INCOMPLETE. Otherwise, if at least one route among routes that
7984 * are aggregated has ORIGIN with the value EGP, then the aggregated
7985 * route must have the origin attribute with the value EGP. In all
7986 * other case the value of the ORIGIN attribute of the aggregated
7987 * route is INTERNAL.
7989 origin
= BGP_ORIGIN_IGP
;
7994 * This must be called before `summary` check to avoid
7995 * "suppressing" twice.
7997 if (aggregate
->match_med
)
7998 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8001 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8002 aggr_suppress_path(aggregate
, pinew
);
8004 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8005 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8006 aggr_suppress_path(aggregate
, pinew
);
8008 switch (pinew
->attr
->origin
) {
8009 case BGP_ORIGIN_INCOMPLETE
:
8010 aggregate
->incomplete_origin_count
++;
8012 case BGP_ORIGIN_EGP
:
8013 aggregate
->egp_origin_count
++;
8021 if (aggregate
->incomplete_origin_count
> 0)
8022 origin
= BGP_ORIGIN_INCOMPLETE
;
8023 else if (aggregate
->egp_origin_count
> 0)
8024 origin
= BGP_ORIGIN_EGP
;
8026 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8027 origin
= aggregate
->origin
;
8029 if (aggregate
->as_set
) {
8030 /* Compute aggregate route's as-path.
8032 bgp_compute_aggregate_aspath(aggregate
,
8033 pinew
->attr
->aspath
);
8035 /* Compute aggregate route's community.
8037 if (bgp_attr_get_community(pinew
->attr
))
8038 bgp_compute_aggregate_community(
8039 aggregate
, bgp_attr_get_community(pinew
->attr
));
8041 /* Compute aggregate route's extended community.
8043 if (bgp_attr_get_ecommunity(pinew
->attr
))
8044 bgp_compute_aggregate_ecommunity(
8046 bgp_attr_get_ecommunity(pinew
->attr
));
8048 /* Compute aggregate route's large community.
8050 if (bgp_attr_get_lcommunity(pinew
->attr
))
8051 bgp_compute_aggregate_lcommunity(
8053 bgp_attr_get_lcommunity(pinew
->attr
));
8055 /* Retrieve aggregate route's as-path.
8057 if (aggregate
->aspath
)
8058 aspath
= aspath_dup(aggregate
->aspath
);
8060 /* Retrieve aggregate route's community.
8062 if (aggregate
->community
)
8063 community
= community_dup(aggregate
->community
);
8065 /* Retrieve aggregate route's ecommunity.
8067 if (aggregate
->ecommunity
)
8068 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8070 /* Retrieve aggregate route's lcommunity.
8072 if (aggregate
->lcommunity
)
8073 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8076 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8077 aspath
, community
, ecommunity
,
8078 lcommunity
, atomic_aggregate
, aggregate
);
8081 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8083 struct bgp_path_info
*pi
,
8084 struct bgp_aggregate
*aggregate
,
8085 const struct prefix
*aggr_p
)
8088 struct aspath
*aspath
= NULL
;
8089 uint8_t atomic_aggregate
= 0;
8090 struct community
*community
= NULL
;
8091 struct ecommunity
*ecommunity
= NULL
;
8092 struct lcommunity
*lcommunity
= NULL
;
8093 unsigned long match
= 0;
8095 /* If the bgp instance is being deleted or self peer is deleted
8096 * then do not create aggregate route
8098 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8099 || (bgp
->peer_self
== NULL
))
8102 if (BGP_PATH_HOLDDOWN(pi
))
8105 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8108 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8109 if (aggr_unsuppress_path(aggregate
, pi
))
8112 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8113 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8114 if (aggr_unsuppress_path(aggregate
, pi
))
8118 * This must be called after `summary`, `suppress-map` check to avoid
8119 * "unsuppressing" twice.
8121 if (aggregate
->match_med
)
8122 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8124 if (aggregate
->count
> 0)
8127 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8128 aggregate
->incomplete_origin_count
--;
8129 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8130 aggregate
->egp_origin_count
--;
8132 if (aggregate
->as_set
) {
8133 /* Remove as-path from aggregate.
8135 bgp_remove_aspath_from_aggregate(aggregate
,
8138 if (bgp_attr_get_community(pi
->attr
))
8139 /* Remove community from aggregate.
8141 bgp_remove_community_from_aggregate(
8142 aggregate
, bgp_attr_get_community(pi
->attr
));
8144 if (bgp_attr_get_ecommunity(pi
->attr
))
8145 /* Remove ecommunity from aggregate.
8147 bgp_remove_ecommunity_from_aggregate(
8148 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8150 if (bgp_attr_get_lcommunity(pi
->attr
))
8151 /* Remove lcommunity from aggregate.
8153 bgp_remove_lcommunity_from_aggregate(
8154 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8157 /* If this node was suppressed, process the change. */
8159 bgp_process(bgp
, pi
->net
, afi
, safi
);
8161 origin
= BGP_ORIGIN_IGP
;
8162 if (aggregate
->incomplete_origin_count
> 0)
8163 origin
= BGP_ORIGIN_INCOMPLETE
;
8164 else if (aggregate
->egp_origin_count
> 0)
8165 origin
= BGP_ORIGIN_EGP
;
8167 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8168 origin
= aggregate
->origin
;
8170 if (aggregate
->as_set
) {
8171 /* Retrieve aggregate route's as-path.
8173 if (aggregate
->aspath
)
8174 aspath
= aspath_dup(aggregate
->aspath
);
8176 /* Retrieve aggregate route's community.
8178 if (aggregate
->community
)
8179 community
= community_dup(aggregate
->community
);
8181 /* Retrieve aggregate route's ecommunity.
8183 if (aggregate
->ecommunity
)
8184 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8186 /* Retrieve aggregate route's lcommunity.
8188 if (aggregate
->lcommunity
)
8189 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8192 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8193 aspath
, community
, ecommunity
,
8194 lcommunity
, atomic_aggregate
, aggregate
);
8197 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8198 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8200 struct bgp_dest
*child
;
8201 struct bgp_dest
*dest
;
8202 struct bgp_aggregate
*aggregate
;
8203 struct bgp_table
*table
;
8205 table
= bgp
->aggregate
[afi
][safi
];
8207 /* No aggregates configured. */
8208 if (bgp_table_top_nolock(table
) == NULL
)
8211 if (p
->prefixlen
== 0)
8214 if (BGP_PATH_HOLDDOWN(pi
))
8217 /* If suppress fib is enabled and route not installed
8218 * in FIB, do not update the aggregate route
8220 if (!bgp_check_advertise(bgp
, pi
->net
))
8223 child
= bgp_node_get(table
, p
);
8225 /* Aggregate address configuration check. */
8226 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8227 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8229 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8230 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8231 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8235 bgp_dest_unlock_node(child
);
8238 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8239 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8241 struct bgp_dest
*child
;
8242 struct bgp_dest
*dest
;
8243 struct bgp_aggregate
*aggregate
;
8244 struct bgp_table
*table
;
8246 table
= bgp
->aggregate
[afi
][safi
];
8248 /* No aggregates configured. */
8249 if (bgp_table_top_nolock(table
) == NULL
)
8252 if (p
->prefixlen
== 0)
8255 child
= bgp_node_get(table
, p
);
8257 /* Aggregate address configuration check. */
8258 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8259 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8261 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8262 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8263 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8267 bgp_dest_unlock_node(child
);
8270 /* Aggregate route attribute. */
8271 #define AGGREGATE_SUMMARY_ONLY 1
8272 #define AGGREGATE_AS_SET 1
8273 #define AGGREGATE_AS_UNSET 0
8275 static const char *bgp_origin2str(uint8_t origin
)
8278 case BGP_ORIGIN_IGP
:
8280 case BGP_ORIGIN_EGP
:
8282 case BGP_ORIGIN_INCOMPLETE
:
8283 return "incomplete";
8288 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8291 case RPKI_NOT_BEING_USED
:
8301 assert(!"We should never get here this is a dev escape");
8305 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8306 afi_t afi
, safi_t safi
)
8308 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8311 struct bgp_dest
*dest
;
8312 struct bgp_aggregate
*aggregate
;
8314 /* Convert string to prefix structure. */
8315 ret
= str2prefix(prefix_str
, &p
);
8317 vty_out(vty
, "Malformed prefix\n");
8318 return CMD_WARNING_CONFIG_FAILED
;
8322 /* Old configuration check. */
8323 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8326 "%% There is no aggregate-address configuration.\n");
8327 return CMD_WARNING_CONFIG_FAILED
;
8330 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8331 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8332 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8333 NULL
, NULL
, 0, aggregate
);
8335 /* Unlock aggregate address configuration. */
8336 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8338 if (aggregate
->community
)
8339 community_free(&aggregate
->community
);
8341 if (aggregate
->community_hash
) {
8342 /* Delete all communities in the hash.
8344 hash_clean(aggregate
->community_hash
,
8345 bgp_aggr_community_remove
);
8346 /* Free up the community_hash.
8348 hash_free(aggregate
->community_hash
);
8351 if (aggregate
->ecommunity
)
8352 ecommunity_free(&aggregate
->ecommunity
);
8354 if (aggregate
->ecommunity_hash
) {
8355 /* Delete all ecommunities in the hash.
8357 hash_clean(aggregate
->ecommunity_hash
,
8358 bgp_aggr_ecommunity_remove
);
8359 /* Free up the ecommunity_hash.
8361 hash_free(aggregate
->ecommunity_hash
);
8364 if (aggregate
->lcommunity
)
8365 lcommunity_free(&aggregate
->lcommunity
);
8367 if (aggregate
->lcommunity_hash
) {
8368 /* Delete all lcommunities in the hash.
8370 hash_clean(aggregate
->lcommunity_hash
,
8371 bgp_aggr_lcommunity_remove
);
8372 /* Free up the lcommunity_hash.
8374 hash_free(aggregate
->lcommunity_hash
);
8377 if (aggregate
->aspath
)
8378 aspath_free(aggregate
->aspath
);
8380 if (aggregate
->aspath_hash
) {
8381 /* Delete all as-paths in the hash.
8383 hash_clean(aggregate
->aspath_hash
,
8384 bgp_aggr_aspath_remove
);
8385 /* Free up the aspath_hash.
8387 hash_free(aggregate
->aspath_hash
);
8390 bgp_aggregate_free(aggregate
);
8391 bgp_dest_unlock_node(dest
);
8392 bgp_dest_unlock_node(dest
);
8397 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8398 safi_t safi
, const char *rmap
,
8399 uint8_t summary_only
, uint8_t as_set
,
8400 uint8_t origin
, bool match_med
,
8401 const char *suppress_map
)
8403 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8406 struct bgp_dest
*dest
;
8407 struct bgp_aggregate
*aggregate
;
8408 uint8_t as_set_new
= as_set
;
8410 if (suppress_map
&& summary_only
) {
8412 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8413 return CMD_WARNING_CONFIG_FAILED
;
8416 /* Convert string to prefix structure. */
8417 ret
= str2prefix(prefix_str
, &p
);
8419 vty_out(vty
, "Malformed prefix\n");
8420 return CMD_WARNING_CONFIG_FAILED
;
8424 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8425 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8426 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8428 return CMD_WARNING_CONFIG_FAILED
;
8431 /* Old configuration check. */
8432 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8433 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8436 vty_out(vty
, "There is already same aggregate network.\n");
8437 /* try to remove the old entry */
8438 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8440 vty_out(vty
, "Error deleting aggregate.\n");
8441 bgp_dest_unlock_node(dest
);
8442 return CMD_WARNING_CONFIG_FAILED
;
8446 /* Make aggregate address structure. */
8447 aggregate
= bgp_aggregate_new();
8448 aggregate
->summary_only
= summary_only
;
8449 aggregate
->match_med
= match_med
;
8451 /* Network operators MUST NOT locally generate any new
8452 * announcements containing AS_SET or AS_CONFED_SET. If they have
8453 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8454 * SHOULD withdraw those routes and re-announce routes for the
8455 * aggregate or component prefixes (i.e., the more-specific routes
8456 * subsumed by the previously aggregated route) without AS_SET
8457 * or AS_CONFED_SET in the updates.
8459 if (bgp
->reject_as_sets
) {
8460 if (as_set
== AGGREGATE_AS_SET
) {
8461 as_set_new
= AGGREGATE_AS_UNSET
;
8463 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8466 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8470 aggregate
->as_set
= as_set_new
;
8471 aggregate
->safi
= safi
;
8472 /* Override ORIGIN attribute if defined.
8473 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8474 * to IGP which is not what rfc4271 says.
8475 * This enables the same behavior, optionally.
8477 aggregate
->origin
= origin
;
8480 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8481 route_map_counter_decrement(aggregate
->rmap
.map
);
8482 aggregate
->rmap
.name
=
8483 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8484 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8485 route_map_counter_increment(aggregate
->rmap
.map
);
8489 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8490 route_map_counter_decrement(aggregate
->suppress_map
);
8492 aggregate
->suppress_map_name
=
8493 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8494 aggregate
->suppress_map
=
8495 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8496 route_map_counter_increment(aggregate
->suppress_map
);
8499 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8501 /* Aggregate address insert into BGP routing table. */
8502 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8507 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8508 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8510 "|summary-only$summary_only"
8511 "|route-map RMAP_NAME$rmap_name"
8512 "|origin <egp|igp|incomplete>$origin_s"
8513 "|matching-MED-only$match_med"
8514 "|suppress-map RMAP_NAME$suppress_map"
8517 "Configure BGP aggregate entries\n"
8518 "Aggregate prefix\n"
8519 "Aggregate address\n"
8521 "Generate AS set path information\n"
8522 "Filter more specific routes from updates\n"
8523 "Apply route map to aggregate network\n"
8528 "Unknown heritage\n"
8529 "Only aggregate routes with matching MED\n"
8530 "Suppress the selected more specific routes\n"
8531 "Route map with the route selectors\n")
8533 const char *prefix_s
= NULL
;
8534 safi_t safi
= bgp_node_safi(vty
);
8535 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8536 int as_set
= AGGREGATE_AS_UNSET
;
8537 char prefix_buf
[PREFIX2STR_BUFFER
];
8540 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8543 vty_out(vty
, "%% Inconsistent address and mask\n");
8544 return CMD_WARNING_CONFIG_FAILED
;
8546 prefix_s
= prefix_buf
;
8548 prefix_s
= prefix_str
;
8551 if (strcmp(origin_s
, "egp") == 0)
8552 origin
= BGP_ORIGIN_EGP
;
8553 else if (strcmp(origin_s
, "igp") == 0)
8554 origin
= BGP_ORIGIN_IGP
;
8555 else if (strcmp(origin_s
, "incomplete") == 0)
8556 origin
= BGP_ORIGIN_INCOMPLETE
;
8560 as_set
= AGGREGATE_AS_SET
;
8562 /* Handle configuration removal, otherwise installation. */
8564 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8566 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8567 summary_only
!= NULL
, as_set
, origin
,
8568 match_med
!= NULL
, suppress_map
);
8571 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8572 "[no] aggregate-address X:X::X:X/M$prefix [{"
8574 "|summary-only$summary_only"
8575 "|route-map RMAP_NAME$rmap_name"
8576 "|origin <egp|igp|incomplete>$origin_s"
8577 "|matching-MED-only$match_med"
8578 "|suppress-map RMAP_NAME$suppress_map"
8581 "Configure BGP aggregate entries\n"
8582 "Aggregate prefix\n"
8583 "Generate AS set path information\n"
8584 "Filter more specific routes from updates\n"
8585 "Apply route map to aggregate network\n"
8590 "Unknown heritage\n"
8591 "Only aggregate routes with matching MED\n"
8592 "Suppress the selected more specific routes\n"
8593 "Route map with the route selectors\n")
8595 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8596 int as_set
= AGGREGATE_AS_UNSET
;
8599 if (strcmp(origin_s
, "egp") == 0)
8600 origin
= BGP_ORIGIN_EGP
;
8601 else if (strcmp(origin_s
, "igp") == 0)
8602 origin
= BGP_ORIGIN_IGP
;
8603 else if (strcmp(origin_s
, "incomplete") == 0)
8604 origin
= BGP_ORIGIN_INCOMPLETE
;
8608 as_set
= AGGREGATE_AS_SET
;
8610 /* Handle configuration removal, otherwise installation. */
8612 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8615 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8616 rmap_name
, summary_only
!= NULL
, as_set
,
8617 origin
, match_med
!= NULL
, suppress_map
);
8620 /* Redistribute route treatment. */
8621 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8622 const union g_addr
*nexthop
, ifindex_t ifindex
,
8623 enum nexthop_types_t nhtype
, uint8_t distance
,
8624 enum blackhole_type bhtype
, uint32_t metric
,
8625 uint8_t type
, unsigned short instance
,
8628 struct bgp_path_info
*new;
8629 struct bgp_path_info
*bpi
;
8630 struct bgp_path_info rmap_path
;
8631 struct bgp_dest
*bn
;
8633 struct attr
*new_attr
;
8635 route_map_result_t ret
;
8636 struct bgp_redist
*red
;
8638 /* Make default attribute. */
8639 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8641 * This must not be NULL to satisfy Coverity SA
8643 assert(attr
.aspath
);
8646 case NEXTHOP_TYPE_IFINDEX
:
8647 switch (p
->family
) {
8649 attr
.nexthop
.s_addr
= INADDR_ANY
;
8650 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8653 memset(&attr
.mp_nexthop_global
, 0,
8654 sizeof(attr
.mp_nexthop_global
));
8655 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8659 case NEXTHOP_TYPE_IPV4
:
8660 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8661 attr
.nexthop
= nexthop
->ipv4
;
8662 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8664 case NEXTHOP_TYPE_IPV6
:
8665 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8666 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8667 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8669 case NEXTHOP_TYPE_BLACKHOLE
:
8670 switch (p
->family
) {
8672 attr
.nexthop
.s_addr
= INADDR_ANY
;
8673 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8676 memset(&attr
.mp_nexthop_global
, 0,
8677 sizeof(attr
.mp_nexthop_global
));
8678 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8681 attr
.bh_type
= bhtype
;
8684 attr
.nh_type
= nhtype
;
8685 attr
.nh_ifindex
= ifindex
;
8688 attr
.distance
= distance
;
8689 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8693 bgp_attr_set_aigp_metric(&attr
, metric
);
8695 afi
= family2afi(p
->family
);
8697 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8699 struct attr attr_new
;
8701 /* Copy attribute for modification. */
8704 if (red
->redist_metric_flag
) {
8705 attr_new
.med
= red
->redist_metric
;
8706 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8709 /* Apply route-map. */
8710 if (red
->rmap
.name
) {
8711 memset(&rmap_path
, 0, sizeof(rmap_path
));
8712 rmap_path
.peer
= bgp
->peer_self
;
8713 rmap_path
.attr
= &attr_new
;
8715 SET_FLAG(bgp
->peer_self
->rmap_type
,
8716 PEER_RMAP_TYPE_REDISTRIBUTE
);
8718 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8720 bgp
->peer_self
->rmap_type
= 0;
8722 if (ret
== RMAP_DENYMATCH
) {
8723 /* Free uninterned attribute. */
8724 bgp_attr_flush(&attr_new
);
8726 /* Unintern original. */
8727 aspath_unintern(&attr
.aspath
);
8728 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8733 if (bgp_in_graceful_shutdown(bgp
))
8734 bgp_attr_add_gshut_community(&attr_new
);
8736 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8737 SAFI_UNICAST
, p
, NULL
);
8739 new_attr
= bgp_attr_intern(&attr_new
);
8741 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8742 if (bpi
->peer
== bgp
->peer_self
8743 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8747 /* Ensure the (source route) type is updated. */
8749 if (attrhash_cmp(bpi
->attr
, new_attr
)
8750 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8751 bgp_attr_unintern(&new_attr
);
8752 aspath_unintern(&attr
.aspath
);
8753 bgp_dest_unlock_node(bn
);
8756 /* The attribute is changed. */
8757 bgp_path_info_set_flag(bn
, bpi
,
8758 BGP_PATH_ATTR_CHANGED
);
8760 /* Rewrite BGP route information. */
8761 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8762 bgp_path_info_restore(bn
, bpi
);
8764 bgp_aggregate_decrement(
8765 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8766 bgp_attr_unintern(&bpi
->attr
);
8767 bpi
->attr
= new_attr
;
8768 bpi
->uptime
= monotime(NULL
);
8770 /* Process change. */
8771 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8773 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8774 bgp_dest_unlock_node(bn
);
8775 aspath_unintern(&attr
.aspath
);
8777 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8779 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8781 vpn_leak_from_vrf_update(
8782 bgp_get_default(), bgp
, bpi
);
8788 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8789 bgp
->peer_self
, new_attr
, bn
);
8790 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8792 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8793 bgp_path_info_add(bn
, new);
8794 bgp_dest_unlock_node(bn
);
8795 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8796 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8798 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8799 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8801 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8805 /* Unintern original. */
8806 aspath_unintern(&attr
.aspath
);
8809 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8810 unsigned short instance
)
8813 struct bgp_dest
*dest
;
8814 struct bgp_path_info
*pi
;
8815 struct bgp_redist
*red
;
8817 afi
= family2afi(p
->family
);
8819 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8821 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8822 SAFI_UNICAST
, p
, NULL
);
8824 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8825 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8829 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8830 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8832 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8835 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8836 bgp_path_info_delete(dest
, pi
);
8837 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8839 bgp_dest_unlock_node(dest
);
8843 /* Withdraw specified route type's route. */
8844 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8845 unsigned short instance
)
8847 struct bgp_dest
*dest
;
8848 struct bgp_path_info
*pi
;
8849 struct bgp_table
*table
;
8851 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8853 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8854 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8855 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8856 && pi
->instance
== instance
)
8860 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8861 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8863 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8866 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8867 pi
, afi
, SAFI_UNICAST
);
8868 bgp_path_info_delete(dest
, pi
);
8869 if (!CHECK_FLAG(bgp
->flags
,
8870 BGP_FLAG_DELETE_IN_PROGRESS
))
8871 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8873 bgp_path_info_reap(dest
, pi
);
8878 /* Static function to display route. */
8879 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8880 struct vty
*vty
, json_object
*json
, bool wide
)
8883 char buf
[INET6_ADDRSTRLEN
];
8885 if (p
->family
== AF_INET
) {
8887 len
= vty_out(vty
, "%pFX", p
);
8889 json_object_string_add(json
, "prefix",
8890 inet_ntop(p
->family
,
8893 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8894 json_object_string_addf(json
, "network", "%pFX", p
);
8895 json_object_int_add(json
, "version", dest
->version
);
8897 } else if (p
->family
== AF_ETHERNET
) {
8898 len
= vty_out(vty
, "%pFX", p
);
8899 } else if (p
->family
== AF_EVPN
) {
8901 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8903 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8904 } else if (p
->family
== AF_FLOWSPEC
) {
8905 route_vty_out_flowspec(vty
, p
, NULL
,
8907 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8908 NLRI_STRING_FORMAT_MIN
, json
);
8911 len
= vty_out(vty
, "%pFX", p
);
8913 json_object_string_add(json
, "prefix",
8914 inet_ntop(p
->family
,
8917 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8918 json_object_string_addf(json
, "network", "%pFX", p
);
8919 json_object_int_add(json
, "version", dest
->version
);
8924 len
= wide
? (45 - len
) : (17 - len
);
8926 vty_out(vty
, "\n%*s", 20, " ");
8928 vty_out(vty
, "%*s", len
, " ");
8932 enum bgp_display_type
{
8936 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8939 case bgp_path_selection_none
:
8940 return "Nothing to Select";
8941 case bgp_path_selection_first
:
8942 return "First path received";
8943 case bgp_path_selection_evpn_sticky_mac
:
8944 return "EVPN Sticky Mac";
8945 case bgp_path_selection_evpn_seq
:
8946 return "EVPN sequence number";
8947 case bgp_path_selection_evpn_lower_ip
:
8948 return "EVPN lower IP";
8949 case bgp_path_selection_evpn_local_path
:
8950 return "EVPN local ES path";
8951 case bgp_path_selection_evpn_non_proxy
:
8952 return "EVPN non proxy";
8953 case bgp_path_selection_weight
:
8955 case bgp_path_selection_local_pref
:
8956 return "Local Pref";
8957 case bgp_path_selection_accept_own
:
8958 return "Accept Own";
8959 case bgp_path_selection_local_route
:
8960 return "Local Route";
8961 case bgp_path_selection_aigp
:
8963 case bgp_path_selection_confed_as_path
:
8964 return "Confederation based AS Path";
8965 case bgp_path_selection_as_path
:
8967 case bgp_path_selection_origin
:
8969 case bgp_path_selection_med
:
8971 case bgp_path_selection_peer
:
8973 case bgp_path_selection_confed
:
8974 return "Confed Peer Type";
8975 case bgp_path_selection_igp_metric
:
8976 return "IGP Metric";
8977 case bgp_path_selection_older
:
8978 return "Older Path";
8979 case bgp_path_selection_router_id
:
8981 case bgp_path_selection_cluster_length
:
8982 return "Cluster length";
8983 case bgp_path_selection_stale
:
8984 return "Path Staleness";
8985 case bgp_path_selection_local_configured
:
8986 return "Locally configured route";
8987 case bgp_path_selection_neighbor_ip
:
8988 return "Neighbor IP";
8989 case bgp_path_selection_default
:
8990 return "Nothing left to compare";
8992 return "Invalid (internal error)";
8995 /* Print the short form route status for a bgp_path_info */
8996 static void route_vty_short_status_out(struct vty
*vty
,
8997 struct bgp_path_info
*path
,
8998 const struct prefix
*p
,
8999 json_object
*json_path
)
9001 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
9005 /* Route status display. */
9006 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9007 json_object_boolean_true_add(json_path
, "removed");
9009 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9010 json_object_boolean_true_add(json_path
, "stale");
9012 if (path
->extra
&& bgp_path_suppressed(path
))
9013 json_object_boolean_true_add(json_path
, "suppressed");
9015 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9016 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9017 json_object_boolean_true_add(json_path
, "valid");
9020 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9021 json_object_boolean_true_add(json_path
, "history");
9023 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9024 json_object_boolean_true_add(json_path
, "damped");
9026 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9027 json_object_boolean_true_add(json_path
, "bestpath");
9028 json_object_string_add(json_path
, "selectionReason",
9029 bgp_path_selection_reason2str(
9030 path
->net
->reason
));
9033 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9034 json_object_boolean_true_add(json_path
, "multipath");
9036 /* Internal route. */
9037 if ((path
->peer
->as
)
9038 && (path
->peer
->as
== path
->peer
->local_as
))
9039 json_object_string_add(json_path
, "pathFrom",
9042 json_object_string_add(json_path
, "pathFrom",
9048 /* RPKI validation state */
9050 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9052 if (rpki_state
== RPKI_VALID
)
9054 else if (rpki_state
== RPKI_INVALID
)
9056 else if (rpki_state
== RPKI_NOTFOUND
)
9061 /* Route status display. */
9062 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9064 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9066 else if (bgp_path_suppressed(path
))
9068 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9069 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9075 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9077 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9079 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9081 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9086 /* Internal route. */
9087 if (path
->peer
&& (path
->peer
->as
)
9088 && (path
->peer
->as
== path
->peer
->local_as
))
9094 static char *bgp_nexthop_hostname(struct peer
*peer
,
9095 struct bgp_nexthop_cache
*bnc
)
9098 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9099 return peer
->hostname
;
9103 /* called from terminal list command */
9104 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9105 struct bgp_path_info
*path
, int display
, safi_t safi
,
9106 json_object
*json_paths
, bool wide
)
9109 struct attr
*attr
= path
->attr
;
9110 json_object
*json_path
= NULL
;
9111 json_object
*json_nexthops
= NULL
;
9112 json_object
*json_nexthop_global
= NULL
;
9113 json_object
*json_nexthop_ll
= NULL
;
9114 json_object
*json_ext_community
= NULL
;
9115 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9117 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9118 bool nexthop_othervrf
= false;
9119 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9120 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9121 char *nexthop_hostname
=
9122 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9123 char esi_buf
[ESI_STR_LEN
];
9126 json_path
= json_object_new_object();
9128 /* short status lead text */
9129 route_vty_short_status_out(vty
, path
, p
, json_path
);
9132 /* print prefix and mask */
9134 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9136 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9138 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9142 * If vrf id of nexthop is different from that of prefix,
9143 * set up printable string to append
9145 if (path
->extra
&& path
->extra
->bgp_orig
) {
9146 const char *self
= "";
9151 nexthop_othervrf
= true;
9152 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9154 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9155 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9156 "@%s%s", VRFID_NONE_STR
, self
);
9158 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9159 path
->extra
->bgp_orig
->vrf_id
, self
);
9161 if (path
->extra
->bgp_orig
->inst_type
9162 != BGP_INSTANCE_TYPE_DEFAULT
)
9164 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9166 const char *self
= "";
9171 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9175 * For ENCAP and EVPN routes, nexthop address family is not
9176 * neccessarily the same as the prefix address family.
9177 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9178 * EVPN routes are also exchanged with a MP nexthop. Currently,
9180 * is only IPv4, the value will be present in either
9182 * attr->mp_nexthop_global_in
9184 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9186 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9190 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9191 &attr
->mp_nexthop_global_in
);
9194 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9195 &attr
->mp_nexthop_global
);
9198 snprintf(nexthop
, sizeof(nexthop
), "?");
9203 json_nexthop_global
= json_object_new_object();
9205 json_object_string_add(json_nexthop_global
, "ip",
9208 if (path
->peer
->hostname
)
9209 json_object_string_add(json_nexthop_global
,
9211 path
->peer
->hostname
);
9213 json_object_string_add(json_nexthop_global
, "afi",
9214 (af
== AF_INET
) ? "ipv4"
9216 json_object_boolean_true_add(json_nexthop_global
,
9219 if (nexthop_hostname
)
9220 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9221 nexthop_hostname
, vrf_id_str
);
9223 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9225 len
= wide
? (41 - len
) : (16 - len
);
9227 vty_out(vty
, "\n%*s", 36, " ");
9229 vty_out(vty
, "%*s", len
, " ");
9231 } else if (safi
== SAFI_EVPN
) {
9233 json_nexthop_global
= json_object_new_object();
9235 json_object_string_addf(json_nexthop_global
, "ip",
9237 &attr
->mp_nexthop_global_in
);
9239 if (path
->peer
->hostname
)
9240 json_object_string_add(json_nexthop_global
,
9242 path
->peer
->hostname
);
9244 json_object_string_add(json_nexthop_global
, "afi",
9246 json_object_boolean_true_add(json_nexthop_global
,
9249 if (nexthop_hostname
)
9250 len
= vty_out(vty
, "%pI4(%s)%s",
9251 &attr
->mp_nexthop_global_in
,
9252 nexthop_hostname
, vrf_id_str
);
9254 len
= vty_out(vty
, "%pI4%s",
9255 &attr
->mp_nexthop_global_in
,
9258 len
= wide
? (41 - len
) : (16 - len
);
9260 vty_out(vty
, "\n%*s", 36, " ");
9262 vty_out(vty
, "%*s", len
, " ");
9264 } else if (safi
== SAFI_FLOWSPEC
) {
9265 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9267 json_nexthop_global
= json_object_new_object();
9269 json_object_string_add(json_nexthop_global
,
9271 json_object_string_addf(json_nexthop_global
,
9275 if (path
->peer
->hostname
)
9276 json_object_string_add(
9277 json_nexthop_global
, "hostname",
9278 path
->peer
->hostname
);
9280 json_object_boolean_true_add(
9281 json_nexthop_global
,
9284 if (nexthop_hostname
)
9285 len
= vty_out(vty
, "%pI4(%s)%s",
9290 len
= vty_out(vty
, "%pI4%s",
9294 len
= wide
? (41 - len
) : (16 - len
);
9296 vty_out(vty
, "\n%*s", 36, " ");
9298 vty_out(vty
, "%*s", len
, " ");
9301 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9303 json_nexthop_global
= json_object_new_object();
9305 json_object_string_addf(json_nexthop_global
, "ip",
9306 "%pI4", &attr
->nexthop
);
9308 if (path
->peer
->hostname
)
9309 json_object_string_add(json_nexthop_global
,
9311 path
->peer
->hostname
);
9313 json_object_string_add(json_nexthop_global
, "afi",
9315 json_object_boolean_true_add(json_nexthop_global
,
9318 if (nexthop_hostname
)
9319 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9320 nexthop_hostname
, vrf_id_str
);
9322 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9325 len
= wide
? (41 - len
) : (16 - len
);
9327 vty_out(vty
, "\n%*s", 36, " ");
9329 vty_out(vty
, "%*s", len
, " ");
9334 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9336 json_nexthop_global
= json_object_new_object();
9337 json_object_string_addf(json_nexthop_global
, "ip",
9339 &attr
->mp_nexthop_global
);
9341 if (path
->peer
->hostname
)
9342 json_object_string_add(json_nexthop_global
,
9344 path
->peer
->hostname
);
9346 json_object_string_add(json_nexthop_global
, "afi",
9348 json_object_string_add(json_nexthop_global
, "scope",
9351 /* We display both LL & GL if both have been
9353 if ((attr
->mp_nexthop_len
9354 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9355 || (path
->peer
->conf_if
)) {
9356 json_nexthop_ll
= json_object_new_object();
9357 json_object_string_addf(
9358 json_nexthop_ll
, "ip", "%pI6",
9359 &attr
->mp_nexthop_local
);
9361 if (path
->peer
->hostname
)
9362 json_object_string_add(
9363 json_nexthop_ll
, "hostname",
9364 path
->peer
->hostname
);
9366 json_object_string_add(json_nexthop_ll
, "afi",
9368 json_object_string_add(json_nexthop_ll
, "scope",
9371 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9372 &attr
->mp_nexthop_local
)
9374 && !attr
->mp_nexthop_prefer_global
)
9375 json_object_boolean_true_add(
9376 json_nexthop_ll
, "used");
9378 json_object_boolean_true_add(
9379 json_nexthop_global
, "used");
9381 json_object_boolean_true_add(
9382 json_nexthop_global
, "used");
9384 /* Display LL if LL/Global both in table unless
9385 * prefer-global is set */
9386 if (((attr
->mp_nexthop_len
9387 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9388 && !attr
->mp_nexthop_prefer_global
)
9389 || (path
->peer
->conf_if
)) {
9390 if (path
->peer
->conf_if
) {
9391 len
= vty_out(vty
, "%s",
9392 path
->peer
->conf_if
);
9393 /* len of IPv6 addr + max len of def
9395 len
= wide
? (41 - len
) : (16 - len
);
9398 vty_out(vty
, "\n%*s", 36, " ");
9400 vty_out(vty
, "%*s", len
, " ");
9402 if (nexthop_hostname
)
9405 &attr
->mp_nexthop_local
,
9411 &attr
->mp_nexthop_local
,
9414 len
= wide
? (41 - len
) : (16 - len
);
9417 vty_out(vty
, "\n%*s", 36, " ");
9419 vty_out(vty
, "%*s", len
, " ");
9422 if (nexthop_hostname
)
9423 len
= vty_out(vty
, "%pI6(%s)%s",
9424 &attr
->mp_nexthop_global
,
9428 len
= vty_out(vty
, "%pI6%s",
9429 &attr
->mp_nexthop_global
,
9432 len
= wide
? (41 - len
) : (16 - len
);
9435 vty_out(vty
, "\n%*s", 36, " ");
9437 vty_out(vty
, "%*s", len
, " ");
9443 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9445 json_object_int_add(json_path
, "metric", attr
->med
);
9447 vty_out(vty
, "%7u", attr
->med
);
9449 vty_out(vty
, "%10u", attr
->med
);
9450 else if (!json_paths
) {
9452 vty_out(vty
, "%*s", 7, " ");
9454 vty_out(vty
, "%*s", 10, " ");
9458 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9460 json_object_int_add(json_path
, "locPrf",
9463 vty_out(vty
, "%7u", attr
->local_pref
);
9464 else if (!json_paths
)
9468 json_object_int_add(json_path
, "weight", attr
->weight
);
9470 vty_out(vty
, "%7u ", attr
->weight
);
9473 json_object_string_addf(json_path
, "peerId", "%pSU",
9479 json_object_string_add(json_path
, "path",
9482 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9487 json_object_string_add(json_path
, "origin",
9488 bgp_origin_long_str
[attr
->origin
]);
9490 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9493 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9494 json_object_string_add(json_path
, "esi",
9495 esi_to_str(&attr
->esi
,
9496 esi_buf
, sizeof(esi_buf
)));
9498 if (safi
== SAFI_EVPN
&&
9499 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9500 json_ext_community
= json_object_new_object();
9501 json_object_string_add(
9502 json_ext_community
, "string",
9503 bgp_attr_get_ecommunity(attr
)->str
);
9504 json_object_object_add(json_path
,
9505 "extendedCommunity",
9506 json_ext_community
);
9510 json_object_boolean_true_add(json_path
,
9511 "announceNexthopSelf");
9512 if (nexthop_othervrf
) {
9513 json_object_string_add(json_path
, "nhVrfName",
9516 json_object_int_add(json_path
, "nhVrfId",
9517 ((nexthop_vrfid
== VRF_UNKNOWN
)
9519 : (int)nexthop_vrfid
));
9524 if (json_nexthop_global
|| json_nexthop_ll
) {
9525 json_nexthops
= json_object_new_array();
9527 if (json_nexthop_global
)
9528 json_object_array_add(json_nexthops
,
9529 json_nexthop_global
);
9531 if (json_nexthop_ll
)
9532 json_object_array_add(json_nexthops
,
9535 json_object_object_add(json_path
, "nexthops",
9539 json_object_array_add(json_paths
, json_path
);
9543 if (safi
== SAFI_EVPN
) {
9544 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9545 /* XXX - add these params to the json out */
9546 vty_out(vty
, "%*s", 20, " ");
9547 vty_out(vty
, "ESI:%s",
9548 esi_to_str(&attr
->esi
, esi_buf
,
9554 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9555 vty_out(vty
, "%*s", 20, " ");
9556 vty_out(vty
, "%s\n",
9557 bgp_attr_get_ecommunity(attr
)->str
);
9561 #ifdef ENABLE_BGP_VNC
9562 /* prints an additional line, indented, with VNC info, if
9564 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9565 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9570 /* called from terminal list command */
9571 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9572 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9573 bool use_json
, json_object
*json_ar
, bool wide
)
9575 json_object
*json_status
= NULL
;
9576 json_object
*json_net
= NULL
;
9580 /* Route status display. */
9582 json_status
= json_object_new_object();
9583 json_net
= json_object_new_object();
9590 /* print prefix and mask */
9592 if (safi
== SAFI_EVPN
)
9593 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9594 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9595 json_object_string_add(
9596 json_net
, "addrPrefix",
9597 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9599 json_object_int_add(json_net
, "prefixLen",
9601 json_object_string_addf(json_net
, "network", "%pFX", p
);
9604 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9606 /* Print attribute */
9609 if (p
->family
== AF_INET
&&
9610 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9611 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9612 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9613 json_object_string_addf(
9614 json_net
, "nextHop", "%pI4",
9615 &attr
->mp_nexthop_global_in
);
9617 json_object_string_addf(
9618 json_net
, "nextHop", "%pI4",
9620 } else if (p
->family
== AF_INET6
||
9621 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9622 json_object_string_addf(
9623 json_net
, "nextHopGlobal", "%pI6",
9624 &attr
->mp_nexthop_global
);
9625 } else if (p
->family
== AF_EVPN
&&
9626 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9627 json_object_string_addf(
9628 json_net
, "nextHop", "%pI4",
9629 &attr
->mp_nexthop_global_in
);
9633 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9634 json_object_int_add(json_net
, "metric",
9637 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9638 json_object_int_add(json_net
, "locPrf",
9641 json_object_int_add(json_net
, "weight", attr
->weight
);
9645 json_object_string_add(json_net
, "path",
9649 #if CONFDATE > 20231208
9650 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9652 json_object_string_add(json_net
, "bgpOriginCode",
9653 bgp_origin_str
[attr
->origin
]);
9654 json_object_string_add(
9656 bgp_origin_long_str
[attr
->origin
]);
9658 if (p
->family
== AF_INET
&&
9659 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9660 safi
== SAFI_EVPN
||
9661 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9662 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9663 || safi
== SAFI_EVPN
)
9664 vty_out(vty
, "%-16pI4",
9665 &attr
->mp_nexthop_global_in
);
9667 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9669 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9670 } else if (p
->family
== AF_INET6
||
9671 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9672 len
= vty_out(vty
, "%pI6",
9673 &attr
->mp_nexthop_global
);
9674 len
= wide
? (41 - len
) : (16 - len
);
9676 vty_out(vty
, "\n%*s", 36, " ");
9678 vty_out(vty
, "%*s", len
, " ");
9681 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9683 vty_out(vty
, "%7u", attr
->med
);
9685 vty_out(vty
, "%10u", attr
->med
);
9691 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9692 vty_out(vty
, "%7u", attr
->local_pref
);
9696 vty_out(vty
, "%7u ", attr
->weight
);
9700 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9703 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9707 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9709 #if CONFDATE > 20231208
9710 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9712 json_object_boolean_true_add(json_status
, "*");
9713 json_object_boolean_true_add(json_status
, ">");
9714 json_object_boolean_true_add(json_net
, "valid");
9715 json_object_boolean_true_add(json_net
, "best");
9717 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9718 json_object_boolean_true_add(json_status
, "=");
9719 json_object_boolean_true_add(json_net
, "multipath");
9721 json_object_object_add(json_net
, "appliedStatusSymbols",
9723 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9728 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9729 struct bgp_path_info
*path
, int display
, safi_t safi
,
9732 json_object
*json_out
= NULL
;
9734 mpls_label_t label
= MPLS_INVALID_LABEL
;
9740 json_out
= json_object_new_object();
9742 /* short status lead text */
9743 route_vty_short_status_out(vty
, path
, p
, json_out
);
9745 /* print prefix and mask */
9748 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9750 vty_out(vty
, "%*s", 17, " ");
9753 /* Print attribute */
9755 if (((p
->family
== AF_INET
) &&
9756 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9757 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9758 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9759 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9760 || safi
== SAFI_EVPN
) {
9762 json_object_string_addf(
9763 json_out
, "mpNexthopGlobalIn", "%pI4",
9764 &attr
->mp_nexthop_global_in
);
9766 vty_out(vty
, "%-16pI4",
9767 &attr
->mp_nexthop_global_in
);
9770 json_object_string_addf(json_out
, "nexthop",
9771 "%pI4", &attr
->nexthop
);
9773 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9775 } else if (((p
->family
== AF_INET6
) &&
9776 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9777 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9778 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9781 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9783 json_object_string_addf(
9784 json_out
, "mpNexthopGlobalIn", "%pI6",
9785 &attr
->mp_nexthop_global
);
9789 &attr
->mp_nexthop_global
,
9790 buf_a
, sizeof(buf_a
)));
9791 } else if (attr
->mp_nexthop_len
9792 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9793 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9794 &attr
->mp_nexthop_global
,
9795 &attr
->mp_nexthop_local
);
9797 json_object_string_add(json_out
,
9798 "mpNexthopGlobalLocal",
9801 vty_out(vty
, "%s", buf_a
);
9805 label
= decode_label(&path
->extra
->label
[0]);
9807 if (bgp_is_valid_label(&label
)) {
9809 json_object_int_add(json_out
, "notag", label
);
9810 json_object_array_add(json
, json_out
);
9812 vty_out(vty
, "notag/%d", label
);
9819 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9820 struct bgp_path_info
*path
, int display
,
9821 json_object
*json_paths
)
9824 json_object
*json_path
= NULL
;
9825 json_object
*json_nexthop
= NULL
;
9826 json_object
*json_overlay
= NULL
;
9832 json_path
= json_object_new_object();
9833 json_overlay
= json_object_new_object();
9834 json_nexthop
= json_object_new_object();
9837 /* short status lead text */
9838 route_vty_short_status_out(vty
, path
, p
, json_path
);
9840 /* print prefix and mask */
9842 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9844 vty_out(vty
, "%*s", 17, " ");
9846 /* Print attribute */
9848 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9853 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9855 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9856 &attr
->mp_nexthop_global_in
);
9858 json_object_string_add(json_nexthop
, "afi", "ipv4");
9860 json_object_object_add(json_path
, "nexthop",
9866 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9867 &attr
->mp_nexthop_local
);
9869 json_object_string_addf(json_nexthop
, "ipv6Global",
9871 &attr
->mp_nexthop_global
);
9873 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9875 &attr
->mp_nexthop_local
);
9877 json_object_string_add(json_nexthop
, "afi", "ipv6");
9879 json_object_object_add(json_path
, "nexthop",
9887 json_object_string_add(json_nexthop
, "Error",
9888 "Unsupported address-family");
9889 json_object_string_add(json_nexthop
, "error",
9890 "Unsupported address-family");
9894 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9897 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9899 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9901 if (bgp_attr_get_ecommunity(attr
)) {
9903 struct ecommunity_val
*routermac
= ecommunity_lookup(
9904 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9905 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9908 mac
= ecom_mac2str((char *)routermac
->val
);
9911 vty_out(vty
, "/%s", mac
);
9913 json_object_string_add(json_overlay
, "rmac",
9916 XFREE(MTYPE_TMP
, mac
);
9923 json_object_object_add(json_path
, "overlay", json_overlay
);
9925 json_object_array_add(json_paths
, json_path
);
9929 /* dampening route */
9930 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9931 struct bgp_path_info
*path
, int display
,
9932 afi_t afi
, safi_t safi
, bool use_json
,
9933 json_object
*json_paths
)
9935 struct attr
*attr
= path
->attr
;
9937 char timebuf
[BGP_UPTIME_LEN
];
9938 json_object
*json_path
= NULL
;
9941 json_path
= json_object_new_object();
9943 /* short status lead text */
9944 route_vty_short_status_out(vty
, path
, p
, json_path
);
9946 /* print prefix and mask */
9949 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9951 vty_out(vty
, "%*s", 17, " ");
9953 len
= vty_out(vty
, "%s", path
->peer
->host
);
9957 vty_out(vty
, "\n%*s", 34, " ");
9959 vty_out(vty
, "%*s", len
, " ");
9962 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9963 BGP_UPTIME_LEN
, afi
, safi
,
9967 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9969 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9973 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9974 safi
, use_json
, json_path
);
9977 json_object_string_add(json_path
, "asPath",
9980 json_object_string_add(json_path
, "origin",
9981 bgp_origin_str
[attr
->origin
]);
9982 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9984 json_object_array_add(json_paths
, json_path
);
9989 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9990 struct bgp_path_info
*path
, int display
,
9991 afi_t afi
, safi_t safi
, bool use_json
,
9992 json_object
*json_paths
)
9994 struct attr
*attr
= path
->attr
;
9995 struct bgp_damp_info
*bdi
;
9996 char timebuf
[BGP_UPTIME_LEN
];
9998 json_object
*json_path
= NULL
;
10004 json_path
= json_object_new_object();
10006 bdi
= path
->extra
->damp_info
;
10008 /* short status lead text */
10009 route_vty_short_status_out(vty
, path
, p
, json_path
);
10013 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10015 vty_out(vty
, "%*s", 17, " ");
10017 len
= vty_out(vty
, "%s", path
->peer
->host
);
10020 vty_out(vty
, "\n%*s", 33, " ");
10022 vty_out(vty
, "%*s", len
, " ");
10024 len
= vty_out(vty
, "%d", bdi
->flap
);
10029 vty_out(vty
, "%*s", len
, " ");
10031 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10032 BGP_UPTIME_LEN
, 0, NULL
));
10034 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10035 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10036 vty_out(vty
, "%s ",
10037 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10038 BGP_UPTIME_LEN
, afi
,
10039 safi
, use_json
, NULL
));
10041 vty_out(vty
, "%*s ", 8, " ");
10044 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
10046 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10048 vty_out(vty
, "\n");
10050 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10051 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10053 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10056 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10057 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10058 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10059 BGP_UPTIME_LEN
, afi
, safi
,
10060 use_json
, json_path
);
10063 json_object_string_add(json_path
, "asPath",
10064 attr
->aspath
->str
);
10066 json_object_string_add(json_path
, "origin",
10067 bgp_origin_str
[attr
->origin
]);
10069 json_object_array_add(json_paths
, json_path
);
10073 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10074 int *first
, const char *header
,
10075 json_object
*json_adv_to
)
10077 json_object
*json_peer
= NULL
;
10080 /* 'advertised-to' is a dictionary of peers we have advertised
10082 * prefix too. The key is the peer's IP or swpX, the value is
10084 * hostname if we know it and "" if not.
10086 json_peer
= json_object_new_object();
10088 if (peer
->hostname
)
10089 json_object_string_add(json_peer
, "hostname",
10093 json_object_object_add(json_adv_to
, peer
->conf_if
,
10096 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10100 vty_out(vty
, "%s", header
);
10105 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10107 vty_out(vty
, " %s(%s)", peer
->hostname
,
10110 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10114 vty_out(vty
, " %s", peer
->conf_if
);
10116 vty_out(vty
, " %pSU", &peer
->su
);
10121 static void route_vty_out_tx_ids(struct vty
*vty
,
10122 struct bgp_addpath_info_data
*d
)
10126 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10127 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10128 d
->addpath_tx_id
[i
],
10129 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10133 static void route_vty_out_detail_es_info(struct vty
*vty
,
10134 struct bgp_path_info
*pi
,
10136 json_object
*json_path
)
10138 char esi_buf
[ESI_STR_LEN
];
10139 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10140 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10141 ATTR_ES_PEER_ROUTER
);
10142 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10143 ATTR_ES_PEER_ACTIVE
);
10144 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10145 ATTR_ES_PEER_PROXY
);
10146 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10148 json_object
*json_es_info
= NULL
;
10150 json_object_string_add(
10153 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10154 json_es_info
= json_object_new_object();
10156 json_object_boolean_true_add(
10157 json_es_info
, "localEs");
10159 json_object_boolean_true_add(
10160 json_es_info
, "peerActive");
10162 json_object_boolean_true_add(
10163 json_es_info
, "peerProxy");
10165 json_object_boolean_true_add(
10166 json_es_info
, "peerRouter");
10167 if (attr
->mm_sync_seqnum
)
10168 json_object_int_add(
10169 json_es_info
, "peerSeq",
10170 attr
->mm_sync_seqnum
);
10171 json_object_object_add(
10172 json_path
, "es_info",
10176 if (bgp_evpn_attr_is_sync(attr
))
10178 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10180 es_local
? "local-es":"",
10181 peer_proxy
? "proxy " : "",
10182 peer_active
? "active ":"",
10183 peer_router
? "router ":"",
10184 attr
->mm_sync_seqnum
);
10186 vty_out(vty
, " ESI %s %s\n",
10188 es_local
? "local-es":"");
10192 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10193 const struct prefix
*p
, struct bgp_path_info
*path
,
10194 afi_t afi
, safi_t safi
,
10195 enum rpki_states rpki_curr_state
,
10196 json_object
*json_paths
)
10198 char buf
[INET6_ADDRSTRLEN
];
10200 struct attr
*attr
= path
->attr
;
10202 json_object
*json_bestpath
= NULL
;
10203 json_object
*json_cluster_list
= NULL
;
10204 json_object
*json_cluster_list_list
= NULL
;
10205 json_object
*json_ext_community
= NULL
;
10206 json_object
*json_last_update
= NULL
;
10207 json_object
*json_pmsi
= NULL
;
10208 json_object
*json_nexthop_global
= NULL
;
10209 json_object
*json_nexthop_ll
= NULL
;
10210 json_object
*json_nexthops
= NULL
;
10211 json_object
*json_path
= NULL
;
10212 json_object
*json_peer
= NULL
;
10213 json_object
*json_string
= NULL
;
10214 json_object
*json_adv_to
= NULL
;
10216 struct listnode
*node
, *nnode
;
10218 bool addpath_capable
;
10220 unsigned int first_as
;
10221 bool nexthop_self
=
10222 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10224 char *nexthop_hostname
=
10225 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10229 mpls_label_t label
= MPLS_INVALID_LABEL
;
10231 struct bgp_path_info
*bpi_ultimate
=
10232 bgp_get_imported_bpi_ultimate(path
);
10235 json_path
= json_object_new_object();
10236 json_peer
= json_object_new_object();
10237 json_nexthop_global
= json_object_new_object();
10240 if (safi
== SAFI_EVPN
) {
10242 vty_out(vty
, " Route %pFX", p
);
10246 if (path
->extra
&& path
->extra
->num_labels
) {
10247 bgp_evpn_label2str(path
->extra
->label
,
10248 path
->extra
->num_labels
, tag_buf
,
10251 if (safi
== SAFI_EVPN
) {
10253 if (tag_buf
[0] != '\0')
10254 vty_out(vty
, " VNI %s", tag_buf
);
10257 json_object_string_add(json_path
, "VNI",
10259 json_object_string_add(json_path
, "vni",
10266 if (safi
== SAFI_EVPN
10267 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10268 char gwip_buf
[INET6_ADDRSTRLEN
];
10270 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10274 json_object_string_add(json_path
, "gatewayIP",
10277 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10280 if (safi
== SAFI_EVPN
&& !json_path
)
10281 vty_out(vty
, "\n");
10284 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10285 struct bgp_path_info
*parent_ri
;
10286 struct bgp_dest
*dest
, *pdest
;
10288 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10289 dest
= parent_ri
->net
;
10290 if (dest
&& dest
->pdest
) {
10291 pdest
= dest
->pdest
;
10292 if (is_pi_family_evpn(parent_ri
)) {
10294 " Imported from %pRD:%pFX, VNI %s",
10295 (struct prefix_rd
*)bgp_dest_get_prefix(
10297 (struct prefix_evpn
*)
10298 bgp_dest_get_prefix(dest
),
10300 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10301 vty_out(vty
, ", L3NHG %s",
10304 ATTR_ES_L3_NHG_ACTIVE
)
10307 vty_out(vty
, "\n");
10310 vty_out(vty
, " Imported from %pRD:%pFX\n",
10311 (struct prefix_rd
*)bgp_dest_get_prefix(
10313 (struct prefix_evpn
*)
10314 bgp_dest_get_prefix(dest
));
10318 /* Line1 display AS-path, Aggregator */
10319 if (attr
->aspath
) {
10321 if (!attr
->aspath
->json
)
10322 aspath_str_update(attr
->aspath
, true);
10323 json_object_lock(attr
->aspath
->json
);
10324 json_object_object_add(json_path
, "aspath",
10325 attr
->aspath
->json
);
10327 if (attr
->aspath
->segments
)
10328 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
10330 vty_out(vty
, " Local");
10334 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10336 json_object_boolean_true_add(json_path
, "removed");
10338 vty_out(vty
, ", (removed)");
10341 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10343 json_object_boolean_true_add(json_path
, "stale");
10345 vty_out(vty
, ", (stale)");
10348 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10350 json_object_int_add(json_path
, "aggregatorAs",
10351 attr
->aggregator_as
);
10352 json_object_string_addf(json_path
, "aggregatorId",
10353 "%pI4", &attr
->aggregator_addr
);
10355 vty_out(vty
, ", (aggregated by %u %pI4)",
10356 attr
->aggregator_as
, &attr
->aggregator_addr
);
10360 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10361 PEER_FLAG_REFLECTOR_CLIENT
)) {
10363 json_object_boolean_true_add(json_path
,
10364 "rxedFromRrClient");
10366 vty_out(vty
, ", (Received from a RR-client)");
10369 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10370 PEER_FLAG_RSERVER_CLIENT
)) {
10372 json_object_boolean_true_add(json_path
,
10373 "rxedFromRsClient");
10375 vty_out(vty
, ", (Received from a RS-client)");
10378 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10380 json_object_boolean_true_add(json_path
,
10381 "dampeningHistoryEntry");
10383 vty_out(vty
, ", (history entry)");
10384 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10386 json_object_boolean_true_add(json_path
,
10387 "dampeningSuppressed");
10389 vty_out(vty
, ", (suppressed due to dampening)");
10393 vty_out(vty
, "\n");
10395 /* Line2 display Next-hop, Neighbor, Router-id */
10396 /* Display the nexthop */
10398 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10399 p
->family
== AF_EVPN
) &&
10400 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10401 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10402 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10403 || safi
== SAFI_EVPN
) {
10405 json_object_string_addf(
10406 json_nexthop_global
, "ip", "%pI4",
10407 &attr
->mp_nexthop_global_in
);
10409 if (path
->peer
->hostname
)
10410 json_object_string_add(
10411 json_nexthop_global
, "hostname",
10412 path
->peer
->hostname
);
10414 if (nexthop_hostname
)
10415 vty_out(vty
, " %pI4(%s)",
10416 &attr
->mp_nexthop_global_in
,
10419 vty_out(vty
, " %pI4",
10420 &attr
->mp_nexthop_global_in
);
10424 json_object_string_addf(json_nexthop_global
,
10428 if (path
->peer
->hostname
)
10429 json_object_string_add(
10430 json_nexthop_global
, "hostname",
10431 path
->peer
->hostname
);
10433 if (nexthop_hostname
)
10434 vty_out(vty
, " %pI4(%s)",
10438 vty_out(vty
, " %pI4",
10444 json_object_string_add(json_nexthop_global
, "afi",
10448 json_object_string_addf(json_nexthop_global
, "ip",
10450 &attr
->mp_nexthop_global
);
10452 if (path
->peer
->hostname
)
10453 json_object_string_add(json_nexthop_global
,
10455 path
->peer
->hostname
);
10457 json_object_string_add(json_nexthop_global
, "afi",
10459 json_object_string_add(json_nexthop_global
, "scope",
10462 if (nexthop_hostname
)
10463 vty_out(vty
, " %pI6(%s)",
10464 &attr
->mp_nexthop_global
,
10467 vty_out(vty
, " %pI6",
10468 &attr
->mp_nexthop_global
);
10472 /* Display the IGP cost or 'inaccessible' */
10473 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10474 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10477 json_object_boolean_false_add(json_nexthop_global
,
10479 json_object_boolean_add(json_nexthop_global
,
10480 "importCheckEnabled", import
);
10482 vty_out(vty
, " (inaccessible%s)",
10483 import
? ", import-check enabled" : "");
10486 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10488 json_object_int_add(
10489 json_nexthop_global
, "metric",
10490 bpi_ultimate
->extra
->igpmetric
);
10492 vty_out(vty
, " (metric %u)",
10493 bpi_ultimate
->extra
->igpmetric
);
10496 /* IGP cost is 0, display this only for json */
10499 json_object_int_add(json_nexthop_global
,
10504 json_object_boolean_true_add(json_nexthop_global
,
10508 /* Display peer "from" output */
10509 /* This path was originated locally */
10510 if (path
->peer
== bgp
->peer_self
) {
10512 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10513 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10515 json_object_string_add(json_peer
, "peerId",
10518 vty_out(vty
, " from 0.0.0.0 ");
10521 json_object_string_add(json_peer
, "peerId",
10524 vty_out(vty
, " from :: ");
10528 json_object_string_addf(json_peer
, "routerId", "%pI4",
10531 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10534 /* We RXed this path from one of our peers */
10538 json_object_string_addf(json_peer
, "peerId", "%pSU",
10540 json_object_string_addf(json_peer
, "routerId", "%pI4",
10541 &path
->peer
->remote_id
);
10543 if (path
->peer
->hostname
)
10544 json_object_string_add(json_peer
, "hostname",
10545 path
->peer
->hostname
);
10547 if (path
->peer
->domainname
)
10548 json_object_string_add(json_peer
, "domainname",
10549 path
->peer
->domainname
);
10551 if (path
->peer
->conf_if
)
10552 json_object_string_add(json_peer
, "interface",
10553 path
->peer
->conf_if
);
10555 if (path
->peer
->conf_if
) {
10556 if (path
->peer
->hostname
10557 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10558 BGP_FLAG_SHOW_HOSTNAME
))
10559 vty_out(vty
, " from %s(%s)",
10560 path
->peer
->hostname
,
10561 path
->peer
->conf_if
);
10563 vty_out(vty
, " from %s",
10564 path
->peer
->conf_if
);
10566 if (path
->peer
->hostname
10567 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10568 BGP_FLAG_SHOW_HOSTNAME
))
10569 vty_out(vty
, " from %s(%s)",
10570 path
->peer
->hostname
,
10573 vty_out(vty
, " from %pSU",
10577 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10578 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10580 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10585 * Note when vrfid of nexthop is different from that of prefix
10587 if (path
->extra
&& path
->extra
->bgp_orig
) {
10588 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10593 if (path
->extra
->bgp_orig
->inst_type
10594 == BGP_INSTANCE_TYPE_DEFAULT
)
10595 vn
= VRF_DEFAULT_NAME
;
10597 vn
= path
->extra
->bgp_orig
->name
;
10599 json_object_string_add(json_path
, "nhVrfName", vn
);
10601 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10602 json_object_int_add(json_path
, "nhVrfId", -1);
10604 json_object_int_add(json_path
, "nhVrfId",
10605 (int)nexthop_vrfid
);
10608 if (nexthop_vrfid
== VRF_UNKNOWN
)
10609 vty_out(vty
, " vrf ?");
10613 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10614 vty_out(vty
, " vrf %s(%u)",
10615 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10620 if (nexthop_self
) {
10622 json_object_boolean_true_add(json_path
,
10623 "announceNexthopSelf");
10625 vty_out(vty
, " announce-nh-self");
10630 vty_out(vty
, "\n");
10632 /* display the link-local nexthop */
10633 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10635 json_nexthop_ll
= json_object_new_object();
10636 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10637 &attr
->mp_nexthop_local
);
10639 if (path
->peer
->hostname
)
10640 json_object_string_add(json_nexthop_ll
,
10642 path
->peer
->hostname
);
10644 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10645 json_object_string_add(json_nexthop_ll
, "scope",
10648 json_object_boolean_true_add(json_nexthop_ll
,
10651 if (!attr
->mp_nexthop_prefer_global
)
10652 json_object_boolean_true_add(json_nexthop_ll
,
10655 json_object_boolean_true_add(
10656 json_nexthop_global
, "used");
10658 vty_out(vty
, " (%s) %s\n",
10659 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10660 buf
, INET6_ADDRSTRLEN
),
10661 attr
->mp_nexthop_prefer_global
10662 ? "(prefer-global)"
10666 /* If we do not have a link-local nexthop then we must flag the
10667 global as "used" */
10670 json_object_boolean_true_add(json_nexthop_global
,
10674 if (safi
== SAFI_EVPN
&&
10675 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10676 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10679 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10680 * Int/Ext/Local, Atomic, best */
10682 json_object_string_add(json_path
, "origin",
10683 bgp_origin_long_str
[attr
->origin
]);
10685 vty_out(vty
, " Origin %s",
10686 bgp_origin_long_str
[attr
->origin
]);
10688 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10690 json_object_int_add(json_path
, "metric", attr
->med
);
10692 vty_out(vty
, ", metric %u", attr
->med
);
10695 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10697 json_object_int_add(json_path
, "locPrf",
10700 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10703 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10705 json_object_int_add(json_path
, "aigpMetric",
10706 bgp_attr_get_aigp_metric(attr
));
10708 vty_out(vty
, ", aigp-metric %" PRIu64
,
10709 bgp_attr_get_aigp_metric(attr
));
10712 if (attr
->weight
!= 0) {
10714 json_object_int_add(json_path
, "weight", attr
->weight
);
10716 vty_out(vty
, ", weight %u", attr
->weight
);
10719 if (attr
->tag
!= 0) {
10721 json_object_int_add(json_path
, "tag", attr
->tag
);
10723 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10726 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10728 json_object_boolean_false_add(json_path
, "valid");
10730 vty_out(vty
, ", invalid");
10731 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10733 json_object_boolean_true_add(json_path
, "valid");
10735 vty_out(vty
, ", valid");
10739 json_object_int_add(json_path
, "version", bn
->version
);
10741 if (path
->peer
!= bgp
->peer_self
) {
10742 if (path
->peer
->as
== path
->peer
->local_as
) {
10743 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10745 json_object_string_add(
10747 "confed-internal");
10749 vty_out(vty
, ", confed-internal");
10752 json_object_string_add(
10753 json_peer
, "type", "internal");
10755 vty_out(vty
, ", internal");
10758 if (bgp_confederation_peers_check(bgp
,
10761 json_object_string_add(
10763 "confed-external");
10765 vty_out(vty
, ", confed-external");
10768 json_object_string_add(
10769 json_peer
, "type", "external");
10771 vty_out(vty
, ", external");
10774 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10776 json_object_boolean_true_add(json_path
, "aggregated");
10777 json_object_boolean_true_add(json_path
, "local");
10779 vty_out(vty
, ", aggregated, local");
10781 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10783 json_object_boolean_true_add(json_path
, "sourced");
10785 vty_out(vty
, ", sourced");
10788 json_object_boolean_true_add(json_path
, "sourced");
10789 json_object_boolean_true_add(json_path
, "local");
10791 vty_out(vty
, ", sourced, local");
10795 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10797 json_object_boolean_true_add(json_path
,
10798 "atomicAggregate");
10800 vty_out(vty
, ", atomic-aggregate");
10803 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10805 json_object_int_add(json_path
, "otc", attr
->otc
);
10807 vty_out(vty
, ", otc %u", attr
->otc
);
10810 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10811 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10812 && bgp_path_info_mpath_count(path
))) {
10814 json_object_boolean_true_add(json_path
, "multipath");
10816 vty_out(vty
, ", multipath");
10819 // Mark the bestpath(s)
10820 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10821 first_as
= aspath_get_first_as(attr
->aspath
);
10824 if (!json_bestpath
)
10825 json_bestpath
= json_object_new_object();
10826 json_object_int_add(json_bestpath
, "bestpathFromAs",
10830 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10832 vty_out(vty
, ", bestpath-from-AS Local");
10836 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10838 if (!json_bestpath
)
10839 json_bestpath
= json_object_new_object();
10840 json_object_boolean_true_add(json_bestpath
, "overall");
10841 json_object_string_add(
10842 json_bestpath
, "selectionReason",
10843 bgp_path_selection_reason2str(bn
->reason
));
10845 vty_out(vty
, ", best");
10846 vty_out(vty
, " (%s)",
10847 bgp_path_selection_reason2str(bn
->reason
));
10851 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10853 json_object_string_add(
10854 json_path
, "rpkiValidationState",
10855 bgp_rpki_validation2str(rpki_curr_state
));
10857 vty_out(vty
, ", rpki validation-state: %s",
10858 bgp_rpki_validation2str(rpki_curr_state
));
10862 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10865 vty_out(vty
, "\n");
10867 /* Line 4 display Community */
10868 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10870 if (!bgp_attr_get_community(attr
)->json
)
10871 community_str(bgp_attr_get_community(attr
),
10873 json_object_lock(bgp_attr_get_community(attr
)->json
);
10874 json_object_object_add(
10875 json_path
, "community",
10876 bgp_attr_get_community(attr
)->json
);
10878 vty_out(vty
, " Community: %s\n",
10879 bgp_attr_get_community(attr
)->str
);
10883 /* Line 5 display Extended-community */
10884 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10886 json_ext_community
= json_object_new_object();
10887 json_object_string_add(
10888 json_ext_community
, "string",
10889 bgp_attr_get_ecommunity(attr
)->str
);
10890 json_object_object_add(json_path
, "extendedCommunity",
10891 json_ext_community
);
10893 vty_out(vty
, " Extended Community: %s\n",
10894 bgp_attr_get_ecommunity(attr
)->str
);
10898 /* Line 6 display Large community */
10899 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10901 if (!bgp_attr_get_lcommunity(attr
)->json
)
10902 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10904 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10905 json_object_object_add(
10906 json_path
, "largeCommunity",
10907 bgp_attr_get_lcommunity(attr
)->json
);
10909 vty_out(vty
, " Large Community: %s\n",
10910 bgp_attr_get_lcommunity(attr
)->str
);
10914 /* Line 7 display Originator, Cluster-id */
10915 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10916 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10917 char buf
[BUFSIZ
] = {0};
10919 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10921 json_object_string_addf(json_path
,
10922 "originatorId", "%pI4",
10923 &attr
->originator_id
);
10925 vty_out(vty
, " Originator: %pI4",
10926 &attr
->originator_id
);
10929 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10930 struct cluster_list
*cluster
=
10931 bgp_attr_get_cluster(attr
);
10935 json_cluster_list
= json_object_new_object();
10936 json_cluster_list_list
=
10937 json_object_new_array();
10939 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10940 json_string
= json_object_new_string(
10943 buf
, sizeof(buf
)));
10944 json_object_array_add(
10945 json_cluster_list_list
,
10950 * struct cluster_list does not have
10951 * "str" variable like aspath and community
10952 * do. Add this someday if someone asks
10954 * json_object_string_add(json_cluster_list,
10955 * "string", cluster->str);
10957 json_object_object_add(json_cluster_list
,
10959 json_cluster_list_list
);
10960 json_object_object_add(json_path
, "clusterList",
10961 json_cluster_list
);
10963 vty_out(vty
, ", Cluster list: ");
10965 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10966 vty_out(vty
, "%pI4 ",
10967 &cluster
->list
[i
]);
10973 vty_out(vty
, "\n");
10976 if (path
->extra
&& path
->extra
->damp_info
)
10977 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10980 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10981 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10982 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10986 json_object_int_add(json_path
, "remoteLabel", label
);
10988 vty_out(vty
, " Remote label: %d\n", label
);
10992 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10994 json_object_string_addf(json_path
, "remoteSid", "%pI6",
10995 &path
->extra
->sid
[0].sid
);
10997 vty_out(vty
, " Remote SID: %pI6\n",
10998 &path
->extra
->sid
[0].sid
);
11002 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
11004 json_object_int_add(json_path
, "labelIndex",
11005 attr
->label_index
);
11007 vty_out(vty
, " Label Index: %d\n",
11008 attr
->label_index
);
11011 /* Line 8 display Addpath IDs */
11012 if (path
->addpath_rx_id
11013 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11015 json_object_int_add(json_path
, "addpathRxId",
11016 path
->addpath_rx_id
);
11018 /* Keep backwards compatibility with the old API
11019 * by putting TX All's ID in the old field
11021 json_object_int_add(
11022 json_path
, "addpathTxId",
11024 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11026 /* ... but create a specific field for each
11029 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11030 json_object_int_add(
11032 bgp_addpath_names(i
)->id_json_name
,
11033 path
->tx_addpath
.addpath_tx_id
[i
]);
11036 vty_out(vty
, " AddPath ID: RX %u, ",
11037 path
->addpath_rx_id
);
11039 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11043 /* If we used addpath to TX a non-bestpath we need to display
11044 * "Advertised to" on a path-by-path basis
11046 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11049 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11051 bgp_addpath_encode_tx(peer
, afi
, safi
);
11052 has_adj
= bgp_adj_out_lookup(
11054 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11055 &path
->tx_addpath
));
11057 if ((addpath_capable
&& has_adj
)
11058 || (!addpath_capable
&& has_adj
11059 && CHECK_FLAG(path
->flags
,
11060 BGP_PATH_SELECTED
))) {
11061 if (json_path
&& !json_adv_to
)
11062 json_adv_to
= json_object_new_object();
11064 route_vty_out_advertised_to(
11066 " Advertised to:", json_adv_to
);
11072 json_object_object_add(
11073 json_path
, "advertisedTo", json_adv_to
);
11077 vty_out(vty
, "\n");
11082 /* Line 9 display Uptime */
11083 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11085 json_last_update
= json_object_new_object();
11086 json_object_int_add(json_last_update
, "epoch", tbuf
);
11087 json_object_string_add(json_last_update
, "string",
11089 json_object_object_add(json_path
, "lastUpdate",
11092 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11094 /* Line 10 display PMSI tunnel attribute, if present */
11095 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11096 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11097 bgp_attr_get_pmsi_tnl_type(attr
),
11098 PMSI_TNLTYPE_STR_DEFAULT
);
11101 json_pmsi
= json_object_new_object();
11102 json_object_string_add(json_pmsi
, "tunnelType", str
);
11103 json_object_int_add(json_pmsi
, "label",
11104 label2vni(&attr
->label
));
11105 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11107 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11108 str
, label2vni(&attr
->label
));
11111 if (path
->peer
->t_gr_restart
&&
11112 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11113 unsigned long gr_remaining
=
11114 thread_timer_remain_second(path
->peer
->t_gr_restart
);
11117 json_object_int_add(json_path
,
11118 "gracefulRestartSecondsRemaining",
11122 " Time until Graceful Restart stale route deleted: %lu\n",
11126 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11127 bgp_attr_get_community(attr
) &&
11128 community_include(bgp_attr_get_community(attr
),
11129 COMMUNITY_LLGR_STALE
)) {
11130 unsigned long llgr_remaining
= thread_timer_remain_second(
11131 path
->peer
->t_llgr_stale
[afi
][safi
]);
11134 json_object_int_add(json_path
, "llgrSecondsRemaining",
11138 " Time until Long-lived stale route deleted: %lu\n",
11142 /* Output some debug about internal state of the dest flags */
11144 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11145 json_object_boolean_true_add(json_path
, "processScheduled");
11146 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11147 json_object_boolean_true_add(json_path
, "userCleared");
11148 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11149 json_object_boolean_true_add(json_path
, "labelChanged");
11150 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11151 json_object_boolean_true_add(json_path
, "registeredForLabel");
11152 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11153 json_object_boolean_true_add(json_path
, "selectDefered");
11154 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11155 json_object_boolean_true_add(json_path
, "fibInstalled");
11156 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11157 json_object_boolean_true_add(json_path
, "fibPending");
11159 if (json_nexthop_global
|| json_nexthop_ll
) {
11160 json_nexthops
= json_object_new_array();
11162 if (json_nexthop_global
)
11163 json_object_array_add(json_nexthops
,
11164 json_nexthop_global
);
11166 if (json_nexthop_ll
)
11167 json_object_array_add(json_nexthops
,
11170 json_object_object_add(json_path
, "nexthops",
11174 json_object_object_add(json_path
, "peer", json_peer
);
11175 json_object_array_add(json_paths
, json_path
);
11179 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11180 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11181 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11183 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11184 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11186 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11187 const char *comstr
, int exact
, afi_t afi
,
11188 safi_t safi
, uint16_t show_flags
);
11190 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11191 struct bgp_table
*table
, enum bgp_show_type type
,
11192 void *output_arg
, const char *rd
, int is_last
,
11193 unsigned long *output_cum
, unsigned long *total_cum
,
11194 unsigned long *json_header_depth
, uint16_t show_flags
,
11195 enum rpki_states rpki_target_state
)
11197 struct bgp_path_info
*pi
;
11198 struct bgp_dest
*dest
;
11199 bool header
= true;
11200 bool json_detail_header
= false;
11202 unsigned long output_count
= 0;
11203 unsigned long total_count
= 0;
11205 json_object
*json_paths
= NULL
;
11207 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11208 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11209 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11210 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11211 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11213 if (output_cum
&& *output_cum
!= 0)
11216 if (use_json
&& !*json_header_depth
) {
11218 *json_header_depth
= 1;
11220 vty_out(vty
, "{\n");
11221 *json_header_depth
= 2;
11225 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11226 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11227 " \"localAS\": %u,\n \"routes\": { ",
11228 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11229 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11232 table
->version
, &bgp
->router_id
,
11233 bgp
->default_local_pref
, bgp
->as
);
11235 vty_out(vty
, " \"routeDistinguishers\" : {");
11236 ++*json_header_depth
;
11240 if (use_json
&& rd
) {
11241 vty_out(vty
, " \"%s\" : { ", rd
);
11244 /* Check for 'json detail', where we need header output once per dest */
11245 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11246 type
!= bgp_show_type_damp_neighbor
&&
11247 type
!= bgp_show_type_flap_statistics
&&
11248 type
!= bgp_show_type_flap_neighbor
)
11249 json_detail_header
= true;
11251 /* Start processing of routes. */
11252 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11253 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11254 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11255 bool json_detail
= json_detail_header
;
11257 pi
= bgp_dest_get_bgp_path_info(dest
);
11263 json_paths
= json_object_new_array();
11267 for (; pi
; pi
= pi
->next
) {
11268 struct community
*picomm
= NULL
;
11270 picomm
= bgp_attr_get_community(pi
->attr
);
11274 if (type
== bgp_show_type_prefix_version
) {
11276 strtoul(output_arg
, NULL
, 10);
11277 if (dest
->version
< version
)
11281 if (type
== bgp_show_type_community_alias
) {
11282 char *alias
= output_arg
;
11283 char **communities
;
11285 bool found
= false;
11288 frrstr_split(picomm
->str
, " ",
11289 &communities
, &num
);
11290 for (int i
= 0; i
< num
; i
++) {
11291 const char *com2alias
=
11292 bgp_community2alias(
11295 && strcmp(alias
, com2alias
)
11301 XFREE(MTYPE_TMP
, communities
);
11305 bgp_attr_get_lcommunity(pi
->attr
)) {
11306 frrstr_split(bgp_attr_get_lcommunity(
11309 " ", &communities
, &num
);
11310 for (int i
= 0; i
< num
; i
++) {
11311 const char *com2alias
=
11312 bgp_community2alias(
11315 && strcmp(alias
, com2alias
)
11321 XFREE(MTYPE_TMP
, communities
);
11328 if (type
== bgp_show_type_rpki
) {
11329 if (dest_p
->family
== AF_INET
11330 || dest_p
->family
== AF_INET6
)
11331 rpki_curr_state
= hook_call(
11332 bgp_rpki_prefix_status
,
11333 pi
->peer
, pi
->attr
, dest_p
);
11334 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11335 && rpki_curr_state
!= rpki_target_state
)
11339 if (type
== bgp_show_type_flap_statistics
11340 || type
== bgp_show_type_flap_neighbor
11341 || type
== bgp_show_type_dampend_paths
11342 || type
== bgp_show_type_damp_neighbor
) {
11343 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11346 if (type
== bgp_show_type_regexp
) {
11347 regex_t
*regex
= output_arg
;
11349 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11353 if (type
== bgp_show_type_prefix_list
) {
11354 struct prefix_list
*plist
= output_arg
;
11356 if (prefix_list_apply(plist
, dest_p
)
11360 if (type
== bgp_show_type_access_list
) {
11361 struct access_list
*alist
= output_arg
;
11363 if (access_list_apply(alist
, dest_p
) !=
11367 if (type
== bgp_show_type_filter_list
) {
11368 struct as_list
*as_list
= output_arg
;
11370 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11371 != AS_FILTER_PERMIT
)
11374 if (type
== bgp_show_type_route_map
) {
11375 struct route_map
*rmap
= output_arg
;
11376 struct bgp_path_info path
;
11377 struct bgp_path_info_extra extra
;
11378 struct attr dummy_attr
= {};
11379 route_map_result_t ret
;
11381 dummy_attr
= *pi
->attr
;
11383 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11384 pi
->peer
, &dummy_attr
);
11386 ret
= route_map_apply(rmap
, dest_p
, &path
);
11387 bgp_attr_flush(&dummy_attr
);
11388 if (ret
== RMAP_DENYMATCH
)
11391 if (type
== bgp_show_type_neighbor
11392 || type
== bgp_show_type_flap_neighbor
11393 || type
== bgp_show_type_damp_neighbor
) {
11394 union sockunion
*su
= output_arg
;
11396 if (pi
->peer
== NULL
11397 || pi
->peer
->su_remote
== NULL
11398 || !sockunion_same(pi
->peer
->su_remote
, su
))
11401 if (type
== bgp_show_type_cidr_only
) {
11402 uint32_t destination
;
11404 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11405 if (IN_CLASSC(destination
)
11406 && dest_p
->prefixlen
== 24)
11408 if (IN_CLASSB(destination
)
11409 && dest_p
->prefixlen
== 16)
11411 if (IN_CLASSA(destination
)
11412 && dest_p
->prefixlen
== 8)
11415 if (type
== bgp_show_type_prefix_longer
) {
11417 if (!prefix_match(p
, dest_p
))
11420 if (type
== bgp_show_type_community_all
) {
11424 if (type
== bgp_show_type_community
) {
11425 struct community
*com
= output_arg
;
11427 if (!picomm
|| !community_match(picomm
, com
))
11430 if (type
== bgp_show_type_community_exact
) {
11431 struct community
*com
= output_arg
;
11433 if (!picomm
|| !community_cmp(picomm
, com
))
11436 if (type
== bgp_show_type_community_list
) {
11437 struct community_list
*list
= output_arg
;
11439 if (!community_list_match(picomm
, list
))
11442 if (type
== bgp_show_type_community_list_exact
) {
11443 struct community_list
*list
= output_arg
;
11445 if (!community_list_exact_match(picomm
, list
))
11448 if (type
== bgp_show_type_lcommunity
) {
11449 struct lcommunity
*lcom
= output_arg
;
11451 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11453 bgp_attr_get_lcommunity(pi
->attr
),
11458 if (type
== bgp_show_type_lcommunity_exact
) {
11459 struct lcommunity
*lcom
= output_arg
;
11461 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11463 bgp_attr_get_lcommunity(pi
->attr
),
11467 if (type
== bgp_show_type_lcommunity_list
) {
11468 struct community_list
*list
= output_arg
;
11470 if (!lcommunity_list_match(
11471 bgp_attr_get_lcommunity(pi
->attr
),
11476 == bgp_show_type_lcommunity_list_exact
) {
11477 struct community_list
*list
= output_arg
;
11479 if (!lcommunity_list_exact_match(
11480 bgp_attr_get_lcommunity(pi
->attr
),
11484 if (type
== bgp_show_type_lcommunity_all
) {
11485 if (!bgp_attr_get_lcommunity(pi
->attr
))
11488 if (type
== bgp_show_type_dampend_paths
11489 || type
== bgp_show_type_damp_neighbor
) {
11490 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11491 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11495 if (!use_json
&& header
) {
11497 "BGP table version is %" PRIu64
11498 ", local router ID is %pI4, vrf id ",
11499 table
->version
, &bgp
->router_id
);
11500 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11501 vty_out(vty
, "%s", VRFID_NONE_STR
);
11503 vty_out(vty
, "%u", bgp
->vrf_id
);
11504 vty_out(vty
, "\n");
11505 vty_out(vty
, "Default local pref %u, ",
11506 bgp
->default_local_pref
);
11507 vty_out(vty
, "local AS %u\n", bgp
->as
);
11508 if (!detail_routes
) {
11509 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11510 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11511 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11512 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11514 if (type
== bgp_show_type_dampend_paths
11515 || type
== bgp_show_type_damp_neighbor
)
11516 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11517 else if (type
== bgp_show_type_flap_statistics
11518 || type
== bgp_show_type_flap_neighbor
)
11519 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11520 else if (!detail_routes
)
11521 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11522 : BGP_SHOW_HEADER
));
11525 } else if (json_detail
&& json_paths
!= NULL
) {
11526 const struct prefix_rd
*prd
;
11527 json_object
*jtemp
;
11529 /* Use common detail header, for most types;
11530 * need a json 'object'.
11533 jtemp
= json_object_new_object();
11534 prd
= bgp_rd_from_dest(dest
, safi
);
11536 route_vty_out_detail_header(
11538 bgp_dest_get_prefix(dest
), prd
,
11539 table
->afi
, safi
, jtemp
);
11541 json_object_array_add(json_paths
, jtemp
);
11543 json_detail
= false;
11546 if (rd
!= NULL
&& !display
&& !output_count
) {
11549 "Route Distinguisher: %s\n",
11552 if (type
== bgp_show_type_dampend_paths
11553 || type
== bgp_show_type_damp_neighbor
)
11554 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11555 AFI_IP
, safi
, use_json
,
11557 else if (type
== bgp_show_type_flap_statistics
11558 || type
== bgp_show_type_flap_neighbor
)
11559 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11560 AFI_IP
, safi
, use_json
,
11563 if (detail_routes
|| detail_json
) {
11564 const struct prefix_rd
*prd
= NULL
;
11567 prd
= bgp_rd_from_dest(
11568 dest
->pdest
, safi
);
11571 route_vty_out_detail_header(
11573 bgp_dest_get_prefix(
11575 prd
, table
->afi
, safi
,
11578 route_vty_out_detail(
11579 vty
, bgp
, dest
, dest_p
, pi
,
11580 family2afi(dest_p
->family
),
11581 safi
, RPKI_NOT_BEING_USED
,
11584 route_vty_out(vty
, dest_p
, pi
, display
,
11585 safi
, json_paths
, wide
);
11596 /* encode prefix */
11597 if (dest_p
->family
== AF_FLOWSPEC
) {
11598 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11601 bgp_fs_nlri_get_string(
11603 dest_p
->u
.prefix_flowspec
.ptr
,
11604 dest_p
->u
.prefix_flowspec
.prefixlen
,
11605 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11606 family2afi(dest_p
->u
11607 .prefix_flowspec
.family
));
11609 vty_out(vty
, "\"%s/%d\": ", retstr
,
11610 dest_p
->u
.prefix_flowspec
11613 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11614 dest_p
->u
.prefix_flowspec
11618 vty_out(vty
, "\"%pFX\": ", dest_p
);
11620 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11622 vty_json(vty
, json_paths
);
11626 json_object_free(json_paths
);
11630 output_count
+= *output_cum
;
11631 *output_cum
= output_count
;
11634 total_count
+= *total_cum
;
11635 *total_cum
= total_count
;
11639 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11643 for (i
= 0; i
< *json_header_depth
; ++i
)
11644 vty_out(vty
, " } ");
11646 vty_out(vty
, "\n");
11650 /* No route is displayed */
11651 if (output_count
== 0) {
11652 if (type
== bgp_show_type_normal
)
11654 "No BGP prefixes displayed, %ld exist\n",
11658 "\nDisplayed %ld routes and %ld total paths\n",
11659 output_count
, total_count
);
11663 return CMD_SUCCESS
;
11666 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11667 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11668 enum bgp_show_type type
, void *output_arg
,
11669 uint16_t show_flags
)
11671 struct bgp_dest
*dest
, *next
;
11672 unsigned long output_cum
= 0;
11673 unsigned long total_cum
= 0;
11674 unsigned long json_header_depth
= 0;
11675 struct bgp_table
*itable
;
11677 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11679 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11681 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11682 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11684 next
= bgp_route_next(dest
);
11685 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11688 itable
= bgp_dest_get_bgp_table_info(dest
);
11689 if (itable
!= NULL
) {
11690 struct prefix_rd prd
;
11691 char rd
[RD_ADDRSTRLEN
];
11693 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11694 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11695 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11696 rd
, next
== NULL
, &output_cum
,
11697 &total_cum
, &json_header_depth
,
11698 show_flags
, RPKI_NOT_BEING_USED
);
11704 if (output_cum
== 0)
11705 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11709 "\nDisplayed %ld routes and %ld total paths\n",
11710 output_cum
, total_cum
);
11712 if (use_json
&& output_cum
== 0)
11713 vty_out(vty
, "{}\n");
11715 return CMD_SUCCESS
;
11718 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11719 enum bgp_show_type type
, void *output_arg
,
11720 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11722 struct bgp_table
*table
;
11723 unsigned long json_header_depth
= 0;
11724 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11727 bgp
= bgp_get_default();
11732 vty_out(vty
, "No BGP process is configured\n");
11734 vty_out(vty
, "{}\n");
11735 return CMD_WARNING
;
11738 /* Labeled-unicast routes live in the unicast table. */
11739 if (safi
== SAFI_LABELED_UNICAST
)
11740 safi
= SAFI_UNICAST
;
11742 table
= bgp
->rib
[afi
][safi
];
11743 /* use MPLS and ENCAP specific shows until they are merged */
11744 if (safi
== SAFI_MPLS_VPN
) {
11745 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11746 output_arg
, show_flags
);
11749 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11750 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11751 output_arg
, use_json
,
11755 if (safi
== SAFI_EVPN
)
11756 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11758 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11759 NULL
, NULL
, &json_header_depth
, show_flags
,
11760 rpki_target_state
);
11763 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11764 safi_t safi
, uint16_t show_flags
)
11766 struct listnode
*node
, *nnode
;
11769 bool route_output
= false;
11770 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11773 vty_out(vty
, "{\n");
11775 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11776 route_output
= true;
11779 vty_out(vty
, ",\n");
11783 vty_out(vty
, "\"%s\":",
11784 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11788 vty_out(vty
, "\nInstance %s:\n",
11789 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11793 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11794 show_flags
, RPKI_NOT_BEING_USED
);
11798 vty_out(vty
, "}\n");
11799 else if (!route_output
)
11800 vty_out(vty
, "%% BGP instance not found\n");
11803 /* Header of detailed BGP route information */
11804 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11805 struct bgp_dest
*dest
, const struct prefix
*p
,
11806 const struct prefix_rd
*prd
, afi_t afi
,
11807 safi_t safi
, json_object
*json
)
11809 struct bgp_path_info
*pi
;
11811 struct listnode
*node
, *nnode
;
11812 char buf1
[RD_ADDRSTRLEN
];
11816 int accept_own
= 0;
11817 int route_filter_translated_v4
= 0;
11818 int route_filter_v4
= 0;
11819 int route_filter_translated_v6
= 0;
11820 int route_filter_v6
= 0;
11821 int llgr_stale
= 0;
11823 int accept_own_nexthop
= 0;
11826 int no_advertise
= 0;
11830 int has_valid_label
= 0;
11831 mpls_label_t label
= 0;
11832 json_object
*json_adv_to
= NULL
;
11837 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11839 has_valid_label
= bgp_is_valid_label(&label
);
11841 if (safi
== SAFI_EVPN
) {
11843 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11844 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11846 prd
? ":" : "", (struct prefix_evpn
*)p
);
11848 json_object_string_add(json
, "rd",
11849 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11851 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11856 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11858 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11859 ? prefix_rd2str(prd
, buf1
,
11862 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11866 json_object_string_addf(json
, "prefix", "%pFX", p
);
11867 json_object_int_add(json
, "version", dest
->version
);
11872 if (has_valid_label
) {
11874 json_object_int_add(json
, "localLabel", label
);
11876 vty_out(vty
, "Local label: %d\n", label
);
11880 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11881 vty_out(vty
, "not allocated\n");
11883 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11884 struct community
*picomm
= NULL
;
11886 picomm
= bgp_attr_get_community(pi
->attr
);
11889 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11891 if (bgp_path_suppressed(pi
))
11897 no_advertise
+= community_include(
11898 picomm
, COMMUNITY_NO_ADVERTISE
);
11900 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11902 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11904 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11905 route_filter_translated_v4
+= community_include(
11906 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11907 route_filter_translated_v6
+= community_include(
11908 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11909 route_filter_v4
+= community_include(
11910 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11911 route_filter_v6
+= community_include(
11912 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11914 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11915 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11916 accept_own_nexthop
+= community_include(
11917 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11919 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11920 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11925 vty_out(vty
, "Paths: (%d available", count
);
11927 vty_out(vty
, ", best #%d", best
);
11928 if (safi
== SAFI_UNICAST
) {
11929 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11930 vty_out(vty
, ", table %s",
11933 vty_out(vty
, ", vrf %s",
11937 vty_out(vty
, ", no best path");
11941 ", accept own local route exported and imported in different VRF");
11942 else if (route_filter_translated_v4
)
11944 ", mark translated RTs for VPNv4 route filtering");
11945 else if (route_filter_v4
)
11947 ", attach RT as-is for VPNv4 route filtering");
11948 else if (route_filter_translated_v6
)
11950 ", mark translated RTs for VPNv6 route filtering");
11951 else if (route_filter_v6
)
11953 ", attach RT as-is for VPNv6 route filtering");
11954 else if (llgr_stale
)
11956 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11959 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11960 else if (accept_own_nexthop
)
11962 ", accept local nexthop");
11963 else if (blackhole
)
11964 vty_out(vty
, ", inform peer to blackhole prefix");
11965 else if (no_export
)
11966 vty_out(vty
, ", not advertised to EBGP peer");
11967 else if (no_advertise
)
11968 vty_out(vty
, ", not advertised to any peer");
11970 vty_out(vty
, ", not advertised outside local AS");
11973 ", inform EBGP peer not to advertise to their EBGP peers");
11977 ", Advertisements suppressed by an aggregate.");
11978 vty_out(vty
, ")\n");
11981 /* If we are not using addpath then we can display Advertised to and
11983 * show what peers we advertised the bestpath to. If we are using
11985 * though then we must display Advertised to on a path-by-path basis. */
11986 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11987 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11988 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11989 if (json
&& !json_adv_to
)
11990 json_adv_to
= json_object_new_object();
11992 route_vty_out_advertised_to(
11994 " Advertised to non peer-group peers:\n ",
12001 json_object_object_add(json
, "advertisedTo",
12006 vty_out(vty
, " Not advertised to any peer");
12007 vty_out(vty
, "\n");
12012 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12013 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12014 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12015 json_object
*json
, enum bgp_path_type pathtype
,
12016 int *display
, enum rpki_states rpki_target_state
)
12018 struct bgp_path_info
*pi
;
12020 json_object
*json_header
= NULL
;
12021 json_object
*json_paths
= NULL
;
12022 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12024 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12025 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12027 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12028 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12029 pi
->peer
, pi
->attr
, p
);
12031 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12032 && rpki_curr_state
!= rpki_target_state
)
12035 if (json
&& !json_paths
) {
12036 /* Instantiate json_paths only if path is valid */
12037 json_paths
= json_object_new_array();
12039 json_header
= json_object_new_object();
12041 json_header
= json
;
12045 route_vty_out_detail_header(
12046 vty
, bgp
, bgp_node
,
12047 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12048 safi
, json_header
);
12053 if (pathtype
== BGP_PATH_SHOW_ALL
12054 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12055 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12056 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12057 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12058 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12059 route_vty_out_detail(vty
, bgp
, bgp_node
,
12060 bgp_dest_get_prefix(bgp_node
), pi
,
12061 AFI_IP
, safi
, rpki_curr_state
,
12065 if (json
&& json_paths
) {
12066 json_object_object_add(json_header
, "paths", json_paths
);
12069 json_object_object_addf(json
, json_header
, "%pRD",
12075 * Return rd based on safi
12077 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12081 case SAFI_MPLS_VPN
:
12084 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12090 /* Display specified route of BGP table. */
12091 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12092 struct bgp_table
*rib
, const char *ip_str
,
12093 afi_t afi
, safi_t safi
,
12094 enum rpki_states rpki_target_state
,
12095 struct prefix_rd
*prd
, int prefix_check
,
12096 enum bgp_path_type pathtype
, bool use_json
)
12100 struct prefix match
;
12101 struct bgp_dest
*dest
;
12102 struct bgp_dest
*rm
;
12103 struct bgp_table
*table
;
12104 json_object
*json
= NULL
;
12105 json_object
*json_paths
= NULL
;
12107 /* Check IP address argument. */
12108 ret
= str2prefix(ip_str
, &match
);
12110 vty_out(vty
, "address is malformed\n");
12111 return CMD_WARNING
;
12114 match
.family
= afi2family(afi
);
12117 json
= json_object_new_object();
12119 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12120 for (dest
= bgp_table_top(rib
); dest
;
12121 dest
= bgp_route_next(dest
)) {
12122 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12124 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12126 table
= bgp_dest_get_bgp_table_info(dest
);
12130 rm
= bgp_node_match(table
, &match
);
12134 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12136 && rm_p
->prefixlen
!= match
.prefixlen
) {
12137 bgp_dest_unlock_node(rm
);
12141 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12142 bgp
, afi
, safi
, json
, pathtype
,
12143 &display
, rpki_target_state
);
12145 bgp_dest_unlock_node(rm
);
12147 } else if (safi
== SAFI_EVPN
) {
12148 struct bgp_dest
*longest_pfx
;
12149 bool is_exact_pfxlen_match
= false;
12151 for (dest
= bgp_table_top(rib
); dest
;
12152 dest
= bgp_route_next(dest
)) {
12153 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12155 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12157 table
= bgp_dest_get_bgp_table_info(dest
);
12161 longest_pfx
= NULL
;
12162 is_exact_pfxlen_match
= false;
12164 * Search through all the prefixes for a match. The
12165 * pfx's are enumerated in ascending order of pfxlens.
12166 * So, the last pfx match is the longest match. Set
12167 * is_exact_pfxlen_match when we get exact pfxlen match
12169 for (rm
= bgp_table_top(table
); rm
;
12170 rm
= bgp_route_next(rm
)) {
12171 const struct prefix
*rm_p
=
12172 bgp_dest_get_prefix(rm
);
12174 * Get prefixlen of the ip-prefix within type5
12177 if (evpn_type5_prefix_match(rm_p
, &match
)
12181 bgp_evpn_get_type5_prefixlen(
12183 if (type5_pfxlen
== match
.prefixlen
) {
12184 is_exact_pfxlen_match
= true;
12185 bgp_dest_unlock_node(rm
);
12194 if (prefix_check
&& !is_exact_pfxlen_match
)
12198 bgp_dest_lock_node(rm
);
12200 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12201 bgp
, afi
, safi
, json
, pathtype
,
12202 &display
, rpki_target_state
);
12204 bgp_dest_unlock_node(rm
);
12206 } else if (safi
== SAFI_FLOWSPEC
) {
12208 json_paths
= json_object_new_array();
12210 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12211 &match
, prefix_check
,
12217 json_object_object_add(json
, "paths",
12220 json_object_free(json_paths
);
12223 dest
= bgp_node_match(rib
, &match
);
12224 if (dest
!= NULL
) {
12225 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12227 || dest_p
->prefixlen
== match
.prefixlen
) {
12228 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12229 safi
, json
, pathtype
,
12230 &display
, rpki_target_state
);
12233 bgp_dest_unlock_node(dest
);
12238 vty_json(vty
, json
);
12241 vty_out(vty
, "%% Network not in table\n");
12242 return CMD_WARNING
;
12246 return CMD_SUCCESS
;
12249 /* Display specified route of Main RIB */
12250 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12251 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12252 int prefix_check
, enum bgp_path_type pathtype
,
12253 enum rpki_states rpki_target_state
, bool use_json
)
12256 bgp
= bgp_get_default();
12259 vty_out(vty
, "No BGP process is configured\n");
12261 vty_out(vty
, "{}\n");
12262 return CMD_WARNING
;
12266 /* labeled-unicast routes live in the unicast table */
12267 if (safi
== SAFI_LABELED_UNICAST
)
12268 safi
= SAFI_UNICAST
;
12270 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12271 afi
, safi
, rpki_target_state
, prd
,
12272 prefix_check
, pathtype
, use_json
);
12275 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12276 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12277 safi_t safi
, bool uj
)
12279 struct lcommunity
*lcom
;
12284 uint16_t show_flags
= 0;
12288 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12290 b
= buffer_new(1024);
12291 for (i
= 0; i
< argc
; i
++) {
12293 buffer_putc(b
, ' ');
12295 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12297 buffer_putstr(b
, argv
[i
]->arg
);
12301 buffer_putc(b
, '\0');
12303 str
= buffer_getstr(b
);
12306 lcom
= lcommunity_str2com(str
);
12307 XFREE(MTYPE_TMP
, str
);
12309 vty_out(vty
, "%% Large-community malformed\n");
12310 return CMD_WARNING
;
12313 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12314 (exact
? bgp_show_type_lcommunity_exact
12315 : bgp_show_type_lcommunity
),
12316 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12318 lcommunity_free(&lcom
);
12322 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12323 const char *lcom
, bool exact
, afi_t afi
,
12324 safi_t safi
, bool uj
)
12326 struct community_list
*list
;
12327 uint16_t show_flags
= 0;
12330 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12333 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12334 LARGE_COMMUNITY_LIST_MASTER
);
12335 if (list
== NULL
) {
12336 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12338 return CMD_WARNING
;
12341 return bgp_show(vty
, bgp
, afi
, safi
,
12342 (exact
? bgp_show_type_lcommunity_list_exact
12343 : bgp_show_type_lcommunity_list
),
12344 list
, show_flags
, RPKI_NOT_BEING_USED
);
12347 DEFUN (show_ip_bgp_large_community_list
,
12348 show_ip_bgp_large_community_list_cmd
,
12349 "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]",
12353 BGP_INSTANCE_HELP_STR
12355 BGP_SAFI_WITH_LABEL_HELP_STR
12356 "Display routes matching the large-community-list\n"
12357 "large-community-list number\n"
12358 "large-community-list name\n"
12359 "Exact match of the large-communities\n"
12362 afi_t afi
= AFI_IP6
;
12363 safi_t safi
= SAFI_UNICAST
;
12365 bool exact_match
= 0;
12366 struct bgp
*bgp
= NULL
;
12367 bool uj
= use_json(argc
, argv
);
12372 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12375 return CMD_WARNING
;
12377 argv_find(argv
, argc
, "large-community-list", &idx
);
12379 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12381 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12384 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12385 exact_match
, afi
, safi
, uj
);
12387 DEFUN (show_ip_bgp_large_community
,
12388 show_ip_bgp_large_community_cmd
,
12389 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12393 BGP_INSTANCE_HELP_STR
12395 BGP_SAFI_WITH_LABEL_HELP_STR
12396 "Display routes matching the large-communities\n"
12397 "List of large-community numbers\n"
12398 "Exact match of the large-communities\n"
12401 afi_t afi
= AFI_IP6
;
12402 safi_t safi
= SAFI_UNICAST
;
12404 bool exact_match
= 0;
12405 struct bgp
*bgp
= NULL
;
12406 bool uj
= use_json(argc
, argv
);
12407 uint16_t show_flags
= 0;
12411 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12414 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12417 return CMD_WARNING
;
12419 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12420 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12424 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12425 exact_match
, afi
, safi
, uj
);
12427 return bgp_show(vty
, bgp
, afi
, safi
,
12428 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12429 RPKI_NOT_BEING_USED
);
12432 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12433 safi_t safi
, struct json_object
*json_array
);
12434 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12435 safi_t safi
, struct json_object
*json
);
12438 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12439 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12440 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12441 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12443 bool uj
= use_json(argc
, argv
);
12444 struct bgp
*bgp
= NULL
;
12445 safi_t safi
= SAFI_UNICAST
;
12446 afi_t afi
= AFI_IP6
;
12448 struct json_object
*json_all
= NULL
;
12449 struct json_object
*json_afi_safi
= NULL
;
12451 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12454 return CMD_WARNING
;
12457 json_all
= json_object_new_object();
12459 FOREACH_AFI_SAFI (afi
, safi
) {
12461 * So limit output to those afi/safi pairs that
12462 * actually have something interesting in them
12464 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12469 json_afi_safi
= json_object_new_array();
12470 json_object_object_add(
12472 get_afi_safi_str(afi
, safi
, true),
12475 json_afi_safi
= NULL
;
12478 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12482 vty_json(vty
, json_all
);
12484 return CMD_SUCCESS
;
12487 /* BGP route print out function without JSON */
12488 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12489 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12490 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12494 BGP_INSTANCE_HELP_STR
12497 "BGP RIB advertisement statistics\n"
12500 afi_t afi
= AFI_IP6
;
12501 safi_t safi
= SAFI_UNICAST
;
12502 struct bgp
*bgp
= NULL
;
12504 bool uj
= use_json(argc
, argv
);
12505 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12507 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12510 return CMD_WARNING
;
12513 json_afi_safi
= json_object_new_array();
12515 json_afi_safi
= NULL
;
12517 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12520 json
= json_object_new_object();
12521 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12523 vty_json(vty
, json
);
12528 /* BGP route print out function without JSON */
12529 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12530 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12531 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12533 statistics [json]",
12534 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12535 BGP_SAFI_WITH_LABEL_HELP_STR
12536 "BGP RIB advertisement statistics\n" JSON_STR
)
12538 afi_t afi
= AFI_IP6
;
12539 safi_t safi
= SAFI_UNICAST
;
12540 struct bgp
*bgp
= NULL
;
12542 bool uj
= use_json(argc
, argv
);
12543 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12545 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12548 return CMD_WARNING
;
12551 json_afi_safi
= json_object_new_array();
12553 json_afi_safi
= NULL
;
12555 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12558 json
= json_object_new_object();
12559 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12561 vty_json(vty
, json
);
12566 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12567 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12568 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12569 "]] [all$all] dampening parameters [json]",
12570 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12571 BGP_SAFI_WITH_LABEL_HELP_STR
12572 "Display the entries for all address families\n"
12573 "Display detailed information about dampening\n"
12574 "Display detail of configured dampening parameters\n"
12577 afi_t afi
= AFI_IP6
;
12578 safi_t safi
= SAFI_UNICAST
;
12579 struct bgp
*bgp
= NULL
;
12581 uint16_t show_flags
= 0;
12582 bool uj
= use_json(argc
, argv
);
12586 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12589 /* [<ipv4|ipv6> [all]] */
12591 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12592 if (argv_find(argv
, argc
, "ipv4", &idx
))
12593 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12595 if (argv_find(argv
, argc
, "ipv6", &idx
))
12596 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12599 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12602 return CMD_WARNING
;
12604 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12607 /* BGP route print out function */
12608 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12609 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12610 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12614 |dampening <flap-statistics|dampened-paths>\
12615 |community [AA:NN|local-AS|no-advertise|no-export\
12616 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12617 |accept-own|accept-own-nexthop|route-filter-v6\
12618 |route-filter-v4|route-filter-translated-v6\
12619 |route-filter-translated-v4] [exact-match]\
12620 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12621 |filter-list AS_PATH_FILTER_NAME\
12623 |access-list ACCESSLIST_NAME\
12624 |route-map RMAP_NAME\
12625 |rpki <invalid|valid|notfound>\
12626 |version (1-4294967295)\
12628 |A.B.C.D/M longer-prefixes\
12629 |X:X::X:X/M longer-prefixes\
12630 |detail-routes$detail_routes\
12631 ] [json$uj [detail$detail_json] | wide$wide]",
12632 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12633 BGP_SAFI_WITH_LABEL_HELP_STR
12634 "Display the entries for all address families\n"
12635 "Display only routes with non-natural netmasks\n"
12636 "Display detailed information about dampening\n"
12637 "Display flap statistics of routes\n"
12638 "Display paths suppressed due to dampening\n"
12639 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12640 "Do not send outside local AS (well-known community)\n"
12641 "Do not advertise to any peer (well-known community)\n"
12642 "Do not export to next AS (well-known community)\n"
12643 "Graceful shutdown (well-known community)\n"
12644 "Do not export to any peer (well-known community)\n"
12645 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12646 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12647 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12648 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12649 "Should accept VPN route with local nexthop (well-known community)\n"
12650 "RT VPNv6 route filtering (well-known community)\n"
12651 "RT VPNv4 route filtering (well-known community)\n"
12652 "RT translated VPNv6 route filtering (well-known community)\n"
12653 "RT translated VPNv4 route filtering (well-known community)\n"
12654 "Exact match of the communities\n"
12655 "Community-list number\n"
12656 "Community-list name\n"
12657 "Display routes matching the community-list\n"
12658 "Exact match of the communities\n"
12659 "Display routes conforming to the filter-list\n"
12660 "Regular expression access list name\n"
12661 "Display routes conforming to the prefix-list\n"
12662 "Prefix-list name\n"
12663 "Display routes conforming to the access-list\n"
12664 "Access-list name\n"
12665 "Display routes matching the route-map\n"
12666 "A route-map to match on\n"
12667 "RPKI route types\n"
12668 "A valid path as determined by rpki\n"
12669 "A invalid path as determined by rpki\n"
12670 "A path that has no rpki data\n"
12671 "Display prefixes with matching version numbers\n"
12672 "Version number and above\n"
12673 "Display prefixes with matching BGP community alias\n"
12674 "BGP community alias\n"
12676 "Display route and more specific routes\n"
12678 "Display route and more specific routes\n"
12679 "Display detailed version of all routes\n"
12681 "Display detailed version of JSON output\n"
12682 "Increase table width for longer prefixes\n")
12684 afi_t afi
= AFI_IP6
;
12685 safi_t safi
= SAFI_UNICAST
;
12686 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12687 void *output_arg
= NULL
;
12688 struct bgp
*bgp
= NULL
;
12690 int exact_match
= 0;
12691 char *community
= NULL
;
12693 uint16_t show_flags
= 0;
12694 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12699 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12703 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12706 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12708 /* [<ipv4|ipv6> [all]] */
12710 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12712 if (argv_find(argv
, argc
, "ipv4", &idx
))
12713 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12715 if (argv_find(argv
, argc
, "ipv6", &idx
))
12716 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12720 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12722 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12725 return CMD_WARNING
;
12727 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12728 sh_type
= bgp_show_type_cidr_only
;
12730 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12731 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12732 sh_type
= bgp_show_type_dampend_paths
;
12733 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12734 sh_type
= bgp_show_type_flap_statistics
;
12737 if (argv_find(argv
, argc
, "community", &idx
)) {
12738 char *maybecomm
= NULL
;
12740 if (idx
+ 1 < argc
) {
12741 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12742 maybecomm
= argv
[idx
+ 1]->arg
;
12744 maybecomm
= argv
[idx
+ 1]->text
;
12747 if (maybecomm
&& !strmatch(maybecomm
, "json")
12748 && !strmatch(maybecomm
, "exact-match"))
12749 community
= maybecomm
;
12751 if (argv_find(argv
, argc
, "exact-match", &idx
))
12755 sh_type
= bgp_show_type_community_all
;
12758 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12759 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12760 struct community_list
*list
;
12762 if (argv_find(argv
, argc
, "exact-match", &idx
))
12765 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12766 COMMUNITY_LIST_MASTER
);
12767 if (list
== NULL
) {
12768 vty_out(vty
, "%% %s community-list not found\n",
12769 clist_number_or_name
);
12770 return CMD_WARNING
;
12774 sh_type
= bgp_show_type_community_list_exact
;
12776 sh_type
= bgp_show_type_community_list
;
12780 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12781 const char *filter
= argv
[++idx
]->arg
;
12782 struct as_list
*as_list
;
12784 as_list
= as_list_lookup(filter
);
12785 if (as_list
== NULL
) {
12786 vty_out(vty
, "%% %s AS-path access-list not found\n",
12788 return CMD_WARNING
;
12791 sh_type
= bgp_show_type_filter_list
;
12792 output_arg
= as_list
;
12795 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12796 const char *prefix_list_str
= argv
[++idx
]->arg
;
12797 struct prefix_list
*plist
;
12799 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12800 if (plist
== NULL
) {
12801 vty_out(vty
, "%% %s prefix-list not found\n",
12803 return CMD_WARNING
;
12806 sh_type
= bgp_show_type_prefix_list
;
12807 output_arg
= plist
;
12810 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12811 const char *access_list_str
= argv
[++idx
]->arg
;
12812 struct access_list
*alist
;
12814 alist
= access_list_lookup(afi
, access_list_str
);
12816 vty_out(vty
, "%% %s access-list not found\n",
12818 return CMD_WARNING
;
12821 sh_type
= bgp_show_type_access_list
;
12822 output_arg
= alist
;
12825 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12826 const char *rmap_str
= argv
[++idx
]->arg
;
12827 struct route_map
*rmap
;
12829 rmap
= route_map_lookup_by_name(rmap_str
);
12831 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12832 return CMD_WARNING
;
12835 sh_type
= bgp_show_type_route_map
;
12839 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12840 sh_type
= bgp_show_type_rpki
;
12841 if (argv_find(argv
, argc
, "valid", &idx
))
12842 rpki_target_state
= RPKI_VALID
;
12843 else if (argv_find(argv
, argc
, "invalid", &idx
))
12844 rpki_target_state
= RPKI_INVALID
;
12847 /* Display prefixes with matching version numbers */
12848 if (argv_find(argv
, argc
, "version", &idx
)) {
12849 sh_type
= bgp_show_type_prefix_version
;
12850 output_arg
= argv
[idx
+ 1]->arg
;
12853 /* Display prefixes with matching BGP community alias */
12854 if (argv_find(argv
, argc
, "alias", &idx
)) {
12855 sh_type
= bgp_show_type_community_alias
;
12856 output_arg
= argv
[idx
+ 1]->arg
;
12859 /* prefix-longer */
12860 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12861 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12862 const char *prefix_str
= argv
[idx
]->arg
;
12864 if (!str2prefix(prefix_str
, &p
)) {
12865 vty_out(vty
, "%% Malformed Prefix\n");
12866 return CMD_WARNING
;
12869 sh_type
= bgp_show_type_prefix_longer
;
12874 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12876 return bgp_show_community(vty
, bgp
, community
,
12877 exact_match
, afi
, safi
,
12880 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12881 output_arg
, show_flags
,
12882 rpki_target_state
);
12884 struct listnode
*node
;
12886 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12890 vty_out(vty
, "{\n");
12892 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12893 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12894 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12897 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12898 FOREACH_SAFI (safi
) {
12899 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12907 vty_out(vty
, ",\n");
12908 vty_out(vty
, "\"%s\":{\n",
12909 get_afi_safi_str(afi
,
12914 "\nFor address family: %s\n",
12920 bgp_show_community(
12921 vty
, abgp
, community
,
12922 exact_match
, afi
, safi
,
12925 bgp_show(vty
, abgp
, afi
, safi
,
12926 sh_type
, output_arg
,
12928 rpki_target_state
);
12930 vty_out(vty
, "}\n");
12934 /* show <ip> bgp all: for each AFI and SAFI*/
12935 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12936 FOREACH_AFI_SAFI (afi
, safi
) {
12937 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12945 vty_out(vty
, ",\n");
12947 vty_out(vty
, "\"%s\":{\n",
12948 get_afi_safi_str(afi
,
12953 "\nFor address family: %s\n",
12959 bgp_show_community(
12960 vty
, abgp
, community
,
12961 exact_match
, afi
, safi
,
12964 bgp_show(vty
, abgp
, afi
, safi
,
12965 sh_type
, output_arg
,
12967 rpki_target_state
);
12969 vty_out(vty
, "}\n");
12974 vty_out(vty
, "}\n");
12976 return CMD_SUCCESS
;
12979 DEFUN (show_ip_bgp_route
,
12980 show_ip_bgp_route_cmd
,
12981 "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]",
12985 BGP_INSTANCE_HELP_STR
12987 BGP_SAFI_WITH_LABEL_HELP_STR
12988 "Network in the BGP routing table to display\n"
12990 "Network in the BGP routing table to display\n"
12992 "Display only the bestpath\n"
12993 "Display only multipaths\n"
12994 "Display only paths that match the specified rpki state\n"
12995 "A valid path as determined by rpki\n"
12996 "A invalid path as determined by rpki\n"
12997 "A path that has no rpki data\n"
13000 int prefix_check
= 0;
13002 afi_t afi
= AFI_IP6
;
13003 safi_t safi
= SAFI_UNICAST
;
13004 char *prefix
= NULL
;
13005 struct bgp
*bgp
= NULL
;
13006 enum bgp_path_type path_type
;
13007 bool uj
= use_json(argc
, argv
);
13011 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13014 return CMD_WARNING
;
13018 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13019 return CMD_WARNING
;
13022 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13023 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13024 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13026 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13027 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13030 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13031 && afi
!= AFI_IP6
) {
13033 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13034 return CMD_WARNING
;
13036 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13037 && afi
!= AFI_IP
) {
13039 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13040 return CMD_WARNING
;
13043 prefix
= argv
[idx
]->arg
;
13045 /* [<bestpath|multipath>] */
13046 if (argv_find(argv
, argc
, "bestpath", &idx
))
13047 path_type
= BGP_PATH_SHOW_BESTPATH
;
13048 else if (argv_find(argv
, argc
, "multipath", &idx
))
13049 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13051 path_type
= BGP_PATH_SHOW_ALL
;
13053 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13054 path_type
, RPKI_NOT_BEING_USED
, uj
);
13057 DEFUN (show_ip_bgp_regexp
,
13058 show_ip_bgp_regexp_cmd
,
13059 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13063 BGP_INSTANCE_HELP_STR
13065 BGP_SAFI_WITH_LABEL_HELP_STR
13066 "Display routes matching the AS path regular expression\n"
13067 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13070 afi_t afi
= AFI_IP6
;
13071 safi_t safi
= SAFI_UNICAST
;
13072 struct bgp
*bgp
= NULL
;
13073 bool uj
= use_json(argc
, argv
);
13074 char *regstr
= NULL
;
13077 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13080 return CMD_WARNING
;
13082 // get index of regex
13083 if (argv_find(argv
, argc
, "REGEX", &idx
))
13084 regstr
= argv
[idx
]->arg
;
13087 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13088 bgp_show_type_regexp
, uj
);
13091 DEFPY (show_ip_bgp_instance_all
,
13092 show_ip_bgp_instance_all_cmd
,
13093 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13097 BGP_INSTANCE_ALL_HELP_STR
13099 BGP_SAFI_WITH_LABEL_HELP_STR
13101 "Increase table width for longer prefixes\n")
13103 afi_t afi
= AFI_IP6
;
13104 safi_t safi
= SAFI_UNICAST
;
13105 struct bgp
*bgp
= NULL
;
13107 uint16_t show_flags
= 0;
13111 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13115 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13117 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13120 return CMD_WARNING
;
13122 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13123 return CMD_SUCCESS
;
13126 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13127 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13132 uint16_t show_flags
= 0;
13135 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13137 if (!config_bgp_aspath_validate(regstr
)) {
13138 vty_out(vty
, "Invalid character in REGEX %s\n",
13140 return CMD_WARNING_CONFIG_FAILED
;
13143 regex
= bgp_regcomp(regstr
);
13145 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13146 return CMD_WARNING
;
13149 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13150 RPKI_NOT_BEING_USED
);
13151 bgp_regex_free(regex
);
13155 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13156 const char *comstr
, int exact
, afi_t afi
,
13157 safi_t safi
, uint16_t show_flags
)
13159 struct community
*com
;
13162 com
= community_str2com(comstr
);
13164 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13165 return CMD_WARNING
;
13168 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13169 (exact
? bgp_show_type_community_exact
13170 : bgp_show_type_community
),
13171 com
, show_flags
, RPKI_NOT_BEING_USED
);
13172 community_free(&com
);
13178 BGP_STATS_MAXBITLEN
= 0,
13180 BGP_STATS_PREFIXES
,
13182 BGP_STATS_UNAGGREGATEABLE
,
13183 BGP_STATS_MAX_AGGREGATEABLE
,
13184 BGP_STATS_AGGREGATES
,
13186 BGP_STATS_ASPATH_COUNT
,
13187 BGP_STATS_ASPATH_MAXHOPS
,
13188 BGP_STATS_ASPATH_TOTHOPS
,
13189 BGP_STATS_ASPATH_MAXSIZE
,
13190 BGP_STATS_ASPATH_TOTSIZE
,
13191 BGP_STATS_ASN_HIGHEST
,
13195 #define TABLE_STATS_IDX_VTY 0
13196 #define TABLE_STATS_IDX_JSON 1
13198 static const char *table_stats_strs
[][2] = {
13199 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13200 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13201 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13202 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13203 "unaggregateablePrefixes"},
13204 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13205 "maximumAggregateablePrefixes"},
13206 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13207 "bgpAggregateAdvertisements"},
13208 [BGP_STATS_SPACE
] = {"Address space advertised",
13209 "addressSpaceAdvertised"},
13210 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13211 "advertisementsWithPaths"},
13212 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13214 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13216 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13217 "averageAsPathLengthHops"},
13218 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13219 "averageAsPathSizeBytes"},
13220 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13221 [BGP_STATS_MAX
] = {NULL
, NULL
}
13224 struct bgp_table_stats
{
13225 struct bgp_table
*table
;
13226 unsigned long long counts
[BGP_STATS_MAX
];
13229 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13232 double total_space
;
13235 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13236 struct bgp_table_stats
*ts
, unsigned int space
)
13238 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13239 struct bgp_path_info
*pi
;
13240 const struct prefix
*rn_p
;
13242 if (!bgp_dest_has_bgp_path_info_data(dest
))
13245 rn_p
= bgp_dest_get_prefix(dest
);
13246 ts
->counts
[BGP_STATS_PREFIXES
]++;
13247 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13249 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13250 /* check if the prefix is included by any other announcements */
13251 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13252 pdest
= bgp_dest_parent_nolock(pdest
);
13254 if (pdest
== NULL
|| pdest
== top
) {
13255 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13256 /* announced address space */
13258 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13259 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13260 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13263 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13264 ts
->counts
[BGP_STATS_RIB
]++;
13266 if (CHECK_FLAG(pi
->attr
->flag
,
13267 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13268 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13270 /* as-path stats */
13271 if (pi
->attr
->aspath
) {
13272 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13273 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13274 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13276 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13278 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13279 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13281 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13282 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13284 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13285 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13286 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13287 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13292 static void bgp_table_stats_walker(struct thread
*t
)
13294 struct bgp_dest
*dest
, *ndest
;
13295 struct bgp_dest
*top
;
13296 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13297 unsigned int space
= 0;
13299 if (!(top
= bgp_table_top(ts
->table
)))
13302 switch (ts
->table
->afi
) {
13304 space
= IPV4_MAX_BITLEN
;
13307 space
= IPV6_MAX_BITLEN
;
13310 space
= EVPN_ROUTE_PREFIXLEN
;
13316 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13318 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13319 if (ts
->table
->safi
== SAFI_MPLS_VPN
13320 || ts
->table
->safi
== SAFI_ENCAP
13321 || ts
->table
->safi
== SAFI_EVPN
) {
13322 struct bgp_table
*table
;
13324 table
= bgp_dest_get_bgp_table_info(dest
);
13328 top
= bgp_table_top(table
);
13329 for (ndest
= bgp_table_top(table
); ndest
;
13330 ndest
= bgp_route_next(ndest
))
13331 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13333 bgp_table_stats_rn(dest
, top
, ts
, space
);
13338 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13339 struct json_object
*json_array
)
13341 struct listnode
*node
, *nnode
;
13344 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13345 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13348 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13349 safi_t safi
, struct json_object
*json_array
)
13351 struct bgp_table_stats ts
;
13353 int ret
= CMD_SUCCESS
;
13355 struct json_object
*json
= NULL
;
13356 uint32_t bitlen
= 0;
13357 struct json_object
*json_bitlen
;
13360 json
= json_object_new_object();
13362 if (!bgp
->rib
[afi
][safi
]) {
13363 char warning_msg
[50];
13365 snprintf(warning_msg
, sizeof(warning_msg
),
13366 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13370 vty_out(vty
, "%s\n", warning_msg
);
13372 json_object_string_add(json
, "warning", warning_msg
);
13375 goto end_table_stats
;
13379 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13380 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13382 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13384 /* labeled-unicast routes live in the unicast table */
13385 if (safi
== SAFI_LABELED_UNICAST
)
13386 safi
= SAFI_UNICAST
;
13388 memset(&ts
, 0, sizeof(ts
));
13389 ts
.table
= bgp
->rib
[afi
][safi
];
13390 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13392 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13393 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13394 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13398 case BGP_STATS_ASPATH_TOTHOPS
:
13399 case BGP_STATS_ASPATH_TOTSIZE
:
13402 temp_buf
, sizeof(temp_buf
), "%12.2f",
13404 ? (float)ts
.counts
[i
]
13406 [BGP_STATS_ASPATH_COUNT
]
13408 vty_out(vty
, "%-30s: %s",
13409 table_stats_strs
[i
]
13410 [TABLE_STATS_IDX_VTY
],
13413 json_object_double_add(
13415 table_stats_strs
[i
]
13416 [TABLE_STATS_IDX_JSON
],
13418 ? (double)ts
.counts
[i
]
13419 / (double)ts
.counts
13420 [BGP_STATS_ASPATH_COUNT
]
13424 case BGP_STATS_TOTPLEN
:
13427 temp_buf
, sizeof(temp_buf
), "%12.2f",
13429 ? (float)ts
.counts
[i
]
13431 [BGP_STATS_PREFIXES
]
13433 vty_out(vty
, "%-30s: %s",
13434 table_stats_strs
[i
]
13435 [TABLE_STATS_IDX_VTY
],
13438 json_object_double_add(
13440 table_stats_strs
[i
]
13441 [TABLE_STATS_IDX_JSON
],
13443 ? (double)ts
.counts
[i
]
13444 / (double)ts
.counts
13445 [BGP_STATS_PREFIXES
]
13449 case BGP_STATS_SPACE
:
13451 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13453 vty_out(vty
, "%-30s: %s\n",
13454 table_stats_strs
[i
]
13455 [TABLE_STATS_IDX_VTY
],
13458 json_object_double_add(
13460 table_stats_strs
[i
]
13461 [TABLE_STATS_IDX_JSON
],
13462 (double)ts
.total_space
);
13464 if (afi
== AFI_IP6
) {
13466 snprintf(temp_buf
, sizeof(temp_buf
),
13469 * pow(2.0, -128 + 32));
13470 vty_out(vty
, "%30s: %s\n",
13471 "/32 equivalent %s\n",
13474 json_object_double_add(
13475 json
, "/32equivalent",
13476 (double)(ts
.total_space
13481 snprintf(temp_buf
, sizeof(temp_buf
),
13484 * pow(2.0, -128 + 48));
13485 vty_out(vty
, "%30s: %s\n",
13486 "/48 equivalent %s\n",
13489 json_object_double_add(
13490 json
, "/48equivalent",
13491 (double)(ts
.total_space
13497 snprintf(temp_buf
, sizeof(temp_buf
),
13499 ts
.total_space
* 100.
13501 vty_out(vty
, "%30s: %s\n",
13502 "% announced ", temp_buf
);
13504 json_object_double_add(
13505 json
, "%announced",
13506 (double)(ts
.total_space
* 100.
13510 snprintf(temp_buf
, sizeof(temp_buf
),
13513 * pow(2.0, -32 + 8));
13514 vty_out(vty
, "%30s: %s\n",
13515 "/8 equivalent ", temp_buf
);
13517 json_object_double_add(
13518 json
, "/8equivalent",
13519 (double)(ts
.total_space
13520 * pow(2.0, -32 + 8)));
13523 snprintf(temp_buf
, sizeof(temp_buf
),
13526 * pow(2.0, -32 + 24));
13527 vty_out(vty
, "%30s: %s\n",
13528 "/24 equivalent ", temp_buf
);
13530 json_object_double_add(
13531 json
, "/24equivalent",
13532 (double)(ts
.total_space
13533 * pow(2.0, -32 + 24)));
13539 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13541 vty_out(vty
, "%-30s: %s",
13542 table_stats_strs
[i
]
13543 [TABLE_STATS_IDX_VTY
],
13546 json_object_int_add(
13548 table_stats_strs
[i
]
13549 [TABLE_STATS_IDX_JSON
],
13554 vty_out(vty
, "\n");
13559 bitlen
= IPV4_MAX_BITLEN
;
13562 bitlen
= IPV6_MAX_BITLEN
;
13565 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13572 json_bitlen
= json_object_new_array();
13574 for (i
= 0; i
<= bitlen
; i
++) {
13575 struct json_object
*ind_bit
= json_object_new_object();
13577 if (!ts
.prefix_len_count
[i
])
13580 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13581 json_object_int_add(ind_bit
, temp_buf
,
13582 ts
.prefix_len_count
[i
]);
13583 json_object_array_add(json_bitlen
, ind_bit
);
13585 json_object_object_add(json
, "prefixLength", json_bitlen
);
13590 json_object_array_add(json_array
, json
);
13594 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13595 safi_t safi
, struct json_object
*json_array
)
13598 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13599 return CMD_SUCCESS
;
13602 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13614 PCOUNT_BPATH_SELECTED
,
13615 PCOUNT_PFCNT
, /* the figure we display to users */
13619 static const char *const pcount_strs
[] = {
13620 [PCOUNT_ADJ_IN
] = "Adj-in",
13621 [PCOUNT_DAMPED
] = "Damped",
13622 [PCOUNT_REMOVED
] = "Removed",
13623 [PCOUNT_HISTORY
] = "History",
13624 [PCOUNT_STALE
] = "Stale",
13625 [PCOUNT_VALID
] = "Valid",
13626 [PCOUNT_ALL
] = "All RIB",
13627 [PCOUNT_COUNTED
] = "PfxCt counted",
13628 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13629 [PCOUNT_PFCNT
] = "Useable",
13630 [PCOUNT_MAX
] = NULL
,
13633 struct peer_pcounts
{
13634 unsigned int count
[PCOUNT_MAX
];
13635 const struct peer
*peer
;
13636 const struct bgp_table
*table
;
13640 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13642 const struct bgp_adj_in
*ain
;
13643 const struct bgp_path_info
*pi
;
13644 const struct peer
*peer
= pc
->peer
;
13646 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13647 if (ain
->peer
== peer
)
13648 pc
->count
[PCOUNT_ADJ_IN
]++;
13650 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13652 if (pi
->peer
!= peer
)
13655 pc
->count
[PCOUNT_ALL
]++;
13657 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13658 pc
->count
[PCOUNT_DAMPED
]++;
13659 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13660 pc
->count
[PCOUNT_HISTORY
]++;
13661 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13662 pc
->count
[PCOUNT_REMOVED
]++;
13663 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13664 pc
->count
[PCOUNT_STALE
]++;
13665 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13666 pc
->count
[PCOUNT_VALID
]++;
13667 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13668 pc
->count
[PCOUNT_PFCNT
]++;
13669 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13670 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13672 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13673 pc
->count
[PCOUNT_COUNTED
]++;
13674 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13676 EC_LIB_DEVELOPMENT
,
13677 "Attempting to count but flags say it is unusable");
13679 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13681 EC_LIB_DEVELOPMENT
,
13682 "Not counted but flags say we should");
13687 static void bgp_peer_count_walker(struct thread
*t
)
13689 struct bgp_dest
*rn
, *rm
;
13690 const struct bgp_table
*table
;
13691 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13693 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13694 || pc
->safi
== SAFI_EVPN
) {
13695 /* Special handling for 2-level routing tables. */
13696 for (rn
= bgp_table_top(pc
->table
); rn
;
13697 rn
= bgp_route_next(rn
)) {
13698 table
= bgp_dest_get_bgp_table_info(rn
);
13700 for (rm
= bgp_table_top(table
); rm
;
13701 rm
= bgp_route_next(rm
))
13702 bgp_peer_count_proc(rm
, pc
);
13705 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13706 bgp_peer_count_proc(rn
, pc
);
13709 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13710 safi_t safi
, bool use_json
)
13712 struct peer_pcounts pcounts
= {.peer
= peer
};
13714 json_object
*json
= NULL
;
13715 json_object
*json_loop
= NULL
;
13718 json
= json_object_new_object();
13719 json_loop
= json_object_new_object();
13722 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13723 || !peer
->bgp
->rib
[afi
][safi
]) {
13725 json_object_string_add(
13727 "No such neighbor or address family");
13728 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13729 json_object_free(json
);
13730 json_object_free(json_loop
);
13732 vty_out(vty
, "%% No such neighbor or address family\n");
13734 return CMD_WARNING
;
13737 memset(&pcounts
, 0, sizeof(pcounts
));
13738 pcounts
.peer
= peer
;
13739 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13740 pcounts
.safi
= safi
;
13742 /* in-place call via thread subsystem so as to record execution time
13743 * stats for the thread-walk (i.e. ensure this can't be blamed on
13744 * on just vty_read()).
13746 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13749 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13750 json_object_string_add(json
, "multiProtocol",
13751 get_afi_safi_str(afi
, safi
, true));
13752 json_object_int_add(json
, "pfxCounter",
13753 peer
->pcount
[afi
][safi
]);
13755 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13756 json_object_int_add(json_loop
, pcount_strs
[i
],
13759 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13761 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13762 json_object_string_add(json
, "pfxctDriftFor",
13764 json_object_string_add(
13765 json
, "recommended",
13766 "Please report this bug, with the above command output");
13768 vty_json(vty
, json
);
13772 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13773 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13774 peer
->hostname
, peer
->host
,
13775 get_afi_safi_str(afi
, safi
, false));
13777 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13778 get_afi_safi_str(afi
, safi
, false));
13781 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13782 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13784 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13785 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13788 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13789 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13791 "Please report this bug, with the above command output\n");
13795 return CMD_SUCCESS
;
13798 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13799 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13800 "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]",
13804 BGP_INSTANCE_HELP_STR
13807 "Detailed information on TCP and BGP neighbor connections\n"
13808 "Neighbor to display information about\n"
13809 "Neighbor to display information about\n"
13810 "Neighbor on BGP configured interface\n"
13811 "Display detailed prefix count information\n"
13814 afi_t afi
= AFI_IP6
;
13815 safi_t safi
= SAFI_UNICAST
;
13818 struct bgp
*bgp
= NULL
;
13819 bool uj
= use_json(argc
, argv
);
13824 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13827 return CMD_WARNING
;
13829 argv_find(argv
, argc
, "neighbors", &idx
);
13830 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13832 return CMD_WARNING
;
13834 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13837 #ifdef KEEP_OLD_VPN_COMMANDS
13838 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13839 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13840 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13845 "Display information about all VPNv4 NLRIs\n"
13846 "Detailed information on TCP and BGP neighbor connections\n"
13847 "Neighbor to display information about\n"
13848 "Neighbor to display information about\n"
13849 "Neighbor on BGP configured interface\n"
13850 "Display detailed prefix count information\n"
13855 bool uj
= use_json(argc
, argv
);
13857 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13859 return CMD_WARNING
;
13861 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13864 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13865 show_ip_bgp_vpn_all_route_prefix_cmd
,
13866 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13871 "Display information about all VPNv4 NLRIs\n"
13872 "Network in the BGP routing table to display\n"
13873 "Network in the BGP routing table to display\n"
13877 char *network
= NULL
;
13878 struct bgp
*bgp
= bgp_get_default();
13880 vty_out(vty
, "Can't find default instance\n");
13881 return CMD_WARNING
;
13884 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13885 network
= argv
[idx
]->arg
;
13886 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13887 network
= argv
[idx
]->arg
;
13889 vty_out(vty
, "Unable to figure out Network\n");
13890 return CMD_WARNING
;
13893 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13894 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13895 use_json(argc
, argv
));
13897 #endif /* KEEP_OLD_VPN_COMMANDS */
13899 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13900 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13901 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13906 "Network in the BGP routing table to display\n"
13907 "Network in the BGP routing table to display\n"
13908 "Network in the BGP routing table to display\n"
13909 "Network in the BGP routing table to display\n"
13913 char *network
= NULL
;
13914 int prefix_check
= 0;
13916 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13917 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13918 network
= argv
[idx
]->arg
;
13919 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13920 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13921 network
= argv
[idx
]->arg
;
13924 vty_out(vty
, "Unable to figure out Network\n");
13925 return CMD_WARNING
;
13927 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13928 prefix_check
, BGP_PATH_SHOW_ALL
,
13929 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13932 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13933 struct bgp_table
*table
, int *header1
,
13934 int *header2
, json_object
*json
,
13935 json_object
*json_scode
,
13936 json_object
*json_ocode
, bool wide
,
13939 uint64_t version
= table
? table
->version
: 0;
13943 json_object_int_add(json
, "bgpTableVersion", version
);
13944 json_object_string_addf(json
, "bgpLocalRouterId",
13945 "%pI4", &peer
->bgp
->router_id
);
13946 json_object_int_add(json
, "defaultLocPrf",
13947 peer
->bgp
->default_local_pref
);
13948 json_object_int_add(json
, "localAS",
13949 peer
->change_local_as
13950 ? peer
->change_local_as
13952 json_object_object_add(json
, "bgpStatusCodes",
13954 json_object_object_add(json
, "bgpOriginCodes",
13958 "BGP table version is %" PRIu64
13959 ", local router ID is %pI4, vrf id ",
13960 version
, &peer
->bgp
->router_id
);
13961 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
13962 vty_out(vty
, "%s", VRFID_NONE_STR
);
13964 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
13965 vty_out(vty
, "\n");
13966 vty_out(vty
, "Default local pref %u, ",
13967 peer
->bgp
->default_local_pref
);
13968 vty_out(vty
, "local AS %u\n",
13969 peer
->change_local_as
? peer
->change_local_as
13972 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13973 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13974 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13975 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13981 if (!json
&& !detail
)
13982 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13983 : BGP_SHOW_HEADER
));
13989 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13990 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13991 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13992 json_object
*json_scode
, json_object
*json_ocode
,
13993 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13994 unsigned long *output_count
, unsigned long *filtered_count
)
13996 struct bgp_adj_in
*ain
;
13997 struct bgp_adj_out
*adj
;
13998 struct bgp_dest
*dest
;
14002 struct update_subgroup
*subgrp
;
14003 struct peer_af
*paf
;
14004 bool route_filtered
;
14005 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14006 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14007 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14008 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14009 || (safi
== SAFI_EVPN
))
14013 json_object
*json_net
= NULL
;
14017 subgrp
= peer_subgroup(peer
, afi
, safi
);
14019 if (type
== bgp_show_adj_route_advertised
&& subgrp
14020 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14022 json_object_int_add(json
, "bgpTableVersion",
14024 json_object_string_addf(json
, "bgpLocalRouterId",
14025 "%pI4", &bgp
->router_id
);
14026 json_object_int_add(json
, "defaultLocPrf",
14027 bgp
->default_local_pref
);
14028 json_object_int_add(json
, "localAS",
14029 peer
->change_local_as
14030 ? peer
->change_local_as
14032 json_object_object_add(json
, "bgpStatusCodes",
14034 json_object_object_add(json
, "bgpOriginCodes",
14036 json_object_string_add(
14037 json
, "bgpOriginatingDefaultNetwork",
14038 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14041 "BGP table version is %" PRIu64
14042 ", local router ID is %pI4, vrf id ",
14043 table
->version
, &bgp
->router_id
);
14044 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14045 vty_out(vty
, "%s", VRFID_NONE_STR
);
14047 vty_out(vty
, "%u", bgp
->vrf_id
);
14048 vty_out(vty
, "\n");
14049 vty_out(vty
, "Default local pref %u, ",
14050 bgp
->default_local_pref
);
14051 vty_out(vty
, "local AS %u\n",
14052 peer
->change_local_as
? peer
->change_local_as
14055 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14056 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14057 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14058 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14061 vty_out(vty
, "Originating default network %s\n\n",
14062 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14068 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14069 if (type
== bgp_show_adj_route_received
14070 || type
== bgp_show_adj_route_filtered
) {
14071 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14072 if (ain
->peer
!= peer
)
14075 show_adj_route_header(vty
, peer
, table
, header1
,
14076 header2
, json
, json_scode
,
14077 json_ocode
, wide
, detail
);
14079 if ((safi
== SAFI_MPLS_VPN
)
14080 || (safi
== SAFI_ENCAP
)
14081 || (safi
== SAFI_EVPN
)) {
14083 json_object_string_add(
14084 json_ar
, "rd", rd_str
);
14085 else if (show_rd
&& rd_str
) {
14087 "Route Distinguisher: %s\n",
14094 route_filtered
= false;
14096 /* Filter prefix using distribute list,
14097 * filter list or prefix list
14099 const struct prefix
*rn_p
=
14100 bgp_dest_get_prefix(dest
);
14101 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14104 route_filtered
= true;
14106 /* Filter prefix using route-map */
14107 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14108 safi
, rmap_name
, NULL
,
14111 if (type
== bgp_show_adj_route_filtered
&&
14112 !route_filtered
&& ret
!= RMAP_DENY
) {
14113 bgp_attr_flush(&attr
);
14117 if (type
== bgp_show_adj_route_received
14118 && (route_filtered
|| ret
== RMAP_DENY
))
14119 (*filtered_count
)++;
14124 json_object_new_object();
14125 bgp_show_path_info(
14126 NULL
/* prefix_rd */, dest
, vty
,
14127 bgp
, afi
, safi
, json_net
,
14128 BGP_PATH_SHOW_ALL
, &display
,
14129 RPKI_NOT_BEING_USED
);
14131 json_object_object_addf(
14135 route_vty_out_tmp(vty
, dest
, rn_p
,
14136 &attr
, safi
, use_json
,
14138 bgp_attr_flush(&attr
);
14141 } else if (type
== bgp_show_adj_route_advertised
) {
14142 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14143 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14144 if (paf
->peer
!= peer
|| !adj
->attr
)
14147 show_adj_route_header(
14148 vty
, peer
, table
, header1
,
14149 header2
, json
, json_scode
,
14150 json_ocode
, wide
, detail
);
14152 const struct prefix
*rn_p
=
14153 bgp_dest_get_prefix(dest
);
14156 ret
= bgp_output_modifier(
14157 peer
, rn_p
, &attr
, afi
, safi
,
14160 if (ret
!= RMAP_DENY
) {
14161 if ((safi
== SAFI_MPLS_VPN
)
14162 || (safi
== SAFI_ENCAP
)
14163 || (safi
== SAFI_EVPN
)) {
14165 json_object_string_add(
14172 "Route Distinguisher: %s\n",
14180 json_object_new_object();
14181 bgp_show_path_info(
14190 RPKI_NOT_BEING_USED
);
14192 json_object_object_addf(
14205 (*filtered_count
)++;
14208 bgp_attr_flush(&attr
);
14210 } else if (type
== bgp_show_adj_route_bestpath
) {
14211 struct bgp_path_info
*pi
;
14213 show_adj_route_header(vty
, peer
, table
, header1
,
14214 header2
, json
, json_scode
,
14215 json_ocode
, wide
, detail
);
14217 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14219 if (pi
->peer
!= peer
)
14222 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14225 route_vty_out_tmp(vty
, dest
,
14226 bgp_dest_get_prefix(dest
),
14227 pi
->attr
, safi
, use_json
,
14235 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14236 safi_t safi
, enum bgp_show_adj_route_type type
,
14237 const char *rmap_name
, uint16_t show_flags
)
14240 struct bgp_table
*table
;
14241 json_object
*json
= NULL
;
14242 json_object
*json_scode
= NULL
;
14243 json_object
*json_ocode
= NULL
;
14244 json_object
*json_ar
= NULL
;
14245 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14247 /* Init BGP headers here so they're only displayed once
14248 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14254 * Initialize variables for each RD
14255 * All prefixes under an RD is aggregated within "json_routes"
14257 char rd_str
[BUFSIZ
] = {0};
14258 json_object
*json_routes
= NULL
;
14261 /* For 2-tier tables, prefix counts need to be
14262 * maintained across multiple runs of show_adj_route()
14264 unsigned long output_count_per_rd
;
14265 unsigned long filtered_count_per_rd
;
14266 unsigned long output_count
= 0;
14267 unsigned long filtered_count
= 0;
14270 json
= json_object_new_object();
14271 json_ar
= json_object_new_object();
14272 json_scode
= json_object_new_object();
14273 json_ocode
= json_object_new_object();
14274 #if CONFDATE > 20231208
14275 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14277 json_object_string_add(json_scode
, "suppressed", "s");
14278 json_object_string_add(json_scode
, "damped", "d");
14279 json_object_string_add(json_scode
, "history", "h");
14280 json_object_string_add(json_scode
, "valid", "*");
14281 json_object_string_add(json_scode
, "best", ">");
14282 json_object_string_add(json_scode
, "multipath", "=");
14283 json_object_string_add(json_scode
, "internal", "i");
14284 json_object_string_add(json_scode
, "ribFailure", "r");
14285 json_object_string_add(json_scode
, "stale", "S");
14286 json_object_string_add(json_scode
, "removed", "R");
14288 #if CONFDATE > 20231208
14289 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14291 json_object_string_add(json_ocode
, "igp", "i");
14292 json_object_string_add(json_ocode
, "egp", "e");
14293 json_object_string_add(json_ocode
, "incomplete", "?");
14296 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14298 json_object_string_add(
14300 "No such neighbor or address family");
14301 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14302 json_object_free(json
);
14303 json_object_free(json_ar
);
14304 json_object_free(json_scode
);
14305 json_object_free(json_ocode
);
14307 vty_out(vty
, "%% No such neighbor or address family\n");
14309 return CMD_WARNING
;
14312 if ((type
== bgp_show_adj_route_received
14313 || type
== bgp_show_adj_route_filtered
)
14314 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14315 PEER_FLAG_SOFT_RECONFIG
)) {
14317 json_object_string_add(
14319 "Inbound soft reconfiguration not enabled");
14320 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14321 json_object_free(json
);
14322 json_object_free(json_ar
);
14323 json_object_free(json_scode
);
14324 json_object_free(json_ocode
);
14327 "%% Inbound soft reconfiguration not enabled\n");
14329 return CMD_WARNING
;
14334 /* labeled-unicast routes live in the unicast table */
14335 if (safi
== SAFI_LABELED_UNICAST
)
14336 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14338 table
= bgp
->rib
[afi
][safi
];
14340 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14341 || (safi
== SAFI_EVPN
)) {
14343 struct bgp_dest
*dest
;
14345 for (dest
= bgp_table_top(table
); dest
;
14346 dest
= bgp_route_next(dest
)) {
14347 table
= bgp_dest_get_bgp_table_info(dest
);
14351 output_count_per_rd
= 0;
14352 filtered_count_per_rd
= 0;
14355 json_routes
= json_object_new_object();
14357 const struct prefix_rd
*prd
;
14358 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14361 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
14363 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
14364 rmap_name
, json
, json_routes
, json_scode
,
14365 json_ocode
, show_flags
, &header1
,
14366 &header2
, rd_str
, &output_count_per_rd
,
14367 &filtered_count_per_rd
);
14369 /* Don't include an empty RD in the output! */
14370 if (json_routes
&& (output_count_per_rd
> 0))
14371 json_object_object_add(json_ar
, rd_str
,
14374 output_count
+= output_count_per_rd
;
14375 filtered_count
+= filtered_count_per_rd
;
14378 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14379 json
, json_ar
, json_scode
, json_ocode
,
14380 show_flags
, &header1
, &header2
, rd_str
,
14381 &output_count
, &filtered_count
);
14384 if (type
== bgp_show_adj_route_advertised
)
14385 json_object_object_add(json
, "advertisedRoutes",
14388 json_object_object_add(json
, "receivedRoutes", json_ar
);
14389 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14390 json_object_int_add(json
, "filteredPrefixCounter",
14394 * These fields only give up ownership to `json` when `header1`
14395 * is used (set to zero). See code in `show_adj_route` and
14396 * `show_adj_route_header`.
14398 if (header1
== 1) {
14399 json_object_free(json_scode
);
14400 json_object_free(json_ocode
);
14403 vty_json(vty
, json
);
14404 } else if (output_count
> 0) {
14405 if (filtered_count
> 0)
14407 "\nTotal number of prefixes %ld (%ld filtered)\n",
14408 output_count
, filtered_count
);
14410 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14414 return CMD_SUCCESS
;
14417 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14418 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14419 "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]",
14423 BGP_INSTANCE_HELP_STR
14425 BGP_SAFI_WITH_LABEL_HELP_STR
14426 "Detailed information on TCP and BGP neighbor connections\n"
14427 "Neighbor to display information about\n"
14428 "Neighbor to display information about\n"
14429 "Neighbor on BGP configured interface\n"
14430 "Display the routes selected by best path\n"
14432 "Increase table width for longer prefixes\n")
14434 afi_t afi
= AFI_IP6
;
14435 safi_t safi
= SAFI_UNICAST
;
14436 char *rmap_name
= NULL
;
14437 char *peerstr
= NULL
;
14438 struct bgp
*bgp
= NULL
;
14440 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14442 uint16_t show_flags
= 0;
14445 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14448 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14450 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14454 return CMD_WARNING
;
14456 argv_find(argv
, argc
, "neighbors", &idx
);
14457 peerstr
= argv
[++idx
]->arg
;
14459 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14461 return CMD_WARNING
;
14463 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14467 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14468 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14469 "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]",
14473 BGP_INSTANCE_HELP_STR
14475 BGP_SAFI_WITH_LABEL_HELP_STR
14476 "Display the entries for all address families\n"
14477 "Detailed information on TCP and BGP neighbor connections\n"
14478 "Neighbor to display information about\n"
14479 "Neighbor to display information about\n"
14480 "Neighbor on BGP configured interface\n"
14481 "Display the routes advertised to a BGP neighbor\n"
14482 "Display the received routes from neighbor\n"
14483 "Display the filtered routes received from neighbor\n"
14484 "Route-map to modify the attributes\n"
14485 "Name of the route map\n"
14486 "Display detailed version of routes\n"
14488 "Increase table width for longer prefixes\n")
14490 afi_t afi
= AFI_IP6
;
14491 safi_t safi
= SAFI_UNICAST
;
14492 char *peerstr
= NULL
;
14493 struct bgp
*bgp
= NULL
;
14495 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14498 uint16_t show_flags
= 0;
14499 struct listnode
*node
;
14503 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14507 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14511 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14512 if (argv_find(argv
, argc
, "ipv4", &idx
))
14513 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14515 if (argv_find(argv
, argc
, "ipv6", &idx
))
14516 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14520 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14522 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14525 return CMD_WARNING
;
14527 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14528 argv_find(argv
, argc
, "neighbors", &idx
);
14529 peerstr
= argv
[++idx
]->arg
;
14531 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14533 return CMD_WARNING
;
14535 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14536 type
= bgp_show_adj_route_advertised
;
14537 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14538 type
= bgp_show_adj_route_received
;
14539 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14540 type
= bgp_show_adj_route_filtered
;
14543 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14546 vty_out(vty
, "{\n");
14548 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14549 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14550 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14552 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14553 FOREACH_SAFI (safi
) {
14554 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14561 vty_out(vty
, ",\n");
14562 vty_out(vty
, "\"%s\":",
14563 get_afi_safi_str(afi
, safi
,
14567 "\nFor address family: %s\n",
14568 get_afi_safi_str(afi
, safi
,
14571 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14572 route_map
, show_flags
);
14576 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14577 FOREACH_AFI_SAFI (afi
, safi
) {
14578 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14585 vty_out(vty
, ",\n");
14586 vty_out(vty
, "\"%s\":",
14587 get_afi_safi_str(afi
, safi
,
14591 "\nFor address family: %s\n",
14592 get_afi_safi_str(afi
, safi
,
14595 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14596 route_map
, show_flags
);
14601 vty_out(vty
, "}\n");
14603 return CMD_SUCCESS
;
14606 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14607 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14608 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14612 BGP_INSTANCE_HELP_STR
14615 BGP_AF_MODIFIER_STR
14616 "Detailed information on TCP and BGP neighbor connections\n"
14617 "Neighbor to display information about\n"
14618 "Neighbor to display information about\n"
14619 "Neighbor on BGP configured interface\n"
14620 "Display information received from a BGP neighbor\n"
14621 "Display the prefixlist filter\n"
14624 afi_t afi
= AFI_IP6
;
14625 safi_t safi
= SAFI_UNICAST
;
14626 char *peerstr
= NULL
;
14631 struct bgp
*bgp
= NULL
;
14632 bool uj
= use_json(argc
, argv
);
14637 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14640 return CMD_WARNING
;
14642 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14643 argv_find(argv
, argc
, "neighbors", &idx
);
14644 peerstr
= argv
[++idx
]->arg
;
14646 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14648 return CMD_WARNING
;
14650 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14651 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14654 vty_out(vty
, "Address Family: %s\n",
14655 get_afi_safi_str(afi
, safi
, false));
14656 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14659 vty_out(vty
, "{}\n");
14661 vty_out(vty
, "No functional output\n");
14664 return CMD_SUCCESS
;
14667 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14668 afi_t afi
, safi_t safi
,
14669 enum bgp_show_type type
, bool use_json
)
14671 uint16_t show_flags
= 0;
14674 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14676 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14678 json_object
*json_no
= NULL
;
14679 json_no
= json_object_new_object();
14680 json_object_string_add(
14681 json_no
, "warning",
14682 "No such neighbor or address family");
14683 vty_out(vty
, "%s\n",
14684 json_object_to_json_string(json_no
));
14685 json_object_free(json_no
);
14687 vty_out(vty
, "%% No such neighbor or address family\n");
14688 return CMD_WARNING
;
14691 /* labeled-unicast routes live in the unicast table */
14692 if (safi
== SAFI_LABELED_UNICAST
)
14693 safi
= SAFI_UNICAST
;
14695 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14696 RPKI_NOT_BEING_USED
);
14699 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14700 show_ip_bgp_flowspec_routes_detailed_cmd
,
14701 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14705 BGP_INSTANCE_HELP_STR
14708 "Detailed information on flowspec entries\n"
14711 afi_t afi
= AFI_IP6
;
14712 safi_t safi
= SAFI_UNICAST
;
14713 struct bgp
*bgp
= NULL
;
14715 bool uj
= use_json(argc
, argv
);
14716 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14720 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14723 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14726 return CMD_WARNING
;
14728 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14729 show_flags
, RPKI_NOT_BEING_USED
);
14732 DEFUN (show_ip_bgp_neighbor_routes
,
14733 show_ip_bgp_neighbor_routes_cmd
,
14734 "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]",
14738 BGP_INSTANCE_HELP_STR
14740 BGP_SAFI_WITH_LABEL_HELP_STR
14741 "Detailed information on TCP and BGP neighbor connections\n"
14742 "Neighbor to display information about\n"
14743 "Neighbor to display information about\n"
14744 "Neighbor on BGP configured interface\n"
14745 "Display flap statistics of the routes learned from neighbor\n"
14746 "Display the dampened routes received from neighbor\n"
14747 "Display routes learned from neighbor\n"
14750 char *peerstr
= NULL
;
14751 struct bgp
*bgp
= NULL
;
14752 afi_t afi
= AFI_IP6
;
14753 safi_t safi
= SAFI_UNICAST
;
14755 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14757 bool uj
= use_json(argc
, argv
);
14762 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14765 return CMD_WARNING
;
14767 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14768 argv_find(argv
, argc
, "neighbors", &idx
);
14769 peerstr
= argv
[++idx
]->arg
;
14771 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14773 return CMD_WARNING
;
14775 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14776 sh_type
= bgp_show_type_flap_neighbor
;
14777 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14778 sh_type
= bgp_show_type_damp_neighbor
;
14779 else if (argv_find(argv
, argc
, "routes", &idx
))
14780 sh_type
= bgp_show_type_neighbor
;
14782 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14785 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14787 struct bgp_distance
{
14788 /* Distance value for the IP source prefix. */
14791 /* Name of the access-list to be matched. */
14795 DEFUN (show_bgp_afi_vpn_rd_route
,
14796 show_bgp_afi_vpn_rd_route_cmd
,
14797 "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]",
14801 BGP_AF_MODIFIER_STR
14802 "Display information for a route distinguisher\n"
14803 "Route Distinguisher\n"
14804 "All Route Distinguishers\n"
14805 "Network in the BGP routing table to display\n"
14806 "Network in the BGP routing table to display\n"
14810 struct prefix_rd prd
;
14811 afi_t afi
= AFI_MAX
;
14814 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14815 vty_out(vty
, "%% Malformed Address Family\n");
14816 return CMD_WARNING
;
14819 if (!strcmp(argv
[5]->arg
, "all"))
14820 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14821 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14822 RPKI_NOT_BEING_USED
,
14823 use_json(argc
, argv
));
14825 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14827 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14828 return CMD_WARNING
;
14831 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14832 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14833 use_json(argc
, argv
));
14836 static struct bgp_distance
*bgp_distance_new(void)
14838 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14841 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14843 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14846 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14847 const char *ip_str
, const char *access_list_str
)
14854 struct bgp_dest
*dest
;
14855 struct bgp_distance
*bdistance
;
14857 afi
= bgp_node_afi(vty
);
14858 safi
= bgp_node_safi(vty
);
14860 ret
= str2prefix(ip_str
, &p
);
14862 vty_out(vty
, "Malformed prefix\n");
14863 return CMD_WARNING_CONFIG_FAILED
;
14866 distance
= atoi(distance_str
);
14868 /* Get BGP distance node. */
14869 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14870 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14872 bgp_dest_unlock_node(dest
);
14874 bdistance
= bgp_distance_new();
14875 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14878 /* Set distance value. */
14879 bdistance
->distance
= distance
;
14881 /* Reset access-list configuration. */
14882 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14883 if (access_list_str
)
14884 bdistance
->access_list
=
14885 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14887 return CMD_SUCCESS
;
14890 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14891 const char *ip_str
, const char *access_list_str
)
14898 struct bgp_dest
*dest
;
14899 struct bgp_distance
*bdistance
;
14901 afi
= bgp_node_afi(vty
);
14902 safi
= bgp_node_safi(vty
);
14904 ret
= str2prefix(ip_str
, &p
);
14906 vty_out(vty
, "Malformed prefix\n");
14907 return CMD_WARNING_CONFIG_FAILED
;
14910 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14912 vty_out(vty
, "Can't find specified prefix\n");
14913 return CMD_WARNING_CONFIG_FAILED
;
14916 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14917 distance
= atoi(distance_str
);
14919 if (bdistance
->distance
!= distance
) {
14920 vty_out(vty
, "Distance does not match configured\n");
14921 bgp_dest_unlock_node(dest
);
14922 return CMD_WARNING_CONFIG_FAILED
;
14925 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14926 bgp_distance_free(bdistance
);
14928 bgp_dest_set_bgp_path_info(dest
, NULL
);
14929 bgp_dest_unlock_node(dest
);
14930 bgp_dest_unlock_node(dest
);
14932 return CMD_SUCCESS
;
14935 /* Apply BGP information to distance method. */
14936 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14937 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14939 struct bgp_dest
*dest
;
14940 struct prefix q
= {0};
14942 struct bgp_distance
*bdistance
;
14943 struct access_list
*alist
;
14944 struct bgp_static
*bgp_static
;
14945 struct bgp_path_info
*bpi_ultimate
;
14950 peer
= pinfo
->peer
;
14952 if (pinfo
->attr
->distance
)
14953 return pinfo
->attr
->distance
;
14955 /* get peer origin to calculate appropriate distance */
14956 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
14957 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
14958 peer
= bpi_ultimate
->peer
;
14961 /* Check source address.
14962 * Note: for aggregate route, peer can have unspec af type.
14964 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14965 && !sockunion2hostprefix(&peer
->su
, &q
))
14968 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14970 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14971 bgp_dest_unlock_node(dest
);
14973 if (bdistance
->access_list
) {
14974 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14976 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14977 return bdistance
->distance
;
14979 return bdistance
->distance
;
14982 /* Backdoor check. */
14983 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14985 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14986 bgp_dest_unlock_node(dest
);
14988 if (bgp_static
->backdoor
) {
14989 if (bgp
->distance_local
[afi
][safi
])
14990 return bgp
->distance_local
[afi
][safi
];
14992 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14996 if (peer
->sort
== BGP_PEER_EBGP
) {
14997 if (bgp
->distance_ebgp
[afi
][safi
])
14998 return bgp
->distance_ebgp
[afi
][safi
];
14999 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15000 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15001 if (bgp
->distance_ibgp
[afi
][safi
])
15002 return bgp
->distance_ibgp
[afi
][safi
];
15003 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15005 if (bgp
->distance_local
[afi
][safi
])
15006 return bgp
->distance_local
[afi
][safi
];
15007 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15011 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15012 * we should tell ZEBRA update the routes for a specific
15013 * AFI/SAFI to reflect changes in RIB.
15015 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15017 safi_t update_safi
)
15022 FOREACH_AFI_SAFI (afi
, safi
) {
15023 if (!bgp_fibupd_safi(safi
))
15026 if (afi
!= update_afi
&& safi
!= update_safi
)
15029 if (BGP_DEBUG(zebra
, ZEBRA
))
15031 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15032 __func__
, afi
, safi
);
15033 bgp_zebra_announce_table(bgp
, afi
, safi
);
15037 DEFUN (bgp_distance
,
15039 "distance bgp (1-255) (1-255) (1-255)",
15040 "Define an administrative distance\n"
15042 "Distance for routes external to the AS\n"
15043 "Distance for routes internal to the AS\n"
15044 "Distance for local routes\n")
15046 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15047 int idx_number
= 2;
15048 int idx_number_2
= 3;
15049 int idx_number_3
= 4;
15050 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15051 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15052 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15056 afi
= bgp_node_afi(vty
);
15057 safi
= bgp_node_safi(vty
);
15059 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15060 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15061 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15062 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15063 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15064 bgp
->distance_local
[afi
][safi
] = distance_local
;
15065 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15067 return CMD_SUCCESS
;
15070 DEFUN (no_bgp_distance
,
15071 no_bgp_distance_cmd
,
15072 "no distance bgp [(1-255) (1-255) (1-255)]",
15074 "Define an administrative distance\n"
15076 "Distance for routes external to the AS\n"
15077 "Distance for routes internal to the AS\n"
15078 "Distance for local routes\n")
15080 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15084 afi
= bgp_node_afi(vty
);
15085 safi
= bgp_node_safi(vty
);
15087 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15088 || bgp
->distance_ibgp
[afi
][safi
] != 0
15089 || bgp
->distance_local
[afi
][safi
] != 0) {
15090 bgp
->distance_ebgp
[afi
][safi
] = 0;
15091 bgp
->distance_ibgp
[afi
][safi
] = 0;
15092 bgp
->distance_local
[afi
][safi
] = 0;
15093 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15095 return CMD_SUCCESS
;
15099 DEFUN (bgp_distance_source
,
15100 bgp_distance_source_cmd
,
15101 "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
= 1;
15107 int idx_ipv4_prefixlen
= 2;
15108 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15109 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15110 return CMD_SUCCESS
;
15113 DEFUN (no_bgp_distance_source
,
15114 no_bgp_distance_source_cmd
,
15115 "no distance (1-255) A.B.C.D/M",
15117 "Define an administrative distance\n"
15118 "Administrative distance\n"
15119 "IP source prefix\n")
15121 int idx_number
= 2;
15122 int idx_ipv4_prefixlen
= 3;
15123 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15124 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15125 return CMD_SUCCESS
;
15128 DEFUN (bgp_distance_source_access_list
,
15129 bgp_distance_source_access_list_cmd
,
15130 "distance (1-255) A.B.C.D/M WORD",
15131 "Define an administrative distance\n"
15132 "Administrative distance\n"
15133 "IP source prefix\n"
15134 "Access list name\n")
15136 int idx_number
= 1;
15137 int idx_ipv4_prefixlen
= 2;
15139 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15140 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15141 return CMD_SUCCESS
;
15144 DEFUN (no_bgp_distance_source_access_list
,
15145 no_bgp_distance_source_access_list_cmd
,
15146 "no distance (1-255) A.B.C.D/M WORD",
15148 "Define an administrative distance\n"
15149 "Administrative distance\n"
15150 "IP source prefix\n"
15151 "Access list name\n")
15153 int idx_number
= 2;
15154 int idx_ipv4_prefixlen
= 3;
15156 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15157 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15158 return CMD_SUCCESS
;
15161 DEFUN (ipv6_bgp_distance_source
,
15162 ipv6_bgp_distance_source_cmd
,
15163 "distance (1-255) X:X::X:X/M",
15164 "Define an administrative distance\n"
15165 "Administrative distance\n"
15166 "IP source prefix\n")
15168 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15169 return CMD_SUCCESS
;
15172 DEFUN (no_ipv6_bgp_distance_source
,
15173 no_ipv6_bgp_distance_source_cmd
,
15174 "no distance (1-255) X:X::X:X/M",
15176 "Define an administrative distance\n"
15177 "Administrative distance\n"
15178 "IP source prefix\n")
15180 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15181 return CMD_SUCCESS
;
15184 DEFUN (ipv6_bgp_distance_source_access_list
,
15185 ipv6_bgp_distance_source_access_list_cmd
,
15186 "distance (1-255) X:X::X:X/M WORD",
15187 "Define an administrative distance\n"
15188 "Administrative distance\n"
15189 "IP source prefix\n"
15190 "Access list name\n")
15192 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15193 return CMD_SUCCESS
;
15196 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15197 no_ipv6_bgp_distance_source_access_list_cmd
,
15198 "no distance (1-255) X:X::X:X/M WORD",
15200 "Define an administrative distance\n"
15201 "Administrative distance\n"
15202 "IP source prefix\n"
15203 "Access list name\n")
15205 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15206 return CMD_SUCCESS
;
15209 DEFUN (bgp_damp_set
,
15211 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15212 "BGP Specific commands\n"
15213 "Enable route-flap dampening\n"
15214 "Half-life time for the penalty\n"
15215 "Value to start reusing a route\n"
15216 "Value to start suppressing a route\n"
15217 "Maximum duration to suppress a stable route\n")
15219 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15220 int idx_half_life
= 2;
15222 int idx_suppress
= 4;
15223 int idx_max_suppress
= 5;
15224 int half
= DEFAULT_HALF_LIFE
* 60;
15225 int reuse
= DEFAULT_REUSE
;
15226 int suppress
= DEFAULT_SUPPRESS
;
15227 int max
= 4 * half
;
15230 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15231 reuse
= atoi(argv
[idx_reuse
]->arg
);
15232 suppress
= atoi(argv
[idx_suppress
]->arg
);
15233 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15234 } else if (argc
== 3) {
15235 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15240 * These can't be 0 but our SA doesn't understand the
15241 * way our cli is constructed
15245 if (suppress
< reuse
) {
15247 "Suppress value cannot be less than reuse value \n");
15251 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15252 reuse
, suppress
, max
);
15255 DEFUN (bgp_damp_unset
,
15256 bgp_damp_unset_cmd
,
15257 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15259 "BGP Specific commands\n"
15260 "Enable route-flap dampening\n"
15261 "Half-life time for the penalty\n"
15262 "Value to start reusing a route\n"
15263 "Value to start suppressing a route\n"
15264 "Maximum duration to suppress a stable route\n")
15266 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15267 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15270 /* Display specified route of BGP table. */
15271 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15272 const char *ip_str
, afi_t afi
, safi_t safi
,
15273 struct prefix_rd
*prd
, int prefix_check
)
15276 struct prefix match
;
15277 struct bgp_dest
*dest
;
15278 struct bgp_dest
*rm
;
15279 struct bgp_path_info
*pi
;
15280 struct bgp_path_info
*pi_temp
;
15282 struct bgp_table
*table
;
15284 /* BGP structure lookup. */
15286 bgp
= bgp_lookup_by_name(view_name
);
15288 vty_out(vty
, "%% Can't find BGP instance %s\n",
15290 return CMD_WARNING
;
15293 bgp
= bgp_get_default();
15295 vty_out(vty
, "%% No BGP process is configured\n");
15296 return CMD_WARNING
;
15300 /* Check IP address argument. */
15301 ret
= str2prefix(ip_str
, &match
);
15303 vty_out(vty
, "%% address is malformed\n");
15304 return CMD_WARNING
;
15307 match
.family
= afi2family(afi
);
15309 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15310 || (safi
== SAFI_EVPN
)) {
15311 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15312 dest
= bgp_route_next(dest
)) {
15313 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15315 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15317 table
= bgp_dest_get_bgp_table_info(dest
);
15320 rm
= bgp_node_match(table
, &match
);
15324 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15327 || rm_p
->prefixlen
== match
.prefixlen
) {
15328 pi
= bgp_dest_get_bgp_path_info(rm
);
15330 if (pi
->extra
&& pi
->extra
->damp_info
) {
15331 pi_temp
= pi
->next
;
15332 bgp_damp_info_free(
15333 pi
->extra
->damp_info
,
15341 bgp_dest_unlock_node(rm
);
15344 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15345 if (dest
!= NULL
) {
15346 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15349 || dest_p
->prefixlen
== match
.prefixlen
) {
15350 pi
= bgp_dest_get_bgp_path_info(dest
);
15352 if (pi
->extra
&& pi
->extra
->damp_info
) {
15353 pi_temp
= pi
->next
;
15354 bgp_damp_info_free(
15355 pi
->extra
->damp_info
,
15363 bgp_dest_unlock_node(dest
);
15367 return CMD_SUCCESS
;
15370 DEFUN (clear_ip_bgp_dampening
,
15371 clear_ip_bgp_dampening_cmd
,
15372 "clear ip bgp dampening",
15376 "Clear route flap dampening information\n")
15378 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15379 return CMD_SUCCESS
;
15382 DEFUN (clear_ip_bgp_dampening_prefix
,
15383 clear_ip_bgp_dampening_prefix_cmd
,
15384 "clear ip bgp dampening A.B.C.D/M",
15388 "Clear route flap dampening information\n"
15391 int idx_ipv4_prefixlen
= 4;
15392 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15393 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15396 DEFUN (clear_ip_bgp_dampening_address
,
15397 clear_ip_bgp_dampening_address_cmd
,
15398 "clear ip bgp dampening A.B.C.D",
15402 "Clear route flap dampening information\n"
15403 "Network to clear damping information\n")
15406 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15407 SAFI_UNICAST
, NULL
, 0);
15410 DEFUN (clear_ip_bgp_dampening_address_mask
,
15411 clear_ip_bgp_dampening_address_mask_cmd
,
15412 "clear ip bgp dampening A.B.C.D A.B.C.D",
15416 "Clear route flap dampening information\n"
15417 "Network to clear damping information\n"
15421 int idx_ipv4_2
= 5;
15423 char prefix_str
[BUFSIZ
];
15425 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15426 prefix_str
, sizeof(prefix_str
));
15428 vty_out(vty
, "%% Inconsistent address and mask\n");
15429 return CMD_WARNING
;
15432 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15436 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15438 struct vty
*vty
= arg
;
15439 struct peer
*peer
= bucket
->data
;
15441 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15444 DEFUN (show_bgp_listeners
,
15445 show_bgp_listeners_cmd
,
15446 "show bgp listeners",
15449 "Display Listen Sockets and who created them\n")
15451 bgp_dump_listener_info(vty
);
15453 return CMD_SUCCESS
;
15456 DEFUN (show_bgp_peerhash
,
15457 show_bgp_peerhash_cmd
,
15458 "show bgp peerhash",
15461 "Display information about the BGP peerhash\n")
15463 struct list
*instances
= bm
->bgp
;
15464 struct listnode
*node
;
15467 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15468 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15469 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15473 return CMD_SUCCESS
;
15476 /* also used for encap safi */
15477 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15478 afi_t afi
, safi_t safi
)
15480 struct bgp_dest
*pdest
;
15481 struct bgp_dest
*dest
;
15482 struct bgp_table
*table
;
15483 const struct prefix
*p
;
15484 const struct prefix_rd
*prd
;
15485 struct bgp_static
*bgp_static
;
15486 mpls_label_t label
;
15488 /* Network configuration. */
15489 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15490 pdest
= bgp_route_next(pdest
)) {
15491 table
= bgp_dest_get_bgp_table_info(pdest
);
15495 for (dest
= bgp_table_top(table
); dest
;
15496 dest
= bgp_route_next(dest
)) {
15497 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15498 if (bgp_static
== NULL
)
15501 p
= bgp_dest_get_prefix(dest
);
15502 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
15505 /* "network" configuration display. */
15506 label
= decode_label(&bgp_static
->label
);
15508 vty_out(vty
, " network %pFX rd %pRD", p
, prd
);
15509 if (safi
== SAFI_MPLS_VPN
)
15510 vty_out(vty
, " label %u", label
);
15512 if (bgp_static
->rmap
.name
)
15513 vty_out(vty
, " route-map %s",
15514 bgp_static
->rmap
.name
);
15516 if (bgp_static
->backdoor
)
15517 vty_out(vty
, " backdoor");
15519 vty_out(vty
, "\n");
15524 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15525 afi_t afi
, safi_t safi
)
15527 struct bgp_dest
*pdest
;
15528 struct bgp_dest
*dest
;
15529 struct bgp_table
*table
;
15530 const struct prefix
*p
;
15531 const struct prefix_rd
*prd
;
15532 struct bgp_static
*bgp_static
;
15533 char buf
[PREFIX_STRLEN
* 2];
15534 char buf2
[SU_ADDRSTRLEN
];
15535 char esi_buf
[ESI_STR_LEN
];
15537 /* Network configuration. */
15538 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15539 pdest
= bgp_route_next(pdest
)) {
15540 table
= bgp_dest_get_bgp_table_info(pdest
);
15544 for (dest
= bgp_table_top(table
); dest
;
15545 dest
= bgp_route_next(dest
)) {
15546 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15547 if (bgp_static
== NULL
)
15550 char *macrouter
= NULL
;
15552 if (bgp_static
->router_mac
)
15553 macrouter
= prefix_mac2str(
15554 bgp_static
->router_mac
, NULL
, 0);
15555 if (bgp_static
->eth_s_id
)
15556 esi_to_str(bgp_static
->eth_s_id
,
15557 esi_buf
, sizeof(esi_buf
));
15558 p
= bgp_dest_get_prefix(dest
);
15559 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15561 /* "network" configuration display. */
15562 if (p
->u
.prefix_evpn
.route_type
== 5) {
15563 char local_buf
[PREFIX_STRLEN
];
15565 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15566 struct prefix_evpn
*)p
)
15570 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15572 local_buf
, sizeof(local_buf
));
15573 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15574 p
->u
.prefix_evpn
.prefix_addr
15575 .ip_prefix_length
);
15577 prefix2str(p
, buf
, sizeof(buf
));
15580 if (bgp_static
->gatewayIp
.family
== AF_INET
15581 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15582 inet_ntop(bgp_static
->gatewayIp
.family
,
15583 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15586 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15587 buf
, prd
, p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15588 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15591 XFREE(MTYPE_TMP
, macrouter
);
15596 /* Configuration of static route announcement and aggregate
15598 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15601 struct bgp_dest
*dest
;
15602 const struct prefix
*p
;
15603 struct bgp_static
*bgp_static
;
15604 struct bgp_aggregate
*bgp_aggregate
;
15606 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15607 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15611 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15612 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15616 /* Network configuration. */
15617 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15618 dest
= bgp_route_next(dest
)) {
15619 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15620 if (bgp_static
== NULL
)
15623 p
= bgp_dest_get_prefix(dest
);
15625 vty_out(vty
, " network %pFX", p
);
15627 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15628 vty_out(vty
, " label-index %u",
15629 bgp_static
->label_index
);
15631 if (bgp_static
->rmap
.name
)
15632 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15634 if (bgp_static
->backdoor
)
15635 vty_out(vty
, " backdoor");
15637 vty_out(vty
, "\n");
15640 /* Aggregate-address configuration. */
15641 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15642 dest
= bgp_route_next(dest
)) {
15643 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15644 if (bgp_aggregate
== NULL
)
15647 p
= bgp_dest_get_prefix(dest
);
15649 vty_out(vty
, " aggregate-address %pFX", p
);
15651 if (bgp_aggregate
->as_set
)
15652 vty_out(vty
, " as-set");
15654 if (bgp_aggregate
->summary_only
)
15655 vty_out(vty
, " summary-only");
15657 if (bgp_aggregate
->rmap
.name
)
15658 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15660 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15661 vty_out(vty
, " origin %s",
15662 bgp_origin2str(bgp_aggregate
->origin
));
15664 if (bgp_aggregate
->match_med
)
15665 vty_out(vty
, " matching-MED-only");
15667 if (bgp_aggregate
->suppress_map_name
)
15668 vty_out(vty
, " suppress-map %s",
15669 bgp_aggregate
->suppress_map_name
);
15671 vty_out(vty
, "\n");
15675 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15678 struct bgp_dest
*dest
;
15679 struct bgp_distance
*bdistance
;
15681 /* Distance configuration. */
15682 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15683 && bgp
->distance_local
[afi
][safi
]
15684 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15685 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15686 || bgp
->distance_local
[afi
][safi
]
15687 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15688 vty_out(vty
, " distance bgp %d %d %d\n",
15689 bgp
->distance_ebgp
[afi
][safi
],
15690 bgp
->distance_ibgp
[afi
][safi
],
15691 bgp
->distance_local
[afi
][safi
]);
15694 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15695 dest
= bgp_route_next(dest
)) {
15696 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15697 if (bdistance
!= NULL
)
15698 vty_out(vty
, " distance %d %pBD %s\n",
15699 bdistance
->distance
, dest
,
15700 bdistance
->access_list
? bdistance
->access_list
15705 /* Allocate routing table structure and install commands. */
15706 void bgp_route_init(void)
15711 /* Init BGP distance table. */
15712 FOREACH_AFI_SAFI (afi
, safi
)
15713 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15715 /* IPv4 BGP commands. */
15716 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15717 install_element(BGP_NODE
, &bgp_network_cmd
);
15718 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15720 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15722 /* IPv4 unicast configuration. */
15723 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15724 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15725 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15727 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15729 /* IPv4 multicast configuration. */
15730 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15731 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15732 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15733 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15735 /* IPv4 labeled-unicast configuration. */
15736 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15737 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15739 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15740 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15741 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15742 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15743 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15744 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15745 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15746 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15748 install_element(VIEW_NODE
,
15749 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15750 install_element(VIEW_NODE
,
15751 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15752 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15753 install_element(VIEW_NODE
,
15754 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15755 #ifdef KEEP_OLD_VPN_COMMANDS
15756 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15757 #endif /* KEEP_OLD_VPN_COMMANDS */
15758 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15759 install_element(VIEW_NODE
,
15760 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15762 /* BGP dampening clear commands */
15763 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15764 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15766 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15767 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15770 install_element(ENABLE_NODE
,
15771 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15772 #ifdef KEEP_OLD_VPN_COMMANDS
15773 install_element(ENABLE_NODE
,
15774 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15775 #endif /* KEEP_OLD_VPN_COMMANDS */
15777 /* New config IPv6 BGP commands. */
15778 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15779 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15780 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15782 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15784 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15786 /* IPv6 labeled unicast address family. */
15787 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15788 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15790 install_element(BGP_NODE
, &bgp_distance_cmd
);
15791 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15792 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15793 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15794 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15795 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15796 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15797 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15798 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15799 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15800 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15801 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15802 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15803 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15804 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15805 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15806 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15807 install_element(BGP_IPV4M_NODE
,
15808 &no_bgp_distance_source_access_list_cmd
);
15809 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15810 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15811 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15812 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15813 install_element(BGP_IPV6_NODE
,
15814 &ipv6_bgp_distance_source_access_list_cmd
);
15815 install_element(BGP_IPV6_NODE
,
15816 &no_ipv6_bgp_distance_source_access_list_cmd
);
15817 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15818 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15819 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15820 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15821 install_element(BGP_IPV6M_NODE
,
15822 &ipv6_bgp_distance_source_access_list_cmd
);
15823 install_element(BGP_IPV6M_NODE
,
15824 &no_ipv6_bgp_distance_source_access_list_cmd
);
15826 /* BGP dampening */
15827 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15828 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15829 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15830 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15831 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15832 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15833 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15834 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15835 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15836 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15837 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15838 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15839 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15840 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15842 /* Large Communities */
15843 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15844 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15846 /* show bgp ipv4 flowspec detailed */
15847 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15849 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15850 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15853 void bgp_route_finish(void)
15858 FOREACH_AFI_SAFI (afi
, safi
) {
15859 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15860 bgp_distance_table
[afi
][safi
] = NULL
;