1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "sockunion.h"
39 #include "workqueue.h"
44 #include "lib_errors.h"
46 #include "bgpd/bgpd.h"
47 #include "bgpd/bgp_table.h"
48 #include "bgpd/bgp_route.h"
49 #include "bgpd/bgp_attr.h"
50 #include "bgpd/bgp_debug.h"
51 #include "bgpd/bgp_errors.h"
52 #include "bgpd/bgp_aspath.h"
53 #include "bgpd/bgp_regex.h"
54 #include "bgpd/bgp_community.h"
55 #include "bgpd/bgp_community_alias.h"
56 #include "bgpd/bgp_ecommunity.h"
57 #include "bgpd/bgp_lcommunity.h"
58 #include "bgpd/bgp_clist.h"
59 #include "bgpd/bgp_packet.h"
60 #include "bgpd/bgp_filter.h"
61 #include "bgpd/bgp_fsm.h"
62 #include "bgpd/bgp_mplsvpn.h"
63 #include "bgpd/bgp_nexthop.h"
64 #include "bgpd/bgp_damp.h"
65 #include "bgpd/bgp_advertise.h"
66 #include "bgpd/bgp_zebra.h"
67 #include "bgpd/bgp_vty.h"
68 #include "bgpd/bgp_mpath.h"
69 #include "bgpd/bgp_nht.h"
70 #include "bgpd/bgp_updgrp.h"
71 #include "bgpd/bgp_label.h"
72 #include "bgpd/bgp_addpath.h"
73 #include "bgpd/bgp_mac.h"
74 #include "bgpd/bgp_network.h"
75 #include "bgpd/bgp_trace.h"
76 #include "bgpd/bgp_rpki.h"
79 #include "bgpd/rfapi/rfapi_backend.h"
80 #include "bgpd/rfapi/vnc_import_bgp.h"
81 #include "bgpd/rfapi/vnc_export_bgp.h"
83 #include "bgpd/bgp_encap_types.h"
84 #include "bgpd/bgp_encap_tlv.h"
85 #include "bgpd/bgp_evpn.h"
86 #include "bgpd/bgp_evpn_mh.h"
87 #include "bgpd/bgp_evpn_vty.h"
88 #include "bgpd/bgp_flowspec.h"
89 #include "bgpd/bgp_flowspec_util.h"
90 #include "bgpd/bgp_pbr.h"
92 #include "bgpd/bgp_route_clippy.c"
94 DEFINE_HOOK(bgp_snmp_update_stats
,
95 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
98 DEFINE_HOOK(bgp_rpki_prefix_status
,
99 (struct peer
*peer
, struct attr
*attr
,
100 const struct prefix
*prefix
),
101 (peer
, attr
, prefix
));
103 /* Extern from bgp_dump.c */
104 extern const char *bgp_origin_str
[];
105 extern const char *bgp_origin_long_str
[];
108 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
109 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
110 static const struct message bgp_pmsi_tnltype_str
[] = {
111 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
112 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
113 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
114 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
115 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
116 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
117 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
118 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
122 #define VRFID_NONE_STR "-"
123 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
125 DEFINE_HOOK(bgp_process
,
126 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
127 struct peer
*peer
, bool withdraw
),
128 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
130 /** Test if path is suppressed. */
131 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
133 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
136 return listcount(pi
->extra
->aggr_suppressors
) > 0;
139 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
140 safi_t safi
, const struct prefix
*p
,
141 struct prefix_rd
*prd
)
143 struct bgp_dest
*dest
;
144 struct bgp_dest
*pdest
= NULL
;
148 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
149 || (safi
== SAFI_EVPN
)) {
150 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
152 if (!bgp_dest_has_bgp_path_info_data(pdest
))
153 bgp_dest_set_bgp_table_info(
154 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
156 bgp_dest_unlock_node(pdest
);
157 table
= bgp_dest_get_bgp_table_info(pdest
);
160 dest
= bgp_node_get(table
, p
);
162 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
163 || (safi
== SAFI_EVPN
))
169 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
170 safi_t safi
, const struct prefix
*p
,
171 struct prefix_rd
*prd
)
173 struct bgp_dest
*dest
;
174 struct bgp_dest
*pdest
= NULL
;
179 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
180 || (safi
== SAFI_EVPN
)) {
181 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
185 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
186 bgp_dest_unlock_node(pdest
);
190 table
= bgp_dest_get_bgp_table_info(pdest
);
193 dest
= bgp_node_lookup(table
, p
);
198 /* Allocate bgp_path_info_extra */
199 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
201 struct bgp_path_info_extra
*new;
202 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
203 sizeof(struct bgp_path_info_extra
));
204 new->label
[0] = MPLS_INVALID_LABEL
;
206 new->bgp_fs_pbr
= NULL
;
207 new->bgp_fs_iprule
= NULL
;
211 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
213 struct bgp_path_info_extra
*e
;
215 if (!extra
|| !*extra
)
220 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
225 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
228 /* FIXME: since multiple e may have the same e->parent
229 * and e->parent->net is holding a refcount for each
230 * of them, we need to do some fudging here.
232 * WARNING: if bpi->net->lock drops to 0, bpi may be
233 * freed as well (because bpi->net was holding the
234 * last reference to bpi) => write after free!
238 bpi
= bgp_path_info_lock(bpi
);
239 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
240 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
243 bgp_path_info_unlock(bpi
);
245 bgp_path_info_unlock(e
->parent
);
250 bgp_unlock(e
->bgp_orig
);
253 peer_unlock(e
->peer_orig
);
255 if (e
->aggr_suppressors
)
256 list_delete(&e
->aggr_suppressors
);
259 bgp_evpn_path_mh_info_free(e
->mh_info
);
261 if ((*extra
)->bgp_fs_iprule
)
262 list_delete(&((*extra
)->bgp_fs_iprule
));
263 if ((*extra
)->bgp_fs_pbr
)
264 list_delete(&((*extra
)->bgp_fs_pbr
));
265 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
268 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
269 * allocated if required.
271 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
274 pi
->extra
= bgp_path_info_extra_new();
278 /* Free bgp route information. */
279 void bgp_path_info_free_with_caller(const char *name
,
280 struct bgp_path_info
*path
)
282 frrtrace(2, frr_bgp
, bgp_path_info_free
, path
, name
);
283 bgp_attr_unintern(&path
->attr
);
285 bgp_unlink_nexthop(path
);
286 bgp_path_info_extra_free(&path
->extra
);
287 bgp_path_info_mpath_free(&path
->mpath
);
289 bgp_addpath_free_info_data(&path
->tx_addpath
,
290 &path
->net
->tx_addpath
);
292 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
294 XFREE(MTYPE_BGP_ROUTE
, path
);
297 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
303 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
305 assert(path
&& path
->lock
> 0);
308 if (path
->lock
== 0) {
309 bgp_path_info_free(path
);
316 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
317 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
320 struct bgp_path_info
*old_pi
, *nextpi
;
321 bool set_flag
= false;
322 struct bgp
*bgp
= NULL
;
323 struct bgp_table
*table
= NULL
;
327 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
328 * then the route selection is deferred
330 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
333 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
334 if (BGP_DEBUG(update
, UPDATE_OUT
))
336 "Route %pBD is in workqueue and being processed, not deferred.",
342 table
= bgp_dest_table(dest
);
349 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
350 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
351 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
354 /* Route selection is deferred if there is a stale path which
355 * which indicates peer is in restart mode
357 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
358 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
361 /* If the peer is graceful restart capable and peer is
362 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
365 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
366 && BGP_PEER_RESTARTING_MODE(peer
)
368 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
376 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
379 if (set_flag
&& table
) {
380 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
381 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
382 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
383 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
384 if (BGP_DEBUG(update
, UPDATE_OUT
))
385 zlog_debug("DEFER route %pBD, dest %p", dest
,
393 void bgp_path_info_add_with_caller(const char *name
, struct bgp_dest
*dest
,
394 struct bgp_path_info
*pi
)
396 frrtrace(3, frr_bgp
, bgp_path_info_add
, dest
, pi
, name
);
397 struct bgp_path_info
*top
;
399 top
= bgp_dest_get_bgp_path_info(dest
);
405 bgp_dest_set_bgp_path_info(dest
, pi
);
407 bgp_path_info_lock(pi
);
408 bgp_dest_lock_node(dest
);
409 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
410 bgp_dest_set_defer_flag(dest
, false);
411 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
414 /* Do the actual removal of info from RIB, for use by bgp_process
415 completion callback *only* */
416 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
419 pi
->next
->prev
= pi
->prev
;
421 pi
->prev
->next
= pi
->next
;
423 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
425 bgp_path_info_mpath_dequeue(pi
);
426 bgp_path_info_unlock(pi
);
427 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
428 bgp_dest_unlock_node(dest
);
431 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
433 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
434 /* set of previous already took care of pcount */
435 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
438 /* undo the effects of a previous call to bgp_path_info_delete; typically
439 called when a route is deleted and then quickly re-added before the
440 deletion has been processed */
441 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
443 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
444 /* unset of previous already took care of pcount */
445 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
448 /* Adjust pcount as required */
449 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
451 struct bgp_table
*table
;
453 assert(dest
&& bgp_dest_table(dest
));
454 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
456 table
= bgp_dest_table(dest
);
458 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
461 if (!BGP_PATH_COUNTABLE(pi
)
462 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
464 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
466 /* slight hack, but more robust against errors. */
467 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
468 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
470 flog_err(EC_LIB_DEVELOPMENT
,
471 "Asked to decrement 0 prefix count for peer");
472 } else if (BGP_PATH_COUNTABLE(pi
)
473 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
474 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
475 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
479 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
480 struct bgp_path_info
*pi2
)
482 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
485 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
486 * This is here primarily to keep prefix-count in check.
488 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
491 SET_FLAG(pi
->flags
, flag
);
493 /* early bath if we know it's not a flag that changes countability state
495 if (!CHECK_FLAG(flag
,
496 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
499 bgp_pcount_adjust(dest
, pi
);
502 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
505 UNSET_FLAG(pi
->flags
, flag
);
507 /* early bath if we know it's not a flag that changes countability state
509 if (!CHECK_FLAG(flag
,
510 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
513 bgp_pcount_adjust(dest
, pi
);
516 /* Get MED value. If MED value is missing and "bgp bestpath
517 missing-as-worst" is specified, treat it as the worst value. */
518 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
520 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
523 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
530 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
533 if (pi
->addpath_rx_id
)
534 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
535 pi
->peer
->host
, pi
->addpath_rx_id
);
537 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
542 * Get the ultimate path info.
544 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
546 struct bgp_path_info
*bpi_ultimate
;
548 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
551 for (bpi_ultimate
= info
;
552 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
553 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
559 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
561 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
562 struct bgp_path_info
*exist
, int *paths_eq
,
563 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
564 char *pfx_buf
, afi_t afi
, safi_t safi
,
565 enum bgp_path_selection_reason
*reason
)
567 const struct prefix
*new_p
;
568 struct attr
*newattr
, *existattr
;
569 enum bgp_peer_sort new_sort
;
570 enum bgp_peer_sort exist_sort
;
576 uint32_t exist_weight
;
577 uint32_t newm
, existm
;
578 struct in_addr new_id
;
579 struct in_addr exist_id
;
582 int internal_as_route
;
585 int igp_metric_ret
= 0;
586 int peer_sort_ret
= -1;
587 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
588 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
590 uint32_t exist_mm_seq
;
597 bool new_origin
, exist_origin
;
598 struct bgp_path_info
*bpi_ultimate
;
604 *reason
= bgp_path_selection_none
;
606 zlog_debug("%s: new is NULL", pfx_buf
);
611 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
612 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
617 *reason
= bgp_path_selection_first
;
619 zlog_debug("%s(%s): %s is the initial bestpath",
620 pfx_buf
, bgp
->name_pretty
, new_buf
);
625 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
626 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
628 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
629 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
630 exist_buf
, exist
->flags
);
634 existattr
= exist
->attr
;
636 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
637 * Capability" to a neighbor MUST perform the following upon receiving
638 * a route from that neighbor with the "LLGR_STALE" community, or upon
639 * attaching the "LLGR_STALE" community itself per Section 4.2:
641 * Treat the route as the least-preferred in route selection (see
642 * below). See the Risks of Depreferencing Routes section (Section 5.2)
643 * for a discussion of potential risks inherent in doing this.
645 if (bgp_attr_get_community(newattr
) &&
646 community_include(bgp_attr_get_community(newattr
),
647 COMMUNITY_LLGR_STALE
)) {
650 "%s: %s wins over %s due to LLGR_STALE community",
651 pfx_buf
, new_buf
, exist_buf
);
655 if (bgp_attr_get_community(existattr
) &&
656 community_include(bgp_attr_get_community(existattr
),
657 COMMUNITY_LLGR_STALE
)) {
660 "%s: %s loses to %s due to LLGR_STALE community",
661 pfx_buf
, new_buf
, exist_buf
);
665 new_p
= bgp_dest_get_prefix(new->net
);
667 /* For EVPN routes, we cannot just go by local vs remote, we have to
668 * look at the MAC mobility sequence number, if present.
670 if ((safi
== SAFI_EVPN
)
671 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
672 /* This is an error condition described in RFC 7432 Section
674 * states that in this scenario "the PE MUST alert the operator"
676 * does not state what other action to take. In order to provide
678 * consistency in this scenario we are going to prefer the path
682 if (newattr
->sticky
!= existattr
->sticky
) {
684 prefix2str(new_p
, pfx_buf
,
686 * PREFIX2STR_BUFFER
);
687 bgp_path_info_path_with_addpath_rx_str(
688 new, new_buf
, sizeof(new_buf
));
689 bgp_path_info_path_with_addpath_rx_str(
690 exist
, exist_buf
, sizeof(exist_buf
));
693 if (newattr
->sticky
&& !existattr
->sticky
) {
694 *reason
= bgp_path_selection_evpn_sticky_mac
;
697 "%s: %s wins over %s due to sticky MAC flag",
698 pfx_buf
, new_buf
, exist_buf
);
702 if (!newattr
->sticky
&& existattr
->sticky
) {
703 *reason
= bgp_path_selection_evpn_sticky_mac
;
706 "%s: %s loses to %s due to sticky MAC flag",
707 pfx_buf
, new_buf
, exist_buf
);
712 new_esi
= bgp_evpn_attr_get_esi(newattr
);
713 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
714 if (bgp_evpn_is_esi_valid(new_esi
) &&
715 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
721 /* If both paths have the same non-zero ES and
722 * one path is local it wins.
723 * PS: Note the local path wins even if the remote
724 * has the higher MM seq. The local path's
725 * MM seq will be fixed up to match the highest
726 * rem seq, subsequently.
729 char esi_buf
[ESI_STR_LEN
];
731 if (bgp_evpn_is_path_local(bgp
, new)) {
732 *reason
= bgp_path_selection_evpn_local_path
;
735 "%s: %s wins over %s as ES %s is same and local",
736 pfx_buf
, new_buf
, exist_buf
,
737 esi_to_str(new_esi
, esi_buf
,
741 if (bgp_evpn_is_path_local(bgp
, exist
)) {
742 *reason
= bgp_path_selection_evpn_local_path
;
745 "%s: %s loses to %s as ES %s is same and local",
746 pfx_buf
, new_buf
, exist_buf
,
747 esi_to_str(new_esi
, esi_buf
,
753 new_mm_seq
= mac_mobility_seqnum(newattr
);
754 exist_mm_seq
= mac_mobility_seqnum(existattr
);
756 if (new_mm_seq
> exist_mm_seq
) {
757 *reason
= bgp_path_selection_evpn_seq
;
760 "%s: %s wins over %s due to MM seq %u > %u",
761 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
766 if (new_mm_seq
< exist_mm_seq
) {
767 *reason
= bgp_path_selection_evpn_seq
;
770 "%s: %s loses to %s due to MM seq %u < %u",
771 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
776 /* if the sequence numbers and ESI are the same and one path
777 * is non-proxy it wins (over proxy)
779 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
780 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
781 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
782 old_proxy
!= new_proxy
) {
784 *reason
= bgp_path_selection_evpn_non_proxy
;
787 "%s: %s wins over %s, same seq/es and non-proxy",
788 pfx_buf
, new_buf
, exist_buf
);
792 *reason
= bgp_path_selection_evpn_non_proxy
;
795 "%s: %s loses to %s, same seq/es and non-proxy",
796 pfx_buf
, new_buf
, exist_buf
);
801 * if sequence numbers are the same path with the lowest IP
804 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
806 *reason
= bgp_path_selection_evpn_lower_ip
;
809 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
810 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
811 &new->attr
->nexthop
);
815 *reason
= bgp_path_selection_evpn_lower_ip
;
818 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
819 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
820 &new->attr
->nexthop
);
825 /* 1. Weight check. */
826 new_weight
= newattr
->weight
;
827 exist_weight
= existattr
->weight
;
829 if (new_weight
> exist_weight
) {
830 *reason
= bgp_path_selection_weight
;
832 zlog_debug("%s: %s wins over %s due to weight %d > %d",
833 pfx_buf
, new_buf
, exist_buf
, new_weight
,
838 if (new_weight
< exist_weight
) {
839 *reason
= bgp_path_selection_weight
;
841 zlog_debug("%s: %s loses to %s due to weight %d < %d",
842 pfx_buf
, new_buf
, exist_buf
, new_weight
,
847 /* 2. Local preference check. */
848 new_pref
= exist_pref
= bgp
->default_local_pref
;
850 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
851 new_pref
= newattr
->local_pref
;
852 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
853 exist_pref
= existattr
->local_pref
;
855 if (new_pref
> exist_pref
) {
856 *reason
= bgp_path_selection_local_pref
;
859 "%s: %s wins over %s due to localpref %d > %d",
860 pfx_buf
, new_buf
, exist_buf
, new_pref
,
865 if (new_pref
< exist_pref
) {
866 *reason
= bgp_path_selection_local_pref
;
869 "%s: %s loses to %s due to localpref %d < %d",
870 pfx_buf
, new_buf
, exist_buf
, new_pref
,
875 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
876 * extensions defined in this document, the following step is inserted
877 * after the LOCAL_PREF comparison step in the BGP decision process:
878 * When comparing a pair of routes for a BGP destination, the
879 * route with the ACCEPT_OWN community attached is preferred over
880 * the route that does not have the community.
881 * This extra step MUST only be invoked during the best path selection
882 * process of VPN-IP routes.
884 if (safi
== SAFI_MPLS_VPN
&&
885 (CHECK_FLAG(new->peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
) ||
886 CHECK_FLAG(exist
->peer
->af_flags
[afi
][safi
],
887 PEER_FLAG_ACCEPT_OWN
))) {
888 bool new_accept_own
= false;
889 bool exist_accept_own
= false;
890 uint32_t accept_own
= COMMUNITY_ACCEPT_OWN
;
892 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
893 new_accept_own
= community_include(
894 bgp_attr_get_community(newattr
), accept_own
);
895 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
896 exist_accept_own
= community_include(
897 bgp_attr_get_community(existattr
), accept_own
);
899 if (new_accept_own
&& !exist_accept_own
) {
900 *reason
= bgp_path_selection_accept_own
;
903 "%s: %s wins over %s due to accept-own",
904 pfx_buf
, new_buf
, exist_buf
);
908 if (!new_accept_own
&& exist_accept_own
) {
909 *reason
= bgp_path_selection_accept_own
;
912 "%s: %s loses to %s due to accept-own",
913 pfx_buf
, new_buf
, exist_buf
);
918 /* Tie-breaker - AIGP (Metric TLV) attribute */
919 if (CHECK_FLAG(newattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
920 CHECK_FLAG(existattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
921 CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_AIGP
)) {
922 uint64_t new_aigp
= bgp_attr_get_aigp_metric(newattr
);
923 uint64_t exist_aigp
= bgp_attr_get_aigp_metric(existattr
);
925 if (new_aigp
< exist_aigp
) {
926 *reason
= bgp_path_selection_aigp
;
929 "%s: %s wins over %s due to AIGP %" PRIu64
931 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
936 if (new_aigp
> exist_aigp
) {
937 *reason
= bgp_path_selection_aigp
;
940 "%s: %s loses to %s due to AIGP %" PRIu64
942 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
948 /* 3. Local route check. We prefer:
950 * - BGP_ROUTE_AGGREGATE
951 * - BGP_ROUTE_REDISTRIBUTE
953 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
954 new->sub_type
== BGP_ROUTE_IMPORTED
);
955 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
956 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
958 if (new_origin
&& !exist_origin
) {
959 *reason
= bgp_path_selection_local_route
;
962 "%s: %s wins over %s due to preferred BGP_ROUTE type",
963 pfx_buf
, new_buf
, exist_buf
);
967 if (!new_origin
&& exist_origin
) {
968 *reason
= bgp_path_selection_local_route
;
971 "%s: %s loses to %s due to preferred BGP_ROUTE type",
972 pfx_buf
, new_buf
, exist_buf
);
976 /* Here if these are imported routes then get ultimate pi for
979 new = bgp_get_imported_bpi_ultimate(new);
980 exist
= bgp_get_imported_bpi_ultimate(exist
);
982 existattr
= exist
->attr
;
984 /* 4. AS path length check. */
985 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
986 int exist_hops
= aspath_count_hops(existattr
->aspath
);
987 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
989 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
992 aspath_hops
= aspath_count_hops(newattr
->aspath
);
993 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
995 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
996 *reason
= bgp_path_selection_confed_as_path
;
999 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
1000 pfx_buf
, new_buf
, exist_buf
,
1002 (exist_hops
+ exist_confeds
));
1006 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
1007 *reason
= bgp_path_selection_confed_as_path
;
1010 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1011 pfx_buf
, new_buf
, exist_buf
,
1013 (exist_hops
+ exist_confeds
));
1017 int newhops
= aspath_count_hops(newattr
->aspath
);
1019 if (newhops
< exist_hops
) {
1020 *reason
= bgp_path_selection_as_path
;
1023 "%s: %s wins over %s due to aspath hopcount %d < %d",
1024 pfx_buf
, new_buf
, exist_buf
,
1025 newhops
, exist_hops
);
1029 if (newhops
> exist_hops
) {
1030 *reason
= bgp_path_selection_as_path
;
1033 "%s: %s loses to %s due to aspath hopcount %d > %d",
1034 pfx_buf
, new_buf
, exist_buf
,
1035 newhops
, exist_hops
);
1041 /* 5. Origin check. */
1042 if (newattr
->origin
< existattr
->origin
) {
1043 *reason
= bgp_path_selection_origin
;
1045 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1046 pfx_buf
, new_buf
, exist_buf
,
1047 bgp_origin_long_str
[newattr
->origin
],
1048 bgp_origin_long_str
[existattr
->origin
]);
1052 if (newattr
->origin
> existattr
->origin
) {
1053 *reason
= bgp_path_selection_origin
;
1055 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1056 pfx_buf
, new_buf
, exist_buf
,
1057 bgp_origin_long_str
[newattr
->origin
],
1058 bgp_origin_long_str
[existattr
->origin
]);
1063 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
1064 && aspath_count_hops(existattr
->aspath
) == 0);
1065 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
1066 && aspath_count_confeds(existattr
->aspath
) > 0
1067 && aspath_count_hops(newattr
->aspath
) == 0
1068 && aspath_count_hops(existattr
->aspath
) == 0);
1070 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1071 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1072 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1073 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1074 || internal_as_route
) {
1075 new_med
= bgp_med_value(new->attr
, bgp
);
1076 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1078 if (new_med
< exist_med
) {
1079 *reason
= bgp_path_selection_med
;
1082 "%s: %s wins over %s due to MED %d < %d",
1083 pfx_buf
, new_buf
, exist_buf
, new_med
,
1088 if (new_med
> exist_med
) {
1089 *reason
= bgp_path_selection_med
;
1092 "%s: %s loses to %s due to MED %d > %d",
1093 pfx_buf
, new_buf
, exist_buf
, new_med
,
1099 /* 7. Peer type check. */
1100 new_sort
= new->peer
->sort
;
1101 exist_sort
= exist
->peer
->sort
;
1103 if (new_sort
== BGP_PEER_EBGP
1104 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1105 *reason
= bgp_path_selection_peer
;
1108 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1109 pfx_buf
, new_buf
, exist_buf
);
1110 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1115 if (exist_sort
== BGP_PEER_EBGP
1116 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1117 *reason
= bgp_path_selection_peer
;
1120 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1121 pfx_buf
, new_buf
, exist_buf
);
1122 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1127 /* 8. IGP metric check. */
1131 newm
= new->extra
->igpmetric
;
1133 existm
= exist
->extra
->igpmetric
;
1135 if (newm
< existm
) {
1136 if (debug
&& peer_sort_ret
< 0)
1138 "%s: %s wins over %s due to IGP metric %u < %u",
1139 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1143 if (newm
> existm
) {
1144 if (debug
&& peer_sort_ret
< 0)
1146 "%s: %s loses to %s due to IGP metric %u > %u",
1147 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1151 /* 9. Same IGP metric. Compare the cluster list length as
1152 representative of IGP hops metric. Rewrite the metric value
1153 pair (newm, existm) with the cluster list length. Prefer the
1154 path with smaller cluster list length. */
1155 if (newm
== existm
) {
1156 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
&&
1157 peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
&&
1158 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1159 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1160 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1162 if (newm
< existm
) {
1163 if (debug
&& peer_sort_ret
< 0)
1165 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1166 pfx_buf
, new_buf
, exist_buf
,
1171 if (newm
> existm
) {
1172 if (debug
&& peer_sort_ret
< 0)
1174 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1175 pfx_buf
, new_buf
, exist_buf
,
1182 /* 10. confed-external vs. confed-internal */
1183 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1184 if (new_sort
== BGP_PEER_CONFED
1185 && exist_sort
== BGP_PEER_IBGP
) {
1186 *reason
= bgp_path_selection_confed
;
1189 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1190 pfx_buf
, new_buf
, exist_buf
);
1191 if (!CHECK_FLAG(bgp
->flags
,
1192 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1197 if (exist_sort
== BGP_PEER_CONFED
1198 && new_sort
== BGP_PEER_IBGP
) {
1199 *reason
= bgp_path_selection_confed
;
1202 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1203 pfx_buf
, new_buf
, exist_buf
);
1204 if (!CHECK_FLAG(bgp
->flags
,
1205 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1211 /* 11. Maximum path check. */
1212 if (newm
== existm
) {
1213 /* If one path has a label but the other does not, do not treat
1214 * them as equals for multipath
1216 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1218 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1221 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1222 pfx_buf
, new_buf
, exist_buf
);
1223 } else if (CHECK_FLAG(bgp
->flags
,
1224 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1227 * For the two paths, all comparison steps till IGP
1229 * have succeeded - including AS_PATH hop count. Since
1231 * bestpath as-path multipath-relax' knob is on, we
1233 * an exact match of AS_PATH. Thus, mark the paths are
1235 * That will trigger both these paths to get into the
1243 "%s: %s and %s are equal via multipath-relax",
1244 pfx_buf
, new_buf
, exist_buf
);
1245 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1246 if (aspath_cmp(new->attr
->aspath
,
1247 exist
->attr
->aspath
)) {
1252 "%s: %s and %s are equal via matching aspaths",
1253 pfx_buf
, new_buf
, exist_buf
);
1255 } else if (new->peer
->as
== exist
->peer
->as
) {
1260 "%s: %s and %s are equal via same remote-as",
1261 pfx_buf
, new_buf
, exist_buf
);
1265 * TODO: If unequal cost ibgp multipath is enabled we can
1266 * mark the paths as equal here instead of returning
1269 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1270 * if either step 7 or 10 (peer type checks) yielded a winner,
1271 * that result was returned immediately. Returning from step 10
1272 * ignored the return value computed in steps 8 and 9 (IGP
1273 * metric checks). In order to preserve that behavior, if
1274 * peer_sort_ret is set, return that rather than igp_metric_ret.
1276 ret
= peer_sort_ret
;
1277 if (peer_sort_ret
< 0) {
1278 ret
= igp_metric_ret
;
1282 "%s: %s wins over %s after IGP metric comparison",
1283 pfx_buf
, new_buf
, exist_buf
);
1286 "%s: %s loses to %s after IGP metric comparison",
1287 pfx_buf
, new_buf
, exist_buf
);
1289 *reason
= bgp_path_selection_igp_metric
;
1295 * At this point, the decision whether to set *paths_eq = 1 has been
1296 * completed. If we deferred returning because of bestpath peer-type
1297 * relax configuration, return now.
1299 if (peer_sort_ret
>= 0)
1300 return peer_sort_ret
;
1302 /* 12. If both paths are external, prefer the path that was received
1303 first (the oldest one). This step minimizes route-flap, since a
1304 newer path won't displace an older one, even if it was the
1305 preferred route based on the additional decision criteria below. */
1306 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1307 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1308 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1309 *reason
= bgp_path_selection_older
;
1312 "%s: %s wins over %s due to oldest external",
1313 pfx_buf
, new_buf
, exist_buf
);
1317 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1318 *reason
= bgp_path_selection_older
;
1321 "%s: %s loses to %s due to oldest external",
1322 pfx_buf
, new_buf
, exist_buf
);
1327 /* 13. Router-ID comparison. */
1328 /* If one of the paths is "stale", the corresponding peer router-id will
1329 * be 0 and would always win over the other path. If originator id is
1330 * used for the comparison, it will decide which path is better.
1332 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1333 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1335 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1336 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1337 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1339 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1341 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1342 *reason
= bgp_path_selection_router_id
;
1345 "%s: %s wins over %s due to Router-ID comparison",
1346 pfx_buf
, new_buf
, exist_buf
);
1350 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1351 *reason
= bgp_path_selection_router_id
;
1354 "%s: %s loses to %s due to Router-ID comparison",
1355 pfx_buf
, new_buf
, exist_buf
);
1359 /* 14. Cluster length comparison. */
1360 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1361 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1363 if (new_cluster
< exist_cluster
) {
1364 *reason
= bgp_path_selection_cluster_length
;
1367 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1368 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1373 if (new_cluster
> exist_cluster
) {
1374 *reason
= bgp_path_selection_cluster_length
;
1377 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1378 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1383 /* 15. Neighbor address comparison. */
1384 /* Do this only if neither path is "stale" as stale paths do not have
1385 * valid peer information (as the connection may or may not be up).
1387 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1388 *reason
= bgp_path_selection_stale
;
1391 "%s: %s wins over %s due to latter path being STALE",
1392 pfx_buf
, new_buf
, exist_buf
);
1396 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1397 *reason
= bgp_path_selection_stale
;
1400 "%s: %s loses to %s due to former path being STALE",
1401 pfx_buf
, new_buf
, exist_buf
);
1405 /* locally configured routes to advertise do not have su_remote */
1406 if (new->peer
->su_remote
== NULL
) {
1407 *reason
= bgp_path_selection_local_configured
;
1410 if (exist
->peer
->su_remote
== NULL
) {
1411 *reason
= bgp_path_selection_local_configured
;
1415 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1418 *reason
= bgp_path_selection_neighbor_ip
;
1421 "%s: %s loses to %s due to Neighor IP comparison",
1422 pfx_buf
, new_buf
, exist_buf
);
1427 *reason
= bgp_path_selection_neighbor_ip
;
1430 "%s: %s wins over %s due to Neighor IP comparison",
1431 pfx_buf
, new_buf
, exist_buf
);
1435 *reason
= bgp_path_selection_default
;
1437 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1438 pfx_buf
, new_buf
, exist_buf
);
1444 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1445 struct bgp_path_info
*exist
, int *paths_eq
)
1447 enum bgp_path_selection_reason reason
;
1448 char pfx_buf
[PREFIX2STR_BUFFER
];
1450 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1451 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1454 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1455 * is preferred, or 0 if they are the same (usually will only occur if
1456 * multipath is enabled
1457 * This version is compatible with */
1458 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1459 struct bgp_path_info
*exist
, char *pfx_buf
,
1460 afi_t afi
, safi_t safi
,
1461 enum bgp_path_selection_reason
*reason
)
1465 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1479 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1480 const struct prefix
*p
,
1481 struct attr
*attr
, afi_t afi
,
1484 struct bgp_filter
*filter
;
1485 enum filter_type ret
= FILTER_PERMIT
;
1487 filter
= &peer
->filter
[afi
][safi
];
1489 #define FILTER_EXIST_WARN(F, f, filter) \
1490 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1491 zlog_debug("%s: Could not find configured input %s-list %s!", \
1492 peer->host, #f, F##_IN_NAME(filter));
1494 if (DISTRIBUTE_IN_NAME(filter
)) {
1495 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1497 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1504 if (PREFIX_LIST_IN_NAME(filter
)) {
1505 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1507 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1514 if (FILTER_LIST_IN_NAME(filter
)) {
1515 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1517 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1518 == AS_FILTER_DENY
) {
1525 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1526 char pfxprint
[PREFIX2STR_BUFFER
];
1528 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1529 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1530 ret
== FILTER_PERMIT
? "permit" : "deny");
1534 #undef FILTER_EXIST_WARN
1537 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1538 const struct prefix
*p
,
1539 struct attr
*attr
, afi_t afi
,
1542 struct bgp_filter
*filter
;
1543 enum filter_type ret
= FILTER_PERMIT
;
1545 filter
= &peer
->filter
[afi
][safi
];
1547 #define FILTER_EXIST_WARN(F, f, filter) \
1548 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1549 zlog_debug("%s: Could not find configured output %s-list %s!", \
1550 peer->host, #f, F##_OUT_NAME(filter));
1552 if (DISTRIBUTE_OUT_NAME(filter
)) {
1553 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1555 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1562 if (PREFIX_LIST_OUT_NAME(filter
)) {
1563 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1565 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1572 if (FILTER_LIST_OUT_NAME(filter
)) {
1573 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1575 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1576 == AS_FILTER_DENY
) {
1582 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1583 char pfxprint
[PREFIX2STR_BUFFER
];
1585 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1586 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1587 ret
== FILTER_PERMIT
? "permit" : "deny");
1592 #undef FILTER_EXIST_WARN
1595 /* If community attribute includes no_export then return 1. */
1596 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1598 if (bgp_attr_get_community(attr
)) {
1599 /* NO_ADVERTISE check. */
1600 if (community_include(bgp_attr_get_community(attr
),
1601 COMMUNITY_NO_ADVERTISE
))
1604 /* NO_EXPORT check. */
1605 if (peer
->sort
== BGP_PEER_EBGP
&&
1606 community_include(bgp_attr_get_community(attr
),
1607 COMMUNITY_NO_EXPORT
))
1610 /* NO_EXPORT_SUBCONFED check. */
1611 if (peer
->sort
== BGP_PEER_EBGP
1612 || peer
->sort
== BGP_PEER_CONFED
)
1613 if (community_include(bgp_attr_get_community(attr
),
1614 COMMUNITY_NO_EXPORT_SUBCONFED
))
1620 /* Route reflection loop check. */
1621 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1623 struct in_addr cluster_id
;
1624 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1627 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1628 cluster_id
= peer
->bgp
->cluster_id
;
1630 cluster_id
= peer
->bgp
->router_id
;
1632 if (cluster_loop_check(cluster
, cluster_id
))
1638 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1640 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1641 if (peer
->local_role
== ROLE_PROVIDER
||
1642 peer
->local_role
== ROLE_RS_SERVER
)
1644 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1648 if (peer
->local_role
== ROLE_CUSTOMER
||
1649 peer
->local_role
== ROLE_PEER
||
1650 peer
->local_role
== ROLE_RS_CLIENT
) {
1651 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1652 attr
->otc
= peer
->as
;
1657 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1659 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1660 if (peer
->local_role
== ROLE_CUSTOMER
||
1661 peer
->local_role
== ROLE_RS_CLIENT
||
1662 peer
->local_role
== ROLE_PEER
)
1666 if (peer
->local_role
== ROLE_PROVIDER
||
1667 peer
->local_role
== ROLE_PEER
||
1668 peer
->local_role
== ROLE_RS_SERVER
) {
1669 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1670 attr
->otc
= peer
->bgp
->as
;
1675 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1677 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1680 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1681 struct attr
*attr
, afi_t afi
, safi_t safi
,
1682 const char *rmap_name
, mpls_label_t
*label
,
1683 uint32_t num_labels
, struct bgp_dest
*dest
)
1685 struct bgp_filter
*filter
;
1686 struct bgp_path_info rmap_path
= { 0 };
1687 struct bgp_path_info_extra extra
= { 0 };
1688 route_map_result_t ret
;
1689 struct route_map
*rmap
= NULL
;
1691 filter
= &peer
->filter
[afi
][safi
];
1693 /* Apply default weight value. */
1694 if (peer
->weight
[afi
][safi
])
1695 attr
->weight
= peer
->weight
[afi
][safi
];
1698 rmap
= route_map_lookup_by_name(rmap_name
);
1703 if (ROUTE_MAP_IN_NAME(filter
)) {
1704 rmap
= ROUTE_MAP_IN(filter
);
1711 /* Route map apply. */
1713 memset(&rmap_path
, 0, sizeof(rmap_path
));
1714 /* Duplicate current value to new structure for modification. */
1715 rmap_path
.peer
= peer
;
1716 rmap_path
.attr
= attr
;
1717 rmap_path
.extra
= &extra
;
1718 rmap_path
.net
= dest
;
1720 extra
.num_labels
= num_labels
;
1721 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1722 memcpy(extra
.label
, label
,
1723 num_labels
* sizeof(mpls_label_t
));
1725 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1727 /* Apply BGP route map to the attribute. */
1728 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1730 peer
->rmap_type
= 0;
1732 if (ret
== RMAP_DENYMATCH
)
1738 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1739 struct attr
*attr
, afi_t afi
, safi_t safi
,
1740 const char *rmap_name
)
1742 struct bgp_path_info rmap_path
;
1743 route_map_result_t ret
;
1744 struct route_map
*rmap
= NULL
;
1748 * So if we get to this point and have no rmap_name
1749 * we want to just show the output as it currently
1755 /* Apply default weight value. */
1756 if (peer
->weight
[afi
][safi
])
1757 attr
->weight
= peer
->weight
[afi
][safi
];
1759 rmap
= route_map_lookup_by_name(rmap_name
);
1762 * If we have a route map name and we do not find
1763 * the routemap that means we have an implicit
1769 memset(&rmap_path
, 0, sizeof(rmap_path
));
1770 /* Route map apply. */
1771 /* Duplicate current value to new structure for modification. */
1772 rmap_path
.peer
= peer
;
1773 rmap_path
.attr
= attr
;
1775 rmap_type
= peer
->rmap_type
;
1776 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1778 /* Apply BGP route map to the attribute. */
1779 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1781 peer
->rmap_type
= rmap_type
;
1783 if (ret
== RMAP_DENYMATCH
)
1785 * caller has multiple error paths with bgp_attr_flush()
1792 /* If this is an EBGP peer with remove-private-AS */
1793 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1794 struct peer
*peer
, struct attr
*attr
)
1796 if (peer
->sort
== BGP_PEER_EBGP
1797 && (peer_af_flag_check(peer
, afi
, safi
,
1798 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1799 || peer_af_flag_check(peer
, afi
, safi
,
1800 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1801 || peer_af_flag_check(peer
, afi
, safi
,
1802 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1803 || peer_af_flag_check(peer
, afi
, safi
,
1804 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1805 // Take action on the entire aspath
1806 if (peer_af_flag_check(peer
, afi
, safi
,
1807 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1808 || peer_af_flag_check(peer
, afi
, safi
,
1809 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1810 if (peer_af_flag_check(
1812 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1813 attr
->aspath
= aspath_replace_private_asns(
1814 attr
->aspath
, bgp
->as
, peer
->as
);
1817 * Even if the aspath consists of just private ASNs we
1818 * need to walk the AS-Path to maintain all instances
1819 * of the peer's ASN to break possible loops.
1822 attr
->aspath
= aspath_remove_private_asns(
1823 attr
->aspath
, peer
->as
);
1826 // 'all' was not specified so the entire aspath must be private
1828 // for us to do anything
1829 else if (aspath_private_as_check(attr
->aspath
)) {
1830 if (peer_af_flag_check(
1832 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1833 attr
->aspath
= aspath_replace_private_asns(
1834 attr
->aspath
, bgp
->as
, peer
->as
);
1837 * Walk the aspath to retain any instances of
1840 attr
->aspath
= aspath_remove_private_asns(
1841 attr
->aspath
, peer
->as
);
1846 /* If this is an EBGP peer with as-override */
1847 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1848 struct peer
*peer
, struct attr
*attr
)
1850 struct aspath
*aspath
;
1852 if (peer
->sort
== BGP_PEER_EBGP
&&
1853 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1854 if (attr
->aspath
->refcnt
)
1855 aspath
= aspath_dup(attr
->aspath
);
1857 aspath
= attr
->aspath
;
1859 attr
->aspath
= aspath_intern(
1860 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1862 aspath_free(aspath
);
1866 void bgp_attr_add_llgr_community(struct attr
*attr
)
1868 struct community
*old
;
1869 struct community
*new;
1870 struct community
*merge
;
1871 struct community
*llgr
;
1873 old
= bgp_attr_get_community(attr
);
1874 llgr
= community_str2com("llgr-stale");
1879 merge
= community_merge(community_dup(old
), llgr
);
1881 if (old
->refcnt
== 0)
1882 community_free(&old
);
1884 new = community_uniq_sort(merge
);
1885 community_free(&merge
);
1887 new = community_dup(llgr
);
1890 community_free(&llgr
);
1892 bgp_attr_set_community(attr
, new);
1895 void bgp_attr_add_gshut_community(struct attr
*attr
)
1897 struct community
*old
;
1898 struct community
*new;
1899 struct community
*merge
;
1900 struct community
*gshut
;
1902 old
= bgp_attr_get_community(attr
);
1903 gshut
= community_str2com("graceful-shutdown");
1908 merge
= community_merge(community_dup(old
), gshut
);
1910 if (old
->refcnt
== 0)
1911 community_free(&old
);
1913 new = community_uniq_sort(merge
);
1914 community_free(&merge
);
1916 new = community_dup(gshut
);
1919 community_free(&gshut
);
1920 bgp_attr_set_community(attr
, new);
1922 /* When we add the graceful-shutdown community we must also
1923 * lower the local-preference */
1924 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1925 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1929 /* Notify BGP Conditional advertisement scanner process. */
1930 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1932 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1933 afi_t afi
= SUBGRP_AFI(subgrp
);
1934 safi_t safi
= SUBGRP_SAFI(subgrp
);
1935 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1937 if (!ADVERTISE_MAP_NAME(filter
))
1940 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1943 peer
->advmap_table_change
= true;
1947 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1949 if (family
== AF_INET
) {
1950 attr
->nexthop
.s_addr
= INADDR_ANY
;
1951 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1953 if (family
== AF_INET6
)
1954 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1955 if (family
== AF_EVPN
)
1956 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1959 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1960 struct update_subgroup
*subgrp
,
1961 const struct prefix
*p
, struct attr
*attr
,
1962 struct attr
*post_attr
)
1964 struct bgp_filter
*filter
;
1967 struct peer
*onlypeer
;
1969 struct attr
*piattr
;
1970 route_map_result_t ret
;
1975 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1976 bool nh_reset
= false;
1979 if (DISABLE_BGP_ANNOUNCE
)
1982 afi
= SUBGRP_AFI(subgrp
);
1983 safi
= SUBGRP_SAFI(subgrp
);
1984 peer
= SUBGRP_PEER(subgrp
);
1986 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1987 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1990 filter
= &peer
->filter
[afi
][safi
];
1991 bgp
= SUBGRP_INST(subgrp
);
1992 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1995 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
1996 peer
->pmax_out
[afi
][safi
] != 0 &&
1997 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
1998 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
1999 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
2000 zlog_debug("%s reached maximum prefix to be send (%u)",
2001 peer
->host
, peer
->pmax_out
[afi
][safi
]);
2006 #ifdef ENABLE_BGP_VNC
2007 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
2008 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
2009 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
2012 * direct and direct_ext type routes originate internally even
2013 * though they can have peer pointers that reference other
2016 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2022 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
2023 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
2024 && (pi
->type
== ZEBRA_ROUTE_BGP
)
2025 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2027 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2032 /* With addpath we may be asked to TX all kinds of paths so make sure
2034 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
2035 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
2036 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
2040 /* If this is not the bestpath then check to see if there is an enabled
2042 * feature that requires us to advertise it */
2043 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2044 if (!bgp_addpath_capable(pi
, peer
, afi
, safi
))
2047 /* Aggregate-address suppress check. */
2048 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
2052 * If we are doing VRF 2 VRF leaking via the import
2053 * statement, we want to prevent the route going
2054 * off box as that the RT and RD created are localy
2055 * significant and globaly useless.
2057 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
2058 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
2061 /* If it's labeled safi, make sure the route has a valid label. */
2062 if (safi
== SAFI_LABELED_UNICAST
) {
2063 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
2064 if (!bgp_is_valid_label(&label
)) {
2065 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2066 zlog_debug("u%" PRIu64
":s%" PRIu64
2067 " %pFX is filtered - no label (%p)",
2068 subgrp
->update_group
->id
, subgrp
->id
,
2074 /* Do not send back route to sender. */
2075 if (onlypeer
&& from
== onlypeer
) {
2079 /* Do not send the default route in the BGP table if the neighbor is
2080 * configured for default-originate */
2081 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2082 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2083 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2085 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2089 /* Transparency check. */
2090 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2091 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2096 /* If community is not disabled check the no-export and local. */
2097 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2098 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2099 zlog_debug("%s: community filter check fail for %pFX",
2104 /* If the attribute has originator-id and it is same as remote
2106 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2107 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2108 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2110 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2115 /* ORF prefix-list filter check */
2116 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2117 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2118 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2119 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2120 if (peer
->orf_plist
[afi
][safi
]) {
2121 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2123 if (bgp_debug_update(NULL
, p
,
2124 subgrp
->update_group
, 0))
2126 "%pBP [Update:SEND] %pFX is filtered via ORF",
2132 /* Output filter check. */
2133 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2134 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2135 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2140 /* AS path loop check. */
2141 if (peer
->as_path_loop_detection
&&
2142 aspath_loop_check(piattr
->aspath
, peer
->as
)) {
2143 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2145 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2150 /* If we're a CONFED we need to loop check the CONFED ID too */
2151 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2152 if (aspath_loop_check_confed(piattr
->aspath
, bgp
->confed_id
)) {
2153 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2155 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2156 peer
, bgp
->confed_id
);
2161 /* Route-Reflect check. */
2162 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2167 /* IBGP reflection check. */
2168 if (reflect
&& !samepeer_safe
) {
2169 /* A route from a Client peer. */
2170 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2171 PEER_FLAG_REFLECTOR_CLIENT
)) {
2172 /* Reflect to all the Non-Client peers and also to the
2173 Client peers other than the originator. Originator
2175 is already done. So there is noting to do. */
2176 /* no bgp client-to-client reflection check. */
2177 if (CHECK_FLAG(bgp
->flags
,
2178 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2179 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2180 PEER_FLAG_REFLECTOR_CLIENT
))
2183 /* A route from a Non-client peer. Reflect to all other
2185 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2186 PEER_FLAG_REFLECTOR_CLIENT
))
2191 /* For modify attribute, copy it to temporary structure.
2192 * post_attr comes from BGP conditional advertisements, where
2193 * attributes are already processed by advertise-map route-map,
2194 * and this needs to be saved instead of overwriting from the
2202 /* If local-preference is not set. */
2203 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2204 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2205 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2206 attr
->local_pref
= bgp
->default_local_pref
;
2209 /* If originator-id is not set and the route is to be reflected,
2210 set the originator id */
2212 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2213 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2214 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2217 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2219 if (peer
->sort
== BGP_PEER_EBGP
2220 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2221 if (from
!= bgp
->peer_self
&& !transparent
2222 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2223 PEER_FLAG_MED_UNCHANGED
))
2225 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2228 /* Since the nexthop attribute can vary per peer, it is not explicitly
2230 * in announce check, only certain flags and length (or number of
2232 * -- for IPv6/MP_REACH) are set here in order to guide the update
2234 * code in setting the nexthop(s) on a per peer basis in
2236 * Typically, the source nexthop in the attribute is preserved but in
2238 * scenarios where we know it will always be overwritten, we reset the
2239 * nexthop to "0" in an attempt to achieve better Update packing. An
2240 * example of this is when a prefix from each of 2 IBGP peers needs to
2242 * announced to an EBGP peer (and they have the same attributes barring
2246 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2248 #define NEXTHOP_IS_V6 \
2249 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2250 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2251 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2252 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2254 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2256 * the peer (group) is configured to receive link-local nexthop
2258 * and it is available in the prefix OR we're not reflecting the route,
2259 * link-local nexthop address is valid and
2260 * the peer (group) to whom we're going to announce is on a shared
2262 * and this is either a self-originated route or the peer is EBGP.
2263 * By checking if nexthop LL address is valid we are sure that
2264 * we do not announce LL address as `::`.
2266 if (NEXTHOP_IS_V6
) {
2267 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2268 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2269 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2270 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2271 || (!reflect
&& !transparent
2272 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2273 && peer
->shared_network
2274 && (from
== bgp
->peer_self
2275 || peer
->sort
== BGP_PEER_EBGP
))) {
2276 if (safi
== SAFI_MPLS_VPN
)
2277 attr
->mp_nexthop_len
=
2278 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
;
2280 attr
->mp_nexthop_len
=
2281 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2284 /* Clear off link-local nexthop in source, whenever it is not
2286 * ensure more prefixes share the same attribute for
2289 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2290 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2291 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2294 if (bgp_check_role_applicability(afi
, safi
) &&
2295 bgp_otc_egress(peer
, attr
))
2298 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2299 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2301 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2302 filter
->advmap
.aname
&&
2303 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2304 struct bgp_path_info rmap_path
= {0};
2305 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2306 struct attr dummy_attr
= *attr
;
2308 /* Fill temp path_info */
2309 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2310 pi
, peer
, &dummy_attr
);
2312 struct route_map
*amap
=
2313 route_map_lookup_by_name(filter
->advmap
.aname
);
2315 ret
= route_map_apply(amap
, p
, &rmap_path
);
2317 bgp_attr_flush(&dummy_attr
);
2320 * The conditional advertisement mode is Withdraw and this
2321 * prefix is a conditional prefix. Don't advertise it
2323 if (ret
== RMAP_PERMITMATCH
)
2327 /* Route map & unsuppress-map apply. */
2329 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2330 struct bgp_path_info rmap_path
= {0};
2331 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2332 struct attr dummy_attr
= {0};
2334 /* Fill temp path_info */
2335 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2338 /* don't confuse inbound and outbound setting */
2339 RESET_FLAG(attr
->rmap_change_flags
);
2342 * The route reflector is not allowed to modify the attributes
2343 * of the reflected IBGP routes unless explicitly allowed.
2345 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2346 && !CHECK_FLAG(bgp
->flags
,
2347 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2349 rmap_path
.attr
= &dummy_attr
;
2352 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2354 if (bgp_path_suppressed(pi
))
2355 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2358 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2361 bgp_attr_flush(&dummy_attr
);
2362 peer
->rmap_type
= 0;
2364 if (ret
== RMAP_DENYMATCH
) {
2365 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2367 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2368 peer
, p
, ROUTE_MAP_OUT_NAME(filter
));
2369 bgp_attr_flush(rmap_path
.attr
);
2374 /* RFC 8212 to prevent route leaks.
2375 * This specification intends to improve this situation by requiring the
2376 * explicit configuration of both BGP Import and Export Policies for any
2377 * External BGP (EBGP) session such as customers, peers, or
2378 * confederation boundaries for all enabled address families. Through
2379 * codification of the aforementioned requirement, operators will
2380 * benefit from consistent behavior across different BGP
2383 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2384 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2385 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2386 NULL
) > FIFTEENMINUTE2USEC
||
2387 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2389 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2390 monotime(&bgp
->ebgprequirespolicywarning
);
2395 /* draft-ietf-idr-deprecate-as-set-confed-set
2396 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2397 * Eventually, This document (if approved) updates RFC 4271
2398 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2399 * and obsoletes RFC 6472.
2401 if (peer
->bgp
->reject_as_sets
)
2402 if (aspath_check_as_sets(attr
->aspath
))
2405 /* If neighbor soo is configured, then check if the route has
2406 * SoO extended community and validate against the configured
2407 * one. If they match, do not announce, to prevent routing
2410 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2411 peer
->soo
[afi
][safi
]) {
2412 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2413 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2415 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2416 ECOMMUNITY_SITE_ORIGIN
) ||
2417 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2418 ECOMMUNITY_SITE_ORIGIN
) ||
2419 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2420 ECOMMUNITY_SITE_ORIGIN
)) &&
2421 ecommunity_include(ecomm
, ecomm_soo
)) {
2422 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2424 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2425 peer
, p
, ecommunity_str(ecomm_soo
));
2430 /* Codification of AS 0 Processing */
2431 if (aspath_check_as_zero(attr
->aspath
))
2434 if (bgp_in_graceful_shutdown(bgp
)) {
2435 if (peer
->sort
== BGP_PEER_IBGP
2436 || peer
->sort
== BGP_PEER_CONFED
) {
2437 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2438 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2440 bgp_attr_add_gshut_community(attr
);
2444 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2445 * Capability" to a neighbor MUST perform the following upon receiving
2446 * a route from that neighbor with the "LLGR_STALE" community, or upon
2447 * attaching the "LLGR_STALE" community itself per Section 4.2:
2449 * The route SHOULD NOT be advertised to any neighbor from which the
2450 * Long-lived Graceful Restart Capability has not been received.
2452 if (bgp_attr_get_community(attr
) &&
2453 community_include(bgp_attr_get_community(attr
),
2454 COMMUNITY_LLGR_STALE
) &&
2455 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2456 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2459 /* After route-map has been applied, we check to see if the nexthop to
2460 * be carried in the attribute (that is used for the announcement) can
2461 * be cleared off or not. We do this in all cases where we would be
2462 * setting the nexthop to "ourselves". For IPv6, we only need to
2464 * the global nexthop here; the link-local nexthop would have been
2466 * already, and if not, it is required by the update formation code.
2467 * Also see earlier comments in this function.
2470 * If route-map has performed some operation on the nexthop or the peer
2471 * configuration says to pass it unchanged, we cannot reset the nexthop
2472 * here, so only attempt to do it if these aren't true. Note that the
2473 * route-map handler itself might have cleared the nexthop, if for
2475 * it is configured as 'peer-address'.
2477 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2478 piattr
->rmap_change_flags
)
2480 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2481 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2482 /* We can reset the nexthop, if setting (or forcing) it to
2484 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2485 PEER_FLAG_NEXTHOP_SELF
)
2486 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2487 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2489 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2490 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2491 subgroup_announce_reset_nhop(
2492 (peer_cap_enhe(peer
, afi
, safi
)
2498 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2499 /* Can also reset the nexthop if announcing to EBGP, but
2501 * no peer in the subgroup is on a shared subnet.
2502 * Note: 3rd party nexthop currently implemented for
2505 if ((p
->family
== AF_INET
) &&
2506 (!bgp_subgrp_multiaccess_check_v4(
2509 subgroup_announce_reset_nhop(
2510 (peer_cap_enhe(peer
, afi
, safi
)
2517 if ((p
->family
== AF_INET6
) &&
2518 (!bgp_subgrp_multiaccess_check_v6(
2519 piattr
->mp_nexthop_global
,
2521 subgroup_announce_reset_nhop(
2522 (peer_cap_enhe(peer
, afi
, safi
)
2531 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2533 * This flag is used for leaked vpn-vrf routes
2535 int family
= p
->family
;
2537 if (peer_cap_enhe(peer
, afi
, safi
))
2540 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2542 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2543 __func__
, p
, family2str(family
));
2544 subgroup_announce_reset_nhop(family
, attr
);
2549 /* If IPv6/MP and nexthop does not have any override and happens
2551 * be a link-local address, reset it so that we don't pass along
2553 * source's link-local IPv6 address to recipients who may not be
2555 * the same interface.
2557 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2558 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2559 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2564 /* If this is an iBGP, send Origin Validation State (OVS)
2565 * extended community (rfc8097).
2567 if (peer
->sort
== BGP_PEER_IBGP
) {
2568 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2570 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2572 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2573 bgp_attr_set_ecommunity(
2574 attr
, ecommunity_add_origin_validation_state(
2576 bgp_attr_get_ecommunity(attr
)));
2580 * When the next hop is set to ourselves, if all multipaths have
2581 * link-bandwidth announce the cumulative bandwidth as that makes
2582 * the most sense. However, don't modify if the link-bandwidth has
2583 * been explicitly set by user policy.
2586 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2587 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2588 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2589 bgp_attr_set_ecommunity(
2591 ecommunity_replace_linkbw(
2592 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2595 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2600 static void bgp_route_select_timer_expire(struct thread
*thread
)
2602 struct afi_safi_info
*info
;
2607 info
= THREAD_ARG(thread
);
2612 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2613 XFREE(MTYPE_TMP
, info
);
2615 /* Best path selection */
2616 bgp_best_path_select_defer(bgp
, afi
, safi
);
2619 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2620 struct bgp_maxpaths_cfg
*mpath_cfg
,
2621 struct bgp_path_info_pair
*result
, afi_t afi
,
2624 struct bgp_path_info
*new_select
;
2625 struct bgp_path_info
*old_select
;
2626 struct bgp_path_info
*pi
;
2627 struct bgp_path_info
*pi1
;
2628 struct bgp_path_info
*pi2
;
2629 struct bgp_path_info
*nextpi
= NULL
;
2630 int paths_eq
, do_mpath
, debug
;
2631 struct list mp_list
;
2632 char pfx_buf
[PREFIX2STR_BUFFER
];
2633 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2635 bgp_mp_list_init(&mp_list
);
2637 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2639 debug
= bgp_debug_bestpath(dest
);
2642 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2644 dest
->reason
= bgp_path_selection_none
;
2645 /* bgp deterministic-med */
2647 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2649 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2650 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2652 bgp_path_info_unset_flag(dest
, pi1
,
2653 BGP_PATH_DMED_SELECTED
);
2655 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2657 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2659 if (BGP_PATH_HOLDDOWN(pi1
))
2661 if (pi1
->peer
!= bgp
->peer_self
)
2662 if (!peer_established(pi1
->peer
))
2667 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2668 if (CHECK_FLAG(pi2
->flags
,
2669 BGP_PATH_DMED_CHECK
))
2671 if (BGP_PATH_HOLDDOWN(pi2
))
2673 if (pi2
->peer
!= bgp
->peer_self
2676 PEER_STATUS_NSF_WAIT
))
2677 if (pi2
->peer
->status
2681 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2683 && !aspath_cmp_left_confed(
2688 if (bgp_path_info_cmp(
2689 bgp
, pi2
, new_select
,
2690 &paths_eq
, mpath_cfg
, debug
,
2693 bgp_path_info_unset_flag(
2695 BGP_PATH_DMED_SELECTED
);
2699 bgp_path_info_set_flag(
2700 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2703 bgp_path_info_set_flag(dest
, new_select
,
2704 BGP_PATH_DMED_CHECK
);
2705 bgp_path_info_set_flag(dest
, new_select
,
2706 BGP_PATH_DMED_SELECTED
);
2709 bgp_path_info_path_with_addpath_rx_str(
2710 new_select
, path_buf
, sizeof(path_buf
));
2712 "%pBD(%s): %s is the bestpath from AS %u",
2713 dest
, bgp
->name_pretty
, path_buf
,
2714 aspath_get_first_as(
2715 new_select
->attr
->aspath
));
2720 /* Check old selected route and new selected route. */
2723 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2724 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2725 enum bgp_path_selection_reason reason
;
2727 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2730 if (BGP_PATH_HOLDDOWN(pi
)) {
2731 /* reap REMOVED routes, if needs be
2732 * selected route must stay for a while longer though
2734 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2735 && (pi
!= old_select
))
2736 bgp_path_info_reap(dest
, pi
);
2739 zlog_debug("%s: pi %p in holddown", __func__
,
2745 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2746 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2747 if (!peer_established(pi
->peer
)) {
2751 "%s: pi %p non self peer %s not estab state",
2752 __func__
, pi
, pi
->peer
->host
);
2757 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2758 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2759 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2761 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2765 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2767 reason
= dest
->reason
;
2768 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2769 debug
, pfx_buf
, afi
, safi
,
2771 if (new_select
== NULL
&&
2772 reason
!= bgp_path_selection_none
)
2773 dest
->reason
= reason
;
2778 /* Now that we know which path is the bestpath see if any of the other
2780 * qualify as multipaths
2784 bgp_path_info_path_with_addpath_rx_str(
2785 new_select
, path_buf
, sizeof(path_buf
));
2787 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2789 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2790 dest
, bgp
->name_pretty
, path_buf
,
2791 old_select
? old_select
->peer
->host
: "NONE");
2794 if (do_mpath
&& new_select
) {
2795 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2796 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2799 bgp_path_info_path_with_addpath_rx_str(
2800 pi
, path_buf
, sizeof(path_buf
));
2802 if (pi
== new_select
) {
2805 "%pBD(%s): %s is the bestpath, add to the multipath list",
2806 dest
, bgp
->name_pretty
,
2808 bgp_mp_list_add(&mp_list
, pi
);
2812 if (BGP_PATH_HOLDDOWN(pi
))
2815 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2816 && !CHECK_FLAG(pi
->peer
->sflags
,
2817 PEER_STATUS_NSF_WAIT
))
2818 if (!peer_established(pi
->peer
))
2821 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2824 "%pBD: %s has the same nexthop as the bestpath, skip it",
2829 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2830 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2836 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2838 bgp_mp_list_add(&mp_list
, pi
);
2843 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2845 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2846 bgp_mp_list_clear(&mp_list
);
2848 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2850 result
->old
= old_select
;
2851 result
->new = new_select
;
2857 * A new route/change in bestpath of an existing route. Evaluate the path
2858 * for advertisement to the subgroup.
2860 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2861 struct bgp_path_info
*selected
,
2862 struct bgp_dest
*dest
,
2863 uint32_t addpath_tx_id
)
2865 const struct prefix
*p
;
2866 struct peer
*onlypeer
;
2873 p
= bgp_dest_get_prefix(dest
);
2874 afi
= SUBGRP_AFI(subgrp
);
2875 safi
= SUBGRP_SAFI(subgrp
);
2876 bgp
= SUBGRP_INST(subgrp
);
2877 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2880 if (BGP_DEBUG(update
, UPDATE_OUT
))
2881 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2883 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2884 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2885 PEER_STATUS_ORF_WAIT_REFRESH
))
2888 memset(&attr
, 0, sizeof(attr
));
2889 /* It's initialized in bgp_announce_check() */
2891 /* Announcement to the subgroup. If the route is filtered withdraw it.
2892 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2893 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2896 advertise
= bgp_check_advertise(bgp
, dest
);
2899 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2901 /* Route is selected, if the route is already installed
2902 * in FIB, then it is advertised
2905 if (!bgp_check_withdrawal(bgp
, dest
))
2906 bgp_adj_out_set_subgroup(
2907 dest
, subgrp
, &attr
, selected
);
2909 bgp_adj_out_unset_subgroup(
2910 dest
, subgrp
, 1, addpath_tx_id
);
2913 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2917 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2919 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2924 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2925 * This is called at the end of route processing.
2927 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2929 struct bgp_path_info
*pi
;
2931 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2932 if (BGP_PATH_HOLDDOWN(pi
))
2934 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2935 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2940 * Has the route changed from the RIB's perspective? This is invoked only
2941 * if the route selection returns the same best route as earlier - to
2942 * determine if we need to update zebra or not.
2944 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2946 struct bgp_path_info
*mpinfo
;
2948 /* If this is multipath, check all selected paths for any nexthop
2949 * change or attribute change. Some attribute changes (e.g., community)
2950 * aren't of relevance to the RIB, but we'll update zebra to ensure
2951 * we handle the case of BGP nexthop change. This is the behavior
2952 * when the best path has an attribute change anyway.
2954 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2955 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2956 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2960 * If this is multipath, check all selected paths for any nexthop change
2962 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2963 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2964 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2965 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2969 /* Nothing has changed from the RIB's perspective. */
2973 struct bgp_process_queue
{
2975 STAILQ_HEAD(, bgp_dest
) pqueue
;
2976 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2978 unsigned int queued
;
2981 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2982 safi_t safi
, struct bgp_dest
*dest
,
2983 struct bgp_path_info
*new_select
,
2984 struct bgp_path_info
*old_select
)
2986 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2988 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2991 if (advertise_type5_routes(bgp
, afi
) && new_select
2992 && is_route_injectable_into_evpn(new_select
)) {
2994 /* apply the route-map */
2995 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2996 route_map_result_t ret
;
2997 struct bgp_path_info rmap_path
;
2998 struct bgp_path_info_extra rmap_path_extra
;
2999 struct attr dummy_attr
;
3001 dummy_attr
= *new_select
->attr
;
3003 /* Fill temp path_info */
3004 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3005 new_select
, new_select
->peer
,
3008 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3010 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3013 if (ret
== RMAP_DENYMATCH
) {
3014 bgp_attr_flush(&dummy_attr
);
3015 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3018 bgp_evpn_advertise_type5_route(
3019 bgp
, p
, &dummy_attr
, afi
, safi
);
3021 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3024 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3025 && is_route_injectable_into_evpn(old_select
))
3026 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3030 * Utility to determine whether a particular path_info should use
3031 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3032 * in a path where we basically _know_ this is a BGP-LU route.
3034 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
3036 /* Certain types get imp null; so do paths where the nexthop is
3039 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3040 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3041 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3043 else if (new_select
->extra
== NULL
||
3044 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
3045 /* TODO -- should be configurable? */
3052 * old_select = The old best path
3053 * new_select = the new best path
3055 * if (!old_select && new_select)
3056 * We are sending new information on.
3058 * if (old_select && new_select) {
3059 * if (new_select != old_select)
3060 * We have a new best path send a change
3062 * We've received a update with new attributes that needs
3066 * if (old_select && !new_select)
3067 * We have no eligible route that we can announce or the rn
3070 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3071 afi_t afi
, safi_t safi
)
3073 struct bgp_path_info
*new_select
;
3074 struct bgp_path_info
*old_select
;
3075 struct bgp_path_info_pair old_and_new
;
3078 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3080 debug
= bgp_debug_bestpath(dest
);
3083 "%s: bgp delete in progress, ignoring event, p=%pBD",
3087 /* Is it end of initial update? (after startup) */
3089 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3090 sizeof(bgp
->update_delay_zebra_resume_time
));
3092 bgp
->main_zebra_update_hold
= 0;
3093 FOREACH_AFI_SAFI (afi
, safi
) {
3094 if (bgp_fibupd_safi(safi
))
3095 bgp_zebra_announce_table(bgp
, afi
, safi
);
3097 bgp
->main_peers_update_hold
= 0;
3099 bgp_start_routeadv(bgp
);
3103 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3105 debug
= bgp_debug_bestpath(dest
);
3107 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__
,
3108 dest
, bgp
->name_pretty
, afi2str(afi
),
3111 /* The best path calculation for the route is deferred if
3112 * BGP_NODE_SELECT_DEFER is set
3114 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3115 if (BGP_DEBUG(update
, UPDATE_OUT
))
3116 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
3120 /* Best path selection. */
3121 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3123 old_select
= old_and_new
.old
;
3124 new_select
= old_and_new
.new;
3126 /* Do we need to allocate or free labels?
3127 * Right now, since we only deal with per-prefix labels, it is not
3128 * necessary to do this upon changes to best path. Exceptions:
3129 * - label index has changed -> recalculate resulting label
3130 * - path_info sub_type changed -> switch to/from implicit-null
3131 * - no valid label (due to removed static label binding) -> get new one
3133 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3136 || bgp_label_index_differs(new_select
, old_select
)
3137 || new_select
->sub_type
!= old_select
->sub_type
3138 || !bgp_is_valid_label(&dest
->local_label
)) {
3139 /* Enforced penultimate hop popping:
3140 * implicit-null for local routes, aggregate
3141 * and redistributed routes
3143 if (bgp_lu_need_imp_null(new_select
)) {
3146 BGP_NODE_REGISTERED_FOR_LABEL
)
3149 BGP_NODE_LABEL_REQUESTED
))
3150 bgp_unregister_for_label(dest
);
3151 dest
->local_label
= mpls_lse_encode(
3152 MPLS_LABEL_IMPLICIT_NULL
, 0, 0,
3154 bgp_set_valid_label(&dest
->local_label
);
3156 bgp_register_for_label(dest
,
3159 } else if (CHECK_FLAG(dest
->flags
,
3160 BGP_NODE_REGISTERED_FOR_LABEL
)
3161 || CHECK_FLAG(dest
->flags
,
3162 BGP_NODE_LABEL_REQUESTED
)) {
3163 bgp_unregister_for_label(dest
);
3165 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3166 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3167 bgp_unregister_for_label(dest
);
3172 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3173 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3174 safi2str(safi
), old_select
, new_select
);
3176 /* If best route remains the same and this is not due to user-initiated
3177 * clear, see exactly what needs to be done.
3179 if (old_select
&& old_select
== new_select
3180 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3181 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3182 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3183 if (bgp_zebra_has_route_changed(old_select
)) {
3184 #ifdef ENABLE_BGP_VNC
3185 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3186 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3188 if (bgp_fibupd_safi(safi
)
3189 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3191 if (BGP_SUPPRESS_FIB_ENABLED(bgp
)
3192 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
3193 SET_FLAG(dest
->flags
,
3194 BGP_NODE_FIB_INSTALL_PENDING
);
3196 if (new_select
->type
== ZEBRA_ROUTE_BGP
3197 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3198 || new_select
->sub_type
3199 == BGP_ROUTE_IMPORTED
))
3201 bgp_zebra_announce(dest
, p
, old_select
,
3206 /* If there is a change of interest to peers, reannounce the
3208 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3209 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3210 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3211 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3213 /* unicast routes must also be annouced to
3214 * labeled-unicast update-groups */
3215 if (safi
== SAFI_UNICAST
)
3216 group_announce_route(bgp
, afi
,
3217 SAFI_LABELED_UNICAST
, dest
,
3220 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3221 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3224 /* advertise/withdraw type-5 routes */
3225 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3226 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3227 bgp_process_evpn_route_injection(
3228 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3230 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3231 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3232 bgp_zebra_clear_route_change_flags(dest
);
3233 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3237 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3239 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3241 /* bestpath has changed; bump version */
3242 if (old_select
|| new_select
) {
3243 bgp_bump_version(dest
);
3245 if (!bgp
->t_rmap_def_originate_eval
) {
3249 update_group_refresh_default_originate_route_map
,
3250 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3251 &bgp
->t_rmap_def_originate_eval
);
3256 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3259 zlog_debug("%s: setting SELECTED flag", __func__
);
3260 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3261 bgp_path_info_unset_flag(dest
, new_select
,
3262 BGP_PATH_ATTR_CHANGED
);
3263 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3264 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3267 #ifdef ENABLE_BGP_VNC
3268 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3269 if (old_select
!= new_select
) {
3271 vnc_import_bgp_exterior_del_route(bgp
, p
,
3273 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3276 vnc_import_bgp_exterior_add_route(bgp
, p
,
3278 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3284 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3286 /* unicast routes must also be annouced to labeled-unicast update-groups
3288 if (safi
== SAFI_UNICAST
)
3289 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3293 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3294 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3296 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3297 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3298 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3299 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3301 if (BGP_SUPPRESS_FIB_ENABLED(bgp
))
3302 SET_FLAG(dest
->flags
,
3303 BGP_NODE_FIB_INSTALL_PENDING
);
3305 /* if this is an evpn imported type-5 prefix,
3306 * we need to withdraw the route first to clear
3307 * the nh neigh and the RMAC entry.
3310 is_route_parent_evpn(old_select
))
3311 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3313 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3315 /* Withdraw the route from the kernel. */
3316 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3317 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3318 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3319 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3321 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3325 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3328 /* Clear any route change flags. */
3329 bgp_zebra_clear_route_change_flags(dest
);
3331 /* Reap old select bgp_path_info, if it has been removed */
3332 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3333 bgp_path_info_reap(dest
, old_select
);
3335 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3339 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3340 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3342 struct bgp_dest
*dest
;
3344 struct afi_safi_info
*thread_info
;
3346 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3347 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3349 thread_info
= THREAD_ARG(t
);
3350 XFREE(MTYPE_TMP
, thread_info
);
3351 THREAD_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3354 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3355 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3356 get_afi_safi_str(afi
, safi
, false),
3357 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3360 /* Process the route list */
3361 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3362 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3363 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3364 dest
= bgp_route_next(dest
)) {
3365 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3368 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3369 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3370 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3373 /* If iteration stopped before the entire table was traversed then the
3374 * node needs to be unlocked.
3377 bgp_dest_unlock_node(dest
);
3381 /* Send EOR message when all routes are processed */
3382 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3383 bgp_send_delayed_eor(bgp
);
3384 /* Send route processing complete message to RIB */
3385 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3386 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3390 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3392 thread_info
->afi
= afi
;
3393 thread_info
->safi
= safi
;
3394 thread_info
->bgp
= bgp
;
3396 /* If there are more routes to be processed, start the
3399 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3400 BGP_ROUTE_SELECT_DELAY
,
3401 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3404 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3406 struct bgp_process_queue
*pqnode
= data
;
3407 struct bgp
*bgp
= pqnode
->bgp
;
3408 struct bgp_table
*table
;
3409 struct bgp_dest
*dest
;
3412 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3413 bgp_process_main_one(bgp
, NULL
, 0, 0);
3414 /* should always have dedicated wq call */
3415 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3419 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3420 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3421 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3422 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3423 table
= bgp_dest_table(dest
);
3424 /* note, new DESTs may be added as part of processing */
3425 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3427 bgp_dest_unlock_node(dest
);
3428 bgp_table_unlock(table
);
3434 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3436 struct bgp_process_queue
*pqnode
= data
;
3438 bgp_unlock(pqnode
->bgp
);
3440 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3443 void bgp_process_queue_init(struct bgp
*bgp
)
3445 if (!bgp
->process_queue
) {
3448 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3449 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3452 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3453 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3454 bgp
->process_queue
->spec
.max_retries
= 0;
3455 bgp
->process_queue
->spec
.hold
= 50;
3456 /* Use a higher yield value of 50ms for main queue processing */
3457 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3460 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3462 struct bgp_process_queue
*pqnode
;
3464 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3465 sizeof(struct bgp_process_queue
));
3467 /* unlocked in bgp_processq_del */
3468 pqnode
->bgp
= bgp_lock(bgp
);
3469 STAILQ_INIT(&pqnode
->pqueue
);
3474 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3476 #define ARBITRARY_PROCESS_QLEN 10000
3477 struct work_queue
*wq
= bgp
->process_queue
;
3478 struct bgp_process_queue
*pqnode
;
3479 int pqnode_reuse
= 0;
3481 /* already scheduled for processing? */
3482 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3485 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3488 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3489 if (BGP_DEBUG(update
, UPDATE_OUT
))
3490 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3495 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3496 if (BGP_DEBUG(update
, UPDATE_OUT
))
3498 "Soft reconfigure table in progress for route %p",
3506 /* Add route nodes to an existing work queue item until reaching the
3507 limit only if is from the same BGP view and it's not an EOIU marker
3509 if (work_queue_item_count(wq
)) {
3510 struct work_queue_item
*item
= work_queue_last_item(wq
);
3511 pqnode
= item
->data
;
3513 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3514 || pqnode
->bgp
!= bgp
3515 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3516 pqnode
= bgp_processq_alloc(bgp
);
3520 pqnode
= bgp_processq_alloc(bgp
);
3521 /* all unlocked in bgp_process_wq */
3522 bgp_table_lock(bgp_dest_table(dest
));
3524 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3525 bgp_dest_lock_node(dest
);
3527 /* can't be enqueued twice */
3528 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3529 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3533 work_queue_add(wq
, pqnode
);
3538 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3540 struct bgp_process_queue
*pqnode
;
3542 if (bgp
->process_queue
== NULL
)
3545 pqnode
= bgp_processq_alloc(bgp
);
3547 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3548 work_queue_add(bgp
->process_queue
, pqnode
);
3551 static void bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3555 peer
= THREAD_ARG(thread
);
3556 peer
->t_pmax_restart
= NULL
;
3558 if (bgp_debug_neighbor_events(peer
))
3560 "%s Maximum-prefix restart timer expired, restore peering",
3563 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3564 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3567 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3571 bool filtered
= false;
3572 struct bgp_dest
*dest
;
3573 struct bgp_adj_in
*ain
;
3574 struct attr attr
= {};
3575 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3577 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3578 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3579 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3583 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3587 if (bgp_input_modifier(
3588 peer
, rn_p
, &attr
, afi
, safi
,
3589 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3597 bgp_attr_flush(&attr
);
3604 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3608 iana_safi_t pkt_safi
;
3609 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3610 PEER_FLAG_MAX_PREFIX_FORCE
))
3611 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3612 + peer
->pcount
[afi
][safi
]
3613 : peer
->pcount
[afi
][safi
];
3615 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3618 if (pcount
> peer
->pmax
[afi
][safi
]) {
3619 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3620 PEER_STATUS_PREFIX_LIMIT
)
3625 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3626 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3627 peer
->pmax
[afi
][safi
]);
3628 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3630 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3631 PEER_FLAG_MAX_PREFIX_WARNING
))
3634 /* Convert AFI, SAFI to values for packet. */
3635 pkt_afi
= afi_int2iana(afi
);
3636 pkt_safi
= safi_int2iana(safi
);
3640 ndata
[0] = (pkt_afi
>> 8);
3642 ndata
[2] = pkt_safi
;
3643 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3644 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3645 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3646 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3648 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3649 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3650 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3654 /* Dynamic peers will just close their connection. */
3655 if (peer_dynamic_neighbor(peer
))
3658 /* restart timer start */
3659 if (peer
->pmax_restart
[afi
][safi
]) {
3660 peer
->v_pmax_restart
=
3661 peer
->pmax_restart
[afi
][safi
] * 60;
3663 if (bgp_debug_neighbor_events(peer
))
3665 "%pBP Maximum-prefix restart timer started for %d secs",
3666 peer
, peer
->v_pmax_restart
);
3668 BGP_TIMER_ON(peer
->t_pmax_restart
,
3669 bgp_maximum_prefix_restart_timer
,
3670 peer
->v_pmax_restart
);
3675 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3676 PEER_STATUS_PREFIX_LIMIT
);
3679 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3680 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3681 PEER_STATUS_PREFIX_THRESHOLD
)
3686 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3687 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3688 peer
->pmax
[afi
][safi
]);
3689 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3690 PEER_STATUS_PREFIX_THRESHOLD
);
3692 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3693 PEER_STATUS_PREFIX_THRESHOLD
);
3697 /* Unconditionally remove the route from the RIB, without taking
3698 * damping into consideration (eg, because the session went down)
3700 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3701 struct peer
*peer
, afi_t afi
, safi_t safi
)
3704 struct bgp
*bgp
= NULL
;
3705 bool delete_route
= false;
3707 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3710 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3711 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3713 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3716 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3717 delete_route
= true;
3718 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3719 delete_route
= true;
3721 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3722 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3723 bgp
= pi
->peer
->bgp
;
3724 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3729 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3730 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3733 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3734 struct peer
*peer
, afi_t afi
, safi_t safi
,
3735 struct prefix_rd
*prd
)
3737 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3739 /* apply dampening, if result is suppressed, we'll be retaining
3740 * the bgp_path_info in the RIB for historical reference.
3742 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3743 && peer
->sort
== BGP_PEER_EBGP
)
3744 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3745 == BGP_DAMP_SUPPRESSED
) {
3746 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3751 #ifdef ENABLE_BGP_VNC
3752 if (safi
== SAFI_MPLS_VPN
) {
3753 struct bgp_dest
*pdest
= NULL
;
3754 struct bgp_table
*table
= NULL
;
3756 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3757 (struct prefix
*)prd
);
3758 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3759 table
= bgp_dest_get_bgp_table_info(pdest
);
3761 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3762 peer
->bgp
, prd
, table
, p
, pi
);
3764 bgp_dest_unlock_node(pdest
);
3766 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3767 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3769 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3770 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3775 /* If this is an EVPN route, process for un-import. */
3776 if (safi
== SAFI_EVPN
)
3777 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3779 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3782 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3783 struct peer
*peer
, struct attr
*attr
,
3784 struct bgp_dest
*dest
)
3786 struct bgp_path_info
*new;
3788 /* Make new BGP info. */
3789 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3791 new->instance
= instance
;
3792 new->sub_type
= sub_type
;
3795 new->uptime
= monotime(NULL
);
3800 /* Check if received nexthop is valid or not. */
3801 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3802 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3803 struct bgp_dest
*dest
)
3806 bool is_bgp_static_route
=
3807 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3811 * Only validated for unicast and multicast currently.
3812 * Also valid for EVPN where the nexthop is an IP address.
3813 * If we are a bgp static route being checked then there is
3814 * no need to check to see if the nexthop is martian as
3815 * that it should be ok.
3817 if (is_bgp_static_route
||
3818 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3821 /* If NEXT_HOP is present, validate it. */
3822 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3823 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3824 !ipv4_unicast_valid(&attr
->nexthop
) ||
3825 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3829 /* If MP_NEXTHOP is present, validate it. */
3830 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3831 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3832 * it is not an IPv6 link-local address.
3834 * If we receive an UPDATE with nexthop length set to 32 bytes
3835 * we shouldn't discard an UPDATE if it's set to (::).
3836 * The link-local (2st) is validated along the code path later.
3838 if (attr
->mp_nexthop_len
) {
3839 switch (attr
->mp_nexthop_len
) {
3840 case BGP_ATTR_NHLEN_IPV4
:
3841 case BGP_ATTR_NHLEN_VPNV4
:
3842 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3844 !ipv4_unicast_valid(
3845 &attr
->mp_nexthop_global_in
) ||
3846 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3850 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3851 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3852 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3853 &attr
->mp_nexthop_global
)
3854 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3855 || IN6_IS_ADDR_MULTICAST(
3856 &attr
->mp_nexthop_global
)
3857 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3860 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3861 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3862 || IN6_IS_ADDR_MULTICAST(
3863 &attr
->mp_nexthop_global
)
3864 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3877 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3879 struct community
*old
;
3880 struct community
*new;
3881 struct community
*merge
;
3882 struct community
*no_export
;
3884 old
= bgp_attr_get_community(attr
);
3885 no_export
= community_str2com("no-export");
3890 merge
= community_merge(community_dup(old
), no_export
);
3893 community_free(&old
);
3895 new = community_uniq_sort(merge
);
3896 community_free(&merge
);
3898 new = community_dup(no_export
);
3901 community_free(&no_export
);
3903 bgp_attr_set_community(attr
, new);
3906 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3907 struct attr
*attr
, const struct prefix
*prefix
,
3910 struct listnode
*node
, *nnode
;
3912 bool accept_own_found
= false;
3914 if (safi
!= SAFI_MPLS_VPN
)
3917 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3918 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3921 /* The route in question carries the ACCEPT_OWN community */
3922 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3923 struct community
*comm
= bgp_attr_get_community(attr
);
3925 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3926 accept_own_found
= true;
3929 /* The route in question is targeted to one or more destination VRFs
3930 * on the router (as determined by inspecting the Route Target(s)).
3932 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3933 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3936 if (accept_own_found
&&
3938 bgp
->vpn_policy
[afi
]
3939 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3940 bgp_attr_get_ecommunity(attr
))) {
3941 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3943 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3946 /* Treat this route as imported, because it's leaked
3947 * already from another VRF, and we got an updated
3948 * version from route-reflector with ACCEPT_OWN
3951 *sub_type
= BGP_ROUTE_IMPORTED
;
3960 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3961 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3962 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3963 uint32_t num_labels
, int soft_reconfig
,
3964 struct bgp_route_evpn
*evpn
)
3967 int aspath_loop_count
= 0;
3968 struct bgp_dest
*dest
;
3970 struct attr new_attr
;
3971 struct attr
*attr_new
;
3972 struct bgp_path_info
*pi
;
3973 struct bgp_path_info
*new = NULL
;
3974 struct bgp_path_info_extra
*extra
;
3976 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3978 int do_loop_check
= 1;
3979 int has_valid_label
= 0;
3981 bool force_evpn_import
= false;
3982 safi_t orig_safi
= safi
;
3983 bool leak_success
= true;
3986 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3987 char pfxprint
[PREFIX2STR_BUFFER
];
3989 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3990 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3994 #ifdef ENABLE_BGP_VNC
3995 int vnc_implicit_withdraw
= 0;
3998 const struct prefix
*bgp_nht_param_prefix
;
4000 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4001 if (orig_safi
== SAFI_LABELED_UNICAST
)
4002 safi
= SAFI_UNICAST
;
4004 memset(&new_attr
, 0, sizeof(new_attr
));
4005 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4006 new_attr
.label
= MPLS_INVALID_LABEL
;
4009 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4010 /* TODO: Check to see if we can get rid of "is_valid_label" */
4011 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4012 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4014 has_valid_label
= bgp_is_valid_label(label
);
4016 if (has_valid_label
)
4017 assert(label
!= NULL
);
4019 /* Update overlay index of the attribute */
4020 if (afi
== AFI_L2VPN
&& evpn
)
4021 memcpy(&attr
->evpn_overlay
, evpn
,
4022 sizeof(struct bgp_route_evpn
));
4024 /* When peer's soft reconfiguration enabled. Record input packet in
4027 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4028 && peer
!= bgp
->peer_self
)
4029 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4031 /* Update permitted loop count */
4032 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4033 allowas_in
= peer
->allowas_in
[afi
][safi
];
4035 /* Check previously received route. */
4036 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4037 if (pi
->peer
== peer
&& pi
->type
== type
4038 && pi
->sub_type
== sub_type
4039 && pi
->addpath_rx_id
== addpath_id
)
4042 /* AS path local-as loop check. */
4043 if (peer
->change_local_as
) {
4045 aspath_loop_count
= allowas_in
;
4046 else if (!CHECK_FLAG(peer
->flags
,
4047 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4048 aspath_loop_count
= 1;
4050 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4051 > aspath_loop_count
) {
4052 peer
->stat_pfx_aspath_loop
++;
4053 reason
= "as-path contains our own AS;";
4058 /* If the peer is configured for "allowas-in origin" and the last ASN in
4060 * as-path is our ASN then we do not need to call aspath_loop_check
4062 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4063 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4066 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4067 bgp_nht_param_prefix
= NULL
;
4069 bgp_nht_param_prefix
= p
;
4071 /* AS path loop check. */
4072 if (do_loop_check
) {
4073 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4074 peer
->allowas_in
[afi
][safi
]) {
4075 peer
->stat_pfx_aspath_loop
++;
4076 reason
= "as-path contains our own AS;";
4081 /* If we're a CONFED we need to loop check the CONFED ID too */
4082 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4083 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4084 peer
->allowas_in
[afi
][safi
]) {
4085 peer
->stat_pfx_aspath_loop
++;
4086 reason
= "as-path contains our own confed AS;";
4090 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4091 * enabled, then take care of that too.
4093 bool accept_own
= false;
4095 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4096 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4098 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4100 peer
->stat_pfx_originator_loop
++;
4101 reason
= "originator is us;";
4106 /* Route reflector cluster ID check. */
4107 if (bgp_cluster_filter(peer
, attr
)) {
4108 peer
->stat_pfx_cluster_loop
++;
4109 reason
= "reflected from the same cluster;";
4113 /* Apply incoming filter. */
4114 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4115 peer
->stat_pfx_filter
++;
4120 /* RFC 8212 to prevent route leaks.
4121 * This specification intends to improve this situation by requiring the
4122 * explicit configuration of both BGP Import and Export Policies for any
4123 * External BGP (EBGP) session such as customers, peers, or
4124 * confederation boundaries for all enabled address families. Through
4125 * codification of the aforementioned requirement, operators will
4126 * benefit from consistent behavior across different BGP
4129 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4130 if (!bgp_inbound_policy_exists(peer
,
4131 &peer
->filter
[afi
][safi
])) {
4132 reason
= "inbound policy missing";
4133 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4134 NULL
) > FIFTEENMINUTE2USEC
||
4135 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4137 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4138 monotime(&bgp
->ebgprequirespolicywarning
);
4143 /* draft-ietf-idr-deprecate-as-set-confed-set
4144 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4145 * Eventually, This document (if approved) updates RFC 4271
4146 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4147 * and obsoletes RFC 6472.
4149 if (peer
->bgp
->reject_as_sets
)
4150 if (aspath_check_as_sets(attr
->aspath
)) {
4152 "as-path contains AS_SET or AS_CONFED_SET type;";
4158 /* Apply incoming route-map.
4159 * NB: new_attr may now contain newly allocated values from route-map
4161 * commands, so we need bgp_attr_flush in the error paths, until we
4163 * the attr (which takes over the memory references) */
4164 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4167 peer
->stat_pfx_filter
++;
4168 reason
= "route-map;";
4169 bgp_attr_flush(&new_attr
);
4173 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4174 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4175 /* remove from RIB previous entry */
4176 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4179 if (peer
->sort
== BGP_PEER_EBGP
) {
4182 * A BGP speaker receiving an announcement tagged with the
4183 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4184 * NO_EXPORT community as defined in RFC1997, or a
4185 * similar community, to prevent propagation of the
4186 * prefix outside the local AS. The community to prevent
4187 * propagation SHOULD be chosen according to the operator's
4190 if (bgp_attr_get_community(&new_attr
) &&
4191 community_include(bgp_attr_get_community(&new_attr
),
4192 COMMUNITY_BLACKHOLE
))
4193 bgp_attr_add_no_export_community(&new_attr
);
4195 /* If we receive the graceful-shutdown community from an eBGP
4196 * peer we must lower local-preference */
4197 if (bgp_attr_get_community(&new_attr
) &&
4198 community_include(bgp_attr_get_community(&new_attr
),
4200 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4201 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4203 /* If graceful-shutdown is configured globally or
4204 * per neighbor, then add the GSHUT community to
4205 * all paths received from eBGP peers. */
4206 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4207 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4208 bgp_attr_add_gshut_community(&new_attr
);
4211 /* next hop check. */
4212 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4213 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4215 peer
->stat_pfx_nh_invalid
++;
4216 reason
= "martian or self next-hop;";
4217 bgp_attr_flush(&new_attr
);
4221 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4222 peer
->stat_pfx_nh_invalid
++;
4223 reason
= "self mac;";
4224 bgp_attr_flush(&new_attr
);
4228 if (bgp_check_role_applicability(afi
, safi
) &&
4229 bgp_otc_filter(peer
, &new_attr
)) {
4230 reason
= "failing otc validation";
4231 bgp_attr_flush(&new_attr
);
4234 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4236 * Suppress fib is enabled
4237 * BGP_OPT_NO_FIB is not enabled
4238 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4239 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4241 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
4242 && (sub_type
== BGP_ROUTE_NORMAL
)
4243 && (!bgp_option_check(BGP_OPT_NO_FIB
))
4244 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
4245 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
4247 /* If neighbor soo is configured, tag all incoming routes with
4248 * this SoO tag and then filter out advertisements in
4249 * subgroup_announce_check() if it matches the configured SoO
4250 * on the other peer.
4252 if (peer
->soo
[afi
][safi
]) {
4253 struct ecommunity
*old_ecomm
=
4254 bgp_attr_get_ecommunity(&new_attr
);
4255 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4256 struct ecommunity
*new_ecomm
;
4259 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4262 if (!old_ecomm
->refcnt
)
4263 ecommunity_free(&old_ecomm
);
4265 new_ecomm
= ecommunity_dup(ecomm_soo
);
4268 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4271 attr_new
= bgp_attr_intern(&new_attr
);
4273 /* If the update is implicit withdraw. */
4275 pi
->uptime
= monotime(NULL
);
4276 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4278 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4280 /* Same attribute comes in. */
4281 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4283 && (!has_valid_label
4284 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4285 num_labels
* sizeof(mpls_label_t
))
4287 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4288 BGP_CONFIG_DAMPENING
)
4289 && peer
->sort
== BGP_PEER_EBGP
4290 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4291 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4292 bgp_debug_rdpfxpath2str(
4293 afi
, safi
, prd
, p
, label
,
4294 num_labels
, addpath_id
? 1 : 0,
4295 addpath_id
, evpn
, pfx_buf
,
4297 zlog_debug("%pBP rcvd %s", peer
,
4301 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4302 != BGP_DAMP_SUPPRESSED
) {
4303 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4305 bgp_process(bgp
, dest
, afi
, safi
);
4307 } else /* Duplicate - odd */
4309 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4310 if (!peer
->rcvd_attr_printed
) {
4312 "%pBP rcvd UPDATE w/ attr: %s",
4314 peer
->rcvd_attr_str
);
4315 peer
->rcvd_attr_printed
= 1;
4318 bgp_debug_rdpfxpath2str(
4319 afi
, safi
, prd
, p
, label
,
4320 num_labels
, addpath_id
? 1 : 0,
4321 addpath_id
, evpn
, pfx_buf
,
4324 "%pBP rcvd %s...duplicate ignored",
4328 /* graceful restart STALE flag unset. */
4329 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4330 bgp_path_info_unset_flag(
4331 dest
, pi
, BGP_PATH_STALE
);
4332 bgp_dest_set_defer_flag(dest
, false);
4333 bgp_process(bgp
, dest
, afi
, safi
);
4337 bgp_dest_unlock_node(dest
);
4338 bgp_attr_unintern(&attr_new
);
4343 /* Withdraw/Announce before we fully processed the withdraw */
4344 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4345 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4346 bgp_debug_rdpfxpath2str(
4347 afi
, safi
, prd
, p
, label
, num_labels
,
4348 addpath_id
? 1 : 0, addpath_id
, evpn
,
4349 pfx_buf
, sizeof(pfx_buf
));
4351 "%pBP rcvd %s, flapped quicker than processing",
4355 bgp_path_info_restore(dest
, pi
);
4358 * If the BGP_PATH_REMOVED flag is set, then EVPN
4359 * routes would have been unimported already when a
4360 * prior BGP withdraw processing happened. Such routes
4361 * need to be imported again, so flag accordingly.
4363 force_evpn_import
= true;
4365 /* implicit withdraw, decrement aggregate and pcount
4366 * here. only if update is accepted, they'll increment
4369 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4372 /* Received Logging. */
4373 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4374 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4375 num_labels
, addpath_id
? 1 : 0,
4376 addpath_id
, evpn
, pfx_buf
,
4378 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4381 /* graceful restart STALE flag unset. */
4382 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4383 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4384 bgp_dest_set_defer_flag(dest
, false);
4387 /* The attribute is changed. */
4388 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4390 /* Update bgp route dampening information. */
4391 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4392 && peer
->sort
== BGP_PEER_EBGP
) {
4393 /* This is implicit withdraw so we should update
4396 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4397 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4399 #ifdef ENABLE_BGP_VNC
4400 if (safi
== SAFI_MPLS_VPN
) {
4401 struct bgp_dest
*pdest
= NULL
;
4402 struct bgp_table
*table
= NULL
;
4404 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4405 (struct prefix
*)prd
);
4406 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4407 table
= bgp_dest_get_bgp_table_info(pdest
);
4409 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4410 bgp
, prd
, table
, p
, pi
);
4412 bgp_dest_unlock_node(pdest
);
4414 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4415 && (safi
== SAFI_UNICAST
)) {
4416 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4418 * Implicit withdraw case.
4420 ++vnc_implicit_withdraw
;
4421 vnc_import_bgp_del_route(bgp
, p
, pi
);
4422 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4427 /* Special handling for EVPN update of an existing route. If the
4428 * extended community attribute has changed, we need to
4430 * the route using its existing extended community. It will be
4431 * subsequently processed for import with the new extended
4434 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4437 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4439 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4442 cmp
= ecommunity_cmp(
4443 bgp_attr_get_ecommunity(pi
->attr
),
4444 bgp_attr_get_ecommunity(attr_new
));
4446 if (bgp_debug_update(peer
, p
, NULL
, 1))
4448 "Change in EXT-COMM, existing %s new %s",
4450 bgp_attr_get_ecommunity(
4453 bgp_attr_get_ecommunity(
4455 if (safi
== SAFI_EVPN
)
4456 bgp_evpn_unimport_route(
4457 bgp
, afi
, safi
, p
, pi
);
4458 else /* SAFI_MPLS_VPN */
4459 vpn_leak_to_vrf_withdraw(bgp
,
4465 /* Update to new attribute. */
4466 bgp_attr_unintern(&pi
->attr
);
4467 pi
->attr
= attr_new
;
4469 /* Update MPLS label */
4470 if (has_valid_label
) {
4471 extra
= bgp_path_info_extra_get(pi
);
4472 if (extra
->label
!= label
) {
4473 memcpy(&extra
->label
, label
,
4474 num_labels
* sizeof(mpls_label_t
));
4475 extra
->num_labels
= num_labels
;
4477 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4478 bgp_set_valid_label(&extra
->label
[0]);
4481 /* Update SRv6 SID */
4482 if (attr
->srv6_l3vpn
) {
4483 extra
= bgp_path_info_extra_get(pi
);
4484 if (sid_diff(&extra
->sid
[0].sid
,
4485 &attr
->srv6_l3vpn
->sid
)) {
4486 sid_copy(&extra
->sid
[0].sid
,
4487 &attr
->srv6_l3vpn
->sid
);
4488 extra
->num_sids
= 1;
4490 extra
->sid
[0].loc_block_len
= 0;
4491 extra
->sid
[0].loc_node_len
= 0;
4492 extra
->sid
[0].func_len
= 0;
4493 extra
->sid
[0].arg_len
= 0;
4494 extra
->sid
[0].transposition_len
= 0;
4495 extra
->sid
[0].transposition_offset
= 0;
4497 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4498 extra
->sid
[0].loc_block_len
=
4499 attr
->srv6_l3vpn
->loc_block_len
;
4500 extra
->sid
[0].loc_node_len
=
4501 attr
->srv6_l3vpn
->loc_node_len
;
4502 extra
->sid
[0].func_len
=
4503 attr
->srv6_l3vpn
->func_len
;
4504 extra
->sid
[0].arg_len
=
4505 attr
->srv6_l3vpn
->arg_len
;
4506 extra
->sid
[0].transposition_len
=
4508 ->transposition_len
;
4509 extra
->sid
[0].transposition_offset
=
4511 ->transposition_offset
;
4514 } else if (attr
->srv6_vpn
) {
4515 extra
= bgp_path_info_extra_get(pi
);
4516 if (sid_diff(&extra
->sid
[0].sid
,
4517 &attr
->srv6_vpn
->sid
)) {
4518 sid_copy(&extra
->sid
[0].sid
,
4519 &attr
->srv6_vpn
->sid
);
4520 extra
->num_sids
= 1;
4524 #ifdef ENABLE_BGP_VNC
4525 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4526 && (safi
== SAFI_UNICAST
)) {
4527 if (vnc_implicit_withdraw
) {
4529 * Add back the route with its new attributes
4531 * The route is still selected, until the route
4533 * queued by bgp_process actually runs. We have
4535 * update to the VNC side immediately to avoid
4537 * configuration changes (e.g., route-map
4539 * trigger re-importation of the entire RIB.
4541 vnc_import_bgp_add_route(bgp
, p
, pi
);
4542 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4547 /* Update bgp route dampening information. */
4548 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4549 && peer
->sort
== BGP_PEER_EBGP
) {
4550 /* Now we do normal update dampening. */
4551 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4552 if (ret
== BGP_DAMP_SUPPRESSED
) {
4553 bgp_dest_unlock_node(dest
);
4558 /* Nexthop reachability check - for unicast and
4559 * labeled-unicast.. */
4560 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4561 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4562 || (safi
== SAFI_EVPN
&&
4563 bgp_evpn_is_prefix_nht_supported(p
))) {
4564 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4565 && peer
->ttl
== BGP_DEFAULT_TTL
4566 && !CHECK_FLAG(peer
->flags
,
4567 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4568 && !CHECK_FLAG(bgp
->flags
,
4569 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4574 struct bgp
*bgp_nexthop
= bgp
;
4576 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4577 bgp_nexthop
= pi
->extra
->bgp_orig
;
4579 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4581 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4582 safi
, pi
, NULL
, connected
,
4583 bgp_nht_param_prefix
) ||
4584 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4585 bgp_path_info_set_flag(dest
, pi
,
4588 if (BGP_DEBUG(nht
, NHT
)) {
4589 zlog_debug("%s(%pI4): NH unresolved",
4591 (in_addr_t
*)&attr_new
->nexthop
);
4593 bgp_path_info_unset_flag(dest
, pi
,
4598 bgp_path_info_set_flag(dest
, pi
,
4599 BGP_PATH_ACCEPT_OWN
);
4601 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4604 #ifdef ENABLE_BGP_VNC
4605 if (safi
== SAFI_MPLS_VPN
) {
4606 struct bgp_dest
*pdest
= NULL
;
4607 struct bgp_table
*table
= NULL
;
4609 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4610 (struct prefix
*)prd
);
4611 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4612 table
= bgp_dest_get_bgp_table_info(pdest
);
4614 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4615 bgp
, prd
, table
, p
, pi
);
4617 bgp_dest_unlock_node(pdest
);
4621 /* If this is an EVPN route and some attribute has changed,
4622 * or we are explicitly told to perform a route import, process
4623 * route for import. If the extended community has changed, we
4625 * have done the un-import earlier and the import would result
4627 * route getting injected into appropriate L2 VNIs. If it is
4629 * some other attribute change, the import will result in
4631 * the attributes for the route in the VNI(s).
4633 if (safi
== SAFI_EVPN
&&
4634 (!same_attr
|| force_evpn_import
) &&
4635 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4636 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4638 /* Process change. */
4639 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4641 bgp_process(bgp
, dest
, afi
, safi
);
4642 bgp_dest_unlock_node(dest
);
4644 if (SAFI_UNICAST
== safi
4645 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4646 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4648 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4650 if ((SAFI_MPLS_VPN
== safi
)
4651 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4652 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4655 #ifdef ENABLE_BGP_VNC
4656 if (SAFI_MPLS_VPN
== safi
) {
4657 mpls_label_t label_decoded
= decode_label(label
);
4659 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4660 type
, sub_type
, &label_decoded
);
4662 if (SAFI_ENCAP
== safi
) {
4663 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4664 type
, sub_type
, NULL
);
4667 if ((safi
== SAFI_MPLS_VPN
) &&
4668 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4669 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4671 bgp_unlink_nexthop(pi
);
4672 bgp_path_info_delete(dest
, pi
);
4675 } // End of implicit withdraw
4677 /* Received Logging. */
4678 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4679 if (!peer
->rcvd_attr_printed
) {
4680 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4681 peer
->rcvd_attr_str
);
4682 peer
->rcvd_attr_printed
= 1;
4685 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4686 addpath_id
? 1 : 0, addpath_id
, evpn
,
4687 pfx_buf
, sizeof(pfx_buf
));
4688 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4691 /* Make new BGP info. */
4692 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4694 /* Update MPLS label */
4695 if (has_valid_label
) {
4696 extra
= bgp_path_info_extra_get(new);
4697 if (extra
->label
!= label
) {
4698 memcpy(&extra
->label
, label
,
4699 num_labels
* sizeof(mpls_label_t
));
4700 extra
->num_labels
= num_labels
;
4702 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4703 bgp_set_valid_label(&extra
->label
[0]);
4706 /* Update SRv6 SID */
4707 if (safi
== SAFI_MPLS_VPN
) {
4708 extra
= bgp_path_info_extra_get(new);
4709 if (attr
->srv6_l3vpn
) {
4710 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4711 extra
->num_sids
= 1;
4713 extra
->sid
[0].loc_block_len
=
4714 attr
->srv6_l3vpn
->loc_block_len
;
4715 extra
->sid
[0].loc_node_len
=
4716 attr
->srv6_l3vpn
->loc_node_len
;
4717 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4718 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4719 extra
->sid
[0].transposition_len
=
4720 attr
->srv6_l3vpn
->transposition_len
;
4721 extra
->sid
[0].transposition_offset
=
4722 attr
->srv6_l3vpn
->transposition_offset
;
4723 } else if (attr
->srv6_vpn
) {
4724 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4725 extra
->num_sids
= 1;
4729 /* Nexthop reachability check. */
4730 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4731 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4732 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4733 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4734 && peer
->ttl
== BGP_DEFAULT_TTL
4735 && !CHECK_FLAG(peer
->flags
,
4736 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4737 && !CHECK_FLAG(bgp
->flags
,
4738 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4743 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4745 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4746 connected
, bgp_nht_param_prefix
) ||
4747 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4748 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4750 if (BGP_DEBUG(nht
, NHT
))
4751 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4752 &attr_new
->nexthop
);
4753 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4757 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4759 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4762 /* If maximum prefix count is configured and current prefix
4765 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4766 reason
= "maximum-prefix overflow";
4767 bgp_attr_flush(&new_attr
);
4772 new->addpath_rx_id
= addpath_id
;
4774 /* Increment prefix */
4775 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4777 /* Register new BGP information. */
4778 bgp_path_info_add(dest
, new);
4780 /* route_node_get lock */
4781 bgp_dest_unlock_node(dest
);
4783 #ifdef ENABLE_BGP_VNC
4784 if (safi
== SAFI_MPLS_VPN
) {
4785 struct bgp_dest
*pdest
= NULL
;
4786 struct bgp_table
*table
= NULL
;
4788 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4789 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4790 table
= bgp_dest_get_bgp_table_info(pdest
);
4792 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4793 bgp
, prd
, table
, p
, new);
4795 bgp_dest_unlock_node(pdest
);
4799 /* If this is an EVPN route, process for import. */
4800 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4801 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4803 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4805 /* Process change. */
4806 bgp_process(bgp
, dest
, afi
, safi
);
4808 if (SAFI_UNICAST
== safi
4809 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4810 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4811 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4813 if ((SAFI_MPLS_VPN
== safi
)
4814 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4815 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4817 #ifdef ENABLE_BGP_VNC
4818 if (SAFI_MPLS_VPN
== safi
) {
4819 mpls_label_t label_decoded
= decode_label(label
);
4821 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4822 sub_type
, &label_decoded
);
4824 if (SAFI_ENCAP
== safi
) {
4825 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4829 if ((safi
== SAFI_MPLS_VPN
) &&
4830 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4831 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4833 bgp_unlink_nexthop(new);
4834 bgp_path_info_delete(dest
, new);
4839 /* This BGP update is filtered. Log the reason then update BGP
4843 bgp_unlink_nexthop(new);
4844 bgp_path_info_delete(dest
, new);
4845 bgp_path_info_extra_free(&new->extra
);
4846 XFREE(MTYPE_BGP_ROUTE
, new);
4849 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4851 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4852 if (!peer
->rcvd_attr_printed
) {
4853 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4854 peer
->rcvd_attr_str
);
4855 peer
->rcvd_attr_printed
= 1;
4858 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4859 addpath_id
? 1 : 0, addpath_id
, evpn
,
4860 pfx_buf
, sizeof(pfx_buf
));
4861 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4862 peer
, pfx_buf
, reason
);
4866 /* If this is an EVPN route, un-import it as it is now filtered.
4868 if (safi
== SAFI_EVPN
)
4869 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4871 if (SAFI_UNICAST
== safi
4872 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4873 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4875 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4877 if ((SAFI_MPLS_VPN
== safi
)
4878 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4880 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4883 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4886 bgp_dest_unlock_node(dest
);
4888 #ifdef ENABLE_BGP_VNC
4890 * Filtered update is treated as an implicit withdrawal (see
4892 * a few lines above)
4894 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4895 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4903 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4904 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4905 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4906 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4909 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4910 struct bgp_dest
*dest
;
4911 struct bgp_path_info
*pi
;
4913 #ifdef ENABLE_BGP_VNC
4914 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4915 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4923 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4925 /* If peer is soft reconfiguration enabled. Record input packet for
4926 * further calculation.
4928 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4929 * routes that are filtered. This tanks out Quagga RS pretty badly due
4931 * the iteration over all RS clients.
4932 * Since we need to remove the entry from adj_in anyway, do that first
4934 * if there was no entry, we don't need to do anything more.
4936 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4937 && peer
!= bgp
->peer_self
)
4938 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4939 peer
->stat_pfx_dup_withdraw
++;
4941 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4942 bgp_debug_rdpfxpath2str(
4943 afi
, safi
, prd
, p
, label
, num_labels
,
4944 addpath_id
? 1 : 0, addpath_id
, NULL
,
4945 pfx_buf
, sizeof(pfx_buf
));
4947 "%s withdrawing route %s not in adj-in",
4948 peer
->host
, pfx_buf
);
4950 bgp_dest_unlock_node(dest
);
4954 /* Lookup withdrawn route. */
4955 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4956 if (pi
->peer
== peer
&& pi
->type
== type
4957 && pi
->sub_type
== sub_type
4958 && pi
->addpath_rx_id
== addpath_id
)
4962 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4963 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4964 addpath_id
? 1 : 0, addpath_id
, NULL
,
4965 pfx_buf
, sizeof(pfx_buf
));
4966 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
4970 /* Withdraw specified route from routing table. */
4971 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4972 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4973 if (SAFI_UNICAST
== safi
4974 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4975 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4976 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4978 if ((SAFI_MPLS_VPN
== safi
)
4979 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4981 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4983 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4984 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4985 addpath_id
? 1 : 0, addpath_id
, NULL
,
4986 pfx_buf
, sizeof(pfx_buf
));
4987 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4990 /* Unlock bgp_node_get() lock. */
4991 bgp_dest_unlock_node(dest
);
4996 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4999 struct update_subgroup
*subgrp
;
5000 subgrp
= peer_subgroup(peer
, afi
, safi
);
5001 subgroup_default_originate(subgrp
, withdraw
);
5006 * bgp_stop_announce_route_timer
5008 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5010 if (!paf
->t_announce_route
)
5013 THREAD_OFF(paf
->t_announce_route
);
5017 * bgp_announce_route_timer_expired
5019 * Callback that is invoked when the route announcement timer for a
5022 static void bgp_announce_route_timer_expired(struct thread
*t
)
5024 struct peer_af
*paf
;
5027 paf
= THREAD_ARG(t
);
5030 if (!peer_established(peer
))
5033 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5036 peer_af_announce_route(paf
, 1);
5038 /* Notify BGP conditional advertisement scanner percess */
5039 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5043 * bgp_announce_route
5045 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5047 * if force is true we will force an update even if the update
5048 * limiting code is attempted to kick in.
5050 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5052 struct peer_af
*paf
;
5053 struct update_subgroup
*subgrp
;
5055 paf
= peer_af_find(peer
, afi
, safi
);
5058 subgrp
= PAF_SUBGRP(paf
);
5061 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5062 * or a refresh has already been triggered.
5064 if (!subgrp
|| paf
->t_announce_route
)
5068 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5071 * Start a timer to stagger/delay the announce. This serves
5072 * two purposes - announcement can potentially be combined for
5073 * multiple peers and the announcement doesn't happen in the
5076 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5077 (subgrp
->peer_count
== 1)
5078 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5079 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5080 &paf
->t_announce_route
);
5084 * Announce routes from all AF tables to a peer.
5086 * This should ONLY be called when there is a need to refresh the
5087 * routes to the peer based on a policy change for this peer alone
5088 * or a route refresh request received from the peer.
5089 * The operation will result in splitting the peer from its existing
5090 * subgroups and putting it in new subgroups.
5092 void bgp_announce_route_all(struct peer
*peer
)
5097 FOREACH_AFI_SAFI (afi
, safi
)
5098 bgp_announce_route(peer
, afi
, safi
, false);
5101 /* Flag or unflag bgp_dest to determine whether it should be treated by
5102 * bgp_soft_reconfig_table_task.
5103 * Flag if flag is true. Unflag if flag is false.
5105 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5107 struct bgp_dest
*dest
;
5108 struct bgp_adj_in
*ain
;
5113 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5114 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5115 if (ain
->peer
!= NULL
)
5118 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5119 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5121 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5125 static int bgp_soft_reconfig_table_update(struct peer
*peer
,
5126 struct bgp_dest
*dest
,
5127 struct bgp_adj_in
*ain
, afi_t afi
,
5128 safi_t safi
, struct prefix_rd
*prd
)
5130 struct bgp_path_info
*pi
;
5131 uint32_t num_labels
= 0;
5132 mpls_label_t
*label_pnt
= NULL
;
5133 struct bgp_route_evpn evpn
;
5135 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5136 if (pi
->peer
== peer
)
5139 if (pi
&& pi
->extra
)
5140 num_labels
= pi
->extra
->num_labels
;
5142 label_pnt
= &pi
->extra
->label
[0];
5144 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5147 memset(&evpn
, 0, sizeof(evpn
));
5149 return bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5150 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
5151 BGP_ROUTE_NORMAL
, prd
, label_pnt
, num_labels
, 1,
5155 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5156 struct bgp_table
*table
,
5157 struct prefix_rd
*prd
)
5160 struct bgp_dest
*dest
;
5161 struct bgp_adj_in
*ain
;
5164 table
= peer
->bgp
->rib
[afi
][safi
];
5166 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5167 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5168 if (ain
->peer
!= peer
)
5171 ret
= bgp_soft_reconfig_table_update(peer
, dest
, ain
,
5175 bgp_dest_unlock_node(dest
);
5181 /* Do soft reconfig table per bgp table.
5182 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5183 * when BGP_NODE_SOFT_RECONFIG is set,
5184 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5185 * Schedule a new thread to continue the job.
5186 * Without splitting the full job into several part,
5187 * vtysh waits for the job to finish before responding to a BGP command
5189 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
5191 uint32_t iter
, max_iter
;
5193 struct bgp_dest
*dest
;
5194 struct bgp_adj_in
*ain
;
5196 struct bgp_table
*table
;
5197 struct prefix_rd
*prd
;
5198 struct listnode
*node
, *nnode
;
5200 table
= THREAD_ARG(thread
);
5203 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5204 if (table
->soft_reconfig_init
) {
5205 /* first call of the function with a new srta structure.
5206 * Don't do any treatment this time on nodes
5207 * in order vtysh to respond quickly
5212 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5213 dest
= bgp_route_next(dest
)) {
5214 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5217 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5219 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5220 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5222 if (ain
->peer
!= peer
)
5225 ret
= bgp_soft_reconfig_table_update(
5226 peer
, dest
, ain
, table
->afi
,
5231 bgp_dest_unlock_node(dest
);
5233 table
->soft_reconfig_peers
,
5235 bgp_announce_route(peer
, table
->afi
,
5236 table
->safi
, false);
5238 table
->soft_reconfig_peers
)) {
5240 &table
->soft_reconfig_peers
);
5241 bgp_soft_reconfig_table_flag(
5250 /* we're either starting the initial iteration,
5251 * or we're going to continue an ongoing iteration
5253 if (dest
|| table
->soft_reconfig_init
) {
5254 table
->soft_reconfig_init
= false;
5255 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
5256 table
, 0, &table
->soft_reconfig_thread
);
5259 /* we're done, clean up the background iteration context info and
5260 schedule route annoucement
5262 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5263 listnode_delete(table
->soft_reconfig_peers
, peer
);
5264 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5267 list_delete(&table
->soft_reconfig_peers
);
5271 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5273 * - bgp cannot be NULL
5274 * - if table and peer are NULL, cancel all threads within the bgp instance
5275 * - if table is NULL and peer is not,
5276 * remove peer in all threads within the bgp instance
5277 * - if peer is NULL, cancel all threads matching table within the bgp instance
5279 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5280 const struct bgp_table
*table
,
5281 const struct peer
*peer
)
5284 struct listnode
*node
, *nnode
;
5286 struct bgp_table
*ntable
;
5291 FOREACH_AFI_SAFI (afi
, safi
) {
5292 ntable
= bgp
->rib
[afi
][safi
];
5295 if (table
&& table
!= ntable
)
5298 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5300 if (peer
&& peer
!= npeer
)
5302 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5305 if (!ntable
->soft_reconfig_peers
5306 || !list_isempty(ntable
->soft_reconfig_peers
))
5309 list_delete(&ntable
->soft_reconfig_peers
);
5310 bgp_soft_reconfig_table_flag(ntable
, false);
5311 THREAD_OFF(ntable
->soft_reconfig_thread
);
5316 * Returns false if the peer is not configured for soft reconfig in
5318 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5320 struct bgp_dest
*dest
;
5321 struct bgp_table
*table
;
5322 struct listnode
*node
, *nnode
;
5324 struct peer_af
*paf
;
5326 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5329 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5330 && (safi
!= SAFI_EVPN
)) {
5331 table
= peer
->bgp
->rib
[afi
][safi
];
5335 table
->soft_reconfig_init
= true;
5337 if (!table
->soft_reconfig_peers
)
5338 table
->soft_reconfig_peers
= list_new();
5340 /* add peer to the table soft_reconfig_peers if not already
5343 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5349 listnode_add(table
->soft_reconfig_peers
, peer
);
5351 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5352 * on table would start back at the beginning.
5354 bgp_soft_reconfig_table_flag(table
, true);
5356 if (!table
->soft_reconfig_thread
)
5357 thread_add_event(bm
->master
,
5358 bgp_soft_reconfig_table_task
, table
, 0,
5359 &table
->soft_reconfig_thread
);
5360 /* Cancel bgp_announce_route_timer_expired threads.
5361 * bgp_announce_route_timer_expired threads have been scheduled
5362 * to announce routes as soon as the soft_reconfigure process
5364 * In this case, soft_reconfigure is also scheduled by using
5365 * a thread but is planned after the
5366 * bgp_announce_route_timer_expired threads. It means that,
5367 * without cancelling the threads, the route announcement task
5368 * would run before the soft reconfiguration one. That would
5369 * useless and would block vtysh during several seconds. Route
5370 * announcements are rescheduled as soon as the soft_reconfigure
5373 paf
= peer_af_find(peer
, afi
, safi
);
5375 bgp_stop_announce_route_timer(paf
);
5377 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5378 dest
= bgp_route_next(dest
)) {
5379 table
= bgp_dest_get_bgp_table_info(dest
);
5384 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5385 struct prefix_rd prd
;
5387 prd
.family
= AF_UNSPEC
;
5389 memcpy(&prd
.val
, p
->u
.val
, 8);
5391 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5398 struct bgp_clear_node_queue
{
5399 struct bgp_dest
*dest
;
5402 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5404 struct bgp_clear_node_queue
*cnq
= data
;
5405 struct bgp_dest
*dest
= cnq
->dest
;
5406 struct peer
*peer
= wq
->spec
.data
;
5407 struct bgp_path_info
*pi
;
5409 afi_t afi
= bgp_dest_table(dest
)->afi
;
5410 safi_t safi
= bgp_dest_table(dest
)->safi
;
5412 assert(dest
&& peer
);
5415 /* It is possible that we have multiple paths for a prefix from a peer
5416 * if that peer is using AddPath.
5418 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5419 if (pi
->peer
!= peer
)
5422 /* graceful restart STALE flag set. */
5423 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5424 && peer
->nsf
[afi
][safi
])
5425 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5426 PEER_STATUS_ENHANCED_REFRESH
))
5427 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5428 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5429 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5431 /* If this is an EVPN route, process for
5433 if (safi
== SAFI_EVPN
)
5434 bgp_evpn_unimport_route(
5436 bgp_dest_get_prefix(dest
), pi
);
5437 /* Handle withdraw for VRF route-leaking and L3VPN */
5438 if (SAFI_UNICAST
== safi
5439 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5440 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5441 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5444 if (SAFI_MPLS_VPN
== safi
&&
5445 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5446 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5449 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5455 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5457 struct bgp_clear_node_queue
*cnq
= data
;
5458 struct bgp_dest
*dest
= cnq
->dest
;
5459 struct bgp_table
*table
= bgp_dest_table(dest
);
5461 bgp_dest_unlock_node(dest
);
5462 bgp_table_unlock(table
);
5463 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5466 static void bgp_clear_node_complete(struct work_queue
*wq
)
5468 struct peer
*peer
= wq
->spec
.data
;
5470 /* Tickle FSM to start moving again */
5471 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5473 peer_unlock(peer
); /* bgp_clear_route */
5476 static void bgp_clear_node_queue_init(struct peer
*peer
)
5478 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5480 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5481 #undef CLEAR_QUEUE_NAME_LEN
5483 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5484 peer
->clear_node_queue
->spec
.hold
= 10;
5485 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5486 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5487 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5488 peer
->clear_node_queue
->spec
.max_retries
= 0;
5490 /* we only 'lock' this peer reference when the queue is actually active
5492 peer
->clear_node_queue
->spec
.data
= peer
;
5495 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5496 struct bgp_table
*table
)
5498 struct bgp_dest
*dest
;
5499 int force
= peer
->bgp
->process_queue
? 0 : 1;
5502 table
= peer
->bgp
->rib
[afi
][safi
];
5504 /* If still no table => afi/safi isn't configured at all or smth. */
5508 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5509 struct bgp_path_info
*pi
, *next
;
5510 struct bgp_adj_in
*ain
;
5511 struct bgp_adj_in
*ain_next
;
5513 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5514 * queued for every clearing peer, regardless of whether it is
5515 * relevant to the peer at hand.
5517 * Overview: There are 3 different indices which need to be
5518 * scrubbed, potentially, when a peer is removed:
5520 * 1 peer's routes visible via the RIB (ie accepted routes)
5521 * 2 peer's routes visible by the (optional) peer's adj-in index
5522 * 3 other routes visible by the peer's adj-out index
5524 * 3 there is no hurry in scrubbing, once the struct peer is
5525 * removed from bgp->peer, we could just GC such deleted peer's
5526 * adj-outs at our leisure.
5528 * 1 and 2 must be 'scrubbed' in some way, at least made
5529 * invisible via RIB index before peer session is allowed to be
5530 * brought back up. So one needs to know when such a 'search' is
5535 * - there'd be a single global queue or a single RIB walker
5536 * - rather than tracking which route_nodes still need to be
5537 * examined on a peer basis, we'd track which peers still
5540 * Given that our per-peer prefix-counts now should be reliable,
5541 * this may actually be achievable. It doesn't seem to be a huge
5542 * problem at this time,
5544 * It is possible that we have multiple paths for a prefix from
5546 * if that peer is using AddPath.
5550 ain_next
= ain
->next
;
5552 if (ain
->peer
== peer
)
5553 bgp_adj_in_remove(dest
, ain
);
5558 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5560 if (pi
->peer
!= peer
)
5564 bgp_path_info_reap(dest
, pi
);
5566 struct bgp_clear_node_queue
*cnq
;
5568 /* both unlocked in bgp_clear_node_queue_del */
5569 bgp_table_lock(bgp_dest_table(dest
));
5570 bgp_dest_lock_node(dest
);
5572 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5573 sizeof(struct bgp_clear_node_queue
));
5575 work_queue_add(peer
->clear_node_queue
, cnq
);
5583 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5585 struct bgp_dest
*dest
;
5586 struct bgp_table
*table
;
5588 if (peer
->clear_node_queue
== NULL
)
5589 bgp_clear_node_queue_init(peer
);
5591 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5592 * Idle until it receives a Clearing_Completed event. This protects
5593 * against peers which flap faster than we can we clear, which could
5596 * a) race with routes from the new session being installed before
5597 * clear_route_node visits the node (to delete the route of that
5599 * b) resource exhaustion, clear_route_node likely leads to an entry
5600 * on the process_main queue. Fast-flapping could cause that queue
5604 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5605 * the unlock will happen upon work-queue completion; other wise, the
5606 * unlock happens at the end of this function.
5608 if (!peer
->clear_node_queue
->thread
)
5611 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5612 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5614 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5615 dest
= bgp_route_next(dest
)) {
5616 table
= bgp_dest_get_bgp_table_info(dest
);
5620 bgp_clear_route_table(peer
, afi
, safi
, table
);
5623 /* unlock if no nodes got added to the clear-node-queue. */
5624 if (!peer
->clear_node_queue
->thread
)
5628 void bgp_clear_route_all(struct peer
*peer
)
5633 FOREACH_AFI_SAFI (afi
, safi
)
5634 bgp_clear_route(peer
, afi
, safi
);
5636 #ifdef ENABLE_BGP_VNC
5637 rfapiProcessPeerDown(peer
);
5641 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5643 struct bgp_table
*table
;
5644 struct bgp_dest
*dest
;
5645 struct bgp_adj_in
*ain
;
5646 struct bgp_adj_in
*ain_next
;
5648 table
= peer
->bgp
->rib
[afi
][safi
];
5650 /* It is possible that we have multiple paths for a prefix from a peer
5651 * if that peer is using AddPath.
5653 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5657 ain_next
= ain
->next
;
5659 if (ain
->peer
== peer
)
5660 bgp_adj_in_remove(dest
, ain
);
5667 /* If any of the routes from the peer have been marked with the NO_LLGR
5668 * community, either as sent by the peer, or as the result of a configured
5669 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5670 * operation of [RFC4271].
5672 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5674 struct bgp_dest
*dest
;
5675 struct bgp_path_info
*pi
;
5676 struct bgp_table
*table
;
5678 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5679 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5680 dest
= bgp_route_next(dest
)) {
5681 struct bgp_dest
*rm
;
5683 /* look for neighbor in tables */
5684 table
= bgp_dest_get_bgp_table_info(dest
);
5688 for (rm
= bgp_table_top(table
); rm
;
5689 rm
= bgp_route_next(rm
))
5690 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5692 if (pi
->peer
!= peer
)
5695 peer
->af_sflags
[afi
][safi
],
5696 PEER_STATUS_LLGR_WAIT
) &&
5697 bgp_attr_get_community(pi
->attr
) &&
5699 bgp_attr_get_community(
5703 if (!CHECK_FLAG(pi
->flags
,
5708 * If this is VRF leaked route
5709 * process for withdraw.
5712 BGP_ROUTE_IMPORTED
&&
5713 peer
->bgp
->inst_type
==
5714 BGP_INSTANCE_TYPE_DEFAULT
)
5715 vpn_leak_to_vrf_withdraw(
5718 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5723 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5724 dest
= bgp_route_next(dest
))
5725 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5727 if (pi
->peer
!= peer
)
5729 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5730 PEER_STATUS_LLGR_WAIT
) &&
5731 bgp_attr_get_community(pi
->attr
) &&
5733 bgp_attr_get_community(pi
->attr
),
5736 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5738 if (safi
== SAFI_UNICAST
&&
5739 (peer
->bgp
->inst_type
==
5740 BGP_INSTANCE_TYPE_VRF
||
5741 peer
->bgp
->inst_type
==
5742 BGP_INSTANCE_TYPE_DEFAULT
))
5743 vpn_leak_from_vrf_withdraw(
5744 bgp_get_default(), peer
->bgp
,
5747 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5753 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5755 struct bgp_dest
*dest
, *ndest
;
5756 struct bgp_path_info
*pi
;
5757 struct bgp_table
*table
;
5759 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5760 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5761 dest
= bgp_route_next(dest
)) {
5762 table
= bgp_dest_get_bgp_table_info(dest
);
5766 for (ndest
= bgp_table_top(table
); ndest
;
5767 ndest
= bgp_route_next(ndest
)) {
5768 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5770 if (pi
->peer
!= peer
)
5774 peer
->af_sflags
[afi
][safi
],
5775 PEER_STATUS_ENHANCED_REFRESH
))
5776 && !CHECK_FLAG(pi
->flags
,
5780 BGP_PATH_UNUSEABLE
)) {
5781 if (bgp_debug_neighbor_events(
5784 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5788 bgp_dest_get_prefix(
5791 bgp_path_info_set_flag(
5799 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5800 dest
= bgp_route_next(dest
)) {
5801 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5803 if (pi
->peer
!= peer
)
5806 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5807 PEER_STATUS_ENHANCED_REFRESH
))
5808 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5809 && !CHECK_FLAG(pi
->flags
,
5810 BGP_PATH_UNUSEABLE
)) {
5811 if (bgp_debug_neighbor_events(peer
))
5813 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5816 bgp_dest_get_prefix(
5819 bgp_path_info_set_flag(dest
, pi
,
5827 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5829 if (peer
->sort
== BGP_PEER_IBGP
)
5832 if (peer
->sort
== BGP_PEER_EBGP
5833 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5834 || FILTER_LIST_OUT_NAME(filter
)
5835 || DISTRIBUTE_OUT_NAME(filter
)))
5840 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5842 if (peer
->sort
== BGP_PEER_IBGP
)
5845 if (peer
->sort
== BGP_PEER_EBGP
5846 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5847 || FILTER_LIST_IN_NAME(filter
)
5848 || DISTRIBUTE_IN_NAME(filter
)))
5853 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5856 struct bgp_dest
*dest
;
5857 struct bgp_path_info
*pi
;
5858 struct bgp_path_info
*next
;
5860 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5861 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5862 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5866 /* Unimport EVPN routes from VRFs */
5867 if (safi
== SAFI_EVPN
)
5868 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5871 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5872 && pi
->type
== ZEBRA_ROUTE_BGP
5873 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5874 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5875 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5877 if (bgp_fibupd_safi(safi
))
5878 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5881 bgp_path_info_reap(dest
, pi
);
5885 /* Delete all kernel routes. */
5886 void bgp_cleanup_routes(struct bgp
*bgp
)
5889 struct bgp_dest
*dest
;
5890 struct bgp_table
*table
;
5892 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5893 if (afi
== AFI_L2VPN
)
5895 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5898 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5900 if (afi
!= AFI_L2VPN
) {
5902 safi
= SAFI_MPLS_VPN
;
5903 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5904 dest
= bgp_route_next(dest
)) {
5905 table
= bgp_dest_get_bgp_table_info(dest
);
5906 if (table
!= NULL
) {
5907 bgp_cleanup_table(bgp
, table
, safi
);
5908 bgp_table_finish(&table
);
5909 bgp_dest_set_bgp_table_info(dest
, NULL
);
5910 bgp_dest_unlock_node(dest
);
5914 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5915 dest
= bgp_route_next(dest
)) {
5916 table
= bgp_dest_get_bgp_table_info(dest
);
5917 if (table
!= NULL
) {
5918 bgp_cleanup_table(bgp
, table
, safi
);
5919 bgp_table_finish(&table
);
5920 bgp_dest_set_bgp_table_info(dest
, NULL
);
5921 bgp_dest_unlock_node(dest
);
5926 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5927 dest
= bgp_route_next(dest
)) {
5928 table
= bgp_dest_get_bgp_table_info(dest
);
5929 if (table
!= NULL
) {
5930 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5931 bgp_table_finish(&table
);
5932 bgp_dest_set_bgp_table_info(dest
, NULL
);
5933 bgp_dest_unlock_node(dest
);
5938 void bgp_reset(void)
5941 bgp_zclient_reset();
5942 access_list_reset();
5943 prefix_list_reset();
5946 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5948 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5949 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5950 PEER_CAP_ADDPATH_AF_TX_RCV
));
5953 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5955 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5956 struct bgp_nlri
*packet
)
5965 bool addpath_capable
;
5966 uint32_t addpath_id
;
5969 lim
= pnt
+ packet
->length
;
5971 safi
= packet
->safi
;
5973 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5975 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5976 syntactic validity. If the field is syntactically incorrect,
5977 then the Error Subcode is set to Invalid Network Field. */
5978 for (; pnt
< lim
; pnt
+= psize
) {
5979 /* Clear prefix structure. */
5980 memset(&p
, 0, sizeof(p
));
5982 if (addpath_capable
) {
5984 /* When packet overflow occurs return immediately. */
5985 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5986 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5988 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5989 addpath_id
= ntohl(addpath_id
);
5990 pnt
+= BGP_ADDPATH_ID_LEN
;
5993 /* Fetch prefix length. */
5994 p
.prefixlen
= *pnt
++;
5995 /* afi/safi validity already verified by caller,
5996 * bgp_update_receive */
5997 p
.family
= afi2family(afi
);
5999 /* Prefix length check. */
6000 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
6003 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
6004 peer
->host
, p
.prefixlen
, packet
->afi
);
6005 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
6008 /* Packet size overflow check. */
6009 psize
= PSIZE(p
.prefixlen
);
6011 /* When packet overflow occur return immediately. */
6012 if (pnt
+ psize
> lim
) {
6015 "%s [Error] Update packet error (prefix length %d overflows packet)",
6016 peer
->host
, p
.prefixlen
);
6017 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6020 /* Defensive coding, double-check the psize fits in a struct
6021 * prefix for the v4 and v6 afi's and unicast/multicast */
6022 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6025 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6026 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6027 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6030 /* Fetch prefix from NLRI packet. */
6031 memcpy(p
.u
.val
, pnt
, psize
);
6033 /* Check address. */
6034 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6035 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6036 /* From RFC4271 Section 6.3:
6038 * If a prefix in the NLRI field is semantically
6040 * (e.g., an unexpected multicast IP address),
6042 * be logged locally, and the prefix SHOULD be
6047 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6048 peer
->host
, &p
.u
.prefix4
);
6053 /* Check address. */
6054 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6055 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6058 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6059 peer
->host
, &p
.u
.prefix6
);
6063 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6066 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6067 peer
->host
, &p
.u
.prefix6
);
6073 /* Normal process. */
6075 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6076 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
6077 NULL
, NULL
, 0, 0, NULL
);
6079 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
6080 safi
, ZEBRA_ROUTE_BGP
,
6081 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
6084 /* Do not send BGP notification twice when maximum-prefix count
6086 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6087 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6089 /* Address family configuration mismatch. */
6091 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
6094 /* Packet length consistency check. */
6098 "%s [Error] Update packet error (prefix length mismatch with total length)",
6100 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6103 return BGP_NLRI_PARSE_OK
;
6106 static struct bgp_static
*bgp_static_new(void)
6108 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6111 static void bgp_static_free(struct bgp_static
*bgp_static
)
6113 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6114 route_map_counter_decrement(bgp_static
->rmap
.map
);
6116 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6117 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6120 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6121 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6123 struct bgp_dest
*dest
;
6124 struct bgp_path_info
*pi
;
6125 struct bgp_path_info
*new;
6126 struct bgp_path_info rmap_path
;
6128 struct attr
*attr_new
;
6129 route_map_result_t ret
;
6130 #ifdef ENABLE_BGP_VNC
6131 int vnc_implicit_withdraw
= 0;
6136 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6138 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6140 attr
.nexthop
= bgp_static
->igpnexthop
;
6141 attr
.med
= bgp_static
->igpmetric
;
6142 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6145 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6147 if (bgp_static
->igpmetric
)
6148 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6150 if (bgp_static
->atomic
)
6151 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6153 /* Store label index, if required. */
6154 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6155 attr
.label_index
= bgp_static
->label_index
;
6156 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6159 /* Apply route-map. */
6160 if (bgp_static
->rmap
.name
) {
6161 struct attr attr_tmp
= attr
;
6163 memset(&rmap_path
, 0, sizeof(rmap_path
));
6164 rmap_path
.peer
= bgp
->peer_self
;
6165 rmap_path
.attr
= &attr_tmp
;
6167 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6169 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6171 bgp
->peer_self
->rmap_type
= 0;
6173 if (ret
== RMAP_DENYMATCH
) {
6174 /* Free uninterned attribute. */
6175 bgp_attr_flush(&attr_tmp
);
6177 /* Unintern original. */
6178 aspath_unintern(&attr
.aspath
);
6179 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6180 bgp_dest_unlock_node(dest
);
6184 if (bgp_in_graceful_shutdown(bgp
))
6185 bgp_attr_add_gshut_community(&attr_tmp
);
6187 attr_new
= bgp_attr_intern(&attr_tmp
);
6190 if (bgp_in_graceful_shutdown(bgp
))
6191 bgp_attr_add_gshut_community(&attr
);
6193 attr_new
= bgp_attr_intern(&attr
);
6196 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6197 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6198 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6202 if (attrhash_cmp(pi
->attr
, attr_new
)
6203 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6204 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6205 bgp_dest_unlock_node(dest
);
6206 bgp_attr_unintern(&attr_new
);
6207 aspath_unintern(&attr
.aspath
);
6210 /* The attribute is changed. */
6211 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6213 /* Rewrite BGP route information. */
6214 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6215 bgp_path_info_restore(dest
, pi
);
6217 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6218 #ifdef ENABLE_BGP_VNC
6219 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6220 && (safi
== SAFI_UNICAST
)) {
6221 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6223 * Implicit withdraw case.
6224 * We have to do this before pi is
6227 ++vnc_implicit_withdraw
;
6228 vnc_import_bgp_del_route(bgp
, p
, pi
);
6229 vnc_import_bgp_exterior_del_route(
6234 bgp_attr_unintern(&pi
->attr
);
6235 pi
->attr
= attr_new
;
6236 pi
->uptime
= monotime(NULL
);
6237 #ifdef ENABLE_BGP_VNC
6238 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6239 && (safi
== SAFI_UNICAST
)) {
6240 if (vnc_implicit_withdraw
) {
6241 vnc_import_bgp_add_route(bgp
, p
, pi
);
6242 vnc_import_bgp_exterior_add_route(
6248 /* Nexthop reachability check. */
6249 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6250 && (safi
== SAFI_UNICAST
6251 || safi
== SAFI_LABELED_UNICAST
)) {
6253 struct bgp
*bgp_nexthop
= bgp
;
6255 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6256 bgp_nexthop
= pi
->extra
->bgp_orig
;
6258 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6259 afi
, safi
, pi
, NULL
,
6261 bgp_path_info_set_flag(dest
, pi
,
6264 if (BGP_DEBUG(nht
, NHT
)) {
6265 char buf1
[INET6_ADDRSTRLEN
];
6266 inet_ntop(p
->family
,
6270 "%s(%s): Route not in table, not advertising",
6273 bgp_path_info_unset_flag(
6274 dest
, pi
, BGP_PATH_VALID
);
6277 /* Delete the NHT structure if any, if we're
6279 * enabling/disabling import check. We
6280 * deregister the route
6281 * from NHT to avoid overloading NHT and the
6282 * process interaction
6284 bgp_unlink_nexthop(pi
);
6285 bgp_path_info_set_flag(dest
, pi
,
6288 /* Process change. */
6289 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6290 bgp_process(bgp
, dest
, afi
, safi
);
6292 if (SAFI_UNICAST
== safi
6293 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6295 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6296 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6300 bgp_dest_unlock_node(dest
);
6301 aspath_unintern(&attr
.aspath
);
6306 /* Make new BGP info. */
6307 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6309 /* Nexthop reachability check. */
6310 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6311 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6312 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6314 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6316 if (BGP_DEBUG(nht
, NHT
)) {
6317 char buf1
[INET6_ADDRSTRLEN
];
6319 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6322 "%s(%s): Route not in table, not advertising",
6325 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6328 /* Delete the NHT structure if any, if we're toggling between
6329 * enabling/disabling import check. We deregister the route
6330 * from NHT to avoid overloading NHT and the process interaction
6332 bgp_unlink_nexthop(new);
6334 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6337 /* Aggregate address increment. */
6338 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6340 /* Register new BGP information. */
6341 bgp_path_info_add(dest
, new);
6343 /* route_node_get lock */
6344 bgp_dest_unlock_node(dest
);
6346 /* Process change. */
6347 bgp_process(bgp
, dest
, afi
, safi
);
6349 if (SAFI_UNICAST
== safi
6350 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6351 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6352 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6355 /* Unintern original. */
6356 aspath_unintern(&attr
.aspath
);
6359 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6362 struct bgp_dest
*dest
;
6363 struct bgp_path_info
*pi
;
6365 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6367 /* Check selected route and self inserted route. */
6368 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6369 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6370 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6373 /* Withdraw static BGP route from routing table. */
6375 if (SAFI_UNICAST
== safi
6376 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6377 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6378 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6380 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6381 bgp_unlink_nexthop(pi
);
6382 bgp_path_info_delete(dest
, pi
);
6383 bgp_process(bgp
, dest
, afi
, safi
);
6386 /* Unlock bgp_node_lookup. */
6387 bgp_dest_unlock_node(dest
);
6391 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6393 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6394 afi_t afi
, safi_t safi
,
6395 struct prefix_rd
*prd
)
6397 struct bgp_dest
*dest
;
6398 struct bgp_path_info
*pi
;
6400 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6402 /* Check selected route and self inserted route. */
6403 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6404 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6405 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6408 /* Withdraw static BGP route from routing table. */
6410 #ifdef ENABLE_BGP_VNC
6411 rfapiProcessWithdraw(
6412 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6413 1); /* Kill, since it is an administrative change */
6415 if (SAFI_MPLS_VPN
== safi
6416 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6417 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6419 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6420 bgp_path_info_delete(dest
, pi
);
6421 bgp_process(bgp
, dest
, afi
, safi
);
6424 /* Unlock bgp_node_lookup. */
6425 bgp_dest_unlock_node(dest
);
6428 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6429 struct bgp_static
*bgp_static
, afi_t afi
,
6432 struct bgp_dest
*dest
;
6433 struct bgp_path_info
*new;
6434 struct attr
*attr_new
;
6435 struct attr attr
= {0};
6436 struct bgp_path_info
*pi
;
6437 #ifdef ENABLE_BGP_VNC
6438 mpls_label_t label
= 0;
6440 uint32_t num_labels
= 0;
6444 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6446 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6449 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6451 attr
.nexthop
= bgp_static
->igpnexthop
;
6452 attr
.med
= bgp_static
->igpmetric
;
6453 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6455 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6456 || (safi
== SAFI_ENCAP
)) {
6457 if (afi
== AFI_IP
) {
6458 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6459 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6462 if (afi
== AFI_L2VPN
) {
6463 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6464 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6465 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6466 &bgp_static
->gatewayIp
.u
.prefix4
,
6468 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6469 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6470 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6471 &bgp_static
->gatewayIp
.u
.prefix6
,
6474 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6475 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6476 struct bgp_encap_type_vxlan bet
;
6477 memset(&bet
, 0, sizeof(bet
));
6478 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6479 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6481 if (bgp_static
->router_mac
) {
6482 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6485 /* Apply route-map. */
6486 if (bgp_static
->rmap
.name
) {
6487 struct attr attr_tmp
= attr
;
6488 struct bgp_path_info rmap_path
;
6489 route_map_result_t ret
;
6491 rmap_path
.peer
= bgp
->peer_self
;
6492 rmap_path
.attr
= &attr_tmp
;
6494 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6496 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6498 bgp
->peer_self
->rmap_type
= 0;
6500 if (ret
== RMAP_DENYMATCH
) {
6501 /* Free uninterned attribute. */
6502 bgp_attr_flush(&attr_tmp
);
6504 /* Unintern original. */
6505 aspath_unintern(&attr
.aspath
);
6506 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6508 bgp_dest_unlock_node(dest
);
6512 attr_new
= bgp_attr_intern(&attr_tmp
);
6514 attr_new
= bgp_attr_intern(&attr
);
6517 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6518 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6519 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6523 if (attrhash_cmp(pi
->attr
, attr_new
)
6524 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6525 bgp_dest_unlock_node(dest
);
6526 bgp_attr_unintern(&attr_new
);
6527 aspath_unintern(&attr
.aspath
);
6530 /* The attribute is changed. */
6531 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6533 /* Rewrite BGP route information. */
6534 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6535 bgp_path_info_restore(dest
, pi
);
6537 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6538 bgp_attr_unintern(&pi
->attr
);
6539 pi
->attr
= attr_new
;
6540 pi
->uptime
= monotime(NULL
);
6541 #ifdef ENABLE_BGP_VNC
6543 label
= decode_label(&pi
->extra
->label
[0]);
6546 /* Process change. */
6547 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6548 bgp_process(bgp
, dest
, afi
, safi
);
6550 if (SAFI_MPLS_VPN
== safi
6551 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6552 vpn_leak_to_vrf_update(bgp
, pi
,
6555 #ifdef ENABLE_BGP_VNC
6556 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6557 pi
->attr
, afi
, safi
, pi
->type
,
6558 pi
->sub_type
, &label
);
6560 bgp_dest_unlock_node(dest
);
6561 aspath_unintern(&attr
.aspath
);
6567 /* Make new BGP info. */
6568 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6570 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6571 bgp_path_info_extra_get(new);
6573 new->extra
->label
[0] = bgp_static
->label
;
6574 new->extra
->num_labels
= num_labels
;
6576 #ifdef ENABLE_BGP_VNC
6577 label
= decode_label(&bgp_static
->label
);
6580 /* Aggregate address increment. */
6581 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6583 /* Register new BGP information. */
6584 bgp_path_info_add(dest
, new);
6585 /* route_node_get lock */
6586 bgp_dest_unlock_node(dest
);
6588 /* Process change. */
6589 bgp_process(bgp
, dest
, afi
, safi
);
6591 if (SAFI_MPLS_VPN
== safi
6592 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6593 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6595 #ifdef ENABLE_BGP_VNC
6596 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6597 safi
, new->type
, new->sub_type
, &label
);
6600 /* Unintern original. */
6601 aspath_unintern(&attr
.aspath
);
6604 /* Configure static BGP network. When user don't run zebra, static
6605 route should be installed as valid. */
6606 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6607 const char *ip_str
, afi_t afi
, safi_t safi
,
6608 const char *rmap
, int backdoor
, uint32_t label_index
)
6610 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6613 struct bgp_static
*bgp_static
;
6614 struct bgp_dest
*dest
;
6615 uint8_t need_update
= 0;
6617 /* Convert IP prefix string to struct prefix. */
6618 ret
= str2prefix(ip_str
, &p
);
6620 vty_out(vty
, "%% Malformed prefix\n");
6621 return CMD_WARNING_CONFIG_FAILED
;
6623 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6624 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6625 return CMD_WARNING_CONFIG_FAILED
;
6632 /* Set BGP static route configuration. */
6633 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6636 vty_out(vty
, "%% Can't find static route specified\n");
6637 return CMD_WARNING_CONFIG_FAILED
;
6640 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6642 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6643 && (label_index
!= bgp_static
->label_index
)) {
6645 "%% label-index doesn't match static route\n");
6646 bgp_dest_unlock_node(dest
);
6647 return CMD_WARNING_CONFIG_FAILED
;
6650 if ((rmap
&& bgp_static
->rmap
.name
)
6651 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6653 "%% route-map name doesn't match static route\n");
6654 bgp_dest_unlock_node(dest
);
6655 return CMD_WARNING_CONFIG_FAILED
;
6658 /* Update BGP RIB. */
6659 if (!bgp_static
->backdoor
)
6660 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6662 /* Clear configuration. */
6663 bgp_static_free(bgp_static
);
6664 bgp_dest_set_bgp_static_info(dest
, NULL
);
6665 bgp_dest_unlock_node(dest
);
6666 bgp_dest_unlock_node(dest
);
6669 /* Set BGP static route configuration. */
6670 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6671 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6673 /* Configuration change. */
6674 /* Label index cannot be changed. */
6675 if (bgp_static
->label_index
!= label_index
) {
6676 vty_out(vty
, "%% cannot change label-index\n");
6677 bgp_dest_unlock_node(dest
);
6678 return CMD_WARNING_CONFIG_FAILED
;
6681 /* Check previous routes are installed into BGP. */
6682 if (bgp_static
->valid
6683 && bgp_static
->backdoor
!= backdoor
)
6686 bgp_static
->backdoor
= backdoor
;
6689 XFREE(MTYPE_ROUTE_MAP_NAME
,
6690 bgp_static
->rmap
.name
);
6691 route_map_counter_decrement(
6692 bgp_static
->rmap
.map
);
6693 bgp_static
->rmap
.name
=
6694 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6695 bgp_static
->rmap
.map
=
6696 route_map_lookup_by_name(rmap
);
6697 route_map_counter_increment(
6698 bgp_static
->rmap
.map
);
6700 XFREE(MTYPE_ROUTE_MAP_NAME
,
6701 bgp_static
->rmap
.name
);
6702 route_map_counter_decrement(
6703 bgp_static
->rmap
.map
);
6704 bgp_static
->rmap
.map
= NULL
;
6705 bgp_static
->valid
= 0;
6707 bgp_dest_unlock_node(dest
);
6709 /* New configuration. */
6710 bgp_static
= bgp_static_new();
6711 bgp_static
->backdoor
= backdoor
;
6712 bgp_static
->valid
= 0;
6713 bgp_static
->igpmetric
= 0;
6714 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6715 bgp_static
->label_index
= label_index
;
6718 XFREE(MTYPE_ROUTE_MAP_NAME
,
6719 bgp_static
->rmap
.name
);
6720 route_map_counter_decrement(
6721 bgp_static
->rmap
.map
);
6722 bgp_static
->rmap
.name
=
6723 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6724 bgp_static
->rmap
.map
=
6725 route_map_lookup_by_name(rmap
);
6726 route_map_counter_increment(
6727 bgp_static
->rmap
.map
);
6729 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6732 bgp_static
->valid
= 1;
6734 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6736 if (!bgp_static
->backdoor
)
6737 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6743 void bgp_static_add(struct bgp
*bgp
)
6747 struct bgp_dest
*dest
;
6748 struct bgp_dest
*rm
;
6749 struct bgp_table
*table
;
6750 struct bgp_static
*bgp_static
;
6752 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6753 FOREACH_AFI_SAFI (afi
, safi
)
6754 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6755 dest
= bgp_route_next(dest
)) {
6756 if (!bgp_dest_has_bgp_path_info_data(dest
))
6759 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6760 || (safi
== SAFI_EVPN
)) {
6761 table
= bgp_dest_get_bgp_table_info(dest
);
6763 for (rm
= bgp_table_top(table
); rm
;
6764 rm
= bgp_route_next(rm
)) {
6766 bgp_dest_get_bgp_static_info(
6768 bgp_static_update_safi(
6769 bgp
, bgp_dest_get_prefix(rm
),
6770 bgp_static
, afi
, safi
);
6774 bgp
, bgp_dest_get_prefix(dest
),
6775 bgp_dest_get_bgp_static_info(dest
), afi
,
6779 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6782 /* Called from bgp_delete(). Delete all static routes from the BGP
6784 void bgp_static_delete(struct bgp
*bgp
)
6788 struct bgp_dest
*dest
;
6789 struct bgp_dest
*rm
;
6790 struct bgp_table
*table
;
6791 struct bgp_static
*bgp_static
;
6793 FOREACH_AFI_SAFI (afi
, safi
)
6794 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6795 dest
= bgp_route_next(dest
)) {
6796 if (!bgp_dest_has_bgp_path_info_data(dest
))
6799 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6800 || (safi
== SAFI_EVPN
)) {
6801 table
= bgp_dest_get_bgp_table_info(dest
);
6803 for (rm
= bgp_table_top(table
); rm
;
6804 rm
= bgp_route_next(rm
)) {
6806 bgp_dest_get_bgp_static_info(
6811 bgp_static_withdraw_safi(
6812 bgp
, bgp_dest_get_prefix(rm
),
6814 (struct prefix_rd
*)
6815 bgp_dest_get_prefix(
6817 bgp_static_free(bgp_static
);
6818 bgp_dest_set_bgp_static_info(rm
,
6820 bgp_dest_unlock_node(rm
);
6823 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6824 bgp_static_withdraw(bgp
,
6825 bgp_dest_get_prefix(dest
),
6827 bgp_static_free(bgp_static
);
6828 bgp_dest_set_bgp_static_info(dest
, NULL
);
6829 bgp_dest_unlock_node(dest
);
6834 void bgp_static_redo_import_check(struct bgp
*bgp
)
6838 struct bgp_dest
*dest
;
6839 struct bgp_dest
*rm
;
6840 struct bgp_table
*table
;
6841 struct bgp_static
*bgp_static
;
6843 /* Use this flag to force reprocessing of the route */
6844 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6845 FOREACH_AFI_SAFI (afi
, safi
) {
6846 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6847 dest
= bgp_route_next(dest
)) {
6848 if (!bgp_dest_has_bgp_path_info_data(dest
))
6851 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6852 || (safi
== SAFI_EVPN
)) {
6853 table
= bgp_dest_get_bgp_table_info(dest
);
6855 for (rm
= bgp_table_top(table
); rm
;
6856 rm
= bgp_route_next(rm
)) {
6858 bgp_dest_get_bgp_static_info(
6860 bgp_static_update_safi(
6861 bgp
, bgp_dest_get_prefix(rm
),
6862 bgp_static
, afi
, safi
);
6865 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6866 bgp_static_update(bgp
,
6867 bgp_dest_get_prefix(dest
),
6868 bgp_static
, afi
, safi
);
6872 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6875 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6878 struct bgp_table
*table
;
6879 struct bgp_dest
*dest
;
6880 struct bgp_path_info
*pi
;
6882 /* Do not install the aggregate route if BGP is in the
6883 * process of termination.
6885 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6886 || (bgp
->peer_self
== NULL
))
6889 table
= bgp
->rib
[afi
][safi
];
6890 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6891 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6892 if (pi
->peer
== bgp
->peer_self
6893 && ((pi
->type
== ZEBRA_ROUTE_BGP
6894 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6895 || (pi
->type
!= ZEBRA_ROUTE_BGP
6897 == BGP_ROUTE_REDISTRIBUTE
))) {
6898 bgp_aggregate_decrement(
6899 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6901 bgp_unlink_nexthop(pi
);
6902 bgp_path_info_delete(dest
, pi
);
6903 bgp_process(bgp
, dest
, afi
, safi
);
6910 * Purge all networks and redistributed routes from routing table.
6911 * Invoked upon the instance going down.
6913 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6918 FOREACH_AFI_SAFI (afi
, safi
)
6919 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6924 * Currently this is used to set static routes for VPN and ENCAP.
6925 * I think it can probably be factored with bgp_static_set.
6927 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6928 const char *ip_str
, const char *rd_str
,
6929 const char *label_str
, const char *rmap_str
,
6930 int evpn_type
, const char *esi
, const char *gwip
,
6931 const char *ethtag
, const char *routermac
)
6933 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6936 struct prefix_rd prd
;
6937 struct bgp_dest
*pdest
;
6938 struct bgp_dest
*dest
;
6939 struct bgp_table
*table
;
6940 struct bgp_static
*bgp_static
;
6941 mpls_label_t label
= MPLS_INVALID_LABEL
;
6942 struct prefix gw_ip
;
6944 /* validate ip prefix */
6945 ret
= str2prefix(ip_str
, &p
);
6947 vty_out(vty
, "%% Malformed prefix\n");
6948 return CMD_WARNING_CONFIG_FAILED
;
6951 if ((afi
== AFI_L2VPN
)
6952 && (bgp_build_evpn_prefix(evpn_type
,
6953 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6954 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6955 return CMD_WARNING_CONFIG_FAILED
;
6958 ret
= str2prefix_rd(rd_str
, &prd
);
6960 vty_out(vty
, "%% Malformed rd\n");
6961 return CMD_WARNING_CONFIG_FAILED
;
6965 unsigned long label_val
;
6966 label_val
= strtoul(label_str
, NULL
, 10);
6967 encode_label(label_val
, &label
);
6970 if (safi
== SAFI_EVPN
) {
6971 if (esi
&& str2esi(esi
, NULL
) == 0) {
6972 vty_out(vty
, "%% Malformed ESI\n");
6973 return CMD_WARNING_CONFIG_FAILED
;
6975 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6976 vty_out(vty
, "%% Malformed Router MAC\n");
6977 return CMD_WARNING_CONFIG_FAILED
;
6980 memset(&gw_ip
, 0, sizeof(gw_ip
));
6981 ret
= str2prefix(gwip
, &gw_ip
);
6983 vty_out(vty
, "%% Malformed GatewayIp\n");
6984 return CMD_WARNING_CONFIG_FAILED
;
6986 if ((gw_ip
.family
== AF_INET
6987 && is_evpn_prefix_ipaddr_v6(
6988 (struct prefix_evpn
*)&p
))
6989 || (gw_ip
.family
== AF_INET6
6990 && is_evpn_prefix_ipaddr_v4(
6991 (struct prefix_evpn
*)&p
))) {
6993 "%% GatewayIp family differs with IP prefix\n");
6994 return CMD_WARNING_CONFIG_FAILED
;
6998 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6999 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7000 bgp_dest_set_bgp_table_info(pdest
,
7001 bgp_table_init(bgp
, afi
, safi
));
7002 table
= bgp_dest_get_bgp_table_info(pdest
);
7004 dest
= bgp_node_get(table
, &p
);
7006 if (bgp_dest_has_bgp_path_info_data(dest
)) {
7007 vty_out(vty
, "%% Same network configuration exists\n");
7008 bgp_dest_unlock_node(dest
);
7010 /* New configuration. */
7011 bgp_static
= bgp_static_new();
7012 bgp_static
->backdoor
= 0;
7013 bgp_static
->valid
= 0;
7014 bgp_static
->igpmetric
= 0;
7015 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7016 bgp_static
->label
= label
;
7017 bgp_static
->prd
= prd
;
7020 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7021 route_map_counter_decrement(bgp_static
->rmap
.map
);
7022 bgp_static
->rmap
.name
=
7023 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7024 bgp_static
->rmap
.map
=
7025 route_map_lookup_by_name(rmap_str
);
7026 route_map_counter_increment(bgp_static
->rmap
.map
);
7029 if (safi
== SAFI_EVPN
) {
7031 bgp_static
->eth_s_id
=
7034 str2esi(esi
, bgp_static
->eth_s_id
);
7037 bgp_static
->router_mac
=
7038 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7039 (void)prefix_str2mac(routermac
,
7040 bgp_static
->router_mac
);
7043 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7045 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7047 bgp_static
->valid
= 1;
7048 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7054 /* Configure static BGP network. */
7055 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7056 const char *ip_str
, const char *rd_str
,
7057 const char *label_str
, int evpn_type
, const char *esi
,
7058 const char *gwip
, const char *ethtag
)
7060 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7063 struct prefix_rd prd
;
7064 struct bgp_dest
*pdest
;
7065 struct bgp_dest
*dest
;
7066 struct bgp_table
*table
;
7067 struct bgp_static
*bgp_static
;
7068 mpls_label_t label
= MPLS_INVALID_LABEL
;
7070 /* Convert IP prefix string to struct prefix. */
7071 ret
= str2prefix(ip_str
, &p
);
7073 vty_out(vty
, "%% Malformed prefix\n");
7074 return CMD_WARNING_CONFIG_FAILED
;
7077 if ((afi
== AFI_L2VPN
)
7078 && (bgp_build_evpn_prefix(evpn_type
,
7079 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7080 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7081 return CMD_WARNING_CONFIG_FAILED
;
7083 ret
= str2prefix_rd(rd_str
, &prd
);
7085 vty_out(vty
, "%% Malformed rd\n");
7086 return CMD_WARNING_CONFIG_FAILED
;
7090 unsigned long label_val
;
7091 label_val
= strtoul(label_str
, NULL
, 10);
7092 encode_label(label_val
, &label
);
7095 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7096 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7097 bgp_dest_set_bgp_table_info(pdest
,
7098 bgp_table_init(bgp
, afi
, safi
));
7100 bgp_dest_unlock_node(pdest
);
7101 table
= bgp_dest_get_bgp_table_info(pdest
);
7103 dest
= bgp_node_lookup(table
, &p
);
7106 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7108 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7109 bgp_static_free(bgp_static
);
7110 bgp_dest_set_bgp_static_info(dest
, NULL
);
7111 bgp_dest_unlock_node(dest
);
7112 bgp_dest_unlock_node(dest
);
7114 vty_out(vty
, "%% Can't find the route\n");
7119 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7120 const char *rmap_name
)
7122 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7123 struct bgp_rmap
*rmap
;
7125 rmap
= &bgp
->table_map
[afi
][safi
];
7127 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7128 route_map_counter_decrement(rmap
->map
);
7129 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7130 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7131 route_map_counter_increment(rmap
->map
);
7133 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7134 route_map_counter_decrement(rmap
->map
);
7138 if (bgp_fibupd_safi(safi
))
7139 bgp_zebra_announce_table(bgp
, afi
, safi
);
7144 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7145 const char *rmap_name
)
7147 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7148 struct bgp_rmap
*rmap
;
7150 rmap
= &bgp
->table_map
[afi
][safi
];
7151 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7152 route_map_counter_decrement(rmap
->map
);
7155 if (bgp_fibupd_safi(safi
))
7156 bgp_zebra_announce_table(bgp
, afi
, safi
);
7161 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7164 if (bgp
->table_map
[afi
][safi
].name
) {
7165 vty_out(vty
, " table-map %s\n",
7166 bgp
->table_map
[afi
][safi
].name
);
7170 DEFUN (bgp_table_map
,
7173 "BGP table to RIB route download filter\n"
7174 "Name of the route map\n")
7177 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7178 argv
[idx_word
]->arg
);
7180 DEFUN (no_bgp_table_map
,
7181 no_bgp_table_map_cmd
,
7182 "no table-map WORD",
7184 "BGP table to RIB route download filter\n"
7185 "Name of the route map\n")
7188 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7189 argv
[idx_word
]->arg
);
7195 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7196 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7197 backdoor$backdoor}]",
7199 "Specify a network to announce via BGP\n"
7204 "Route-map to modify the attributes\n"
7205 "Name of the route map\n"
7206 "Label index to associate with the prefix\n"
7207 "Label index value\n"
7208 "Specify a BGP backdoor route\n")
7210 char addr_prefix_str
[BUFSIZ
];
7215 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7217 sizeof(addr_prefix_str
));
7219 vty_out(vty
, "%% Inconsistent address and mask\n");
7220 return CMD_WARNING_CONFIG_FAILED
;
7224 return bgp_static_set(
7225 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7226 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7227 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7230 DEFPY(ipv6_bgp_network
,
7231 ipv6_bgp_network_cmd
,
7232 "[no] network X:X::X:X/M$prefix \
7233 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7235 "Specify a network to announce via BGP\n"
7237 "Route-map to modify the attributes\n"
7238 "Name of the route map\n"
7239 "Label index to associate with the prefix\n"
7240 "Label index value\n")
7242 return bgp_static_set(
7243 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7244 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7247 static struct bgp_aggregate
*bgp_aggregate_new(void)
7249 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7252 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7254 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7255 route_map_counter_decrement(aggregate
->suppress_map
);
7256 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7257 route_map_counter_decrement(aggregate
->rmap
.map
);
7258 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7262 * Helper function to avoid repeated code: prepare variables for a
7263 * `route_map_apply` call.
7265 * \returns `true` on route map match, otherwise `false`.
7267 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7268 struct bgp_aggregate
*aggregate
,
7269 struct bgp_path_info
*pi
)
7271 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7272 route_map_result_t rmr
= RMAP_DENYMATCH
;
7273 struct bgp_path_info rmap_path
= {};
7274 struct attr attr
= {};
7276 /* No route map entries created, just don't match. */
7277 if (aggregate
->suppress_map
== NULL
)
7280 /* Call route map matching and return result. */
7281 attr
.aspath
= aspath_empty();
7282 rmap_path
.peer
= bgp
->peer_self
;
7283 rmap_path
.attr
= &attr
;
7285 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7286 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7287 bgp
->peer_self
->rmap_type
= 0;
7289 bgp_attr_flush(&attr
);
7290 aspath_unintern(&attr
.aspath
);
7292 return rmr
== RMAP_PERMITMATCH
;
7295 /** Test whether the aggregation has suppressed this path or not. */
7296 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7297 struct bgp_path_info
*pi
)
7299 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7302 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7306 * Suppress this path and keep the reference.
7308 * \returns `true` if needs processing otherwise `false`.
7310 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7311 struct bgp_path_info
*pi
)
7313 struct bgp_path_info_extra
*pie
;
7315 /* Path is already suppressed by this aggregation. */
7316 if (aggr_suppress_exists(aggregate
, pi
))
7319 pie
= bgp_path_info_extra_get(pi
);
7321 /* This is the first suppression, allocate memory and list it. */
7322 if (pie
->aggr_suppressors
== NULL
)
7323 pie
->aggr_suppressors
= list_new();
7325 listnode_add(pie
->aggr_suppressors
, aggregate
);
7327 /* Only mark for processing if suppressed. */
7328 if (listcount(pie
->aggr_suppressors
) == 1) {
7329 if (BGP_DEBUG(update
, UPDATE_OUT
))
7330 zlog_debug("aggregate-address suppressing: %pFX",
7331 bgp_dest_get_prefix(pi
->net
));
7333 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7341 * Unsuppress this path and remove the reference.
7343 * \returns `true` if needs processing otherwise `false`.
7345 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7346 struct bgp_path_info
*pi
)
7348 /* Path wasn't suppressed. */
7349 if (!aggr_suppress_exists(aggregate
, pi
))
7352 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7354 /* Unsuppress and free extra memory if last item. */
7355 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7356 if (BGP_DEBUG(update
, UPDATE_OUT
))
7357 zlog_debug("aggregate-address unsuppressing: %pFX",
7358 bgp_dest_get_prefix(pi
->net
));
7360 list_delete(&pi
->extra
->aggr_suppressors
);
7361 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7368 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7369 struct aspath
*aspath
,
7370 struct community
*comm
,
7371 struct ecommunity
*ecomm
,
7372 struct lcommunity
*lcomm
)
7374 static struct aspath
*ae
= NULL
;
7377 ae
= aspath_empty();
7382 if (origin
!= pi
->attr
->origin
)
7385 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7388 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7391 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7394 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7397 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7403 static void bgp_aggregate_install(
7404 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7405 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7406 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7407 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7409 struct bgp_dest
*dest
;
7410 struct bgp_table
*table
;
7411 struct bgp_path_info
*pi
, *orig
, *new;
7414 table
= bgp
->rib
[afi
][safi
];
7416 dest
= bgp_node_get(table
, p
);
7418 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7419 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7420 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7424 * If we have paths with different MEDs, then don't install
7425 * (or uninstall) the aggregate route.
7427 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7428 goto uninstall_aggregate_route
;
7430 if (aggregate
->count
> 0) {
7432 * If the aggregate information has not changed
7433 * no need to re-install it again.
7435 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7436 ecommunity
, lcommunity
)) {
7437 bgp_dest_unlock_node(dest
);
7440 aspath_free(aspath
);
7442 community_free(&community
);
7444 ecommunity_free(&ecommunity
);
7446 lcommunity_free(&lcommunity
);
7452 * Mark the old as unusable
7455 bgp_path_info_delete(dest
, pi
);
7457 attr
= bgp_attr_aggregate_intern(
7458 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7459 aggregate
, atomic_aggregate
, p
);
7462 bgp_dest_unlock_node(dest
);
7463 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7464 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7465 zlog_debug("%s: %pFX null attribute", __func__
,
7470 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7471 bgp
->peer_self
, attr
, dest
);
7473 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7475 bgp_path_info_add(dest
, new);
7476 bgp_process(bgp
, dest
, afi
, safi
);
7478 uninstall_aggregate_route
:
7479 for (pi
= orig
; pi
; pi
= pi
->next
)
7480 if (pi
->peer
== bgp
->peer_self
7481 && pi
->type
== ZEBRA_ROUTE_BGP
7482 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7485 /* Withdraw static BGP route from routing table. */
7487 bgp_path_info_delete(dest
, pi
);
7488 bgp_process(bgp
, dest
, afi
, safi
);
7492 bgp_dest_unlock_node(dest
);
7496 * Check if the current path has different MED than other known paths.
7498 * \returns `true` if the MED matched the others else `false`.
7500 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7501 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7503 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7505 /* This is the first route being analyzed. */
7506 if (!aggregate
->med_initialized
) {
7507 aggregate
->med_initialized
= true;
7508 aggregate
->med_mismatched
= false;
7509 aggregate
->med_matched_value
= cur_med
;
7511 /* Check if routes with different MED showed up. */
7512 if (cur_med
!= aggregate
->med_matched_value
)
7513 aggregate
->med_mismatched
= true;
7516 return !aggregate
->med_mismatched
;
7520 * Initializes and tests all routes in the aggregate address path for MED
7523 * \returns `true` if all MEDs are the same otherwise `false`.
7525 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7526 struct bgp
*bgp
, const struct prefix
*p
,
7527 afi_t afi
, safi_t safi
)
7529 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7530 const struct prefix
*dest_p
;
7531 struct bgp_dest
*dest
, *top
;
7532 struct bgp_path_info
*pi
;
7533 bool med_matched
= true;
7535 aggregate
->med_initialized
= false;
7537 top
= bgp_node_get(table
, p
);
7538 for (dest
= bgp_node_get(table
, p
); dest
;
7539 dest
= bgp_route_next_until(dest
, top
)) {
7540 dest_p
= bgp_dest_get_prefix(dest
);
7541 if (dest_p
->prefixlen
<= p
->prefixlen
)
7544 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7545 if (BGP_PATH_HOLDDOWN(pi
))
7547 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7549 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7550 med_matched
= false;
7557 bgp_dest_unlock_node(top
);
7563 * Toggles the route suppression status for this aggregate address
7566 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7567 struct bgp
*bgp
, const struct prefix
*p
,
7568 afi_t afi
, safi_t safi
, bool suppress
)
7570 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7571 const struct prefix
*dest_p
;
7572 struct bgp_dest
*dest
, *top
;
7573 struct bgp_path_info
*pi
;
7574 bool toggle_suppression
;
7576 /* We've found a different MED we must revert any suppressed routes. */
7577 top
= bgp_node_get(table
, p
);
7578 for (dest
= bgp_node_get(table
, p
); dest
;
7579 dest
= bgp_route_next_until(dest
, top
)) {
7580 dest_p
= bgp_dest_get_prefix(dest
);
7581 if (dest_p
->prefixlen
<= p
->prefixlen
)
7584 toggle_suppression
= false;
7585 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7586 if (BGP_PATH_HOLDDOWN(pi
))
7588 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7591 /* We are toggling suppression back. */
7593 /* Suppress route if not suppressed already. */
7594 if (aggr_suppress_path(aggregate
, pi
))
7595 toggle_suppression
= true;
7599 /* Install route if there is no more suppression. */
7600 if (aggr_unsuppress_path(aggregate
, pi
))
7601 toggle_suppression
= true;
7604 if (toggle_suppression
)
7605 bgp_process(bgp
, dest
, afi
, safi
);
7607 bgp_dest_unlock_node(top
);
7611 * Aggregate address MED matching incremental test: this function is called
7612 * when the initial aggregation occurred and we are only testing a single
7615 * In addition to testing and setting the MED validity it also installs back
7616 * suppressed routes (if summary is configured).
7618 * Must not be called in `bgp_aggregate_route`.
7620 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7621 struct bgp
*bgp
, const struct prefix
*p
,
7622 afi_t afi
, safi_t safi
,
7623 struct bgp_path_info
*pi
)
7625 /* MED matching disabled. */
7626 if (!aggregate
->match_med
)
7629 /* Aggregation with different MED, recheck if we have got equal MEDs
7632 if (aggregate
->med_mismatched
&&
7633 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7634 aggregate
->summary_only
)
7635 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7638 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7640 /* No mismatches, just quit. */
7641 if (!aggregate
->med_mismatched
)
7644 /* Route summarization is disabled. */
7645 if (!aggregate
->summary_only
)
7648 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7651 /* Update an aggregate as routes are added/removed from the BGP table */
7652 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7653 safi_t safi
, struct bgp_aggregate
*aggregate
)
7655 struct bgp_table
*table
;
7656 struct bgp_dest
*top
;
7657 struct bgp_dest
*dest
;
7659 struct aspath
*aspath
= NULL
;
7660 struct community
*community
= NULL
;
7661 struct ecommunity
*ecommunity
= NULL
;
7662 struct lcommunity
*lcommunity
= NULL
;
7663 struct bgp_path_info
*pi
;
7664 unsigned long match
= 0;
7665 uint8_t atomic_aggregate
= 0;
7667 /* If the bgp instance is being deleted or self peer is deleted
7668 * then do not create aggregate route
7670 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7671 || (bgp
->peer_self
== NULL
))
7674 /* Initialize and test routes for MED difference. */
7675 if (aggregate
->match_med
)
7676 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7679 * Reset aggregate count: we might've been called from route map
7680 * update so in that case we must retest all more specific routes.
7682 * \see `bgp_route_map_process_update`.
7684 aggregate
->count
= 0;
7685 aggregate
->incomplete_origin_count
= 0;
7686 aggregate
->incomplete_origin_count
= 0;
7687 aggregate
->egp_origin_count
= 0;
7689 /* ORIGIN attribute: If at least one route among routes that are
7690 aggregated has ORIGIN with the value INCOMPLETE, then the
7691 aggregated route must have the ORIGIN attribute with the value
7692 INCOMPLETE. Otherwise, if at least one route among routes that
7693 are aggregated has ORIGIN with the value EGP, then the aggregated
7694 route must have the origin attribute with the value EGP. In all
7695 other case the value of the ORIGIN attribute of the aggregated
7696 route is INTERNAL. */
7697 origin
= BGP_ORIGIN_IGP
;
7699 table
= bgp
->rib
[afi
][safi
];
7701 top
= bgp_node_get(table
, p
);
7702 for (dest
= bgp_node_get(table
, p
); dest
;
7703 dest
= bgp_route_next_until(dest
, top
)) {
7704 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7706 if (dest_p
->prefixlen
<= p
->prefixlen
)
7709 /* If suppress fib is enabled and route not installed
7710 * in FIB, skip the route
7712 if (!bgp_check_advertise(bgp
, dest
))
7717 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7718 if (BGP_PATH_HOLDDOWN(pi
))
7722 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7723 atomic_aggregate
= 1;
7725 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7729 * summary-only aggregate route suppress
7730 * aggregated route announcements.
7733 * Don't create summaries if MED didn't match
7734 * otherwise neither the specific routes and the
7735 * aggregation will be announced.
7737 if (aggregate
->summary_only
7738 && AGGREGATE_MED_VALID(aggregate
)) {
7739 if (aggr_suppress_path(aggregate
, pi
))
7744 * Suppress more specific routes that match the route
7748 * Don't suppress routes if MED matching is enabled and
7749 * it mismatched otherwise we might end up with no
7750 * routes for this path.
7752 if (aggregate
->suppress_map_name
7753 && AGGREGATE_MED_VALID(aggregate
)
7754 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7755 if (aggr_suppress_path(aggregate
, pi
))
7762 * If at least one route among routes that are
7763 * aggregated has ORIGIN with the value INCOMPLETE,
7764 * then the aggregated route MUST have the ORIGIN
7765 * attribute with the value INCOMPLETE. Otherwise, if
7766 * at least one route among routes that are aggregated
7767 * has ORIGIN with the value EGP, then the aggregated
7768 * route MUST have the ORIGIN attribute with the value
7771 switch (pi
->attr
->origin
) {
7772 case BGP_ORIGIN_INCOMPLETE
:
7773 aggregate
->incomplete_origin_count
++;
7775 case BGP_ORIGIN_EGP
:
7776 aggregate
->egp_origin_count
++;
7784 if (!aggregate
->as_set
)
7788 * as-set aggregate route generate origin, as path,
7789 * and community aggregation.
7791 /* Compute aggregate route's as-path.
7793 bgp_compute_aggregate_aspath_hash(aggregate
,
7796 /* Compute aggregate route's community.
7798 if (bgp_attr_get_community(pi
->attr
))
7799 bgp_compute_aggregate_community_hash(
7801 bgp_attr_get_community(pi
->attr
));
7803 /* Compute aggregate route's extended community.
7805 if (bgp_attr_get_ecommunity(pi
->attr
))
7806 bgp_compute_aggregate_ecommunity_hash(
7808 bgp_attr_get_ecommunity(pi
->attr
));
7810 /* Compute aggregate route's large community.
7812 if (bgp_attr_get_lcommunity(pi
->attr
))
7813 bgp_compute_aggregate_lcommunity_hash(
7815 bgp_attr_get_lcommunity(pi
->attr
));
7818 bgp_process(bgp
, dest
, afi
, safi
);
7820 if (aggregate
->as_set
) {
7821 bgp_compute_aggregate_aspath_val(aggregate
);
7822 bgp_compute_aggregate_community_val(aggregate
);
7823 bgp_compute_aggregate_ecommunity_val(aggregate
);
7824 bgp_compute_aggregate_lcommunity_val(aggregate
);
7828 bgp_dest_unlock_node(top
);
7831 if (aggregate
->incomplete_origin_count
> 0)
7832 origin
= BGP_ORIGIN_INCOMPLETE
;
7833 else if (aggregate
->egp_origin_count
> 0)
7834 origin
= BGP_ORIGIN_EGP
;
7836 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7837 origin
= aggregate
->origin
;
7839 if (aggregate
->as_set
) {
7840 if (aggregate
->aspath
)
7841 /* Retrieve aggregate route's as-path.
7843 aspath
= aspath_dup(aggregate
->aspath
);
7845 if (aggregate
->community
)
7846 /* Retrieve aggregate route's community.
7848 community
= community_dup(aggregate
->community
);
7850 if (aggregate
->ecommunity
)
7851 /* Retrieve aggregate route's ecommunity.
7853 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7855 if (aggregate
->lcommunity
)
7856 /* Retrieve aggregate route's lcommunity.
7858 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7861 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7862 ecommunity
, lcommunity
, atomic_aggregate
,
7866 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7867 safi_t safi
, struct bgp_aggregate
*aggregate
)
7869 struct bgp_table
*table
;
7870 struct bgp_dest
*top
;
7871 struct bgp_dest
*dest
;
7872 struct bgp_path_info
*pi
;
7873 unsigned long match
;
7875 table
= bgp
->rib
[afi
][safi
];
7877 /* If routes exists below this node, generate aggregate routes. */
7878 top
= bgp_node_get(table
, p
);
7879 for (dest
= bgp_node_get(table
, p
); dest
;
7880 dest
= bgp_route_next_until(dest
, top
)) {
7881 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7883 if (dest_p
->prefixlen
<= p
->prefixlen
)
7887 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7888 if (BGP_PATH_HOLDDOWN(pi
))
7891 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7895 * This route is suppressed: attempt to unsuppress it.
7897 * `aggr_unsuppress_path` will fail if this particular
7898 * aggregate route was not the suppressor.
7900 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7901 listcount(pi
->extra
->aggr_suppressors
)) {
7902 if (aggr_unsuppress_path(aggregate
, pi
))
7908 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7909 aggregate
->incomplete_origin_count
--;
7910 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7911 aggregate
->egp_origin_count
--;
7913 if (aggregate
->as_set
) {
7914 /* Remove as-path from aggregate.
7916 bgp_remove_aspath_from_aggregate_hash(
7920 if (bgp_attr_get_community(pi
->attr
))
7921 /* Remove community from aggregate.
7923 bgp_remove_comm_from_aggregate_hash(
7925 bgp_attr_get_community(
7928 if (bgp_attr_get_ecommunity(pi
->attr
))
7929 /* Remove ecommunity from aggregate.
7931 bgp_remove_ecomm_from_aggregate_hash(
7933 bgp_attr_get_ecommunity(
7936 if (bgp_attr_get_lcommunity(pi
->attr
))
7937 /* Remove lcommunity from aggregate.
7939 bgp_remove_lcomm_from_aggregate_hash(
7941 bgp_attr_get_lcommunity(
7946 /* If this node was suppressed, process the change. */
7948 bgp_process(bgp
, dest
, afi
, safi
);
7950 if (aggregate
->as_set
) {
7951 aspath_free(aggregate
->aspath
);
7952 aggregate
->aspath
= NULL
;
7953 if (aggregate
->community
)
7954 community_free(&aggregate
->community
);
7955 if (aggregate
->ecommunity
)
7956 ecommunity_free(&aggregate
->ecommunity
);
7957 if (aggregate
->lcommunity
)
7958 lcommunity_free(&aggregate
->lcommunity
);
7961 bgp_dest_unlock_node(top
);
7964 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7965 const struct prefix
*aggr_p
,
7966 struct bgp_path_info
*pinew
, afi_t afi
,
7968 struct bgp_aggregate
*aggregate
)
7971 struct aspath
*aspath
= NULL
;
7972 uint8_t atomic_aggregate
= 0;
7973 struct community
*community
= NULL
;
7974 struct ecommunity
*ecommunity
= NULL
;
7975 struct lcommunity
*lcommunity
= NULL
;
7977 /* If the bgp instance is being deleted or self peer is deleted
7978 * then do not create aggregate route
7980 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7981 || (bgp
->peer_self
== NULL
))
7984 /* ORIGIN attribute: If at least one route among routes that are
7985 * aggregated has ORIGIN with the value INCOMPLETE, then the
7986 * aggregated route must have the ORIGIN attribute with the value
7987 * INCOMPLETE. Otherwise, if at least one route among routes that
7988 * are aggregated has ORIGIN with the value EGP, then the aggregated
7989 * route must have the origin attribute with the value EGP. In all
7990 * other case the value of the ORIGIN attribute of the aggregated
7991 * route is INTERNAL.
7993 origin
= BGP_ORIGIN_IGP
;
7998 * This must be called before `summary` check to avoid
7999 * "suppressing" twice.
8001 if (aggregate
->match_med
)
8002 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8005 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8006 aggr_suppress_path(aggregate
, pinew
);
8008 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8009 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8010 aggr_suppress_path(aggregate
, pinew
);
8012 switch (pinew
->attr
->origin
) {
8013 case BGP_ORIGIN_INCOMPLETE
:
8014 aggregate
->incomplete_origin_count
++;
8016 case BGP_ORIGIN_EGP
:
8017 aggregate
->egp_origin_count
++;
8025 if (aggregate
->incomplete_origin_count
> 0)
8026 origin
= BGP_ORIGIN_INCOMPLETE
;
8027 else if (aggregate
->egp_origin_count
> 0)
8028 origin
= BGP_ORIGIN_EGP
;
8030 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8031 origin
= aggregate
->origin
;
8033 if (aggregate
->as_set
) {
8034 /* Compute aggregate route's as-path.
8036 bgp_compute_aggregate_aspath(aggregate
,
8037 pinew
->attr
->aspath
);
8039 /* Compute aggregate route's community.
8041 if (bgp_attr_get_community(pinew
->attr
))
8042 bgp_compute_aggregate_community(
8043 aggregate
, bgp_attr_get_community(pinew
->attr
));
8045 /* Compute aggregate route's extended community.
8047 if (bgp_attr_get_ecommunity(pinew
->attr
))
8048 bgp_compute_aggregate_ecommunity(
8050 bgp_attr_get_ecommunity(pinew
->attr
));
8052 /* Compute aggregate route's large community.
8054 if (bgp_attr_get_lcommunity(pinew
->attr
))
8055 bgp_compute_aggregate_lcommunity(
8057 bgp_attr_get_lcommunity(pinew
->attr
));
8059 /* Retrieve aggregate route's as-path.
8061 if (aggregate
->aspath
)
8062 aspath
= aspath_dup(aggregate
->aspath
);
8064 /* Retrieve aggregate route's community.
8066 if (aggregate
->community
)
8067 community
= community_dup(aggregate
->community
);
8069 /* Retrieve aggregate route's ecommunity.
8071 if (aggregate
->ecommunity
)
8072 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8074 /* Retrieve aggregate route's lcommunity.
8076 if (aggregate
->lcommunity
)
8077 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8080 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8081 aspath
, community
, ecommunity
,
8082 lcommunity
, atomic_aggregate
, aggregate
);
8085 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8087 struct bgp_path_info
*pi
,
8088 struct bgp_aggregate
*aggregate
,
8089 const struct prefix
*aggr_p
)
8092 struct aspath
*aspath
= NULL
;
8093 uint8_t atomic_aggregate
= 0;
8094 struct community
*community
= NULL
;
8095 struct ecommunity
*ecommunity
= NULL
;
8096 struct lcommunity
*lcommunity
= NULL
;
8097 unsigned long match
= 0;
8099 /* If the bgp instance is being deleted or self peer is deleted
8100 * then do not create aggregate route
8102 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8103 || (bgp
->peer_self
== NULL
))
8106 if (BGP_PATH_HOLDDOWN(pi
))
8109 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8112 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8113 if (aggr_unsuppress_path(aggregate
, pi
))
8116 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8117 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8118 if (aggr_unsuppress_path(aggregate
, pi
))
8122 * This must be called after `summary`, `suppress-map` check to avoid
8123 * "unsuppressing" twice.
8125 if (aggregate
->match_med
)
8126 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8128 if (aggregate
->count
> 0)
8131 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8132 aggregate
->incomplete_origin_count
--;
8133 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8134 aggregate
->egp_origin_count
--;
8136 if (aggregate
->as_set
) {
8137 /* Remove as-path from aggregate.
8139 bgp_remove_aspath_from_aggregate(aggregate
,
8142 if (bgp_attr_get_community(pi
->attr
))
8143 /* Remove community from aggregate.
8145 bgp_remove_community_from_aggregate(
8146 aggregate
, bgp_attr_get_community(pi
->attr
));
8148 if (bgp_attr_get_ecommunity(pi
->attr
))
8149 /* Remove ecommunity from aggregate.
8151 bgp_remove_ecommunity_from_aggregate(
8152 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8154 if (bgp_attr_get_lcommunity(pi
->attr
))
8155 /* Remove lcommunity from aggregate.
8157 bgp_remove_lcommunity_from_aggregate(
8158 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8161 /* If this node was suppressed, process the change. */
8163 bgp_process(bgp
, pi
->net
, afi
, safi
);
8165 origin
= BGP_ORIGIN_IGP
;
8166 if (aggregate
->incomplete_origin_count
> 0)
8167 origin
= BGP_ORIGIN_INCOMPLETE
;
8168 else if (aggregate
->egp_origin_count
> 0)
8169 origin
= BGP_ORIGIN_EGP
;
8171 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8172 origin
= aggregate
->origin
;
8174 if (aggregate
->as_set
) {
8175 /* Retrieve aggregate route's as-path.
8177 if (aggregate
->aspath
)
8178 aspath
= aspath_dup(aggregate
->aspath
);
8180 /* Retrieve aggregate route's community.
8182 if (aggregate
->community
)
8183 community
= community_dup(aggregate
->community
);
8185 /* Retrieve aggregate route's ecommunity.
8187 if (aggregate
->ecommunity
)
8188 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8190 /* Retrieve aggregate route's lcommunity.
8192 if (aggregate
->lcommunity
)
8193 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8196 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8197 aspath
, community
, ecommunity
,
8198 lcommunity
, atomic_aggregate
, aggregate
);
8201 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8202 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8204 struct bgp_dest
*child
;
8205 struct bgp_dest
*dest
;
8206 struct bgp_aggregate
*aggregate
;
8207 struct bgp_table
*table
;
8209 table
= bgp
->aggregate
[afi
][safi
];
8211 /* No aggregates configured. */
8212 if (bgp_table_top_nolock(table
) == NULL
)
8215 if (p
->prefixlen
== 0)
8218 if (BGP_PATH_HOLDDOWN(pi
))
8221 /* If suppress fib is enabled and route not installed
8222 * in FIB, do not update the aggregate route
8224 if (!bgp_check_advertise(bgp
, pi
->net
))
8227 child
= bgp_node_get(table
, p
);
8229 /* Aggregate address configuration check. */
8230 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8231 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8233 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8234 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8235 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8239 bgp_dest_unlock_node(child
);
8242 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8243 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8245 struct bgp_dest
*child
;
8246 struct bgp_dest
*dest
;
8247 struct bgp_aggregate
*aggregate
;
8248 struct bgp_table
*table
;
8250 table
= bgp
->aggregate
[afi
][safi
];
8252 /* No aggregates configured. */
8253 if (bgp_table_top_nolock(table
) == NULL
)
8256 if (p
->prefixlen
== 0)
8259 child
= bgp_node_get(table
, p
);
8261 /* Aggregate address configuration check. */
8262 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8263 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8265 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8266 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8267 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8271 bgp_dest_unlock_node(child
);
8274 /* Aggregate route attribute. */
8275 #define AGGREGATE_SUMMARY_ONLY 1
8276 #define AGGREGATE_AS_SET 1
8277 #define AGGREGATE_AS_UNSET 0
8279 static const char *bgp_origin2str(uint8_t origin
)
8282 case BGP_ORIGIN_IGP
:
8284 case BGP_ORIGIN_EGP
:
8286 case BGP_ORIGIN_INCOMPLETE
:
8287 return "incomplete";
8292 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8295 case RPKI_NOT_BEING_USED
:
8305 assert(!"We should never get here this is a dev escape");
8309 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8310 afi_t afi
, safi_t safi
)
8312 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8315 struct bgp_dest
*dest
;
8316 struct bgp_aggregate
*aggregate
;
8318 /* Convert string to prefix structure. */
8319 ret
= str2prefix(prefix_str
, &p
);
8321 vty_out(vty
, "Malformed prefix\n");
8322 return CMD_WARNING_CONFIG_FAILED
;
8326 /* Old configuration check. */
8327 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8330 "%% There is no aggregate-address configuration.\n");
8331 return CMD_WARNING_CONFIG_FAILED
;
8334 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8335 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8336 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8337 NULL
, NULL
, 0, aggregate
);
8339 /* Unlock aggregate address configuration. */
8340 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8342 if (aggregate
->community
)
8343 community_free(&aggregate
->community
);
8345 if (aggregate
->community_hash
) {
8346 /* Delete all communities in the hash.
8348 hash_clean(aggregate
->community_hash
,
8349 bgp_aggr_community_remove
);
8350 /* Free up the community_hash.
8352 hash_free(aggregate
->community_hash
);
8355 if (aggregate
->ecommunity
)
8356 ecommunity_free(&aggregate
->ecommunity
);
8358 if (aggregate
->ecommunity_hash
) {
8359 /* Delete all ecommunities in the hash.
8361 hash_clean(aggregate
->ecommunity_hash
,
8362 bgp_aggr_ecommunity_remove
);
8363 /* Free up the ecommunity_hash.
8365 hash_free(aggregate
->ecommunity_hash
);
8368 if (aggregate
->lcommunity
)
8369 lcommunity_free(&aggregate
->lcommunity
);
8371 if (aggregate
->lcommunity_hash
) {
8372 /* Delete all lcommunities in the hash.
8374 hash_clean(aggregate
->lcommunity_hash
,
8375 bgp_aggr_lcommunity_remove
);
8376 /* Free up the lcommunity_hash.
8378 hash_free(aggregate
->lcommunity_hash
);
8381 if (aggregate
->aspath
)
8382 aspath_free(aggregate
->aspath
);
8384 if (aggregate
->aspath_hash
) {
8385 /* Delete all as-paths in the hash.
8387 hash_clean(aggregate
->aspath_hash
,
8388 bgp_aggr_aspath_remove
);
8389 /* Free up the aspath_hash.
8391 hash_free(aggregate
->aspath_hash
);
8394 bgp_aggregate_free(aggregate
);
8395 bgp_dest_unlock_node(dest
);
8396 bgp_dest_unlock_node(dest
);
8401 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8402 safi_t safi
, const char *rmap
,
8403 uint8_t summary_only
, uint8_t as_set
,
8404 uint8_t origin
, bool match_med
,
8405 const char *suppress_map
)
8407 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8410 struct bgp_dest
*dest
;
8411 struct bgp_aggregate
*aggregate
;
8412 uint8_t as_set_new
= as_set
;
8414 if (suppress_map
&& summary_only
) {
8416 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8417 return CMD_WARNING_CONFIG_FAILED
;
8420 /* Convert string to prefix structure. */
8421 ret
= str2prefix(prefix_str
, &p
);
8423 vty_out(vty
, "Malformed prefix\n");
8424 return CMD_WARNING_CONFIG_FAILED
;
8428 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8429 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8430 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8432 return CMD_WARNING_CONFIG_FAILED
;
8435 /* Old configuration check. */
8436 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8437 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8440 vty_out(vty
, "There is already same aggregate network.\n");
8441 /* try to remove the old entry */
8442 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8444 vty_out(vty
, "Error deleting aggregate.\n");
8445 bgp_dest_unlock_node(dest
);
8446 return CMD_WARNING_CONFIG_FAILED
;
8450 /* Make aggregate address structure. */
8451 aggregate
= bgp_aggregate_new();
8452 aggregate
->summary_only
= summary_only
;
8453 aggregate
->match_med
= match_med
;
8455 /* Network operators MUST NOT locally generate any new
8456 * announcements containing AS_SET or AS_CONFED_SET. If they have
8457 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8458 * SHOULD withdraw those routes and re-announce routes for the
8459 * aggregate or component prefixes (i.e., the more-specific routes
8460 * subsumed by the previously aggregated route) without AS_SET
8461 * or AS_CONFED_SET in the updates.
8463 if (bgp
->reject_as_sets
) {
8464 if (as_set
== AGGREGATE_AS_SET
) {
8465 as_set_new
= AGGREGATE_AS_UNSET
;
8467 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8470 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8474 aggregate
->as_set
= as_set_new
;
8475 aggregate
->safi
= safi
;
8476 /* Override ORIGIN attribute if defined.
8477 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8478 * to IGP which is not what rfc4271 says.
8479 * This enables the same behavior, optionally.
8481 aggregate
->origin
= origin
;
8484 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8485 route_map_counter_decrement(aggregate
->rmap
.map
);
8486 aggregate
->rmap
.name
=
8487 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8488 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8489 route_map_counter_increment(aggregate
->rmap
.map
);
8493 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8494 route_map_counter_decrement(aggregate
->suppress_map
);
8496 aggregate
->suppress_map_name
=
8497 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8498 aggregate
->suppress_map
=
8499 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8500 route_map_counter_increment(aggregate
->suppress_map
);
8503 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8505 /* Aggregate address insert into BGP routing table. */
8506 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8511 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8512 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8514 "|summary-only$summary_only"
8515 "|route-map RMAP_NAME$rmap_name"
8516 "|origin <egp|igp|incomplete>$origin_s"
8517 "|matching-MED-only$match_med"
8518 "|suppress-map RMAP_NAME$suppress_map"
8521 "Configure BGP aggregate entries\n"
8522 "Aggregate prefix\n"
8523 "Aggregate address\n"
8525 "Generate AS set path information\n"
8526 "Filter more specific routes from updates\n"
8527 "Apply route map to aggregate network\n"
8532 "Unknown heritage\n"
8533 "Only aggregate routes with matching MED\n"
8534 "Suppress the selected more specific routes\n"
8535 "Route map with the route selectors\n")
8537 const char *prefix_s
= NULL
;
8538 safi_t safi
= bgp_node_safi(vty
);
8539 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8540 int as_set
= AGGREGATE_AS_UNSET
;
8541 char prefix_buf
[PREFIX2STR_BUFFER
];
8544 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8547 vty_out(vty
, "%% Inconsistent address and mask\n");
8548 return CMD_WARNING_CONFIG_FAILED
;
8550 prefix_s
= prefix_buf
;
8552 prefix_s
= prefix_str
;
8555 if (strcmp(origin_s
, "egp") == 0)
8556 origin
= BGP_ORIGIN_EGP
;
8557 else if (strcmp(origin_s
, "igp") == 0)
8558 origin
= BGP_ORIGIN_IGP
;
8559 else if (strcmp(origin_s
, "incomplete") == 0)
8560 origin
= BGP_ORIGIN_INCOMPLETE
;
8564 as_set
= AGGREGATE_AS_SET
;
8566 /* Handle configuration removal, otherwise installation. */
8568 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8570 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8571 summary_only
!= NULL
, as_set
, origin
,
8572 match_med
!= NULL
, suppress_map
);
8575 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8576 "[no] aggregate-address X:X::X:X/M$prefix [{"
8578 "|summary-only$summary_only"
8579 "|route-map RMAP_NAME$rmap_name"
8580 "|origin <egp|igp|incomplete>$origin_s"
8581 "|matching-MED-only$match_med"
8582 "|suppress-map RMAP_NAME$suppress_map"
8585 "Configure BGP aggregate entries\n"
8586 "Aggregate prefix\n"
8587 "Generate AS set path information\n"
8588 "Filter more specific routes from updates\n"
8589 "Apply route map to aggregate network\n"
8594 "Unknown heritage\n"
8595 "Only aggregate routes with matching MED\n"
8596 "Suppress the selected more specific routes\n"
8597 "Route map with the route selectors\n")
8599 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8600 int as_set
= AGGREGATE_AS_UNSET
;
8603 if (strcmp(origin_s
, "egp") == 0)
8604 origin
= BGP_ORIGIN_EGP
;
8605 else if (strcmp(origin_s
, "igp") == 0)
8606 origin
= BGP_ORIGIN_IGP
;
8607 else if (strcmp(origin_s
, "incomplete") == 0)
8608 origin
= BGP_ORIGIN_INCOMPLETE
;
8612 as_set
= AGGREGATE_AS_SET
;
8614 /* Handle configuration removal, otherwise installation. */
8616 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8619 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8620 rmap_name
, summary_only
!= NULL
, as_set
,
8621 origin
, match_med
!= NULL
, suppress_map
);
8624 /* Redistribute route treatment. */
8625 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8626 const union g_addr
*nexthop
, ifindex_t ifindex
,
8627 enum nexthop_types_t nhtype
, uint8_t distance
,
8628 enum blackhole_type bhtype
, uint32_t metric
,
8629 uint8_t type
, unsigned short instance
,
8632 struct bgp_path_info
*new;
8633 struct bgp_path_info
*bpi
;
8634 struct bgp_path_info rmap_path
;
8635 struct bgp_dest
*bn
;
8637 struct attr
*new_attr
;
8639 route_map_result_t ret
;
8640 struct bgp_redist
*red
;
8642 /* Make default attribute. */
8643 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8645 * This must not be NULL to satisfy Coverity SA
8647 assert(attr
.aspath
);
8650 case NEXTHOP_TYPE_IFINDEX
:
8651 switch (p
->family
) {
8653 attr
.nexthop
.s_addr
= INADDR_ANY
;
8654 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8657 memset(&attr
.mp_nexthop_global
, 0,
8658 sizeof(attr
.mp_nexthop_global
));
8659 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8663 case NEXTHOP_TYPE_IPV4
:
8664 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8665 attr
.nexthop
= nexthop
->ipv4
;
8666 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8668 case NEXTHOP_TYPE_IPV6
:
8669 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8670 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8671 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8673 case NEXTHOP_TYPE_BLACKHOLE
:
8674 switch (p
->family
) {
8676 attr
.nexthop
.s_addr
= INADDR_ANY
;
8677 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8680 memset(&attr
.mp_nexthop_global
, 0,
8681 sizeof(attr
.mp_nexthop_global
));
8682 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8685 attr
.bh_type
= bhtype
;
8688 attr
.nh_type
= nhtype
;
8689 attr
.nh_ifindex
= ifindex
;
8692 attr
.distance
= distance
;
8693 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8697 bgp_attr_set_aigp_metric(&attr
, metric
);
8699 afi
= family2afi(p
->family
);
8701 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8703 struct attr attr_new
;
8705 /* Copy attribute for modification. */
8708 if (red
->redist_metric_flag
) {
8709 attr_new
.med
= red
->redist_metric
;
8710 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8713 /* Apply route-map. */
8714 if (red
->rmap
.name
) {
8715 memset(&rmap_path
, 0, sizeof(rmap_path
));
8716 rmap_path
.peer
= bgp
->peer_self
;
8717 rmap_path
.attr
= &attr_new
;
8719 SET_FLAG(bgp
->peer_self
->rmap_type
,
8720 PEER_RMAP_TYPE_REDISTRIBUTE
);
8722 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8724 bgp
->peer_self
->rmap_type
= 0;
8726 if (ret
== RMAP_DENYMATCH
) {
8727 /* Free uninterned attribute. */
8728 bgp_attr_flush(&attr_new
);
8730 /* Unintern original. */
8731 aspath_unintern(&attr
.aspath
);
8732 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8737 if (bgp_in_graceful_shutdown(bgp
))
8738 bgp_attr_add_gshut_community(&attr_new
);
8740 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8741 SAFI_UNICAST
, p
, NULL
);
8743 new_attr
= bgp_attr_intern(&attr_new
);
8745 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8746 if (bpi
->peer
== bgp
->peer_self
8747 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8751 /* Ensure the (source route) type is updated. */
8753 if (attrhash_cmp(bpi
->attr
, new_attr
)
8754 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8755 bgp_attr_unintern(&new_attr
);
8756 aspath_unintern(&attr
.aspath
);
8757 bgp_dest_unlock_node(bn
);
8760 /* The attribute is changed. */
8761 bgp_path_info_set_flag(bn
, bpi
,
8762 BGP_PATH_ATTR_CHANGED
);
8764 /* Rewrite BGP route information. */
8765 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8766 bgp_path_info_restore(bn
, bpi
);
8768 bgp_aggregate_decrement(
8769 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8770 bgp_attr_unintern(&bpi
->attr
);
8771 bpi
->attr
= new_attr
;
8772 bpi
->uptime
= monotime(NULL
);
8774 /* Process change. */
8775 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8777 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8778 bgp_dest_unlock_node(bn
);
8779 aspath_unintern(&attr
.aspath
);
8781 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8783 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8785 vpn_leak_from_vrf_update(
8786 bgp_get_default(), bgp
, bpi
);
8792 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8793 bgp
->peer_self
, new_attr
, bn
);
8794 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8796 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8797 bgp_path_info_add(bn
, new);
8798 bgp_dest_unlock_node(bn
);
8799 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8800 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8802 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8803 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8805 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8809 /* Unintern original. */
8810 aspath_unintern(&attr
.aspath
);
8813 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8814 unsigned short instance
)
8817 struct bgp_dest
*dest
;
8818 struct bgp_path_info
*pi
;
8819 struct bgp_redist
*red
;
8821 afi
= family2afi(p
->family
);
8823 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8825 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8826 SAFI_UNICAST
, p
, NULL
);
8828 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8829 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8833 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8834 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8836 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8839 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8840 bgp_path_info_delete(dest
, pi
);
8841 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8843 bgp_dest_unlock_node(dest
);
8847 /* Withdraw specified route type's route. */
8848 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8849 unsigned short instance
)
8851 struct bgp_dest
*dest
;
8852 struct bgp_path_info
*pi
;
8853 struct bgp_table
*table
;
8855 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8857 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8858 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8859 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8860 && pi
->instance
== instance
)
8864 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8865 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8867 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8870 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8871 pi
, afi
, SAFI_UNICAST
);
8872 bgp_path_info_delete(dest
, pi
);
8873 if (!CHECK_FLAG(bgp
->flags
,
8874 BGP_FLAG_DELETE_IN_PROGRESS
))
8875 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8877 bgp_path_info_reap(dest
, pi
);
8882 /* Static function to display route. */
8883 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8884 struct vty
*vty
, json_object
*json
, bool wide
)
8887 char buf
[INET6_ADDRSTRLEN
];
8889 if (p
->family
== AF_INET
) {
8891 len
= vty_out(vty
, "%pFX", p
);
8893 json_object_string_add(json
, "prefix",
8894 inet_ntop(p
->family
,
8897 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8898 json_object_string_addf(json
, "network", "%pFX", p
);
8899 json_object_int_add(json
, "version", dest
->version
);
8901 } else if (p
->family
== AF_ETHERNET
) {
8902 len
= vty_out(vty
, "%pFX", p
);
8903 } else if (p
->family
== AF_EVPN
) {
8905 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8907 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8908 } else if (p
->family
== AF_FLOWSPEC
) {
8909 route_vty_out_flowspec(vty
, p
, NULL
,
8911 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8912 NLRI_STRING_FORMAT_MIN
, json
);
8915 len
= vty_out(vty
, "%pFX", p
);
8917 json_object_string_add(json
, "prefix",
8918 inet_ntop(p
->family
,
8921 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8922 json_object_string_addf(json
, "network", "%pFX", p
);
8923 json_object_int_add(json
, "version", dest
->version
);
8928 len
= wide
? (45 - len
) : (17 - len
);
8930 vty_out(vty
, "\n%*s", 20, " ");
8932 vty_out(vty
, "%*s", len
, " ");
8936 enum bgp_display_type
{
8940 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8943 case bgp_path_selection_none
:
8944 return "Nothing to Select";
8945 case bgp_path_selection_first
:
8946 return "First path received";
8947 case bgp_path_selection_evpn_sticky_mac
:
8948 return "EVPN Sticky Mac";
8949 case bgp_path_selection_evpn_seq
:
8950 return "EVPN sequence number";
8951 case bgp_path_selection_evpn_lower_ip
:
8952 return "EVPN lower IP";
8953 case bgp_path_selection_evpn_local_path
:
8954 return "EVPN local ES path";
8955 case bgp_path_selection_evpn_non_proxy
:
8956 return "EVPN non proxy";
8957 case bgp_path_selection_weight
:
8959 case bgp_path_selection_local_pref
:
8960 return "Local Pref";
8961 case bgp_path_selection_accept_own
:
8962 return "Accept Own";
8963 case bgp_path_selection_local_route
:
8964 return "Local Route";
8965 case bgp_path_selection_aigp
:
8967 case bgp_path_selection_confed_as_path
:
8968 return "Confederation based AS Path";
8969 case bgp_path_selection_as_path
:
8971 case bgp_path_selection_origin
:
8973 case bgp_path_selection_med
:
8975 case bgp_path_selection_peer
:
8977 case bgp_path_selection_confed
:
8978 return "Confed Peer Type";
8979 case bgp_path_selection_igp_metric
:
8980 return "IGP Metric";
8981 case bgp_path_selection_older
:
8982 return "Older Path";
8983 case bgp_path_selection_router_id
:
8985 case bgp_path_selection_cluster_length
:
8986 return "Cluster length";
8987 case bgp_path_selection_stale
:
8988 return "Path Staleness";
8989 case bgp_path_selection_local_configured
:
8990 return "Locally configured route";
8991 case bgp_path_selection_neighbor_ip
:
8992 return "Neighbor IP";
8993 case bgp_path_selection_default
:
8994 return "Nothing left to compare";
8996 return "Invalid (internal error)";
8999 /* Print the short form route status for a bgp_path_info */
9000 static void route_vty_short_status_out(struct vty
*vty
,
9001 struct bgp_path_info
*path
,
9002 const struct prefix
*p
,
9003 json_object
*json_path
)
9005 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
9009 /* Route status display. */
9010 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9011 json_object_boolean_true_add(json_path
, "removed");
9013 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9014 json_object_boolean_true_add(json_path
, "stale");
9016 if (path
->extra
&& bgp_path_suppressed(path
))
9017 json_object_boolean_true_add(json_path
, "suppressed");
9019 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9020 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9021 json_object_boolean_true_add(json_path
, "valid");
9024 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9025 json_object_boolean_true_add(json_path
, "history");
9027 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9028 json_object_boolean_true_add(json_path
, "damped");
9030 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9031 json_object_boolean_true_add(json_path
, "bestpath");
9032 json_object_string_add(json_path
, "selectionReason",
9033 bgp_path_selection_reason2str(
9034 path
->net
->reason
));
9037 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9038 json_object_boolean_true_add(json_path
, "multipath");
9040 /* Internal route. */
9041 if ((path
->peer
->as
)
9042 && (path
->peer
->as
== path
->peer
->local_as
))
9043 json_object_string_add(json_path
, "pathFrom",
9046 json_object_string_add(json_path
, "pathFrom",
9052 /* RPKI validation state */
9054 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9056 if (rpki_state
== RPKI_VALID
)
9058 else if (rpki_state
== RPKI_INVALID
)
9060 else if (rpki_state
== RPKI_NOTFOUND
)
9065 /* Route status display. */
9066 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9068 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9070 else if (bgp_path_suppressed(path
))
9072 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9073 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9079 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9081 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9083 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9085 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9090 /* Internal route. */
9091 if (path
->peer
&& (path
->peer
->as
)
9092 && (path
->peer
->as
== path
->peer
->local_as
))
9098 static char *bgp_nexthop_hostname(struct peer
*peer
,
9099 struct bgp_nexthop_cache
*bnc
)
9102 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9103 return peer
->hostname
;
9107 /* called from terminal list command */
9108 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9109 struct bgp_path_info
*path
, int display
, safi_t safi
,
9110 json_object
*json_paths
, bool wide
)
9113 struct attr
*attr
= path
->attr
;
9114 json_object
*json_path
= NULL
;
9115 json_object
*json_nexthops
= NULL
;
9116 json_object
*json_nexthop_global
= NULL
;
9117 json_object
*json_nexthop_ll
= NULL
;
9118 json_object
*json_ext_community
= NULL
;
9119 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9121 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9122 bool nexthop_othervrf
= false;
9123 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9124 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9125 char *nexthop_hostname
=
9126 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9127 char esi_buf
[ESI_STR_LEN
];
9130 json_path
= json_object_new_object();
9132 /* short status lead text */
9133 route_vty_short_status_out(vty
, path
, p
, json_path
);
9136 /* print prefix and mask */
9138 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9140 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9142 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9146 * If vrf id of nexthop is different from that of prefix,
9147 * set up printable string to append
9149 if (path
->extra
&& path
->extra
->bgp_orig
) {
9150 const char *self
= "";
9155 nexthop_othervrf
= true;
9156 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9158 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9159 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9160 "@%s%s", VRFID_NONE_STR
, self
);
9162 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9163 path
->extra
->bgp_orig
->vrf_id
, self
);
9165 if (path
->extra
->bgp_orig
->inst_type
9166 != BGP_INSTANCE_TYPE_DEFAULT
)
9168 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9170 const char *self
= "";
9175 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9179 * For ENCAP and EVPN routes, nexthop address family is not
9180 * neccessarily the same as the prefix address family.
9181 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9182 * EVPN routes are also exchanged with a MP nexthop. Currently,
9184 * is only IPv4, the value will be present in either
9186 * attr->mp_nexthop_global_in
9188 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9190 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9194 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9195 &attr
->mp_nexthop_global_in
);
9198 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9199 &attr
->mp_nexthop_global
);
9202 snprintf(nexthop
, sizeof(nexthop
), "?");
9207 json_nexthop_global
= json_object_new_object();
9209 json_object_string_add(json_nexthop_global
, "ip",
9212 if (path
->peer
->hostname
)
9213 json_object_string_add(json_nexthop_global
,
9215 path
->peer
->hostname
);
9217 json_object_string_add(json_nexthop_global
, "afi",
9218 (af
== AF_INET
) ? "ipv4"
9220 json_object_boolean_true_add(json_nexthop_global
,
9223 if (nexthop_hostname
)
9224 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9225 nexthop_hostname
, vrf_id_str
);
9227 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9229 len
= wide
? (41 - len
) : (16 - len
);
9231 vty_out(vty
, "\n%*s", 36, " ");
9233 vty_out(vty
, "%*s", len
, " ");
9235 } else if (safi
== SAFI_EVPN
) {
9237 json_nexthop_global
= json_object_new_object();
9239 json_object_string_addf(json_nexthop_global
, "ip",
9241 &attr
->mp_nexthop_global_in
);
9243 if (path
->peer
->hostname
)
9244 json_object_string_add(json_nexthop_global
,
9246 path
->peer
->hostname
);
9248 json_object_string_add(json_nexthop_global
, "afi",
9250 json_object_boolean_true_add(json_nexthop_global
,
9253 if (nexthop_hostname
)
9254 len
= vty_out(vty
, "%pI4(%s)%s",
9255 &attr
->mp_nexthop_global_in
,
9256 nexthop_hostname
, vrf_id_str
);
9258 len
= vty_out(vty
, "%pI4%s",
9259 &attr
->mp_nexthop_global_in
,
9262 len
= wide
? (41 - len
) : (16 - len
);
9264 vty_out(vty
, "\n%*s", 36, " ");
9266 vty_out(vty
, "%*s", len
, " ");
9268 } else if (safi
== SAFI_FLOWSPEC
) {
9269 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9271 json_nexthop_global
= json_object_new_object();
9273 json_object_string_add(json_nexthop_global
,
9275 json_object_string_addf(json_nexthop_global
,
9279 if (path
->peer
->hostname
)
9280 json_object_string_add(
9281 json_nexthop_global
, "hostname",
9282 path
->peer
->hostname
);
9284 json_object_boolean_true_add(
9285 json_nexthop_global
,
9288 if (nexthop_hostname
)
9289 len
= vty_out(vty
, "%pI4(%s)%s",
9294 len
= vty_out(vty
, "%pI4%s",
9298 len
= wide
? (41 - len
) : (16 - len
);
9300 vty_out(vty
, "\n%*s", 36, " ");
9302 vty_out(vty
, "%*s", len
, " ");
9305 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9307 json_nexthop_global
= json_object_new_object();
9309 json_object_string_addf(json_nexthop_global
, "ip",
9310 "%pI4", &attr
->nexthop
);
9312 if (path
->peer
->hostname
)
9313 json_object_string_add(json_nexthop_global
,
9315 path
->peer
->hostname
);
9317 json_object_string_add(json_nexthop_global
, "afi",
9319 json_object_boolean_true_add(json_nexthop_global
,
9322 if (nexthop_hostname
)
9323 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9324 nexthop_hostname
, vrf_id_str
);
9326 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9329 len
= wide
? (41 - len
) : (16 - len
);
9331 vty_out(vty
, "\n%*s", 36, " ");
9333 vty_out(vty
, "%*s", len
, " ");
9338 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9340 json_nexthop_global
= json_object_new_object();
9341 json_object_string_addf(json_nexthop_global
, "ip",
9343 &attr
->mp_nexthop_global
);
9345 if (path
->peer
->hostname
)
9346 json_object_string_add(json_nexthop_global
,
9348 path
->peer
->hostname
);
9350 json_object_string_add(json_nexthop_global
, "afi",
9352 json_object_string_add(json_nexthop_global
, "scope",
9355 /* We display both LL & GL if both have been
9357 if ((attr
->mp_nexthop_len
9358 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9359 || (path
->peer
->conf_if
)) {
9360 json_nexthop_ll
= json_object_new_object();
9361 json_object_string_addf(
9362 json_nexthop_ll
, "ip", "%pI6",
9363 &attr
->mp_nexthop_local
);
9365 if (path
->peer
->hostname
)
9366 json_object_string_add(
9367 json_nexthop_ll
, "hostname",
9368 path
->peer
->hostname
);
9370 json_object_string_add(json_nexthop_ll
, "afi",
9372 json_object_string_add(json_nexthop_ll
, "scope",
9375 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9376 &attr
->mp_nexthop_local
)
9378 && !attr
->mp_nexthop_prefer_global
)
9379 json_object_boolean_true_add(
9380 json_nexthop_ll
, "used");
9382 json_object_boolean_true_add(
9383 json_nexthop_global
, "used");
9385 json_object_boolean_true_add(
9386 json_nexthop_global
, "used");
9388 /* Display LL if LL/Global both in table unless
9389 * prefer-global is set */
9390 if (((attr
->mp_nexthop_len
9391 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9392 && !attr
->mp_nexthop_prefer_global
)
9393 || (path
->peer
->conf_if
)) {
9394 if (path
->peer
->conf_if
) {
9395 len
= vty_out(vty
, "%s",
9396 path
->peer
->conf_if
);
9397 /* len of IPv6 addr + max len of def
9399 len
= wide
? (41 - len
) : (16 - len
);
9402 vty_out(vty
, "\n%*s", 36, " ");
9404 vty_out(vty
, "%*s", len
, " ");
9406 if (nexthop_hostname
)
9409 &attr
->mp_nexthop_local
,
9415 &attr
->mp_nexthop_local
,
9418 len
= wide
? (41 - len
) : (16 - len
);
9421 vty_out(vty
, "\n%*s", 36, " ");
9423 vty_out(vty
, "%*s", len
, " ");
9426 if (nexthop_hostname
)
9427 len
= vty_out(vty
, "%pI6(%s)%s",
9428 &attr
->mp_nexthop_global
,
9432 len
= vty_out(vty
, "%pI6%s",
9433 &attr
->mp_nexthop_global
,
9436 len
= wide
? (41 - len
) : (16 - len
);
9439 vty_out(vty
, "\n%*s", 36, " ");
9441 vty_out(vty
, "%*s", len
, " ");
9447 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9449 json_object_int_add(json_path
, "metric", attr
->med
);
9451 vty_out(vty
, "%7u", attr
->med
);
9453 vty_out(vty
, "%10u", attr
->med
);
9454 else if (!json_paths
) {
9456 vty_out(vty
, "%*s", 7, " ");
9458 vty_out(vty
, "%*s", 10, " ");
9462 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9464 json_object_int_add(json_path
, "locPrf",
9467 vty_out(vty
, "%7u", attr
->local_pref
);
9468 else if (!json_paths
)
9472 json_object_int_add(json_path
, "weight", attr
->weight
);
9474 vty_out(vty
, "%7u ", attr
->weight
);
9477 json_object_string_addf(json_path
, "peerId", "%pSU",
9483 json_object_string_add(json_path
, "path",
9486 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9491 json_object_string_add(json_path
, "origin",
9492 bgp_origin_long_str
[attr
->origin
]);
9494 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9497 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9498 json_object_string_add(json_path
, "esi",
9499 esi_to_str(&attr
->esi
,
9500 esi_buf
, sizeof(esi_buf
)));
9502 if (safi
== SAFI_EVPN
&&
9503 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9504 json_ext_community
= json_object_new_object();
9505 json_object_string_add(
9506 json_ext_community
, "string",
9507 bgp_attr_get_ecommunity(attr
)->str
);
9508 json_object_object_add(json_path
,
9509 "extendedCommunity",
9510 json_ext_community
);
9514 json_object_boolean_true_add(json_path
,
9515 "announceNexthopSelf");
9516 if (nexthop_othervrf
) {
9517 json_object_string_add(json_path
, "nhVrfName",
9520 json_object_int_add(json_path
, "nhVrfId",
9521 ((nexthop_vrfid
== VRF_UNKNOWN
)
9523 : (int)nexthop_vrfid
));
9528 if (json_nexthop_global
|| json_nexthop_ll
) {
9529 json_nexthops
= json_object_new_array();
9531 if (json_nexthop_global
)
9532 json_object_array_add(json_nexthops
,
9533 json_nexthop_global
);
9535 if (json_nexthop_ll
)
9536 json_object_array_add(json_nexthops
,
9539 json_object_object_add(json_path
, "nexthops",
9543 json_object_array_add(json_paths
, json_path
);
9547 if (safi
== SAFI_EVPN
) {
9548 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9549 /* XXX - add these params to the json out */
9550 vty_out(vty
, "%*s", 20, " ");
9551 vty_out(vty
, "ESI:%s",
9552 esi_to_str(&attr
->esi
, esi_buf
,
9558 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9559 vty_out(vty
, "%*s", 20, " ");
9560 vty_out(vty
, "%s\n",
9561 bgp_attr_get_ecommunity(attr
)->str
);
9565 #ifdef ENABLE_BGP_VNC
9566 /* prints an additional line, indented, with VNC info, if
9568 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9569 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9574 /* called from terminal list command */
9575 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9576 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9577 bool use_json
, json_object
*json_ar
, bool wide
)
9579 json_object
*json_status
= NULL
;
9580 json_object
*json_net
= NULL
;
9584 /* Route status display. */
9586 json_status
= json_object_new_object();
9587 json_net
= json_object_new_object();
9594 /* print prefix and mask */
9596 if (safi
== SAFI_EVPN
)
9597 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9598 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9599 json_object_string_add(
9600 json_net
, "addrPrefix",
9601 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9603 json_object_int_add(json_net
, "prefixLen",
9605 json_object_string_addf(json_net
, "network", "%pFX", p
);
9608 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9610 /* Print attribute */
9613 if (p
->family
== AF_INET
&&
9614 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9615 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9616 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9617 json_object_string_addf(
9618 json_net
, "nextHop", "%pI4",
9619 &attr
->mp_nexthop_global_in
);
9621 json_object_string_addf(
9622 json_net
, "nextHop", "%pI4",
9624 } else if (p
->family
== AF_INET6
||
9625 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9626 json_object_string_addf(
9627 json_net
, "nextHopGlobal", "%pI6",
9628 &attr
->mp_nexthop_global
);
9629 } else if (p
->family
== AF_EVPN
&&
9630 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9631 json_object_string_addf(
9632 json_net
, "nextHop", "%pI4",
9633 &attr
->mp_nexthop_global_in
);
9637 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9638 json_object_int_add(json_net
, "metric",
9641 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9642 json_object_int_add(json_net
, "locPrf",
9645 json_object_int_add(json_net
, "weight", attr
->weight
);
9649 json_object_string_add(json_net
, "path",
9653 #if CONFDATE > 20231208
9654 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9656 json_object_string_add(json_net
, "bgpOriginCode",
9657 bgp_origin_str
[attr
->origin
]);
9658 json_object_string_add(
9660 bgp_origin_long_str
[attr
->origin
]);
9662 if (p
->family
== AF_INET
&&
9663 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9664 safi
== SAFI_EVPN
||
9665 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9666 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9667 || safi
== SAFI_EVPN
)
9668 vty_out(vty
, "%-16pI4",
9669 &attr
->mp_nexthop_global_in
);
9671 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9673 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9674 } else if (p
->family
== AF_INET6
||
9675 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9676 len
= vty_out(vty
, "%pI6",
9677 &attr
->mp_nexthop_global
);
9678 len
= wide
? (41 - len
) : (16 - len
);
9680 vty_out(vty
, "\n%*s", 36, " ");
9682 vty_out(vty
, "%*s", len
, " ");
9685 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9687 vty_out(vty
, "%7u", attr
->med
);
9689 vty_out(vty
, "%10u", attr
->med
);
9695 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9696 vty_out(vty
, "%7u", attr
->local_pref
);
9700 vty_out(vty
, "%7u ", attr
->weight
);
9704 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9707 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9711 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9713 #if CONFDATE > 20231208
9714 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9716 json_object_boolean_true_add(json_status
, "*");
9717 json_object_boolean_true_add(json_status
, ">");
9718 json_object_boolean_true_add(json_net
, "valid");
9719 json_object_boolean_true_add(json_net
, "best");
9721 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9722 json_object_boolean_true_add(json_status
, "=");
9723 json_object_boolean_true_add(json_net
, "multipath");
9725 json_object_object_add(json_net
, "appliedStatusSymbols",
9727 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9732 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9733 struct bgp_path_info
*path
, int display
, safi_t safi
,
9736 json_object
*json_out
= NULL
;
9738 mpls_label_t label
= MPLS_INVALID_LABEL
;
9744 json_out
= json_object_new_object();
9746 /* short status lead text */
9747 route_vty_short_status_out(vty
, path
, p
, json_out
);
9749 /* print prefix and mask */
9752 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9754 vty_out(vty
, "%*s", 17, " ");
9757 /* Print attribute */
9759 if (((p
->family
== AF_INET
) &&
9760 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9761 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9762 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9763 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9764 || safi
== SAFI_EVPN
) {
9766 json_object_string_addf(
9767 json_out
, "mpNexthopGlobalIn", "%pI4",
9768 &attr
->mp_nexthop_global_in
);
9770 vty_out(vty
, "%-16pI4",
9771 &attr
->mp_nexthop_global_in
);
9774 json_object_string_addf(json_out
, "nexthop",
9775 "%pI4", &attr
->nexthop
);
9777 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9779 } else if (((p
->family
== AF_INET6
) &&
9780 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9781 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9782 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9785 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9787 json_object_string_addf(
9788 json_out
, "mpNexthopGlobalIn", "%pI6",
9789 &attr
->mp_nexthop_global
);
9793 &attr
->mp_nexthop_global
,
9794 buf_a
, sizeof(buf_a
)));
9795 } else if (attr
->mp_nexthop_len
9796 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9797 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9798 &attr
->mp_nexthop_global
,
9799 &attr
->mp_nexthop_local
);
9801 json_object_string_add(json_out
,
9802 "mpNexthopGlobalLocal",
9805 vty_out(vty
, "%s", buf_a
);
9809 label
= decode_label(&path
->extra
->label
[0]);
9811 if (bgp_is_valid_label(&label
)) {
9813 json_object_int_add(json_out
, "notag", label
);
9814 json_object_array_add(json
, json_out
);
9816 vty_out(vty
, "notag/%d", label
);
9823 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9824 struct bgp_path_info
*path
, int display
,
9825 json_object
*json_paths
)
9828 json_object
*json_path
= NULL
;
9829 json_object
*json_nexthop
= NULL
;
9830 json_object
*json_overlay
= NULL
;
9836 json_path
= json_object_new_object();
9837 json_overlay
= json_object_new_object();
9838 json_nexthop
= json_object_new_object();
9841 /* short status lead text */
9842 route_vty_short_status_out(vty
, path
, p
, json_path
);
9844 /* print prefix and mask */
9846 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9848 vty_out(vty
, "%*s", 17, " ");
9850 /* Print attribute */
9852 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9857 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9859 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9860 &attr
->mp_nexthop_global_in
);
9862 json_object_string_add(json_nexthop
, "afi", "ipv4");
9864 json_object_object_add(json_path
, "nexthop",
9870 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9871 &attr
->mp_nexthop_local
);
9873 json_object_string_addf(json_nexthop
, "ipv6Global",
9875 &attr
->mp_nexthop_global
);
9877 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9879 &attr
->mp_nexthop_local
);
9881 json_object_string_add(json_nexthop
, "afi", "ipv6");
9883 json_object_object_add(json_path
, "nexthop",
9891 json_object_string_add(json_nexthop
, "Error",
9892 "Unsupported address-family");
9893 json_object_string_add(json_nexthop
, "error",
9894 "Unsupported address-family");
9898 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9901 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9903 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9905 if (bgp_attr_get_ecommunity(attr
)) {
9907 struct ecommunity_val
*routermac
= ecommunity_lookup(
9908 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9909 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9912 mac
= ecom_mac2str((char *)routermac
->val
);
9915 vty_out(vty
, "/%s", mac
);
9917 json_object_string_add(json_overlay
, "rmac",
9920 XFREE(MTYPE_TMP
, mac
);
9927 json_object_object_add(json_path
, "overlay", json_overlay
);
9929 json_object_array_add(json_paths
, json_path
);
9933 /* dampening route */
9934 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9935 struct bgp_path_info
*path
, int display
,
9936 afi_t afi
, safi_t safi
, bool use_json
,
9937 json_object
*json_paths
)
9939 struct attr
*attr
= path
->attr
;
9941 char timebuf
[BGP_UPTIME_LEN
];
9942 json_object
*json_path
= NULL
;
9945 json_path
= json_object_new_object();
9947 /* short status lead text */
9948 route_vty_short_status_out(vty
, path
, p
, json_path
);
9950 /* print prefix and mask */
9953 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9955 vty_out(vty
, "%*s", 17, " ");
9957 len
= vty_out(vty
, "%s", path
->peer
->host
);
9961 vty_out(vty
, "\n%*s", 34, " ");
9963 vty_out(vty
, "%*s", len
, " ");
9966 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9967 BGP_UPTIME_LEN
, afi
, safi
,
9971 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9973 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9977 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9978 safi
, use_json
, json_path
);
9981 json_object_string_add(json_path
, "asPath",
9984 json_object_string_add(json_path
, "origin",
9985 bgp_origin_str
[attr
->origin
]);
9986 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9988 json_object_array_add(json_paths
, json_path
);
9993 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9994 struct bgp_path_info
*path
, int display
,
9995 afi_t afi
, safi_t safi
, bool use_json
,
9996 json_object
*json_paths
)
9998 struct attr
*attr
= path
->attr
;
9999 struct bgp_damp_info
*bdi
;
10000 char timebuf
[BGP_UPTIME_LEN
];
10002 json_object
*json_path
= NULL
;
10008 json_path
= json_object_new_object();
10010 bdi
= path
->extra
->damp_info
;
10012 /* short status lead text */
10013 route_vty_short_status_out(vty
, path
, p
, json_path
);
10017 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10019 vty_out(vty
, "%*s", 17, " ");
10021 len
= vty_out(vty
, "%s", path
->peer
->host
);
10024 vty_out(vty
, "\n%*s", 33, " ");
10026 vty_out(vty
, "%*s", len
, " ");
10028 len
= vty_out(vty
, "%d", bdi
->flap
);
10033 vty_out(vty
, "%*s", len
, " ");
10035 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10036 BGP_UPTIME_LEN
, 0, NULL
));
10038 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10039 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10040 vty_out(vty
, "%s ",
10041 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10042 BGP_UPTIME_LEN
, afi
,
10043 safi
, use_json
, NULL
));
10045 vty_out(vty
, "%*s ", 8, " ");
10048 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
10050 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10052 vty_out(vty
, "\n");
10054 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10055 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10057 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10060 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10061 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10062 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10063 BGP_UPTIME_LEN
, afi
, safi
,
10064 use_json
, json_path
);
10067 json_object_string_add(json_path
, "asPath",
10068 attr
->aspath
->str
);
10070 json_object_string_add(json_path
, "origin",
10071 bgp_origin_str
[attr
->origin
]);
10073 json_object_array_add(json_paths
, json_path
);
10077 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10078 int *first
, const char *header
,
10079 json_object
*json_adv_to
)
10081 json_object
*json_peer
= NULL
;
10084 /* 'advertised-to' is a dictionary of peers we have advertised
10086 * prefix too. The key is the peer's IP or swpX, the value is
10088 * hostname if we know it and "" if not.
10090 json_peer
= json_object_new_object();
10092 if (peer
->hostname
)
10093 json_object_string_add(json_peer
, "hostname",
10097 json_object_object_add(json_adv_to
, peer
->conf_if
,
10100 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10104 vty_out(vty
, "%s", header
);
10109 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10111 vty_out(vty
, " %s(%s)", peer
->hostname
,
10114 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10118 vty_out(vty
, " %s", peer
->conf_if
);
10120 vty_out(vty
, " %pSU", &peer
->su
);
10125 static void route_vty_out_tx_ids(struct vty
*vty
,
10126 struct bgp_addpath_info_data
*d
)
10130 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10131 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10132 d
->addpath_tx_id
[i
],
10133 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10137 static void route_vty_out_detail_es_info(struct vty
*vty
,
10138 struct bgp_path_info
*pi
,
10140 json_object
*json_path
)
10142 char esi_buf
[ESI_STR_LEN
];
10143 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10144 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10145 ATTR_ES_PEER_ROUTER
);
10146 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10147 ATTR_ES_PEER_ACTIVE
);
10148 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10149 ATTR_ES_PEER_PROXY
);
10150 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10152 json_object
*json_es_info
= NULL
;
10154 json_object_string_add(
10157 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10158 json_es_info
= json_object_new_object();
10160 json_object_boolean_true_add(
10161 json_es_info
, "localEs");
10163 json_object_boolean_true_add(
10164 json_es_info
, "peerActive");
10166 json_object_boolean_true_add(
10167 json_es_info
, "peerProxy");
10169 json_object_boolean_true_add(
10170 json_es_info
, "peerRouter");
10171 if (attr
->mm_sync_seqnum
)
10172 json_object_int_add(
10173 json_es_info
, "peerSeq",
10174 attr
->mm_sync_seqnum
);
10175 json_object_object_add(
10176 json_path
, "es_info",
10180 if (bgp_evpn_attr_is_sync(attr
))
10182 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10184 es_local
? "local-es":"",
10185 peer_proxy
? "proxy " : "",
10186 peer_active
? "active ":"",
10187 peer_router
? "router ":"",
10188 attr
->mm_sync_seqnum
);
10190 vty_out(vty
, " ESI %s %s\n",
10192 es_local
? "local-es":"");
10196 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10197 const struct prefix
*p
, struct bgp_path_info
*path
,
10198 afi_t afi
, safi_t safi
,
10199 enum rpki_states rpki_curr_state
,
10200 json_object
*json_paths
)
10202 char buf
[INET6_ADDRSTRLEN
];
10204 struct attr
*attr
= path
->attr
;
10206 json_object
*json_bestpath
= NULL
;
10207 json_object
*json_cluster_list
= NULL
;
10208 json_object
*json_cluster_list_list
= NULL
;
10209 json_object
*json_ext_community
= NULL
;
10210 json_object
*json_last_update
= NULL
;
10211 json_object
*json_pmsi
= NULL
;
10212 json_object
*json_nexthop_global
= NULL
;
10213 json_object
*json_nexthop_ll
= NULL
;
10214 json_object
*json_nexthops
= NULL
;
10215 json_object
*json_path
= NULL
;
10216 json_object
*json_peer
= NULL
;
10217 json_object
*json_string
= NULL
;
10218 json_object
*json_adv_to
= NULL
;
10220 struct listnode
*node
, *nnode
;
10222 bool addpath_capable
;
10224 unsigned int first_as
;
10225 bool nexthop_self
=
10226 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10228 char *nexthop_hostname
=
10229 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10233 mpls_label_t label
= MPLS_INVALID_LABEL
;
10235 struct bgp_path_info
*bpi_ultimate
=
10236 bgp_get_imported_bpi_ultimate(path
);
10239 json_path
= json_object_new_object();
10240 json_peer
= json_object_new_object();
10241 json_nexthop_global
= json_object_new_object();
10244 if (safi
== SAFI_EVPN
) {
10246 vty_out(vty
, " Route %pFX", p
);
10250 if (path
->extra
&& path
->extra
->num_labels
) {
10251 bgp_evpn_label2str(path
->extra
->label
,
10252 path
->extra
->num_labels
, tag_buf
,
10255 if (safi
== SAFI_EVPN
) {
10257 if (tag_buf
[0] != '\0')
10258 vty_out(vty
, " VNI %s", tag_buf
);
10261 json_object_string_add(json_path
, "VNI",
10263 json_object_string_add(json_path
, "vni",
10270 if (safi
== SAFI_EVPN
10271 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10272 char gwip_buf
[INET6_ADDRSTRLEN
];
10274 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10278 json_object_string_add(json_path
, "gatewayIP",
10281 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10284 if (safi
== SAFI_EVPN
&& !json_path
)
10285 vty_out(vty
, "\n");
10288 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10289 struct bgp_path_info
*parent_ri
;
10290 struct bgp_dest
*dest
, *pdest
;
10292 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10293 dest
= parent_ri
->net
;
10294 if (dest
&& dest
->pdest
) {
10295 pdest
= dest
->pdest
;
10296 if (is_pi_family_evpn(parent_ri
)) {
10298 " Imported from %pRD:%pFX, VNI %s",
10299 (struct prefix_rd
*)bgp_dest_get_prefix(
10301 (struct prefix_evpn
*)
10302 bgp_dest_get_prefix(dest
),
10304 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10305 vty_out(vty
, ", L3NHG %s",
10308 ATTR_ES_L3_NHG_ACTIVE
)
10311 vty_out(vty
, "\n");
10314 vty_out(vty
, " Imported from %pRD:%pFX\n",
10315 (struct prefix_rd
*)bgp_dest_get_prefix(
10317 (struct prefix_evpn
*)
10318 bgp_dest_get_prefix(dest
));
10322 /* Line1 display AS-path, Aggregator */
10323 if (attr
->aspath
) {
10325 if (!attr
->aspath
->json
)
10326 aspath_str_update(attr
->aspath
, true);
10327 json_object_lock(attr
->aspath
->json
);
10328 json_object_object_add(json_path
, "aspath",
10329 attr
->aspath
->json
);
10331 if (attr
->aspath
->segments
)
10332 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
10334 vty_out(vty
, " Local");
10338 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10340 json_object_boolean_true_add(json_path
, "removed");
10342 vty_out(vty
, ", (removed)");
10345 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10347 json_object_boolean_true_add(json_path
, "stale");
10349 vty_out(vty
, ", (stale)");
10352 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10354 json_object_int_add(json_path
, "aggregatorAs",
10355 attr
->aggregator_as
);
10356 json_object_string_addf(json_path
, "aggregatorId",
10357 "%pI4", &attr
->aggregator_addr
);
10359 vty_out(vty
, ", (aggregated by %u %pI4)",
10360 attr
->aggregator_as
, &attr
->aggregator_addr
);
10364 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10365 PEER_FLAG_REFLECTOR_CLIENT
)) {
10367 json_object_boolean_true_add(json_path
,
10368 "rxedFromRrClient");
10370 vty_out(vty
, ", (Received from a RR-client)");
10373 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10374 PEER_FLAG_RSERVER_CLIENT
)) {
10376 json_object_boolean_true_add(json_path
,
10377 "rxedFromRsClient");
10379 vty_out(vty
, ", (Received from a RS-client)");
10382 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10384 json_object_boolean_true_add(json_path
,
10385 "dampeningHistoryEntry");
10387 vty_out(vty
, ", (history entry)");
10388 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10390 json_object_boolean_true_add(json_path
,
10391 "dampeningSuppressed");
10393 vty_out(vty
, ", (suppressed due to dampening)");
10397 vty_out(vty
, "\n");
10399 /* Line2 display Next-hop, Neighbor, Router-id */
10400 /* Display the nexthop */
10402 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10403 p
->family
== AF_EVPN
) &&
10404 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10405 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10406 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10407 || safi
== SAFI_EVPN
) {
10409 json_object_string_addf(
10410 json_nexthop_global
, "ip", "%pI4",
10411 &attr
->mp_nexthop_global_in
);
10413 if (path
->peer
->hostname
)
10414 json_object_string_add(
10415 json_nexthop_global
, "hostname",
10416 path
->peer
->hostname
);
10418 if (nexthop_hostname
)
10419 vty_out(vty
, " %pI4(%s)",
10420 &attr
->mp_nexthop_global_in
,
10423 vty_out(vty
, " %pI4",
10424 &attr
->mp_nexthop_global_in
);
10428 json_object_string_addf(json_nexthop_global
,
10432 if (path
->peer
->hostname
)
10433 json_object_string_add(
10434 json_nexthop_global
, "hostname",
10435 path
->peer
->hostname
);
10437 if (nexthop_hostname
)
10438 vty_out(vty
, " %pI4(%s)",
10442 vty_out(vty
, " %pI4",
10448 json_object_string_add(json_nexthop_global
, "afi",
10452 json_object_string_addf(json_nexthop_global
, "ip",
10454 &attr
->mp_nexthop_global
);
10456 if (path
->peer
->hostname
)
10457 json_object_string_add(json_nexthop_global
,
10459 path
->peer
->hostname
);
10461 json_object_string_add(json_nexthop_global
, "afi",
10463 json_object_string_add(json_nexthop_global
, "scope",
10466 if (nexthop_hostname
)
10467 vty_out(vty
, " %pI6(%s)",
10468 &attr
->mp_nexthop_global
,
10471 vty_out(vty
, " %pI6",
10472 &attr
->mp_nexthop_global
);
10476 /* Display the IGP cost or 'inaccessible' */
10477 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10478 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10481 json_object_boolean_false_add(json_nexthop_global
,
10483 json_object_boolean_add(json_nexthop_global
,
10484 "importCheckEnabled", import
);
10486 vty_out(vty
, " (inaccessible%s)",
10487 import
? ", import-check enabled" : "");
10490 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10492 json_object_int_add(
10493 json_nexthop_global
, "metric",
10494 bpi_ultimate
->extra
->igpmetric
);
10496 vty_out(vty
, " (metric %u)",
10497 bpi_ultimate
->extra
->igpmetric
);
10500 /* IGP cost is 0, display this only for json */
10503 json_object_int_add(json_nexthop_global
,
10508 json_object_boolean_true_add(json_nexthop_global
,
10512 /* Display peer "from" output */
10513 /* This path was originated locally */
10514 if (path
->peer
== bgp
->peer_self
) {
10516 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10517 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10519 json_object_string_add(json_peer
, "peerId",
10522 vty_out(vty
, " from 0.0.0.0 ");
10525 json_object_string_add(json_peer
, "peerId",
10528 vty_out(vty
, " from :: ");
10532 json_object_string_addf(json_peer
, "routerId", "%pI4",
10535 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10538 /* We RXed this path from one of our peers */
10542 json_object_string_addf(json_peer
, "peerId", "%pSU",
10544 json_object_string_addf(json_peer
, "routerId", "%pI4",
10545 &path
->peer
->remote_id
);
10547 if (path
->peer
->hostname
)
10548 json_object_string_add(json_peer
, "hostname",
10549 path
->peer
->hostname
);
10551 if (path
->peer
->domainname
)
10552 json_object_string_add(json_peer
, "domainname",
10553 path
->peer
->domainname
);
10555 if (path
->peer
->conf_if
)
10556 json_object_string_add(json_peer
, "interface",
10557 path
->peer
->conf_if
);
10559 if (path
->peer
->conf_if
) {
10560 if (path
->peer
->hostname
10561 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10562 BGP_FLAG_SHOW_HOSTNAME
))
10563 vty_out(vty
, " from %s(%s)",
10564 path
->peer
->hostname
,
10565 path
->peer
->conf_if
);
10567 vty_out(vty
, " from %s",
10568 path
->peer
->conf_if
);
10570 if (path
->peer
->hostname
10571 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10572 BGP_FLAG_SHOW_HOSTNAME
))
10573 vty_out(vty
, " from %s(%s)",
10574 path
->peer
->hostname
,
10577 vty_out(vty
, " from %pSU",
10581 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10582 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10584 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10589 * Note when vrfid of nexthop is different from that of prefix
10591 if (path
->extra
&& path
->extra
->bgp_orig
) {
10592 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10597 if (path
->extra
->bgp_orig
->inst_type
10598 == BGP_INSTANCE_TYPE_DEFAULT
)
10599 vn
= VRF_DEFAULT_NAME
;
10601 vn
= path
->extra
->bgp_orig
->name
;
10603 json_object_string_add(json_path
, "nhVrfName", vn
);
10605 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10606 json_object_int_add(json_path
, "nhVrfId", -1);
10608 json_object_int_add(json_path
, "nhVrfId",
10609 (int)nexthop_vrfid
);
10612 if (nexthop_vrfid
== VRF_UNKNOWN
)
10613 vty_out(vty
, " vrf ?");
10617 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10618 vty_out(vty
, " vrf %s(%u)",
10619 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10624 if (nexthop_self
) {
10626 json_object_boolean_true_add(json_path
,
10627 "announceNexthopSelf");
10629 vty_out(vty
, " announce-nh-self");
10634 vty_out(vty
, "\n");
10636 /* display the link-local nexthop */
10637 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10639 json_nexthop_ll
= json_object_new_object();
10640 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10641 &attr
->mp_nexthop_local
);
10643 if (path
->peer
->hostname
)
10644 json_object_string_add(json_nexthop_ll
,
10646 path
->peer
->hostname
);
10648 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10649 json_object_string_add(json_nexthop_ll
, "scope",
10652 json_object_boolean_true_add(json_nexthop_ll
,
10655 if (!attr
->mp_nexthop_prefer_global
)
10656 json_object_boolean_true_add(json_nexthop_ll
,
10659 json_object_boolean_true_add(
10660 json_nexthop_global
, "used");
10662 vty_out(vty
, " (%s) %s\n",
10663 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10664 buf
, INET6_ADDRSTRLEN
),
10665 attr
->mp_nexthop_prefer_global
10666 ? "(prefer-global)"
10670 /* If we do not have a link-local nexthop then we must flag the
10671 global as "used" */
10674 json_object_boolean_true_add(json_nexthop_global
,
10678 if (safi
== SAFI_EVPN
&&
10679 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10680 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10683 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10684 * Int/Ext/Local, Atomic, best */
10686 json_object_string_add(json_path
, "origin",
10687 bgp_origin_long_str
[attr
->origin
]);
10689 vty_out(vty
, " Origin %s",
10690 bgp_origin_long_str
[attr
->origin
]);
10692 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10694 json_object_int_add(json_path
, "metric", attr
->med
);
10696 vty_out(vty
, ", metric %u", attr
->med
);
10699 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10701 json_object_int_add(json_path
, "locPrf",
10704 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10707 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10709 json_object_int_add(json_path
, "aigpMetric",
10710 bgp_attr_get_aigp_metric(attr
));
10712 vty_out(vty
, ", aigp-metric %" PRIu64
,
10713 bgp_attr_get_aigp_metric(attr
));
10716 if (attr
->weight
!= 0) {
10718 json_object_int_add(json_path
, "weight", attr
->weight
);
10720 vty_out(vty
, ", weight %u", attr
->weight
);
10723 if (attr
->tag
!= 0) {
10725 json_object_int_add(json_path
, "tag", attr
->tag
);
10727 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10730 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10732 json_object_boolean_false_add(json_path
, "valid");
10734 vty_out(vty
, ", invalid");
10735 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10737 json_object_boolean_true_add(json_path
, "valid");
10739 vty_out(vty
, ", valid");
10743 json_object_int_add(json_path
, "version", bn
->version
);
10745 if (path
->peer
!= bgp
->peer_self
) {
10746 if (path
->peer
->as
== path
->peer
->local_as
) {
10747 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10749 json_object_string_add(
10751 "confed-internal");
10753 vty_out(vty
, ", confed-internal");
10756 json_object_string_add(
10757 json_peer
, "type", "internal");
10759 vty_out(vty
, ", internal");
10762 if (bgp_confederation_peers_check(bgp
,
10765 json_object_string_add(
10767 "confed-external");
10769 vty_out(vty
, ", confed-external");
10772 json_object_string_add(
10773 json_peer
, "type", "external");
10775 vty_out(vty
, ", external");
10778 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10780 json_object_boolean_true_add(json_path
, "aggregated");
10781 json_object_boolean_true_add(json_path
, "local");
10783 vty_out(vty
, ", aggregated, local");
10785 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10787 json_object_boolean_true_add(json_path
, "sourced");
10789 vty_out(vty
, ", sourced");
10792 json_object_boolean_true_add(json_path
, "sourced");
10793 json_object_boolean_true_add(json_path
, "local");
10795 vty_out(vty
, ", sourced, local");
10799 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10801 json_object_boolean_true_add(json_path
,
10802 "atomicAggregate");
10804 vty_out(vty
, ", atomic-aggregate");
10807 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10809 json_object_int_add(json_path
, "otc", attr
->otc
);
10811 vty_out(vty
, ", otc %u", attr
->otc
);
10814 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10815 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10816 && bgp_path_info_mpath_count(path
))) {
10818 json_object_boolean_true_add(json_path
, "multipath");
10820 vty_out(vty
, ", multipath");
10823 // Mark the bestpath(s)
10824 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10825 first_as
= aspath_get_first_as(attr
->aspath
);
10828 if (!json_bestpath
)
10829 json_bestpath
= json_object_new_object();
10830 json_object_int_add(json_bestpath
, "bestpathFromAs",
10834 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10836 vty_out(vty
, ", bestpath-from-AS Local");
10840 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10842 if (!json_bestpath
)
10843 json_bestpath
= json_object_new_object();
10844 json_object_boolean_true_add(json_bestpath
, "overall");
10845 json_object_string_add(
10846 json_bestpath
, "selectionReason",
10847 bgp_path_selection_reason2str(bn
->reason
));
10849 vty_out(vty
, ", best");
10850 vty_out(vty
, " (%s)",
10851 bgp_path_selection_reason2str(bn
->reason
));
10855 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10857 json_object_string_add(
10858 json_path
, "rpkiValidationState",
10859 bgp_rpki_validation2str(rpki_curr_state
));
10861 vty_out(vty
, ", rpki validation-state: %s",
10862 bgp_rpki_validation2str(rpki_curr_state
));
10866 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10869 vty_out(vty
, "\n");
10871 /* Line 4 display Community */
10872 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10874 if (!bgp_attr_get_community(attr
)->json
)
10875 community_str(bgp_attr_get_community(attr
),
10877 json_object_lock(bgp_attr_get_community(attr
)->json
);
10878 json_object_object_add(
10879 json_path
, "community",
10880 bgp_attr_get_community(attr
)->json
);
10882 vty_out(vty
, " Community: %s\n",
10883 bgp_attr_get_community(attr
)->str
);
10887 /* Line 5 display Extended-community */
10888 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10890 json_ext_community
= json_object_new_object();
10891 json_object_string_add(
10892 json_ext_community
, "string",
10893 bgp_attr_get_ecommunity(attr
)->str
);
10894 json_object_object_add(json_path
, "extendedCommunity",
10895 json_ext_community
);
10897 vty_out(vty
, " Extended Community: %s\n",
10898 bgp_attr_get_ecommunity(attr
)->str
);
10902 /* Line 6 display Large community */
10903 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10905 if (!bgp_attr_get_lcommunity(attr
)->json
)
10906 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10908 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10909 json_object_object_add(
10910 json_path
, "largeCommunity",
10911 bgp_attr_get_lcommunity(attr
)->json
);
10913 vty_out(vty
, " Large Community: %s\n",
10914 bgp_attr_get_lcommunity(attr
)->str
);
10918 /* Line 7 display Originator, Cluster-id */
10919 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10920 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10921 char buf
[BUFSIZ
] = {0};
10923 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10925 json_object_string_addf(json_path
,
10926 "originatorId", "%pI4",
10927 &attr
->originator_id
);
10929 vty_out(vty
, " Originator: %pI4",
10930 &attr
->originator_id
);
10933 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10934 struct cluster_list
*cluster
=
10935 bgp_attr_get_cluster(attr
);
10939 json_cluster_list
= json_object_new_object();
10940 json_cluster_list_list
=
10941 json_object_new_array();
10943 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10944 json_string
= json_object_new_string(
10947 buf
, sizeof(buf
)));
10948 json_object_array_add(
10949 json_cluster_list_list
,
10954 * struct cluster_list does not have
10955 * "str" variable like aspath and community
10956 * do. Add this someday if someone asks
10958 * json_object_string_add(json_cluster_list,
10959 * "string", cluster->str);
10961 json_object_object_add(json_cluster_list
,
10963 json_cluster_list_list
);
10964 json_object_object_add(json_path
, "clusterList",
10965 json_cluster_list
);
10967 vty_out(vty
, ", Cluster list: ");
10969 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10970 vty_out(vty
, "%pI4 ",
10971 &cluster
->list
[i
]);
10977 vty_out(vty
, "\n");
10980 if (path
->extra
&& path
->extra
->damp_info
)
10981 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10984 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10985 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10986 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10990 json_object_int_add(json_path
, "remoteLabel", label
);
10992 vty_out(vty
, " Remote label: %d\n", label
);
10996 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10998 json_object_string_addf(json_path
, "remoteSid", "%pI6",
10999 &path
->extra
->sid
[0].sid
);
11001 vty_out(vty
, " Remote SID: %pI6\n",
11002 &path
->extra
->sid
[0].sid
);
11006 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
11008 json_object_int_add(json_path
, "labelIndex",
11009 attr
->label_index
);
11011 vty_out(vty
, " Label Index: %d\n",
11012 attr
->label_index
);
11015 /* Line 8 display Addpath IDs */
11016 if (path
->addpath_rx_id
11017 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11019 json_object_int_add(json_path
, "addpathRxId",
11020 path
->addpath_rx_id
);
11022 /* Keep backwards compatibility with the old API
11023 * by putting TX All's ID in the old field
11025 json_object_int_add(
11026 json_path
, "addpathTxId",
11028 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11030 /* ... but create a specific field for each
11033 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11034 json_object_int_add(
11036 bgp_addpath_names(i
)->id_json_name
,
11037 path
->tx_addpath
.addpath_tx_id
[i
]);
11040 vty_out(vty
, " AddPath ID: RX %u, ",
11041 path
->addpath_rx_id
);
11043 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11047 /* If we used addpath to TX a non-bestpath we need to display
11048 * "Advertised to" on a path-by-path basis
11050 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11053 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11055 bgp_addpath_encode_tx(peer
, afi
, safi
);
11056 has_adj
= bgp_adj_out_lookup(
11058 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11059 &path
->tx_addpath
));
11061 if ((addpath_capable
&& has_adj
)
11062 || (!addpath_capable
&& has_adj
11063 && CHECK_FLAG(path
->flags
,
11064 BGP_PATH_SELECTED
))) {
11065 if (json_path
&& !json_adv_to
)
11066 json_adv_to
= json_object_new_object();
11068 route_vty_out_advertised_to(
11070 " Advertised to:", json_adv_to
);
11076 json_object_object_add(
11077 json_path
, "advertisedTo", json_adv_to
);
11081 vty_out(vty
, "\n");
11086 /* Line 9 display Uptime */
11087 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11089 json_last_update
= json_object_new_object();
11090 json_object_int_add(json_last_update
, "epoch", tbuf
);
11091 json_object_string_add(json_last_update
, "string",
11093 json_object_object_add(json_path
, "lastUpdate",
11096 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11098 /* Line 10 display PMSI tunnel attribute, if present */
11099 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11100 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11101 bgp_attr_get_pmsi_tnl_type(attr
),
11102 PMSI_TNLTYPE_STR_DEFAULT
);
11105 json_pmsi
= json_object_new_object();
11106 json_object_string_add(json_pmsi
, "tunnelType", str
);
11107 json_object_int_add(json_pmsi
, "label",
11108 label2vni(&attr
->label
));
11109 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11111 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11112 str
, label2vni(&attr
->label
));
11115 if (path
->peer
->t_gr_restart
&&
11116 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11117 unsigned long gr_remaining
=
11118 thread_timer_remain_second(path
->peer
->t_gr_restart
);
11121 json_object_int_add(json_path
,
11122 "gracefulRestartSecondsRemaining",
11126 " Time until Graceful Restart stale route deleted: %lu\n",
11130 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11131 bgp_attr_get_community(attr
) &&
11132 community_include(bgp_attr_get_community(attr
),
11133 COMMUNITY_LLGR_STALE
)) {
11134 unsigned long llgr_remaining
= thread_timer_remain_second(
11135 path
->peer
->t_llgr_stale
[afi
][safi
]);
11138 json_object_int_add(json_path
, "llgrSecondsRemaining",
11142 " Time until Long-lived stale route deleted: %lu\n",
11146 /* Output some debug about internal state of the dest flags */
11148 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11149 json_object_boolean_true_add(json_path
, "processScheduled");
11150 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11151 json_object_boolean_true_add(json_path
, "userCleared");
11152 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11153 json_object_boolean_true_add(json_path
, "labelChanged");
11154 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11155 json_object_boolean_true_add(json_path
, "registeredForLabel");
11156 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11157 json_object_boolean_true_add(json_path
, "selectDefered");
11158 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11159 json_object_boolean_true_add(json_path
, "fibInstalled");
11160 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11161 json_object_boolean_true_add(json_path
, "fibPending");
11163 if (json_nexthop_global
|| json_nexthop_ll
) {
11164 json_nexthops
= json_object_new_array();
11166 if (json_nexthop_global
)
11167 json_object_array_add(json_nexthops
,
11168 json_nexthop_global
);
11170 if (json_nexthop_ll
)
11171 json_object_array_add(json_nexthops
,
11174 json_object_object_add(json_path
, "nexthops",
11178 json_object_object_add(json_path
, "peer", json_peer
);
11179 json_object_array_add(json_paths
, json_path
);
11183 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11184 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11185 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11187 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11188 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11190 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11191 const char *comstr
, int exact
, afi_t afi
,
11192 safi_t safi
, uint16_t show_flags
);
11194 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11195 struct bgp_table
*table
, enum bgp_show_type type
,
11196 void *output_arg
, const char *rd
, int is_last
,
11197 unsigned long *output_cum
, unsigned long *total_cum
,
11198 unsigned long *json_header_depth
, uint16_t show_flags
,
11199 enum rpki_states rpki_target_state
)
11201 struct bgp_path_info
*pi
;
11202 struct bgp_dest
*dest
;
11203 bool header
= true;
11204 bool json_detail_header
= false;
11206 unsigned long output_count
= 0;
11207 unsigned long total_count
= 0;
11209 json_object
*json_paths
= NULL
;
11211 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11212 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11213 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11214 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11215 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11217 if (output_cum
&& *output_cum
!= 0)
11220 if (use_json
&& !*json_header_depth
) {
11222 *json_header_depth
= 1;
11224 vty_out(vty
, "{\n");
11225 *json_header_depth
= 2;
11229 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11230 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11231 " \"localAS\": %u,\n \"routes\": { ",
11232 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11233 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11236 table
->version
, &bgp
->router_id
,
11237 bgp
->default_local_pref
, bgp
->as
);
11239 vty_out(vty
, " \"routeDistinguishers\" : {");
11240 ++*json_header_depth
;
11244 if (use_json
&& rd
) {
11245 vty_out(vty
, " \"%s\" : { ", rd
);
11248 /* Check for 'json detail', where we need header output once per dest */
11249 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11250 type
!= bgp_show_type_damp_neighbor
&&
11251 type
!= bgp_show_type_flap_statistics
&&
11252 type
!= bgp_show_type_flap_neighbor
)
11253 json_detail_header
= true;
11255 /* Start processing of routes. */
11256 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11257 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11258 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11259 bool json_detail
= json_detail_header
;
11261 pi
= bgp_dest_get_bgp_path_info(dest
);
11267 json_paths
= json_object_new_array();
11271 for (; pi
; pi
= pi
->next
) {
11272 struct community
*picomm
= NULL
;
11274 picomm
= bgp_attr_get_community(pi
->attr
);
11278 if (type
== bgp_show_type_prefix_version
) {
11280 strtoul(output_arg
, NULL
, 10);
11281 if (dest
->version
< version
)
11285 if (type
== bgp_show_type_community_alias
) {
11286 char *alias
= output_arg
;
11287 char **communities
;
11289 bool found
= false;
11292 frrstr_split(picomm
->str
, " ",
11293 &communities
, &num
);
11294 for (int i
= 0; i
< num
; i
++) {
11295 const char *com2alias
=
11296 bgp_community2alias(
11299 && strcmp(alias
, com2alias
)
11305 XFREE(MTYPE_TMP
, communities
);
11309 bgp_attr_get_lcommunity(pi
->attr
)) {
11310 frrstr_split(bgp_attr_get_lcommunity(
11313 " ", &communities
, &num
);
11314 for (int i
= 0; i
< num
; i
++) {
11315 const char *com2alias
=
11316 bgp_community2alias(
11319 && strcmp(alias
, com2alias
)
11325 XFREE(MTYPE_TMP
, communities
);
11332 if (type
== bgp_show_type_rpki
) {
11333 if (dest_p
->family
== AF_INET
11334 || dest_p
->family
== AF_INET6
)
11335 rpki_curr_state
= hook_call(
11336 bgp_rpki_prefix_status
,
11337 pi
->peer
, pi
->attr
, dest_p
);
11338 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11339 && rpki_curr_state
!= rpki_target_state
)
11343 if (type
== bgp_show_type_flap_statistics
11344 || type
== bgp_show_type_flap_neighbor
11345 || type
== bgp_show_type_dampend_paths
11346 || type
== bgp_show_type_damp_neighbor
) {
11347 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11350 if (type
== bgp_show_type_regexp
) {
11351 regex_t
*regex
= output_arg
;
11353 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11357 if (type
== bgp_show_type_prefix_list
) {
11358 struct prefix_list
*plist
= output_arg
;
11360 if (prefix_list_apply(plist
, dest_p
)
11364 if (type
== bgp_show_type_access_list
) {
11365 struct access_list
*alist
= output_arg
;
11367 if (access_list_apply(alist
, dest_p
) !=
11371 if (type
== bgp_show_type_filter_list
) {
11372 struct as_list
*as_list
= output_arg
;
11374 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11375 != AS_FILTER_PERMIT
)
11378 if (type
== bgp_show_type_route_map
) {
11379 struct route_map
*rmap
= output_arg
;
11380 struct bgp_path_info path
;
11381 struct bgp_path_info_extra extra
;
11382 struct attr dummy_attr
= {};
11383 route_map_result_t ret
;
11385 dummy_attr
= *pi
->attr
;
11387 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11388 pi
->peer
, &dummy_attr
);
11390 ret
= route_map_apply(rmap
, dest_p
, &path
);
11391 bgp_attr_flush(&dummy_attr
);
11392 if (ret
== RMAP_DENYMATCH
)
11395 if (type
== bgp_show_type_neighbor
11396 || type
== bgp_show_type_flap_neighbor
11397 || type
== bgp_show_type_damp_neighbor
) {
11398 union sockunion
*su
= output_arg
;
11400 if (pi
->peer
== NULL
11401 || pi
->peer
->su_remote
== NULL
11402 || !sockunion_same(pi
->peer
->su_remote
, su
))
11405 if (type
== bgp_show_type_cidr_only
) {
11406 uint32_t destination
;
11408 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11409 if (IN_CLASSC(destination
)
11410 && dest_p
->prefixlen
== 24)
11412 if (IN_CLASSB(destination
)
11413 && dest_p
->prefixlen
== 16)
11415 if (IN_CLASSA(destination
)
11416 && dest_p
->prefixlen
== 8)
11419 if (type
== bgp_show_type_prefix_longer
) {
11421 if (!prefix_match(p
, dest_p
))
11424 if (type
== bgp_show_type_community_all
) {
11428 if (type
== bgp_show_type_community
) {
11429 struct community
*com
= output_arg
;
11431 if (!picomm
|| !community_match(picomm
, com
))
11434 if (type
== bgp_show_type_community_exact
) {
11435 struct community
*com
= output_arg
;
11437 if (!picomm
|| !community_cmp(picomm
, com
))
11440 if (type
== bgp_show_type_community_list
) {
11441 struct community_list
*list
= output_arg
;
11443 if (!community_list_match(picomm
, list
))
11446 if (type
== bgp_show_type_community_list_exact
) {
11447 struct community_list
*list
= output_arg
;
11449 if (!community_list_exact_match(picomm
, list
))
11452 if (type
== bgp_show_type_lcommunity
) {
11453 struct lcommunity
*lcom
= output_arg
;
11455 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11457 bgp_attr_get_lcommunity(pi
->attr
),
11462 if (type
== bgp_show_type_lcommunity_exact
) {
11463 struct lcommunity
*lcom
= output_arg
;
11465 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11467 bgp_attr_get_lcommunity(pi
->attr
),
11471 if (type
== bgp_show_type_lcommunity_list
) {
11472 struct community_list
*list
= output_arg
;
11474 if (!lcommunity_list_match(
11475 bgp_attr_get_lcommunity(pi
->attr
),
11480 == bgp_show_type_lcommunity_list_exact
) {
11481 struct community_list
*list
= output_arg
;
11483 if (!lcommunity_list_exact_match(
11484 bgp_attr_get_lcommunity(pi
->attr
),
11488 if (type
== bgp_show_type_lcommunity_all
) {
11489 if (!bgp_attr_get_lcommunity(pi
->attr
))
11492 if (type
== bgp_show_type_dampend_paths
11493 || type
== bgp_show_type_damp_neighbor
) {
11494 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11495 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11499 if (!use_json
&& header
) {
11501 "BGP table version is %" PRIu64
11502 ", local router ID is %pI4, vrf id ",
11503 table
->version
, &bgp
->router_id
);
11504 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11505 vty_out(vty
, "%s", VRFID_NONE_STR
);
11507 vty_out(vty
, "%u", bgp
->vrf_id
);
11508 vty_out(vty
, "\n");
11509 vty_out(vty
, "Default local pref %u, ",
11510 bgp
->default_local_pref
);
11511 vty_out(vty
, "local AS %u\n", bgp
->as
);
11512 if (!detail_routes
) {
11513 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11514 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11515 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11516 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11518 if (type
== bgp_show_type_dampend_paths
11519 || type
== bgp_show_type_damp_neighbor
)
11520 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11521 else if (type
== bgp_show_type_flap_statistics
11522 || type
== bgp_show_type_flap_neighbor
)
11523 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11524 else if (!detail_routes
)
11525 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11526 : BGP_SHOW_HEADER
));
11529 } else if (json_detail
&& json_paths
!= NULL
) {
11530 const struct prefix_rd
*prd
;
11531 json_object
*jtemp
;
11533 /* Use common detail header, for most types;
11534 * need a json 'object'.
11537 jtemp
= json_object_new_object();
11538 prd
= bgp_rd_from_dest(dest
, safi
);
11540 route_vty_out_detail_header(
11542 bgp_dest_get_prefix(dest
), prd
,
11543 table
->afi
, safi
, jtemp
);
11545 json_object_array_add(json_paths
, jtemp
);
11547 json_detail
= false;
11550 if (rd
!= NULL
&& !display
&& !output_count
) {
11553 "Route Distinguisher: %s\n",
11556 if (type
== bgp_show_type_dampend_paths
11557 || type
== bgp_show_type_damp_neighbor
)
11558 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11559 AFI_IP
, safi
, use_json
,
11561 else if (type
== bgp_show_type_flap_statistics
11562 || type
== bgp_show_type_flap_neighbor
)
11563 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11564 AFI_IP
, safi
, use_json
,
11567 if (detail_routes
|| detail_json
) {
11568 const struct prefix_rd
*prd
= NULL
;
11571 prd
= bgp_rd_from_dest(
11572 dest
->pdest
, safi
);
11575 route_vty_out_detail_header(
11577 bgp_dest_get_prefix(
11579 prd
, table
->afi
, safi
,
11582 route_vty_out_detail(
11583 vty
, bgp
, dest
, dest_p
, pi
,
11584 family2afi(dest_p
->family
),
11585 safi
, RPKI_NOT_BEING_USED
,
11588 route_vty_out(vty
, dest_p
, pi
, display
,
11589 safi
, json_paths
, wide
);
11600 /* encode prefix */
11601 if (dest_p
->family
== AF_FLOWSPEC
) {
11602 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11605 bgp_fs_nlri_get_string(
11607 dest_p
->u
.prefix_flowspec
.ptr
,
11608 dest_p
->u
.prefix_flowspec
.prefixlen
,
11609 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11610 family2afi(dest_p
->u
11611 .prefix_flowspec
.family
));
11613 vty_out(vty
, "\"%s/%d\": ", retstr
,
11614 dest_p
->u
.prefix_flowspec
11617 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11618 dest_p
->u
.prefix_flowspec
11622 vty_out(vty
, "\"%pFX\": ", dest_p
);
11624 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11626 vty_json(vty
, json_paths
);
11630 json_object_free(json_paths
);
11634 output_count
+= *output_cum
;
11635 *output_cum
= output_count
;
11638 total_count
+= *total_cum
;
11639 *total_cum
= total_count
;
11643 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11647 for (i
= 0; i
< *json_header_depth
; ++i
)
11648 vty_out(vty
, " } ");
11650 vty_out(vty
, "\n");
11654 /* No route is displayed */
11655 if (output_count
== 0) {
11656 if (type
== bgp_show_type_normal
)
11658 "No BGP prefixes displayed, %ld exist\n",
11662 "\nDisplayed %ld routes and %ld total paths\n",
11663 output_count
, total_count
);
11667 return CMD_SUCCESS
;
11670 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11671 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11672 enum bgp_show_type type
, void *output_arg
,
11673 uint16_t show_flags
)
11675 struct bgp_dest
*dest
, *next
;
11676 unsigned long output_cum
= 0;
11677 unsigned long total_cum
= 0;
11678 unsigned long json_header_depth
= 0;
11679 struct bgp_table
*itable
;
11681 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11683 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11685 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11686 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11688 next
= bgp_route_next(dest
);
11689 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11692 itable
= bgp_dest_get_bgp_table_info(dest
);
11693 if (itable
!= NULL
) {
11694 struct prefix_rd prd
;
11695 char rd
[RD_ADDRSTRLEN
];
11697 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11698 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11699 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11700 rd
, next
== NULL
, &output_cum
,
11701 &total_cum
, &json_header_depth
,
11702 show_flags
, RPKI_NOT_BEING_USED
);
11708 if (output_cum
== 0)
11709 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11713 "\nDisplayed %ld routes and %ld total paths\n",
11714 output_cum
, total_cum
);
11716 if (use_json
&& output_cum
== 0)
11717 vty_out(vty
, "{}\n");
11719 return CMD_SUCCESS
;
11722 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11723 enum bgp_show_type type
, void *output_arg
,
11724 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11726 struct bgp_table
*table
;
11727 unsigned long json_header_depth
= 0;
11728 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11731 bgp
= bgp_get_default();
11736 vty_out(vty
, "No BGP process is configured\n");
11738 vty_out(vty
, "{}\n");
11739 return CMD_WARNING
;
11742 /* Labeled-unicast routes live in the unicast table. */
11743 if (safi
== SAFI_LABELED_UNICAST
)
11744 safi
= SAFI_UNICAST
;
11746 table
= bgp
->rib
[afi
][safi
];
11747 /* use MPLS and ENCAP specific shows until they are merged */
11748 if (safi
== SAFI_MPLS_VPN
) {
11749 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11750 output_arg
, show_flags
);
11753 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11754 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11755 output_arg
, use_json
,
11759 if (safi
== SAFI_EVPN
)
11760 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11762 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11763 NULL
, NULL
, &json_header_depth
, show_flags
,
11764 rpki_target_state
);
11767 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11768 safi_t safi
, uint16_t show_flags
)
11770 struct listnode
*node
, *nnode
;
11773 bool route_output
= false;
11774 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11777 vty_out(vty
, "{\n");
11779 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11780 route_output
= true;
11783 vty_out(vty
, ",\n");
11787 vty_out(vty
, "\"%s\":",
11788 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11792 vty_out(vty
, "\nInstance %s:\n",
11793 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11797 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11798 show_flags
, RPKI_NOT_BEING_USED
);
11802 vty_out(vty
, "}\n");
11803 else if (!route_output
)
11804 vty_out(vty
, "%% BGP instance not found\n");
11807 /* Header of detailed BGP route information */
11808 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11809 struct bgp_dest
*dest
, const struct prefix
*p
,
11810 const struct prefix_rd
*prd
, afi_t afi
,
11811 safi_t safi
, json_object
*json
)
11813 struct bgp_path_info
*pi
;
11815 struct listnode
*node
, *nnode
;
11816 char buf1
[RD_ADDRSTRLEN
];
11820 int accept_own
= 0;
11821 int route_filter_translated_v4
= 0;
11822 int route_filter_v4
= 0;
11823 int route_filter_translated_v6
= 0;
11824 int route_filter_v6
= 0;
11825 int llgr_stale
= 0;
11827 int accept_own_nexthop
= 0;
11830 int no_advertise
= 0;
11834 int has_valid_label
= 0;
11835 mpls_label_t label
= 0;
11836 json_object
*json_adv_to
= NULL
;
11841 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11843 has_valid_label
= bgp_is_valid_label(&label
);
11845 if (safi
== SAFI_EVPN
) {
11847 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11848 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11850 prd
? ":" : "", (struct prefix_evpn
*)p
);
11852 json_object_string_add(json
, "rd",
11853 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11855 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11860 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11862 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11863 ? prefix_rd2str(prd
, buf1
,
11866 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11870 json_object_string_addf(json
, "prefix", "%pFX", p
);
11871 json_object_int_add(json
, "version", dest
->version
);
11876 if (has_valid_label
) {
11878 json_object_int_add(json
, "localLabel", label
);
11880 vty_out(vty
, "Local label: %d\n", label
);
11884 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11885 vty_out(vty
, "not allocated\n");
11887 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11888 struct community
*picomm
= NULL
;
11890 picomm
= bgp_attr_get_community(pi
->attr
);
11893 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11895 if (bgp_path_suppressed(pi
))
11901 no_advertise
+= community_include(
11902 picomm
, COMMUNITY_NO_ADVERTISE
);
11904 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11906 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11908 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11909 route_filter_translated_v4
+= community_include(
11910 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11911 route_filter_translated_v6
+= community_include(
11912 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11913 route_filter_v4
+= community_include(
11914 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11915 route_filter_v6
+= community_include(
11916 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11918 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11919 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11920 accept_own_nexthop
+= community_include(
11921 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11923 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11924 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11929 vty_out(vty
, "Paths: (%d available", count
);
11931 vty_out(vty
, ", best #%d", best
);
11932 if (safi
== SAFI_UNICAST
) {
11933 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11934 vty_out(vty
, ", table %s",
11937 vty_out(vty
, ", vrf %s",
11941 vty_out(vty
, ", no best path");
11945 ", accept own local route exported and imported in different VRF");
11946 else if (route_filter_translated_v4
)
11948 ", mark translated RTs for VPNv4 route filtering");
11949 else if (route_filter_v4
)
11951 ", attach RT as-is for VPNv4 route filtering");
11952 else if (route_filter_translated_v6
)
11954 ", mark translated RTs for VPNv6 route filtering");
11955 else if (route_filter_v6
)
11957 ", attach RT as-is for VPNv6 route filtering");
11958 else if (llgr_stale
)
11960 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11963 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11964 else if (accept_own_nexthop
)
11966 ", accept local nexthop");
11967 else if (blackhole
)
11968 vty_out(vty
, ", inform peer to blackhole prefix");
11969 else if (no_export
)
11970 vty_out(vty
, ", not advertised to EBGP peer");
11971 else if (no_advertise
)
11972 vty_out(vty
, ", not advertised to any peer");
11974 vty_out(vty
, ", not advertised outside local AS");
11977 ", inform EBGP peer not to advertise to their EBGP peers");
11981 ", Advertisements suppressed by an aggregate.");
11982 vty_out(vty
, ")\n");
11985 /* If we are not using addpath then we can display Advertised to and
11987 * show what peers we advertised the bestpath to. If we are using
11989 * though then we must display Advertised to on a path-by-path basis. */
11990 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11991 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11992 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11993 if (json
&& !json_adv_to
)
11994 json_adv_to
= json_object_new_object();
11996 route_vty_out_advertised_to(
11998 " Advertised to non peer-group peers:\n ",
12005 json_object_object_add(json
, "advertisedTo",
12010 vty_out(vty
, " Not advertised to any peer");
12011 vty_out(vty
, "\n");
12016 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12017 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12018 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12019 json_object
*json
, enum bgp_path_type pathtype
,
12020 int *display
, enum rpki_states rpki_target_state
)
12022 struct bgp_path_info
*pi
;
12024 json_object
*json_header
= NULL
;
12025 json_object
*json_paths
= NULL
;
12026 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12028 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12029 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12031 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12032 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12033 pi
->peer
, pi
->attr
, p
);
12035 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12036 && rpki_curr_state
!= rpki_target_state
)
12039 if (json
&& !json_paths
) {
12040 /* Instantiate json_paths only if path is valid */
12041 json_paths
= json_object_new_array();
12043 json_header
= json_object_new_object();
12045 json_header
= json
;
12049 route_vty_out_detail_header(
12050 vty
, bgp
, bgp_node
,
12051 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12052 safi
, json_header
);
12057 if (pathtype
== BGP_PATH_SHOW_ALL
12058 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12059 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12060 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12061 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12062 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12063 route_vty_out_detail(vty
, bgp
, bgp_node
,
12064 bgp_dest_get_prefix(bgp_node
), pi
,
12065 AFI_IP
, safi
, rpki_curr_state
,
12069 if (json
&& json_paths
) {
12070 json_object_object_add(json_header
, "paths", json_paths
);
12073 json_object_object_addf(json
, json_header
, "%pRD",
12079 * Return rd based on safi
12081 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12085 case SAFI_MPLS_VPN
:
12088 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12094 /* Display specified route of BGP table. */
12095 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12096 struct bgp_table
*rib
, const char *ip_str
,
12097 afi_t afi
, safi_t safi
,
12098 enum rpki_states rpki_target_state
,
12099 struct prefix_rd
*prd
, int prefix_check
,
12100 enum bgp_path_type pathtype
, bool use_json
)
12104 struct prefix match
;
12105 struct bgp_dest
*dest
;
12106 struct bgp_dest
*rm
;
12107 struct bgp_table
*table
;
12108 json_object
*json
= NULL
;
12109 json_object
*json_paths
= NULL
;
12111 /* Check IP address argument. */
12112 ret
= str2prefix(ip_str
, &match
);
12114 vty_out(vty
, "address is malformed\n");
12115 return CMD_WARNING
;
12118 match
.family
= afi2family(afi
);
12121 json
= json_object_new_object();
12123 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12124 for (dest
= bgp_table_top(rib
); dest
;
12125 dest
= bgp_route_next(dest
)) {
12126 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12128 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12130 table
= bgp_dest_get_bgp_table_info(dest
);
12134 rm
= bgp_node_match(table
, &match
);
12138 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12140 && rm_p
->prefixlen
!= match
.prefixlen
) {
12141 bgp_dest_unlock_node(rm
);
12145 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12146 bgp
, afi
, safi
, json
, pathtype
,
12147 &display
, rpki_target_state
);
12149 bgp_dest_unlock_node(rm
);
12151 } else if (safi
== SAFI_EVPN
) {
12152 struct bgp_dest
*longest_pfx
;
12153 bool is_exact_pfxlen_match
= false;
12155 for (dest
= bgp_table_top(rib
); dest
;
12156 dest
= bgp_route_next(dest
)) {
12157 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12159 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12161 table
= bgp_dest_get_bgp_table_info(dest
);
12165 longest_pfx
= NULL
;
12166 is_exact_pfxlen_match
= false;
12168 * Search through all the prefixes for a match. The
12169 * pfx's are enumerated in ascending order of pfxlens.
12170 * So, the last pfx match is the longest match. Set
12171 * is_exact_pfxlen_match when we get exact pfxlen match
12173 for (rm
= bgp_table_top(table
); rm
;
12174 rm
= bgp_route_next(rm
)) {
12175 const struct prefix
*rm_p
=
12176 bgp_dest_get_prefix(rm
);
12178 * Get prefixlen of the ip-prefix within type5
12181 if (evpn_type5_prefix_match(rm_p
, &match
)
12185 bgp_evpn_get_type5_prefixlen(
12187 if (type5_pfxlen
== match
.prefixlen
) {
12188 is_exact_pfxlen_match
= true;
12189 bgp_dest_unlock_node(rm
);
12198 if (prefix_check
&& !is_exact_pfxlen_match
)
12202 bgp_dest_lock_node(rm
);
12204 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12205 bgp
, afi
, safi
, json
, pathtype
,
12206 &display
, rpki_target_state
);
12208 bgp_dest_unlock_node(rm
);
12210 } else if (safi
== SAFI_FLOWSPEC
) {
12212 json_paths
= json_object_new_array();
12214 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12215 &match
, prefix_check
,
12221 json_object_object_add(json
, "paths",
12224 json_object_free(json_paths
);
12227 dest
= bgp_node_match(rib
, &match
);
12228 if (dest
!= NULL
) {
12229 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12231 || dest_p
->prefixlen
== match
.prefixlen
) {
12232 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12233 safi
, json
, pathtype
,
12234 &display
, rpki_target_state
);
12237 bgp_dest_unlock_node(dest
);
12242 vty_json(vty
, json
);
12245 vty_out(vty
, "%% Network not in table\n");
12246 return CMD_WARNING
;
12250 return CMD_SUCCESS
;
12253 /* Display specified route of Main RIB */
12254 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12255 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12256 int prefix_check
, enum bgp_path_type pathtype
,
12257 enum rpki_states rpki_target_state
, bool use_json
)
12260 bgp
= bgp_get_default();
12263 vty_out(vty
, "No BGP process is configured\n");
12265 vty_out(vty
, "{}\n");
12266 return CMD_WARNING
;
12270 /* labeled-unicast routes live in the unicast table */
12271 if (safi
== SAFI_LABELED_UNICAST
)
12272 safi
= SAFI_UNICAST
;
12274 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12275 afi
, safi
, rpki_target_state
, prd
,
12276 prefix_check
, pathtype
, use_json
);
12279 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12280 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12281 safi_t safi
, bool uj
)
12283 struct lcommunity
*lcom
;
12288 uint16_t show_flags
= 0;
12292 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12294 b
= buffer_new(1024);
12295 for (i
= 0; i
< argc
; i
++) {
12297 buffer_putc(b
, ' ');
12299 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12301 buffer_putstr(b
, argv
[i
]->arg
);
12305 buffer_putc(b
, '\0');
12307 str
= buffer_getstr(b
);
12310 lcom
= lcommunity_str2com(str
);
12311 XFREE(MTYPE_TMP
, str
);
12313 vty_out(vty
, "%% Large-community malformed\n");
12314 return CMD_WARNING
;
12317 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12318 (exact
? bgp_show_type_lcommunity_exact
12319 : bgp_show_type_lcommunity
),
12320 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12322 lcommunity_free(&lcom
);
12326 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12327 const char *lcom
, bool exact
, afi_t afi
,
12328 safi_t safi
, bool uj
)
12330 struct community_list
*list
;
12331 uint16_t show_flags
= 0;
12334 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12337 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12338 LARGE_COMMUNITY_LIST_MASTER
);
12339 if (list
== NULL
) {
12340 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12342 return CMD_WARNING
;
12345 return bgp_show(vty
, bgp
, afi
, safi
,
12346 (exact
? bgp_show_type_lcommunity_list_exact
12347 : bgp_show_type_lcommunity_list
),
12348 list
, show_flags
, RPKI_NOT_BEING_USED
);
12351 DEFUN (show_ip_bgp_large_community_list
,
12352 show_ip_bgp_large_community_list_cmd
,
12353 "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]",
12357 BGP_INSTANCE_HELP_STR
12359 BGP_SAFI_WITH_LABEL_HELP_STR
12360 "Display routes matching the large-community-list\n"
12361 "large-community-list number\n"
12362 "large-community-list name\n"
12363 "Exact match of the large-communities\n"
12366 afi_t afi
= AFI_IP6
;
12367 safi_t safi
= SAFI_UNICAST
;
12369 bool exact_match
= 0;
12370 struct bgp
*bgp
= NULL
;
12371 bool uj
= use_json(argc
, argv
);
12376 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12379 return CMD_WARNING
;
12381 argv_find(argv
, argc
, "large-community-list", &idx
);
12383 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12385 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12388 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12389 exact_match
, afi
, safi
, uj
);
12391 DEFUN (show_ip_bgp_large_community
,
12392 show_ip_bgp_large_community_cmd
,
12393 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12397 BGP_INSTANCE_HELP_STR
12399 BGP_SAFI_WITH_LABEL_HELP_STR
12400 "Display routes matching the large-communities\n"
12401 "List of large-community numbers\n"
12402 "Exact match of the large-communities\n"
12405 afi_t afi
= AFI_IP6
;
12406 safi_t safi
= SAFI_UNICAST
;
12408 bool exact_match
= 0;
12409 struct bgp
*bgp
= NULL
;
12410 bool uj
= use_json(argc
, argv
);
12411 uint16_t show_flags
= 0;
12415 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12418 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12421 return CMD_WARNING
;
12423 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12424 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12428 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12429 exact_match
, afi
, safi
, uj
);
12431 return bgp_show(vty
, bgp
, afi
, safi
,
12432 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12433 RPKI_NOT_BEING_USED
);
12436 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12437 safi_t safi
, struct json_object
*json_array
);
12438 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12439 safi_t safi
, struct json_object
*json
);
12442 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12443 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12444 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12445 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12447 bool uj
= use_json(argc
, argv
);
12448 struct bgp
*bgp
= NULL
;
12449 safi_t safi
= SAFI_UNICAST
;
12450 afi_t afi
= AFI_IP6
;
12452 struct json_object
*json_all
= NULL
;
12453 struct json_object
*json_afi_safi
= NULL
;
12455 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12458 return CMD_WARNING
;
12461 json_all
= json_object_new_object();
12463 FOREACH_AFI_SAFI (afi
, safi
) {
12465 * So limit output to those afi/safi pairs that
12466 * actually have something interesting in them
12468 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12473 json_afi_safi
= json_object_new_array();
12474 json_object_object_add(
12476 get_afi_safi_str(afi
, safi
, true),
12479 json_afi_safi
= NULL
;
12482 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12486 vty_json(vty
, json_all
);
12488 return CMD_SUCCESS
;
12491 /* BGP route print out function without JSON */
12492 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12493 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12494 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12498 BGP_INSTANCE_HELP_STR
12501 "BGP RIB advertisement statistics\n"
12504 afi_t afi
= AFI_IP6
;
12505 safi_t safi
= SAFI_UNICAST
;
12506 struct bgp
*bgp
= NULL
;
12508 bool uj
= use_json(argc
, argv
);
12509 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12511 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12514 return CMD_WARNING
;
12517 json_afi_safi
= json_object_new_array();
12519 json_afi_safi
= NULL
;
12521 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12524 json
= json_object_new_object();
12525 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12527 vty_json(vty
, json
);
12532 /* BGP route print out function without JSON */
12533 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12534 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12535 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12537 statistics [json]",
12538 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12539 BGP_SAFI_WITH_LABEL_HELP_STR
12540 "BGP RIB advertisement statistics\n" JSON_STR
)
12542 afi_t afi
= AFI_IP6
;
12543 safi_t safi
= SAFI_UNICAST
;
12544 struct bgp
*bgp
= NULL
;
12546 bool uj
= use_json(argc
, argv
);
12547 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12549 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12552 return CMD_WARNING
;
12555 json_afi_safi
= json_object_new_array();
12557 json_afi_safi
= NULL
;
12559 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12562 json
= json_object_new_object();
12563 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12565 vty_json(vty
, json
);
12570 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12571 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12572 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12573 "]] [all$all] dampening parameters [json]",
12574 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12575 BGP_SAFI_WITH_LABEL_HELP_STR
12576 "Display the entries for all address families\n"
12577 "Display detailed information about dampening\n"
12578 "Display detail of configured dampening parameters\n"
12581 afi_t afi
= AFI_IP6
;
12582 safi_t safi
= SAFI_UNICAST
;
12583 struct bgp
*bgp
= NULL
;
12585 uint16_t show_flags
= 0;
12586 bool uj
= use_json(argc
, argv
);
12590 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12593 /* [<ipv4|ipv6> [all]] */
12595 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12596 if (argv_find(argv
, argc
, "ipv4", &idx
))
12597 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12599 if (argv_find(argv
, argc
, "ipv6", &idx
))
12600 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12603 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12606 return CMD_WARNING
;
12608 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12611 /* BGP route print out function */
12612 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12613 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12614 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12618 |dampening <flap-statistics|dampened-paths>\
12619 |community [AA:NN|local-AS|no-advertise|no-export\
12620 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12621 |accept-own|accept-own-nexthop|route-filter-v6\
12622 |route-filter-v4|route-filter-translated-v6\
12623 |route-filter-translated-v4] [exact-match]\
12624 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12625 |filter-list AS_PATH_FILTER_NAME\
12627 |access-list ACCESSLIST_NAME\
12628 |route-map RMAP_NAME\
12629 |rpki <invalid|valid|notfound>\
12630 |version (1-4294967295)\
12632 |A.B.C.D/M longer-prefixes\
12633 |X:X::X:X/M longer-prefixes\
12634 |detail-routes$detail_routes\
12635 ] [json$uj [detail$detail_json] | wide$wide]",
12636 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12637 BGP_SAFI_WITH_LABEL_HELP_STR
12638 "Display the entries for all address families\n"
12639 "Display only routes with non-natural netmasks\n"
12640 "Display detailed information about dampening\n"
12641 "Display flap statistics of routes\n"
12642 "Display paths suppressed due to dampening\n"
12643 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12644 "Do not send outside local AS (well-known community)\n"
12645 "Do not advertise to any peer (well-known community)\n"
12646 "Do not export to next AS (well-known community)\n"
12647 "Graceful shutdown (well-known community)\n"
12648 "Do not export to any peer (well-known community)\n"
12649 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12650 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12651 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12652 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12653 "Should accept VPN route with local nexthop (well-known community)\n"
12654 "RT VPNv6 route filtering (well-known community)\n"
12655 "RT VPNv4 route filtering (well-known community)\n"
12656 "RT translated VPNv6 route filtering (well-known community)\n"
12657 "RT translated VPNv4 route filtering (well-known community)\n"
12658 "Exact match of the communities\n"
12659 "Community-list number\n"
12660 "Community-list name\n"
12661 "Display routes matching the community-list\n"
12662 "Exact match of the communities\n"
12663 "Display routes conforming to the filter-list\n"
12664 "Regular expression access list name\n"
12665 "Display routes conforming to the prefix-list\n"
12666 "Prefix-list name\n"
12667 "Display routes conforming to the access-list\n"
12668 "Access-list name\n"
12669 "Display routes matching the route-map\n"
12670 "A route-map to match on\n"
12671 "RPKI route types\n"
12672 "A valid path as determined by rpki\n"
12673 "A invalid path as determined by rpki\n"
12674 "A path that has no rpki data\n"
12675 "Display prefixes with matching version numbers\n"
12676 "Version number and above\n"
12677 "Display prefixes with matching BGP community alias\n"
12678 "BGP community alias\n"
12680 "Display route and more specific routes\n"
12682 "Display route and more specific routes\n"
12683 "Display detailed version of all routes\n"
12685 "Display detailed version of JSON output\n"
12686 "Increase table width for longer prefixes\n")
12688 afi_t afi
= AFI_IP6
;
12689 safi_t safi
= SAFI_UNICAST
;
12690 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12691 void *output_arg
= NULL
;
12692 struct bgp
*bgp
= NULL
;
12694 int exact_match
= 0;
12695 char *community
= NULL
;
12697 uint16_t show_flags
= 0;
12698 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12703 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12707 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12710 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12712 /* [<ipv4|ipv6> [all]] */
12714 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12716 if (argv_find(argv
, argc
, "ipv4", &idx
))
12717 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12719 if (argv_find(argv
, argc
, "ipv6", &idx
))
12720 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12724 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12726 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12729 return CMD_WARNING
;
12731 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12732 sh_type
= bgp_show_type_cidr_only
;
12734 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12735 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12736 sh_type
= bgp_show_type_dampend_paths
;
12737 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12738 sh_type
= bgp_show_type_flap_statistics
;
12741 if (argv_find(argv
, argc
, "community", &idx
)) {
12742 char *maybecomm
= NULL
;
12744 if (idx
+ 1 < argc
) {
12745 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12746 maybecomm
= argv
[idx
+ 1]->arg
;
12748 maybecomm
= argv
[idx
+ 1]->text
;
12751 if (maybecomm
&& !strmatch(maybecomm
, "json")
12752 && !strmatch(maybecomm
, "exact-match"))
12753 community
= maybecomm
;
12755 if (argv_find(argv
, argc
, "exact-match", &idx
))
12759 sh_type
= bgp_show_type_community_all
;
12762 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12763 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12764 struct community_list
*list
;
12766 if (argv_find(argv
, argc
, "exact-match", &idx
))
12769 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12770 COMMUNITY_LIST_MASTER
);
12771 if (list
== NULL
) {
12772 vty_out(vty
, "%% %s community-list not found\n",
12773 clist_number_or_name
);
12774 return CMD_WARNING
;
12778 sh_type
= bgp_show_type_community_list_exact
;
12780 sh_type
= bgp_show_type_community_list
;
12784 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12785 const char *filter
= argv
[++idx
]->arg
;
12786 struct as_list
*as_list
;
12788 as_list
= as_list_lookup(filter
);
12789 if (as_list
== NULL
) {
12790 vty_out(vty
, "%% %s AS-path access-list not found\n",
12792 return CMD_WARNING
;
12795 sh_type
= bgp_show_type_filter_list
;
12796 output_arg
= as_list
;
12799 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12800 const char *prefix_list_str
= argv
[++idx
]->arg
;
12801 struct prefix_list
*plist
;
12803 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12804 if (plist
== NULL
) {
12805 vty_out(vty
, "%% %s prefix-list not found\n",
12807 return CMD_WARNING
;
12810 sh_type
= bgp_show_type_prefix_list
;
12811 output_arg
= plist
;
12814 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12815 const char *access_list_str
= argv
[++idx
]->arg
;
12816 struct access_list
*alist
;
12818 alist
= access_list_lookup(afi
, access_list_str
);
12820 vty_out(vty
, "%% %s access-list not found\n",
12822 return CMD_WARNING
;
12825 sh_type
= bgp_show_type_access_list
;
12826 output_arg
= alist
;
12829 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12830 const char *rmap_str
= argv
[++idx
]->arg
;
12831 struct route_map
*rmap
;
12833 rmap
= route_map_lookup_by_name(rmap_str
);
12835 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12836 return CMD_WARNING
;
12839 sh_type
= bgp_show_type_route_map
;
12843 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12844 sh_type
= bgp_show_type_rpki
;
12845 if (argv_find(argv
, argc
, "valid", &idx
))
12846 rpki_target_state
= RPKI_VALID
;
12847 else if (argv_find(argv
, argc
, "invalid", &idx
))
12848 rpki_target_state
= RPKI_INVALID
;
12851 /* Display prefixes with matching version numbers */
12852 if (argv_find(argv
, argc
, "version", &idx
)) {
12853 sh_type
= bgp_show_type_prefix_version
;
12854 output_arg
= argv
[idx
+ 1]->arg
;
12857 /* Display prefixes with matching BGP community alias */
12858 if (argv_find(argv
, argc
, "alias", &idx
)) {
12859 sh_type
= bgp_show_type_community_alias
;
12860 output_arg
= argv
[idx
+ 1]->arg
;
12863 /* prefix-longer */
12864 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12865 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12866 const char *prefix_str
= argv
[idx
]->arg
;
12868 if (!str2prefix(prefix_str
, &p
)) {
12869 vty_out(vty
, "%% Malformed Prefix\n");
12870 return CMD_WARNING
;
12873 sh_type
= bgp_show_type_prefix_longer
;
12878 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12880 return bgp_show_community(vty
, bgp
, community
,
12881 exact_match
, afi
, safi
,
12884 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12885 output_arg
, show_flags
,
12886 rpki_target_state
);
12888 struct listnode
*node
;
12890 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12894 vty_out(vty
, "{\n");
12896 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12897 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12898 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12901 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12902 FOREACH_SAFI (safi
) {
12903 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12911 vty_out(vty
, ",\n");
12912 vty_out(vty
, "\"%s\":{\n",
12913 get_afi_safi_str(afi
,
12918 "\nFor address family: %s\n",
12924 bgp_show_community(
12925 vty
, abgp
, community
,
12926 exact_match
, afi
, safi
,
12929 bgp_show(vty
, abgp
, afi
, safi
,
12930 sh_type
, output_arg
,
12932 rpki_target_state
);
12934 vty_out(vty
, "}\n");
12938 /* show <ip> bgp all: for each AFI and SAFI*/
12939 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12940 FOREACH_AFI_SAFI (afi
, safi
) {
12941 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12949 vty_out(vty
, ",\n");
12951 vty_out(vty
, "\"%s\":{\n",
12952 get_afi_safi_str(afi
,
12957 "\nFor address family: %s\n",
12963 bgp_show_community(
12964 vty
, abgp
, community
,
12965 exact_match
, afi
, safi
,
12968 bgp_show(vty
, abgp
, afi
, safi
,
12969 sh_type
, output_arg
,
12971 rpki_target_state
);
12973 vty_out(vty
, "}\n");
12978 vty_out(vty
, "}\n");
12980 return CMD_SUCCESS
;
12983 DEFUN (show_ip_bgp_route
,
12984 show_ip_bgp_route_cmd
,
12985 "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]",
12989 BGP_INSTANCE_HELP_STR
12991 BGP_SAFI_WITH_LABEL_HELP_STR
12992 "Network in the BGP routing table to display\n"
12994 "Network in the BGP routing table to display\n"
12996 "Display only the bestpath\n"
12997 "Display only multipaths\n"
12998 "Display only paths that match the specified rpki state\n"
12999 "A valid path as determined by rpki\n"
13000 "A invalid path as determined by rpki\n"
13001 "A path that has no rpki data\n"
13004 int prefix_check
= 0;
13006 afi_t afi
= AFI_IP6
;
13007 safi_t safi
= SAFI_UNICAST
;
13008 char *prefix
= NULL
;
13009 struct bgp
*bgp
= NULL
;
13010 enum bgp_path_type path_type
;
13011 bool uj
= use_json(argc
, argv
);
13015 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13018 return CMD_WARNING
;
13022 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13023 return CMD_WARNING
;
13026 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13027 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13028 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13030 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13031 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13034 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13035 && afi
!= AFI_IP6
) {
13037 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13038 return CMD_WARNING
;
13040 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13041 && afi
!= AFI_IP
) {
13043 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13044 return CMD_WARNING
;
13047 prefix
= argv
[idx
]->arg
;
13049 /* [<bestpath|multipath>] */
13050 if (argv_find(argv
, argc
, "bestpath", &idx
))
13051 path_type
= BGP_PATH_SHOW_BESTPATH
;
13052 else if (argv_find(argv
, argc
, "multipath", &idx
))
13053 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13055 path_type
= BGP_PATH_SHOW_ALL
;
13057 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13058 path_type
, RPKI_NOT_BEING_USED
, uj
);
13061 DEFUN (show_ip_bgp_regexp
,
13062 show_ip_bgp_regexp_cmd
,
13063 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13067 BGP_INSTANCE_HELP_STR
13069 BGP_SAFI_WITH_LABEL_HELP_STR
13070 "Display routes matching the AS path regular expression\n"
13071 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13074 afi_t afi
= AFI_IP6
;
13075 safi_t safi
= SAFI_UNICAST
;
13076 struct bgp
*bgp
= NULL
;
13077 bool uj
= use_json(argc
, argv
);
13078 char *regstr
= NULL
;
13081 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13084 return CMD_WARNING
;
13086 // get index of regex
13087 if (argv_find(argv
, argc
, "REGEX", &idx
))
13088 regstr
= argv
[idx
]->arg
;
13091 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13092 bgp_show_type_regexp
, uj
);
13095 DEFPY (show_ip_bgp_instance_all
,
13096 show_ip_bgp_instance_all_cmd
,
13097 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13101 BGP_INSTANCE_ALL_HELP_STR
13103 BGP_SAFI_WITH_LABEL_HELP_STR
13105 "Increase table width for longer prefixes\n")
13107 afi_t afi
= AFI_IP6
;
13108 safi_t safi
= SAFI_UNICAST
;
13109 struct bgp
*bgp
= NULL
;
13111 uint16_t show_flags
= 0;
13115 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13119 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13121 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13124 return CMD_WARNING
;
13126 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13127 return CMD_SUCCESS
;
13130 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13131 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13136 uint16_t show_flags
= 0;
13139 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13141 if (!config_bgp_aspath_validate(regstr
)) {
13142 vty_out(vty
, "Invalid character in REGEX %s\n",
13144 return CMD_WARNING_CONFIG_FAILED
;
13147 regex
= bgp_regcomp(regstr
);
13149 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13150 return CMD_WARNING
;
13153 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13154 RPKI_NOT_BEING_USED
);
13155 bgp_regex_free(regex
);
13159 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13160 const char *comstr
, int exact
, afi_t afi
,
13161 safi_t safi
, uint16_t show_flags
)
13163 struct community
*com
;
13166 com
= community_str2com(comstr
);
13168 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13169 return CMD_WARNING
;
13172 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13173 (exact
? bgp_show_type_community_exact
13174 : bgp_show_type_community
),
13175 com
, show_flags
, RPKI_NOT_BEING_USED
);
13176 community_free(&com
);
13182 BGP_STATS_MAXBITLEN
= 0,
13184 BGP_STATS_PREFIXES
,
13186 BGP_STATS_UNAGGREGATEABLE
,
13187 BGP_STATS_MAX_AGGREGATEABLE
,
13188 BGP_STATS_AGGREGATES
,
13190 BGP_STATS_ASPATH_COUNT
,
13191 BGP_STATS_ASPATH_MAXHOPS
,
13192 BGP_STATS_ASPATH_TOTHOPS
,
13193 BGP_STATS_ASPATH_MAXSIZE
,
13194 BGP_STATS_ASPATH_TOTSIZE
,
13195 BGP_STATS_ASN_HIGHEST
,
13199 #define TABLE_STATS_IDX_VTY 0
13200 #define TABLE_STATS_IDX_JSON 1
13202 static const char *table_stats_strs
[][2] = {
13203 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13204 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13205 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13206 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13207 "unaggregateablePrefixes"},
13208 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13209 "maximumAggregateablePrefixes"},
13210 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13211 "bgpAggregateAdvertisements"},
13212 [BGP_STATS_SPACE
] = {"Address space advertised",
13213 "addressSpaceAdvertised"},
13214 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13215 "advertisementsWithPaths"},
13216 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13218 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13220 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13221 "averageAsPathLengthHops"},
13222 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13223 "averageAsPathSizeBytes"},
13224 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13225 [BGP_STATS_MAX
] = {NULL
, NULL
}
13228 struct bgp_table_stats
{
13229 struct bgp_table
*table
;
13230 unsigned long long counts
[BGP_STATS_MAX
];
13233 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13236 double total_space
;
13239 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13240 struct bgp_table_stats
*ts
, unsigned int space
)
13242 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13243 struct bgp_path_info
*pi
;
13244 const struct prefix
*rn_p
;
13246 if (!bgp_dest_has_bgp_path_info_data(dest
))
13249 rn_p
= bgp_dest_get_prefix(dest
);
13250 ts
->counts
[BGP_STATS_PREFIXES
]++;
13251 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13253 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13254 /* check if the prefix is included by any other announcements */
13255 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13256 pdest
= bgp_dest_parent_nolock(pdest
);
13258 if (pdest
== NULL
|| pdest
== top
) {
13259 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13260 /* announced address space */
13262 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13263 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13264 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13267 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13268 ts
->counts
[BGP_STATS_RIB
]++;
13270 if (CHECK_FLAG(pi
->attr
->flag
,
13271 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13272 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13274 /* as-path stats */
13275 if (pi
->attr
->aspath
) {
13276 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13277 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13278 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13280 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13282 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13283 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13285 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13286 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13288 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13289 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13290 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13291 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13296 static void bgp_table_stats_walker(struct thread
*t
)
13298 struct bgp_dest
*dest
, *ndest
;
13299 struct bgp_dest
*top
;
13300 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13301 unsigned int space
= 0;
13303 if (!(top
= bgp_table_top(ts
->table
)))
13306 switch (ts
->table
->afi
) {
13308 space
= IPV4_MAX_BITLEN
;
13311 space
= IPV6_MAX_BITLEN
;
13314 space
= EVPN_ROUTE_PREFIXLEN
;
13320 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13322 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13323 if (ts
->table
->safi
== SAFI_MPLS_VPN
13324 || ts
->table
->safi
== SAFI_ENCAP
13325 || ts
->table
->safi
== SAFI_EVPN
) {
13326 struct bgp_table
*table
;
13328 table
= bgp_dest_get_bgp_table_info(dest
);
13332 top
= bgp_table_top(table
);
13333 for (ndest
= bgp_table_top(table
); ndest
;
13334 ndest
= bgp_route_next(ndest
))
13335 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13337 bgp_table_stats_rn(dest
, top
, ts
, space
);
13342 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13343 struct json_object
*json_array
)
13345 struct listnode
*node
, *nnode
;
13348 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13349 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13352 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13353 safi_t safi
, struct json_object
*json_array
)
13355 struct bgp_table_stats ts
;
13357 int ret
= CMD_SUCCESS
;
13359 struct json_object
*json
= NULL
;
13360 uint32_t bitlen
= 0;
13361 struct json_object
*json_bitlen
;
13364 json
= json_object_new_object();
13366 if (!bgp
->rib
[afi
][safi
]) {
13367 char warning_msg
[50];
13369 snprintf(warning_msg
, sizeof(warning_msg
),
13370 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13374 vty_out(vty
, "%s\n", warning_msg
);
13376 json_object_string_add(json
, "warning", warning_msg
);
13379 goto end_table_stats
;
13383 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13384 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13386 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13388 /* labeled-unicast routes live in the unicast table */
13389 if (safi
== SAFI_LABELED_UNICAST
)
13390 safi
= SAFI_UNICAST
;
13392 memset(&ts
, 0, sizeof(ts
));
13393 ts
.table
= bgp
->rib
[afi
][safi
];
13394 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13396 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13397 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13398 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13402 case BGP_STATS_ASPATH_TOTHOPS
:
13403 case BGP_STATS_ASPATH_TOTSIZE
:
13406 temp_buf
, sizeof(temp_buf
), "%12.2f",
13408 ? (float)ts
.counts
[i
]
13410 [BGP_STATS_ASPATH_COUNT
]
13412 vty_out(vty
, "%-30s: %s",
13413 table_stats_strs
[i
]
13414 [TABLE_STATS_IDX_VTY
],
13417 json_object_double_add(
13419 table_stats_strs
[i
]
13420 [TABLE_STATS_IDX_JSON
],
13422 ? (double)ts
.counts
[i
]
13423 / (double)ts
.counts
13424 [BGP_STATS_ASPATH_COUNT
]
13428 case BGP_STATS_TOTPLEN
:
13431 temp_buf
, sizeof(temp_buf
), "%12.2f",
13433 ? (float)ts
.counts
[i
]
13435 [BGP_STATS_PREFIXES
]
13437 vty_out(vty
, "%-30s: %s",
13438 table_stats_strs
[i
]
13439 [TABLE_STATS_IDX_VTY
],
13442 json_object_double_add(
13444 table_stats_strs
[i
]
13445 [TABLE_STATS_IDX_JSON
],
13447 ? (double)ts
.counts
[i
]
13448 / (double)ts
.counts
13449 [BGP_STATS_PREFIXES
]
13453 case BGP_STATS_SPACE
:
13455 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13457 vty_out(vty
, "%-30s: %s\n",
13458 table_stats_strs
[i
]
13459 [TABLE_STATS_IDX_VTY
],
13462 json_object_double_add(
13464 table_stats_strs
[i
]
13465 [TABLE_STATS_IDX_JSON
],
13466 (double)ts
.total_space
);
13468 if (afi
== AFI_IP6
) {
13470 snprintf(temp_buf
, sizeof(temp_buf
),
13473 * pow(2.0, -128 + 32));
13474 vty_out(vty
, "%30s: %s\n",
13475 "/32 equivalent %s\n",
13478 json_object_double_add(
13479 json
, "/32equivalent",
13480 (double)(ts
.total_space
13485 snprintf(temp_buf
, sizeof(temp_buf
),
13488 * pow(2.0, -128 + 48));
13489 vty_out(vty
, "%30s: %s\n",
13490 "/48 equivalent %s\n",
13493 json_object_double_add(
13494 json
, "/48equivalent",
13495 (double)(ts
.total_space
13501 snprintf(temp_buf
, sizeof(temp_buf
),
13503 ts
.total_space
* 100.
13505 vty_out(vty
, "%30s: %s\n",
13506 "% announced ", temp_buf
);
13508 json_object_double_add(
13509 json
, "%announced",
13510 (double)(ts
.total_space
* 100.
13514 snprintf(temp_buf
, sizeof(temp_buf
),
13517 * pow(2.0, -32 + 8));
13518 vty_out(vty
, "%30s: %s\n",
13519 "/8 equivalent ", temp_buf
);
13521 json_object_double_add(
13522 json
, "/8equivalent",
13523 (double)(ts
.total_space
13524 * pow(2.0, -32 + 8)));
13527 snprintf(temp_buf
, sizeof(temp_buf
),
13530 * pow(2.0, -32 + 24));
13531 vty_out(vty
, "%30s: %s\n",
13532 "/24 equivalent ", temp_buf
);
13534 json_object_double_add(
13535 json
, "/24equivalent",
13536 (double)(ts
.total_space
13537 * pow(2.0, -32 + 24)));
13543 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13545 vty_out(vty
, "%-30s: %s",
13546 table_stats_strs
[i
]
13547 [TABLE_STATS_IDX_VTY
],
13550 json_object_int_add(
13552 table_stats_strs
[i
]
13553 [TABLE_STATS_IDX_JSON
],
13558 vty_out(vty
, "\n");
13563 bitlen
= IPV4_MAX_BITLEN
;
13566 bitlen
= IPV6_MAX_BITLEN
;
13569 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13576 json_bitlen
= json_object_new_array();
13578 for (i
= 0; i
<= bitlen
; i
++) {
13579 struct json_object
*ind_bit
= json_object_new_object();
13581 if (!ts
.prefix_len_count
[i
])
13584 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13585 json_object_int_add(ind_bit
, temp_buf
,
13586 ts
.prefix_len_count
[i
]);
13587 json_object_array_add(json_bitlen
, ind_bit
);
13589 json_object_object_add(json
, "prefixLength", json_bitlen
);
13594 json_object_array_add(json_array
, json
);
13598 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13599 safi_t safi
, struct json_object
*json_array
)
13602 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13603 return CMD_SUCCESS
;
13606 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13618 PCOUNT_BPATH_SELECTED
,
13619 PCOUNT_PFCNT
, /* the figure we display to users */
13623 static const char *const pcount_strs
[] = {
13624 [PCOUNT_ADJ_IN
] = "Adj-in",
13625 [PCOUNT_DAMPED
] = "Damped",
13626 [PCOUNT_REMOVED
] = "Removed",
13627 [PCOUNT_HISTORY
] = "History",
13628 [PCOUNT_STALE
] = "Stale",
13629 [PCOUNT_VALID
] = "Valid",
13630 [PCOUNT_ALL
] = "All RIB",
13631 [PCOUNT_COUNTED
] = "PfxCt counted",
13632 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13633 [PCOUNT_PFCNT
] = "Useable",
13634 [PCOUNT_MAX
] = NULL
,
13637 struct peer_pcounts
{
13638 unsigned int count
[PCOUNT_MAX
];
13639 const struct peer
*peer
;
13640 const struct bgp_table
*table
;
13644 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13646 const struct bgp_adj_in
*ain
;
13647 const struct bgp_path_info
*pi
;
13648 const struct peer
*peer
= pc
->peer
;
13650 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13651 if (ain
->peer
== peer
)
13652 pc
->count
[PCOUNT_ADJ_IN
]++;
13654 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13656 if (pi
->peer
!= peer
)
13659 pc
->count
[PCOUNT_ALL
]++;
13661 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13662 pc
->count
[PCOUNT_DAMPED
]++;
13663 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13664 pc
->count
[PCOUNT_HISTORY
]++;
13665 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13666 pc
->count
[PCOUNT_REMOVED
]++;
13667 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13668 pc
->count
[PCOUNT_STALE
]++;
13669 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13670 pc
->count
[PCOUNT_VALID
]++;
13671 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13672 pc
->count
[PCOUNT_PFCNT
]++;
13673 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13674 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13676 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13677 pc
->count
[PCOUNT_COUNTED
]++;
13678 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13680 EC_LIB_DEVELOPMENT
,
13681 "Attempting to count but flags say it is unusable");
13683 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13685 EC_LIB_DEVELOPMENT
,
13686 "Not counted but flags say we should");
13691 static void bgp_peer_count_walker(struct thread
*t
)
13693 struct bgp_dest
*rn
, *rm
;
13694 const struct bgp_table
*table
;
13695 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13697 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13698 || pc
->safi
== SAFI_EVPN
) {
13699 /* Special handling for 2-level routing tables. */
13700 for (rn
= bgp_table_top(pc
->table
); rn
;
13701 rn
= bgp_route_next(rn
)) {
13702 table
= bgp_dest_get_bgp_table_info(rn
);
13704 for (rm
= bgp_table_top(table
); rm
;
13705 rm
= bgp_route_next(rm
))
13706 bgp_peer_count_proc(rm
, pc
);
13709 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13710 bgp_peer_count_proc(rn
, pc
);
13713 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13714 safi_t safi
, bool use_json
)
13716 struct peer_pcounts pcounts
= {.peer
= peer
};
13718 json_object
*json
= NULL
;
13719 json_object
*json_loop
= NULL
;
13722 json
= json_object_new_object();
13723 json_loop
= json_object_new_object();
13726 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13727 || !peer
->bgp
->rib
[afi
][safi
]) {
13729 json_object_string_add(
13731 "No such neighbor or address family");
13732 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13733 json_object_free(json
);
13734 json_object_free(json_loop
);
13736 vty_out(vty
, "%% No such neighbor or address family\n");
13738 return CMD_WARNING
;
13741 memset(&pcounts
, 0, sizeof(pcounts
));
13742 pcounts
.peer
= peer
;
13743 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13744 pcounts
.safi
= safi
;
13746 /* in-place call via thread subsystem so as to record execution time
13747 * stats for the thread-walk (i.e. ensure this can't be blamed on
13748 * on just vty_read()).
13750 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13753 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13754 json_object_string_add(json
, "multiProtocol",
13755 get_afi_safi_str(afi
, safi
, true));
13756 json_object_int_add(json
, "pfxCounter",
13757 peer
->pcount
[afi
][safi
]);
13759 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13760 json_object_int_add(json_loop
, pcount_strs
[i
],
13763 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13765 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13766 json_object_string_add(json
, "pfxctDriftFor",
13768 json_object_string_add(
13769 json
, "recommended",
13770 "Please report this bug, with the above command output");
13772 vty_json(vty
, json
);
13776 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13777 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13778 peer
->hostname
, peer
->host
,
13779 get_afi_safi_str(afi
, safi
, false));
13781 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13782 get_afi_safi_str(afi
, safi
, false));
13785 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13786 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13788 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13789 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13792 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13793 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13795 "Please report this bug, with the above command output\n");
13799 return CMD_SUCCESS
;
13802 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13803 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13804 "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]",
13808 BGP_INSTANCE_HELP_STR
13811 "Detailed information on TCP and BGP neighbor connections\n"
13812 "Neighbor to display information about\n"
13813 "Neighbor to display information about\n"
13814 "Neighbor on BGP configured interface\n"
13815 "Display detailed prefix count information\n"
13818 afi_t afi
= AFI_IP6
;
13819 safi_t safi
= SAFI_UNICAST
;
13822 struct bgp
*bgp
= NULL
;
13823 bool uj
= use_json(argc
, argv
);
13828 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13831 return CMD_WARNING
;
13833 argv_find(argv
, argc
, "neighbors", &idx
);
13834 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13836 return CMD_WARNING
;
13838 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13841 #ifdef KEEP_OLD_VPN_COMMANDS
13842 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13843 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13844 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13849 "Display information about all VPNv4 NLRIs\n"
13850 "Detailed information on TCP and BGP neighbor connections\n"
13851 "Neighbor to display information about\n"
13852 "Neighbor to display information about\n"
13853 "Neighbor on BGP configured interface\n"
13854 "Display detailed prefix count information\n"
13859 bool uj
= use_json(argc
, argv
);
13861 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13863 return CMD_WARNING
;
13865 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13868 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13869 show_ip_bgp_vpn_all_route_prefix_cmd
,
13870 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13875 "Display information about all VPNv4 NLRIs\n"
13876 "Network in the BGP routing table to display\n"
13877 "Network in the BGP routing table to display\n"
13881 char *network
= NULL
;
13882 struct bgp
*bgp
= bgp_get_default();
13884 vty_out(vty
, "Can't find default instance\n");
13885 return CMD_WARNING
;
13888 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13889 network
= argv
[idx
]->arg
;
13890 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13891 network
= argv
[idx
]->arg
;
13893 vty_out(vty
, "Unable to figure out Network\n");
13894 return CMD_WARNING
;
13897 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13898 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13899 use_json(argc
, argv
));
13901 #endif /* KEEP_OLD_VPN_COMMANDS */
13903 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13904 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13905 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13910 "Network in the BGP routing table to display\n"
13911 "Network in the BGP routing table to display\n"
13912 "Network in the BGP routing table to display\n"
13913 "Network in the BGP routing table to display\n"
13917 char *network
= NULL
;
13918 int prefix_check
= 0;
13920 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13921 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13922 network
= argv
[idx
]->arg
;
13923 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13924 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13925 network
= argv
[idx
]->arg
;
13928 vty_out(vty
, "Unable to figure out Network\n");
13929 return CMD_WARNING
;
13931 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13932 prefix_check
, BGP_PATH_SHOW_ALL
,
13933 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13936 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13937 struct bgp_table
*table
, int *header1
,
13938 int *header2
, json_object
*json
,
13939 json_object
*json_scode
,
13940 json_object
*json_ocode
, bool wide
,
13943 uint64_t version
= table
? table
->version
: 0;
13947 json_object_int_add(json
, "bgpTableVersion", version
);
13948 json_object_string_addf(json
, "bgpLocalRouterId",
13949 "%pI4", &peer
->bgp
->router_id
);
13950 json_object_int_add(json
, "defaultLocPrf",
13951 peer
->bgp
->default_local_pref
);
13952 json_object_int_add(json
, "localAS",
13953 peer
->change_local_as
13954 ? peer
->change_local_as
13956 json_object_object_add(json
, "bgpStatusCodes",
13958 json_object_object_add(json
, "bgpOriginCodes",
13962 "BGP table version is %" PRIu64
13963 ", local router ID is %pI4, vrf id ",
13964 version
, &peer
->bgp
->router_id
);
13965 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
13966 vty_out(vty
, "%s", VRFID_NONE_STR
);
13968 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
13969 vty_out(vty
, "\n");
13970 vty_out(vty
, "Default local pref %u, ",
13971 peer
->bgp
->default_local_pref
);
13972 vty_out(vty
, "local AS %u\n",
13973 peer
->change_local_as
? peer
->change_local_as
13976 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13977 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13978 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13979 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13985 if (!json
&& !detail
)
13986 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13987 : BGP_SHOW_HEADER
));
13993 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13994 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13995 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13996 json_object
*json_scode
, json_object
*json_ocode
,
13997 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13998 unsigned long *output_count
, unsigned long *filtered_count
)
14000 struct bgp_adj_in
*ain
;
14001 struct bgp_adj_out
*adj
;
14002 struct bgp_dest
*dest
;
14006 struct update_subgroup
*subgrp
;
14007 struct peer_af
*paf
;
14008 bool route_filtered
;
14009 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14010 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14011 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14012 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14013 || (safi
== SAFI_EVPN
))
14017 json_object
*json_net
= NULL
;
14021 subgrp
= peer_subgroup(peer
, afi
, safi
);
14023 if (type
== bgp_show_adj_route_advertised
&& subgrp
14024 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14026 json_object_int_add(json
, "bgpTableVersion",
14028 json_object_string_addf(json
, "bgpLocalRouterId",
14029 "%pI4", &bgp
->router_id
);
14030 json_object_int_add(json
, "defaultLocPrf",
14031 bgp
->default_local_pref
);
14032 json_object_int_add(json
, "localAS",
14033 peer
->change_local_as
14034 ? peer
->change_local_as
14036 json_object_object_add(json
, "bgpStatusCodes",
14038 json_object_object_add(json
, "bgpOriginCodes",
14040 json_object_string_add(
14041 json
, "bgpOriginatingDefaultNetwork",
14042 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14045 "BGP table version is %" PRIu64
14046 ", local router ID is %pI4, vrf id ",
14047 table
->version
, &bgp
->router_id
);
14048 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14049 vty_out(vty
, "%s", VRFID_NONE_STR
);
14051 vty_out(vty
, "%u", bgp
->vrf_id
);
14052 vty_out(vty
, "\n");
14053 vty_out(vty
, "Default local pref %u, ",
14054 bgp
->default_local_pref
);
14055 vty_out(vty
, "local AS %u\n",
14056 peer
->change_local_as
? peer
->change_local_as
14059 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14060 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14061 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14062 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14065 vty_out(vty
, "Originating default network %s\n\n",
14066 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14072 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14073 if (type
== bgp_show_adj_route_received
14074 || type
== bgp_show_adj_route_filtered
) {
14075 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14076 if (ain
->peer
!= peer
)
14079 show_adj_route_header(vty
, peer
, table
, header1
,
14080 header2
, json
, json_scode
,
14081 json_ocode
, wide
, detail
);
14083 if ((safi
== SAFI_MPLS_VPN
)
14084 || (safi
== SAFI_ENCAP
)
14085 || (safi
== SAFI_EVPN
)) {
14087 json_object_string_add(
14088 json_ar
, "rd", rd_str
);
14089 else if (show_rd
&& rd_str
) {
14091 "Route Distinguisher: %s\n",
14098 route_filtered
= false;
14100 /* Filter prefix using distribute list,
14101 * filter list or prefix list
14103 const struct prefix
*rn_p
=
14104 bgp_dest_get_prefix(dest
);
14105 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14108 route_filtered
= true;
14110 /* Filter prefix using route-map */
14111 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14112 safi
, rmap_name
, NULL
,
14115 if (type
== bgp_show_adj_route_filtered
&&
14116 !route_filtered
&& ret
!= RMAP_DENY
) {
14117 bgp_attr_flush(&attr
);
14121 if (type
== bgp_show_adj_route_received
14122 && (route_filtered
|| ret
== RMAP_DENY
))
14123 (*filtered_count
)++;
14128 json_object_new_object();
14129 bgp_show_path_info(
14130 NULL
/* prefix_rd */, dest
, vty
,
14131 bgp
, afi
, safi
, json_net
,
14132 BGP_PATH_SHOW_ALL
, &display
,
14133 RPKI_NOT_BEING_USED
);
14135 json_object_object_addf(
14139 route_vty_out_tmp(vty
, dest
, rn_p
,
14140 &attr
, safi
, use_json
,
14142 bgp_attr_flush(&attr
);
14145 } else if (type
== bgp_show_adj_route_advertised
) {
14146 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14147 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14148 if (paf
->peer
!= peer
|| !adj
->attr
)
14151 show_adj_route_header(
14152 vty
, peer
, table
, header1
,
14153 header2
, json
, json_scode
,
14154 json_ocode
, wide
, detail
);
14156 const struct prefix
*rn_p
=
14157 bgp_dest_get_prefix(dest
);
14160 ret
= bgp_output_modifier(
14161 peer
, rn_p
, &attr
, afi
, safi
,
14164 if (ret
!= RMAP_DENY
) {
14165 if ((safi
== SAFI_MPLS_VPN
)
14166 || (safi
== SAFI_ENCAP
)
14167 || (safi
== SAFI_EVPN
)) {
14169 json_object_string_add(
14176 "Route Distinguisher: %s\n",
14184 json_object_new_object();
14185 bgp_show_path_info(
14194 RPKI_NOT_BEING_USED
);
14196 json_object_object_addf(
14209 (*filtered_count
)++;
14212 bgp_attr_flush(&attr
);
14214 } else if (type
== bgp_show_adj_route_bestpath
) {
14215 struct bgp_path_info
*pi
;
14217 show_adj_route_header(vty
, peer
, table
, header1
,
14218 header2
, json
, json_scode
,
14219 json_ocode
, wide
, detail
);
14221 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14223 if (pi
->peer
!= peer
)
14226 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14229 route_vty_out_tmp(vty
, dest
,
14230 bgp_dest_get_prefix(dest
),
14231 pi
->attr
, safi
, use_json
,
14239 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14240 safi_t safi
, enum bgp_show_adj_route_type type
,
14241 const char *rmap_name
, uint16_t show_flags
)
14244 struct bgp_table
*table
;
14245 json_object
*json
= NULL
;
14246 json_object
*json_scode
= NULL
;
14247 json_object
*json_ocode
= NULL
;
14248 json_object
*json_ar
= NULL
;
14249 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14251 /* Init BGP headers here so they're only displayed once
14252 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14258 * Initialize variables for each RD
14259 * All prefixes under an RD is aggregated within "json_routes"
14261 char rd_str
[BUFSIZ
] = {0};
14262 json_object
*json_routes
= NULL
;
14265 /* For 2-tier tables, prefix counts need to be
14266 * maintained across multiple runs of show_adj_route()
14268 unsigned long output_count_per_rd
;
14269 unsigned long filtered_count_per_rd
;
14270 unsigned long output_count
= 0;
14271 unsigned long filtered_count
= 0;
14274 json
= json_object_new_object();
14275 json_ar
= json_object_new_object();
14276 json_scode
= json_object_new_object();
14277 json_ocode
= json_object_new_object();
14278 #if CONFDATE > 20231208
14279 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14281 json_object_string_add(json_scode
, "suppressed", "s");
14282 json_object_string_add(json_scode
, "damped", "d");
14283 json_object_string_add(json_scode
, "history", "h");
14284 json_object_string_add(json_scode
, "valid", "*");
14285 json_object_string_add(json_scode
, "best", ">");
14286 json_object_string_add(json_scode
, "multipath", "=");
14287 json_object_string_add(json_scode
, "internal", "i");
14288 json_object_string_add(json_scode
, "ribFailure", "r");
14289 json_object_string_add(json_scode
, "stale", "S");
14290 json_object_string_add(json_scode
, "removed", "R");
14292 #if CONFDATE > 20231208
14293 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14295 json_object_string_add(json_ocode
, "igp", "i");
14296 json_object_string_add(json_ocode
, "egp", "e");
14297 json_object_string_add(json_ocode
, "incomplete", "?");
14300 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14302 json_object_string_add(
14304 "No such neighbor or address family");
14305 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14306 json_object_free(json
);
14307 json_object_free(json_ar
);
14308 json_object_free(json_scode
);
14309 json_object_free(json_ocode
);
14311 vty_out(vty
, "%% No such neighbor or address family\n");
14313 return CMD_WARNING
;
14316 if ((type
== bgp_show_adj_route_received
14317 || type
== bgp_show_adj_route_filtered
)
14318 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14319 PEER_FLAG_SOFT_RECONFIG
)) {
14321 json_object_string_add(
14323 "Inbound soft reconfiguration not enabled");
14324 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14325 json_object_free(json
);
14326 json_object_free(json_ar
);
14327 json_object_free(json_scode
);
14328 json_object_free(json_ocode
);
14331 "%% Inbound soft reconfiguration not enabled\n");
14333 return CMD_WARNING
;
14338 /* labeled-unicast routes live in the unicast table */
14339 if (safi
== SAFI_LABELED_UNICAST
)
14340 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14342 table
= bgp
->rib
[afi
][safi
];
14344 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14345 || (safi
== SAFI_EVPN
)) {
14347 struct bgp_dest
*dest
;
14349 for (dest
= bgp_table_top(table
); dest
;
14350 dest
= bgp_route_next(dest
)) {
14351 table
= bgp_dest_get_bgp_table_info(dest
);
14355 output_count_per_rd
= 0;
14356 filtered_count_per_rd
= 0;
14359 json_routes
= json_object_new_object();
14361 const struct prefix_rd
*prd
;
14362 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14365 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
14367 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
14368 rmap_name
, json
, json_routes
, json_scode
,
14369 json_ocode
, show_flags
, &header1
,
14370 &header2
, rd_str
, &output_count_per_rd
,
14371 &filtered_count_per_rd
);
14373 /* Don't include an empty RD in the output! */
14374 if (json_routes
&& (output_count_per_rd
> 0))
14375 json_object_object_add(json_ar
, rd_str
,
14378 output_count
+= output_count_per_rd
;
14379 filtered_count
+= filtered_count_per_rd
;
14382 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14383 json
, json_ar
, json_scode
, json_ocode
,
14384 show_flags
, &header1
, &header2
, rd_str
,
14385 &output_count
, &filtered_count
);
14388 if (type
== bgp_show_adj_route_advertised
)
14389 json_object_object_add(json
, "advertisedRoutes",
14392 json_object_object_add(json
, "receivedRoutes", json_ar
);
14393 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14394 json_object_int_add(json
, "filteredPrefixCounter",
14398 * These fields only give up ownership to `json` when `header1`
14399 * is used (set to zero). See code in `show_adj_route` and
14400 * `show_adj_route_header`.
14402 if (header1
== 1) {
14403 json_object_free(json_scode
);
14404 json_object_free(json_ocode
);
14407 vty_json(vty
, json
);
14408 } else if (output_count
> 0) {
14409 if (filtered_count
> 0)
14411 "\nTotal number of prefixes %ld (%ld filtered)\n",
14412 output_count
, filtered_count
);
14414 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14418 return CMD_SUCCESS
;
14421 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14422 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14423 "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]",
14427 BGP_INSTANCE_HELP_STR
14429 BGP_SAFI_WITH_LABEL_HELP_STR
14430 "Detailed information on TCP and BGP neighbor connections\n"
14431 "Neighbor to display information about\n"
14432 "Neighbor to display information about\n"
14433 "Neighbor on BGP configured interface\n"
14434 "Display the routes selected by best path\n"
14436 "Increase table width for longer prefixes\n")
14438 afi_t afi
= AFI_IP6
;
14439 safi_t safi
= SAFI_UNICAST
;
14440 char *rmap_name
= NULL
;
14441 char *peerstr
= NULL
;
14442 struct bgp
*bgp
= NULL
;
14444 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14446 uint16_t show_flags
= 0;
14449 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14452 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14454 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14458 return CMD_WARNING
;
14460 argv_find(argv
, argc
, "neighbors", &idx
);
14461 peerstr
= argv
[++idx
]->arg
;
14463 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14465 return CMD_WARNING
;
14467 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14471 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14472 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14473 "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]",
14477 BGP_INSTANCE_HELP_STR
14479 BGP_SAFI_WITH_LABEL_HELP_STR
14480 "Display the entries for all address families\n"
14481 "Detailed information on TCP and BGP neighbor connections\n"
14482 "Neighbor to display information about\n"
14483 "Neighbor to display information about\n"
14484 "Neighbor on BGP configured interface\n"
14485 "Display the routes advertised to a BGP neighbor\n"
14486 "Display the received routes from neighbor\n"
14487 "Display the filtered routes received from neighbor\n"
14488 "Route-map to modify the attributes\n"
14489 "Name of the route map\n"
14490 "Display detailed version of routes\n"
14492 "Increase table width for longer prefixes\n")
14494 afi_t afi
= AFI_IP6
;
14495 safi_t safi
= SAFI_UNICAST
;
14496 char *peerstr
= NULL
;
14497 struct bgp
*bgp
= NULL
;
14499 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14502 uint16_t show_flags
= 0;
14503 struct listnode
*node
;
14507 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14511 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14515 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14516 if (argv_find(argv
, argc
, "ipv4", &idx
))
14517 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14519 if (argv_find(argv
, argc
, "ipv6", &idx
))
14520 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14524 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14526 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14529 return CMD_WARNING
;
14531 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14532 argv_find(argv
, argc
, "neighbors", &idx
);
14533 peerstr
= argv
[++idx
]->arg
;
14535 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14537 return CMD_WARNING
;
14539 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14540 type
= bgp_show_adj_route_advertised
;
14541 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14542 type
= bgp_show_adj_route_received
;
14543 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14544 type
= bgp_show_adj_route_filtered
;
14547 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14550 vty_out(vty
, "{\n");
14552 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14553 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14554 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14556 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14557 FOREACH_SAFI (safi
) {
14558 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14565 vty_out(vty
, ",\n");
14566 vty_out(vty
, "\"%s\":",
14567 get_afi_safi_str(afi
, safi
,
14571 "\nFor address family: %s\n",
14572 get_afi_safi_str(afi
, safi
,
14575 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14576 route_map
, show_flags
);
14580 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14581 FOREACH_AFI_SAFI (afi
, safi
) {
14582 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14589 vty_out(vty
, ",\n");
14590 vty_out(vty
, "\"%s\":",
14591 get_afi_safi_str(afi
, safi
,
14595 "\nFor address family: %s\n",
14596 get_afi_safi_str(afi
, safi
,
14599 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14600 route_map
, show_flags
);
14605 vty_out(vty
, "}\n");
14607 return CMD_SUCCESS
;
14610 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14611 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14612 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14616 BGP_INSTANCE_HELP_STR
14619 BGP_AF_MODIFIER_STR
14620 "Detailed information on TCP and BGP neighbor connections\n"
14621 "Neighbor to display information about\n"
14622 "Neighbor to display information about\n"
14623 "Neighbor on BGP configured interface\n"
14624 "Display information received from a BGP neighbor\n"
14625 "Display the prefixlist filter\n"
14628 afi_t afi
= AFI_IP6
;
14629 safi_t safi
= SAFI_UNICAST
;
14630 char *peerstr
= NULL
;
14635 struct bgp
*bgp
= NULL
;
14636 bool uj
= use_json(argc
, argv
);
14641 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14644 return CMD_WARNING
;
14646 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14647 argv_find(argv
, argc
, "neighbors", &idx
);
14648 peerstr
= argv
[++idx
]->arg
;
14650 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14652 return CMD_WARNING
;
14654 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14655 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14658 vty_out(vty
, "Address Family: %s\n",
14659 get_afi_safi_str(afi
, safi
, false));
14660 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14663 vty_out(vty
, "{}\n");
14665 vty_out(vty
, "No functional output\n");
14668 return CMD_SUCCESS
;
14671 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14672 afi_t afi
, safi_t safi
,
14673 enum bgp_show_type type
, bool use_json
)
14675 uint16_t show_flags
= 0;
14678 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14680 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14682 json_object
*json_no
= NULL
;
14683 json_no
= json_object_new_object();
14684 json_object_string_add(
14685 json_no
, "warning",
14686 "No such neighbor or address family");
14687 vty_out(vty
, "%s\n",
14688 json_object_to_json_string(json_no
));
14689 json_object_free(json_no
);
14691 vty_out(vty
, "%% No such neighbor or address family\n");
14692 return CMD_WARNING
;
14695 /* labeled-unicast routes live in the unicast table */
14696 if (safi
== SAFI_LABELED_UNICAST
)
14697 safi
= SAFI_UNICAST
;
14699 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14700 RPKI_NOT_BEING_USED
);
14703 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14704 show_ip_bgp_flowspec_routes_detailed_cmd
,
14705 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14709 BGP_INSTANCE_HELP_STR
14712 "Detailed information on flowspec entries\n"
14715 afi_t afi
= AFI_IP6
;
14716 safi_t safi
= SAFI_UNICAST
;
14717 struct bgp
*bgp
= NULL
;
14719 bool uj
= use_json(argc
, argv
);
14720 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14724 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14727 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14730 return CMD_WARNING
;
14732 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14733 show_flags
, RPKI_NOT_BEING_USED
);
14736 DEFUN (show_ip_bgp_neighbor_routes
,
14737 show_ip_bgp_neighbor_routes_cmd
,
14738 "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]",
14742 BGP_INSTANCE_HELP_STR
14744 BGP_SAFI_WITH_LABEL_HELP_STR
14745 "Detailed information on TCP and BGP neighbor connections\n"
14746 "Neighbor to display information about\n"
14747 "Neighbor to display information about\n"
14748 "Neighbor on BGP configured interface\n"
14749 "Display flap statistics of the routes learned from neighbor\n"
14750 "Display the dampened routes received from neighbor\n"
14751 "Display routes learned from neighbor\n"
14754 char *peerstr
= NULL
;
14755 struct bgp
*bgp
= NULL
;
14756 afi_t afi
= AFI_IP6
;
14757 safi_t safi
= SAFI_UNICAST
;
14759 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14761 bool uj
= use_json(argc
, argv
);
14766 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14769 return CMD_WARNING
;
14771 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14772 argv_find(argv
, argc
, "neighbors", &idx
);
14773 peerstr
= argv
[++idx
]->arg
;
14775 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14777 return CMD_WARNING
;
14779 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14780 sh_type
= bgp_show_type_flap_neighbor
;
14781 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14782 sh_type
= bgp_show_type_damp_neighbor
;
14783 else if (argv_find(argv
, argc
, "routes", &idx
))
14784 sh_type
= bgp_show_type_neighbor
;
14786 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14789 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14791 struct bgp_distance
{
14792 /* Distance value for the IP source prefix. */
14795 /* Name of the access-list to be matched. */
14799 DEFUN (show_bgp_afi_vpn_rd_route
,
14800 show_bgp_afi_vpn_rd_route_cmd
,
14801 "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]",
14805 BGP_AF_MODIFIER_STR
14806 "Display information for a route distinguisher\n"
14807 "Route Distinguisher\n"
14808 "All Route Distinguishers\n"
14809 "Network in the BGP routing table to display\n"
14810 "Network in the BGP routing table to display\n"
14814 struct prefix_rd prd
;
14815 afi_t afi
= AFI_MAX
;
14818 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14819 vty_out(vty
, "%% Malformed Address Family\n");
14820 return CMD_WARNING
;
14823 if (!strcmp(argv
[5]->arg
, "all"))
14824 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14825 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14826 RPKI_NOT_BEING_USED
,
14827 use_json(argc
, argv
));
14829 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14831 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14832 return CMD_WARNING
;
14835 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14836 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14837 use_json(argc
, argv
));
14840 static struct bgp_distance
*bgp_distance_new(void)
14842 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14845 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14847 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14850 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14851 const char *ip_str
, const char *access_list_str
)
14858 struct bgp_dest
*dest
;
14859 struct bgp_distance
*bdistance
;
14861 afi
= bgp_node_afi(vty
);
14862 safi
= bgp_node_safi(vty
);
14864 ret
= str2prefix(ip_str
, &p
);
14866 vty_out(vty
, "Malformed prefix\n");
14867 return CMD_WARNING_CONFIG_FAILED
;
14870 distance
= atoi(distance_str
);
14872 /* Get BGP distance node. */
14873 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14874 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14876 bgp_dest_unlock_node(dest
);
14878 bdistance
= bgp_distance_new();
14879 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14882 /* Set distance value. */
14883 bdistance
->distance
= distance
;
14885 /* Reset access-list configuration. */
14886 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14887 if (access_list_str
)
14888 bdistance
->access_list
=
14889 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14891 return CMD_SUCCESS
;
14894 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14895 const char *ip_str
, const char *access_list_str
)
14902 struct bgp_dest
*dest
;
14903 struct bgp_distance
*bdistance
;
14905 afi
= bgp_node_afi(vty
);
14906 safi
= bgp_node_safi(vty
);
14908 ret
= str2prefix(ip_str
, &p
);
14910 vty_out(vty
, "Malformed prefix\n");
14911 return CMD_WARNING_CONFIG_FAILED
;
14914 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14916 vty_out(vty
, "Can't find specified prefix\n");
14917 return CMD_WARNING_CONFIG_FAILED
;
14920 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14921 distance
= atoi(distance_str
);
14923 if (bdistance
->distance
!= distance
) {
14924 vty_out(vty
, "Distance does not match configured\n");
14925 bgp_dest_unlock_node(dest
);
14926 return CMD_WARNING_CONFIG_FAILED
;
14929 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14930 bgp_distance_free(bdistance
);
14932 bgp_dest_set_bgp_path_info(dest
, NULL
);
14933 bgp_dest_unlock_node(dest
);
14934 bgp_dest_unlock_node(dest
);
14936 return CMD_SUCCESS
;
14939 /* Apply BGP information to distance method. */
14940 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14941 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14943 struct bgp_dest
*dest
;
14944 struct prefix q
= {0};
14946 struct bgp_distance
*bdistance
;
14947 struct access_list
*alist
;
14948 struct bgp_static
*bgp_static
;
14949 struct bgp_path_info
*bpi_ultimate
;
14954 peer
= pinfo
->peer
;
14956 if (pinfo
->attr
->distance
)
14957 return pinfo
->attr
->distance
;
14959 /* get peer origin to calculate appropriate distance */
14960 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
14961 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
14962 peer
= bpi_ultimate
->peer
;
14965 /* Check source address.
14966 * Note: for aggregate route, peer can have unspec af type.
14968 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14969 && !sockunion2hostprefix(&peer
->su
, &q
))
14972 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14974 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14975 bgp_dest_unlock_node(dest
);
14977 if (bdistance
->access_list
) {
14978 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14980 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14981 return bdistance
->distance
;
14983 return bdistance
->distance
;
14986 /* Backdoor check. */
14987 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14989 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14990 bgp_dest_unlock_node(dest
);
14992 if (bgp_static
->backdoor
) {
14993 if (bgp
->distance_local
[afi
][safi
])
14994 return bgp
->distance_local
[afi
][safi
];
14996 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15000 if (peer
->sort
== BGP_PEER_EBGP
) {
15001 if (bgp
->distance_ebgp
[afi
][safi
])
15002 return bgp
->distance_ebgp
[afi
][safi
];
15003 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15004 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15005 if (bgp
->distance_ibgp
[afi
][safi
])
15006 return bgp
->distance_ibgp
[afi
][safi
];
15007 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15009 if (bgp
->distance_local
[afi
][safi
])
15010 return bgp
->distance_local
[afi
][safi
];
15011 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15015 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15016 * we should tell ZEBRA update the routes for a specific
15017 * AFI/SAFI to reflect changes in RIB.
15019 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15021 safi_t update_safi
)
15026 FOREACH_AFI_SAFI (afi
, safi
) {
15027 if (!bgp_fibupd_safi(safi
))
15030 if (afi
!= update_afi
&& safi
!= update_safi
)
15033 if (BGP_DEBUG(zebra
, ZEBRA
))
15035 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15036 __func__
, afi
, safi
);
15037 bgp_zebra_announce_table(bgp
, afi
, safi
);
15041 DEFUN (bgp_distance
,
15043 "distance bgp (1-255) (1-255) (1-255)",
15044 "Define an administrative distance\n"
15046 "Distance for routes external to the AS\n"
15047 "Distance for routes internal to the AS\n"
15048 "Distance for local routes\n")
15050 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15051 int idx_number
= 2;
15052 int idx_number_2
= 3;
15053 int idx_number_3
= 4;
15054 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15055 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15056 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15060 afi
= bgp_node_afi(vty
);
15061 safi
= bgp_node_safi(vty
);
15063 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15064 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15065 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15066 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15067 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15068 bgp
->distance_local
[afi
][safi
] = distance_local
;
15069 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15071 return CMD_SUCCESS
;
15074 DEFUN (no_bgp_distance
,
15075 no_bgp_distance_cmd
,
15076 "no distance bgp [(1-255) (1-255) (1-255)]",
15078 "Define an administrative distance\n"
15080 "Distance for routes external to the AS\n"
15081 "Distance for routes internal to the AS\n"
15082 "Distance for local routes\n")
15084 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15088 afi
= bgp_node_afi(vty
);
15089 safi
= bgp_node_safi(vty
);
15091 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15092 || bgp
->distance_ibgp
[afi
][safi
] != 0
15093 || bgp
->distance_local
[afi
][safi
] != 0) {
15094 bgp
->distance_ebgp
[afi
][safi
] = 0;
15095 bgp
->distance_ibgp
[afi
][safi
] = 0;
15096 bgp
->distance_local
[afi
][safi
] = 0;
15097 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15099 return CMD_SUCCESS
;
15103 DEFUN (bgp_distance_source
,
15104 bgp_distance_source_cmd
,
15105 "distance (1-255) A.B.C.D/M",
15106 "Define an administrative distance\n"
15107 "Administrative distance\n"
15108 "IP source prefix\n")
15110 int idx_number
= 1;
15111 int idx_ipv4_prefixlen
= 2;
15112 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15113 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15114 return CMD_SUCCESS
;
15117 DEFUN (no_bgp_distance_source
,
15118 no_bgp_distance_source_cmd
,
15119 "no distance (1-255) A.B.C.D/M",
15121 "Define an administrative distance\n"
15122 "Administrative distance\n"
15123 "IP source prefix\n")
15125 int idx_number
= 2;
15126 int idx_ipv4_prefixlen
= 3;
15127 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15128 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15129 return CMD_SUCCESS
;
15132 DEFUN (bgp_distance_source_access_list
,
15133 bgp_distance_source_access_list_cmd
,
15134 "distance (1-255) A.B.C.D/M WORD",
15135 "Define an administrative distance\n"
15136 "Administrative distance\n"
15137 "IP source prefix\n"
15138 "Access list name\n")
15140 int idx_number
= 1;
15141 int idx_ipv4_prefixlen
= 2;
15143 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15144 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15145 return CMD_SUCCESS
;
15148 DEFUN (no_bgp_distance_source_access_list
,
15149 no_bgp_distance_source_access_list_cmd
,
15150 "no distance (1-255) A.B.C.D/M WORD",
15152 "Define an administrative distance\n"
15153 "Administrative distance\n"
15154 "IP source prefix\n"
15155 "Access list name\n")
15157 int idx_number
= 2;
15158 int idx_ipv4_prefixlen
= 3;
15160 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15161 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15162 return CMD_SUCCESS
;
15165 DEFUN (ipv6_bgp_distance_source
,
15166 ipv6_bgp_distance_source_cmd
,
15167 "distance (1-255) X:X::X:X/M",
15168 "Define an administrative distance\n"
15169 "Administrative distance\n"
15170 "IP source prefix\n")
15172 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15173 return CMD_SUCCESS
;
15176 DEFUN (no_ipv6_bgp_distance_source
,
15177 no_ipv6_bgp_distance_source_cmd
,
15178 "no distance (1-255) X:X::X:X/M",
15180 "Define an administrative distance\n"
15181 "Administrative distance\n"
15182 "IP source prefix\n")
15184 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15185 return CMD_SUCCESS
;
15188 DEFUN (ipv6_bgp_distance_source_access_list
,
15189 ipv6_bgp_distance_source_access_list_cmd
,
15190 "distance (1-255) X:X::X:X/M WORD",
15191 "Define an administrative distance\n"
15192 "Administrative distance\n"
15193 "IP source prefix\n"
15194 "Access list name\n")
15196 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15197 return CMD_SUCCESS
;
15200 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15201 no_ipv6_bgp_distance_source_access_list_cmd
,
15202 "no distance (1-255) X:X::X:X/M WORD",
15204 "Define an administrative distance\n"
15205 "Administrative distance\n"
15206 "IP source prefix\n"
15207 "Access list name\n")
15209 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15210 return CMD_SUCCESS
;
15213 DEFUN (bgp_damp_set
,
15215 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15216 "BGP Specific commands\n"
15217 "Enable route-flap dampening\n"
15218 "Half-life time for the penalty\n"
15219 "Value to start reusing a route\n"
15220 "Value to start suppressing a route\n"
15221 "Maximum duration to suppress a stable route\n")
15223 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15224 int idx_half_life
= 2;
15226 int idx_suppress
= 4;
15227 int idx_max_suppress
= 5;
15228 int half
= DEFAULT_HALF_LIFE
* 60;
15229 int reuse
= DEFAULT_REUSE
;
15230 int suppress
= DEFAULT_SUPPRESS
;
15231 int max
= 4 * half
;
15234 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15235 reuse
= atoi(argv
[idx_reuse
]->arg
);
15236 suppress
= atoi(argv
[idx_suppress
]->arg
);
15237 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15238 } else if (argc
== 3) {
15239 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15244 * These can't be 0 but our SA doesn't understand the
15245 * way our cli is constructed
15249 if (suppress
< reuse
) {
15251 "Suppress value cannot be less than reuse value \n");
15255 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15256 reuse
, suppress
, max
);
15259 DEFUN (bgp_damp_unset
,
15260 bgp_damp_unset_cmd
,
15261 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15263 "BGP Specific commands\n"
15264 "Enable route-flap dampening\n"
15265 "Half-life time for the penalty\n"
15266 "Value to start reusing a route\n"
15267 "Value to start suppressing a route\n"
15268 "Maximum duration to suppress a stable route\n")
15270 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15271 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15274 /* Display specified route of BGP table. */
15275 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15276 const char *ip_str
, afi_t afi
, safi_t safi
,
15277 struct prefix_rd
*prd
, int prefix_check
)
15280 struct prefix match
;
15281 struct bgp_dest
*dest
;
15282 struct bgp_dest
*rm
;
15283 struct bgp_path_info
*pi
;
15284 struct bgp_path_info
*pi_temp
;
15286 struct bgp_table
*table
;
15288 /* BGP structure lookup. */
15290 bgp
= bgp_lookup_by_name(view_name
);
15292 vty_out(vty
, "%% Can't find BGP instance %s\n",
15294 return CMD_WARNING
;
15297 bgp
= bgp_get_default();
15299 vty_out(vty
, "%% No BGP process is configured\n");
15300 return CMD_WARNING
;
15304 /* Check IP address argument. */
15305 ret
= str2prefix(ip_str
, &match
);
15307 vty_out(vty
, "%% address is malformed\n");
15308 return CMD_WARNING
;
15311 match
.family
= afi2family(afi
);
15313 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15314 || (safi
== SAFI_EVPN
)) {
15315 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15316 dest
= bgp_route_next(dest
)) {
15317 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15319 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15321 table
= bgp_dest_get_bgp_table_info(dest
);
15324 rm
= bgp_node_match(table
, &match
);
15328 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15331 || rm_p
->prefixlen
== match
.prefixlen
) {
15332 pi
= bgp_dest_get_bgp_path_info(rm
);
15334 if (pi
->extra
&& pi
->extra
->damp_info
) {
15335 pi_temp
= pi
->next
;
15336 bgp_damp_info_free(
15337 pi
->extra
->damp_info
,
15345 bgp_dest_unlock_node(rm
);
15348 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15349 if (dest
!= NULL
) {
15350 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15353 || dest_p
->prefixlen
== match
.prefixlen
) {
15354 pi
= bgp_dest_get_bgp_path_info(dest
);
15356 if (pi
->extra
&& pi
->extra
->damp_info
) {
15357 pi_temp
= pi
->next
;
15358 bgp_damp_info_free(
15359 pi
->extra
->damp_info
,
15367 bgp_dest_unlock_node(dest
);
15371 return CMD_SUCCESS
;
15374 DEFUN (clear_ip_bgp_dampening
,
15375 clear_ip_bgp_dampening_cmd
,
15376 "clear ip bgp dampening",
15380 "Clear route flap dampening information\n")
15382 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15383 return CMD_SUCCESS
;
15386 DEFUN (clear_ip_bgp_dampening_prefix
,
15387 clear_ip_bgp_dampening_prefix_cmd
,
15388 "clear ip bgp dampening A.B.C.D/M",
15392 "Clear route flap dampening information\n"
15395 int idx_ipv4_prefixlen
= 4;
15396 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15397 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15400 DEFUN (clear_ip_bgp_dampening_address
,
15401 clear_ip_bgp_dampening_address_cmd
,
15402 "clear ip bgp dampening A.B.C.D",
15406 "Clear route flap dampening information\n"
15407 "Network to clear damping information\n")
15410 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15411 SAFI_UNICAST
, NULL
, 0);
15414 DEFUN (clear_ip_bgp_dampening_address_mask
,
15415 clear_ip_bgp_dampening_address_mask_cmd
,
15416 "clear ip bgp dampening A.B.C.D A.B.C.D",
15420 "Clear route flap dampening information\n"
15421 "Network to clear damping information\n"
15425 int idx_ipv4_2
= 5;
15427 char prefix_str
[BUFSIZ
];
15429 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15430 prefix_str
, sizeof(prefix_str
));
15432 vty_out(vty
, "%% Inconsistent address and mask\n");
15433 return CMD_WARNING
;
15436 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15440 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15442 struct vty
*vty
= arg
;
15443 struct peer
*peer
= bucket
->data
;
15445 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15448 DEFUN (show_bgp_listeners
,
15449 show_bgp_listeners_cmd
,
15450 "show bgp listeners",
15453 "Display Listen Sockets and who created them\n")
15455 bgp_dump_listener_info(vty
);
15457 return CMD_SUCCESS
;
15460 DEFUN (show_bgp_peerhash
,
15461 show_bgp_peerhash_cmd
,
15462 "show bgp peerhash",
15465 "Display information about the BGP peerhash\n")
15467 struct list
*instances
= bm
->bgp
;
15468 struct listnode
*node
;
15471 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15472 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15473 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15477 return CMD_SUCCESS
;
15480 /* also used for encap safi */
15481 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15482 afi_t afi
, safi_t safi
)
15484 struct bgp_dest
*pdest
;
15485 struct bgp_dest
*dest
;
15486 struct bgp_table
*table
;
15487 const struct prefix
*p
;
15488 const struct prefix_rd
*prd
;
15489 struct bgp_static
*bgp_static
;
15490 mpls_label_t label
;
15492 /* Network configuration. */
15493 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15494 pdest
= bgp_route_next(pdest
)) {
15495 table
= bgp_dest_get_bgp_table_info(pdest
);
15499 for (dest
= bgp_table_top(table
); dest
;
15500 dest
= bgp_route_next(dest
)) {
15501 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15502 if (bgp_static
== NULL
)
15505 p
= bgp_dest_get_prefix(dest
);
15506 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
15509 /* "network" configuration display. */
15510 label
= decode_label(&bgp_static
->label
);
15512 vty_out(vty
, " network %pFX rd %pRD", p
, prd
);
15513 if (safi
== SAFI_MPLS_VPN
)
15514 vty_out(vty
, " label %u", label
);
15516 if (bgp_static
->rmap
.name
)
15517 vty_out(vty
, " route-map %s",
15518 bgp_static
->rmap
.name
);
15520 if (bgp_static
->backdoor
)
15521 vty_out(vty
, " backdoor");
15523 vty_out(vty
, "\n");
15528 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15529 afi_t afi
, safi_t safi
)
15531 struct bgp_dest
*pdest
;
15532 struct bgp_dest
*dest
;
15533 struct bgp_table
*table
;
15534 const struct prefix
*p
;
15535 const struct prefix_rd
*prd
;
15536 struct bgp_static
*bgp_static
;
15537 char buf
[PREFIX_STRLEN
* 2];
15538 char buf2
[SU_ADDRSTRLEN
];
15539 char esi_buf
[ESI_STR_LEN
];
15541 /* Network configuration. */
15542 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15543 pdest
= bgp_route_next(pdest
)) {
15544 table
= bgp_dest_get_bgp_table_info(pdest
);
15548 for (dest
= bgp_table_top(table
); dest
;
15549 dest
= bgp_route_next(dest
)) {
15550 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15551 if (bgp_static
== NULL
)
15554 char *macrouter
= NULL
;
15556 if (bgp_static
->router_mac
)
15557 macrouter
= prefix_mac2str(
15558 bgp_static
->router_mac
, NULL
, 0);
15559 if (bgp_static
->eth_s_id
)
15560 esi_to_str(bgp_static
->eth_s_id
,
15561 esi_buf
, sizeof(esi_buf
));
15562 p
= bgp_dest_get_prefix(dest
);
15563 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15565 /* "network" configuration display. */
15566 if (p
->u
.prefix_evpn
.route_type
== 5) {
15567 char local_buf
[PREFIX_STRLEN
];
15569 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15570 struct prefix_evpn
*)p
)
15574 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15576 local_buf
, sizeof(local_buf
));
15577 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15578 p
->u
.prefix_evpn
.prefix_addr
15579 .ip_prefix_length
);
15581 prefix2str(p
, buf
, sizeof(buf
));
15584 if (bgp_static
->gatewayIp
.family
== AF_INET
15585 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15586 inet_ntop(bgp_static
->gatewayIp
.family
,
15587 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15590 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15591 buf
, prd
, p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15592 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15595 XFREE(MTYPE_TMP
, macrouter
);
15600 /* Configuration of static route announcement and aggregate
15602 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15605 struct bgp_dest
*dest
;
15606 const struct prefix
*p
;
15607 struct bgp_static
*bgp_static
;
15608 struct bgp_aggregate
*bgp_aggregate
;
15610 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15611 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15615 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15616 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15620 /* Network configuration. */
15621 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15622 dest
= bgp_route_next(dest
)) {
15623 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15624 if (bgp_static
== NULL
)
15627 p
= bgp_dest_get_prefix(dest
);
15629 vty_out(vty
, " network %pFX", p
);
15631 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15632 vty_out(vty
, " label-index %u",
15633 bgp_static
->label_index
);
15635 if (bgp_static
->rmap
.name
)
15636 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15638 if (bgp_static
->backdoor
)
15639 vty_out(vty
, " backdoor");
15641 vty_out(vty
, "\n");
15644 /* Aggregate-address configuration. */
15645 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15646 dest
= bgp_route_next(dest
)) {
15647 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15648 if (bgp_aggregate
== NULL
)
15651 p
= bgp_dest_get_prefix(dest
);
15653 vty_out(vty
, " aggregate-address %pFX", p
);
15655 if (bgp_aggregate
->as_set
)
15656 vty_out(vty
, " as-set");
15658 if (bgp_aggregate
->summary_only
)
15659 vty_out(vty
, " summary-only");
15661 if (bgp_aggregate
->rmap
.name
)
15662 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15664 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15665 vty_out(vty
, " origin %s",
15666 bgp_origin2str(bgp_aggregate
->origin
));
15668 if (bgp_aggregate
->match_med
)
15669 vty_out(vty
, " matching-MED-only");
15671 if (bgp_aggregate
->suppress_map_name
)
15672 vty_out(vty
, " suppress-map %s",
15673 bgp_aggregate
->suppress_map_name
);
15675 vty_out(vty
, "\n");
15679 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15682 struct bgp_dest
*dest
;
15683 struct bgp_distance
*bdistance
;
15685 /* Distance configuration. */
15686 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15687 && bgp
->distance_local
[afi
][safi
]
15688 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15689 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15690 || bgp
->distance_local
[afi
][safi
]
15691 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15692 vty_out(vty
, " distance bgp %d %d %d\n",
15693 bgp
->distance_ebgp
[afi
][safi
],
15694 bgp
->distance_ibgp
[afi
][safi
],
15695 bgp
->distance_local
[afi
][safi
]);
15698 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15699 dest
= bgp_route_next(dest
)) {
15700 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15701 if (bdistance
!= NULL
)
15702 vty_out(vty
, " distance %d %pBD %s\n",
15703 bdistance
->distance
, dest
,
15704 bdistance
->access_list
? bdistance
->access_list
15709 /* Allocate routing table structure and install commands. */
15710 void bgp_route_init(void)
15715 /* Init BGP distance table. */
15716 FOREACH_AFI_SAFI (afi
, safi
)
15717 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15719 /* IPv4 BGP commands. */
15720 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15721 install_element(BGP_NODE
, &bgp_network_cmd
);
15722 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15724 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15726 /* IPv4 unicast configuration. */
15727 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15728 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15729 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15731 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15733 /* IPv4 multicast configuration. */
15734 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15735 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15736 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15737 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15739 /* IPv4 labeled-unicast configuration. */
15740 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15741 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15743 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15744 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15745 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15746 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15747 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15748 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15749 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15750 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15752 install_element(VIEW_NODE
,
15753 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15754 install_element(VIEW_NODE
,
15755 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15756 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15757 install_element(VIEW_NODE
,
15758 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15759 #ifdef KEEP_OLD_VPN_COMMANDS
15760 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15761 #endif /* KEEP_OLD_VPN_COMMANDS */
15762 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15763 install_element(VIEW_NODE
,
15764 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15766 /* BGP dampening clear commands */
15767 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15768 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15770 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15771 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15774 install_element(ENABLE_NODE
,
15775 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15776 #ifdef KEEP_OLD_VPN_COMMANDS
15777 install_element(ENABLE_NODE
,
15778 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15779 #endif /* KEEP_OLD_VPN_COMMANDS */
15781 /* New config IPv6 BGP commands. */
15782 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15783 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15784 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15786 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15788 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15790 /* IPv6 labeled unicast address family. */
15791 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15792 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15794 install_element(BGP_NODE
, &bgp_distance_cmd
);
15795 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15796 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15797 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15798 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15799 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15800 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15801 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15802 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15803 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15804 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15805 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15806 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15807 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15808 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15809 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15810 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15811 install_element(BGP_IPV4M_NODE
,
15812 &no_bgp_distance_source_access_list_cmd
);
15813 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15814 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15815 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15816 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15817 install_element(BGP_IPV6_NODE
,
15818 &ipv6_bgp_distance_source_access_list_cmd
);
15819 install_element(BGP_IPV6_NODE
,
15820 &no_ipv6_bgp_distance_source_access_list_cmd
);
15821 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15822 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15823 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15824 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15825 install_element(BGP_IPV6M_NODE
,
15826 &ipv6_bgp_distance_source_access_list_cmd
);
15827 install_element(BGP_IPV6M_NODE
,
15828 &no_ipv6_bgp_distance_source_access_list_cmd
);
15830 /* BGP dampening */
15831 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15832 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15833 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15834 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15835 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15836 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15837 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15838 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15839 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15840 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15841 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15842 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15843 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15844 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15846 /* Large Communities */
15847 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15848 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15850 /* show bgp ipv4 flowspec detailed */
15851 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15853 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15854 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15857 void bgp_route_finish(void)
15862 FOREACH_AFI_SAFI (afi
, safi
) {
15863 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15864 bgp_distance_table
[afi
][safi
] = NULL
;