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_orr.h"
76 #include "bgpd/bgp_trace.h"
77 #include "bgpd/bgp_rpki.h"
80 #include "bgpd/rfapi/rfapi_backend.h"
81 #include "bgpd/rfapi/vnc_import_bgp.h"
82 #include "bgpd/rfapi/vnc_export_bgp.h"
84 #include "bgpd/bgp_encap_types.h"
85 #include "bgpd/bgp_encap_tlv.h"
86 #include "bgpd/bgp_evpn.h"
87 #include "bgpd/bgp_evpn_mh.h"
88 #include "bgpd/bgp_evpn_vty.h"
89 #include "bgpd/bgp_flowspec.h"
90 #include "bgpd/bgp_flowspec_util.h"
91 #include "bgpd/bgp_pbr.h"
93 #ifndef VTYSH_EXTRACT_PL
94 #include "bgpd/bgp_route_clippy.c"
97 DEFINE_HOOK(bgp_snmp_update_stats
,
98 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
101 DEFINE_HOOK(bgp_rpki_prefix_status
,
102 (struct peer
*peer
, struct attr
*attr
,
103 const struct prefix
*prefix
),
104 (peer
, attr
, prefix
));
106 /* Extern from bgp_dump.c */
107 extern const char *bgp_origin_str
[];
108 extern const char *bgp_origin_long_str
[];
111 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
112 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
113 static const struct message bgp_pmsi_tnltype_str
[] = {
114 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
115 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
116 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
117 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
118 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
119 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
120 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
121 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
125 #define VRFID_NONE_STR "-"
126 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
128 DEFINE_HOOK(bgp_process
,
129 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
130 struct peer
*peer
, bool withdraw
),
131 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
133 /** Test if path is suppressed. */
134 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
136 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
139 return listcount(pi
->extra
->aggr_suppressors
) > 0;
142 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
143 safi_t safi
, const struct prefix
*p
,
144 struct prefix_rd
*prd
)
146 struct bgp_dest
*dest
;
147 struct bgp_dest
*pdest
= NULL
;
151 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
152 || (safi
== SAFI_EVPN
)) {
153 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
155 if (!bgp_dest_has_bgp_path_info_data(pdest
))
156 bgp_dest_set_bgp_table_info(
157 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
159 bgp_dest_unlock_node(pdest
);
160 table
= bgp_dest_get_bgp_table_info(pdest
);
163 dest
= bgp_node_get(table
, p
);
165 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
166 || (safi
== SAFI_EVPN
))
172 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
173 safi_t safi
, const struct prefix
*p
,
174 struct prefix_rd
*prd
)
176 struct bgp_dest
*dest
;
177 struct bgp_dest
*pdest
= NULL
;
182 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
183 || (safi
== SAFI_EVPN
)) {
184 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
188 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
189 bgp_dest_unlock_node(pdest
);
193 table
= bgp_dest_get_bgp_table_info(pdest
);
196 dest
= bgp_node_lookup(table
, p
);
201 /* Allocate bgp_path_info_extra */
202 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
204 struct bgp_path_info_extra
*new;
205 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
206 sizeof(struct bgp_path_info_extra
));
207 new->label
[0] = MPLS_INVALID_LABEL
;
209 new->bgp_fs_pbr
= NULL
;
210 new->bgp_fs_iprule
= NULL
;
214 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
216 struct bgp_path_info_extra
*e
;
218 if (!extra
|| !*extra
)
223 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
228 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
231 /* FIXME: since multiple e may have the same e->parent
232 * and e->parent->net is holding a refcount for each
233 * of them, we need to do some fudging here.
235 * WARNING: if bpi->net->lock drops to 0, bpi may be
236 * freed as well (because bpi->net was holding the
237 * last reference to bpi) => write after free!
241 bpi
= bgp_path_info_lock(bpi
);
242 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
243 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
246 bgp_path_info_unlock(bpi
);
248 bgp_path_info_unlock(e
->parent
);
253 bgp_unlock(e
->bgp_orig
);
256 peer_unlock(e
->peer_orig
);
258 if (e
->aggr_suppressors
)
259 list_delete(&e
->aggr_suppressors
);
262 bgp_evpn_path_mh_info_free(e
->mh_info
);
264 if ((*extra
)->bgp_fs_iprule
)
265 list_delete(&((*extra
)->bgp_fs_iprule
));
266 if ((*extra
)->bgp_fs_pbr
)
267 list_delete(&((*extra
)->bgp_fs_pbr
));
268 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
271 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
272 * allocated if required.
274 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
277 pi
->extra
= bgp_path_info_extra_new();
281 /* Free bgp route information. */
282 static void bgp_path_info_free(struct bgp_path_info
*path
)
284 bgp_attr_unintern(&path
->attr
);
286 bgp_unlink_nexthop(path
);
287 bgp_path_info_extra_free(&path
->extra
);
288 bgp_path_info_mpath_free(&path
->mpath
);
290 bgp_addpath_free_info_data(&path
->tx_addpath
,
291 &path
->net
->tx_addpath
);
293 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
295 XFREE(MTYPE_BGP_ROUTE
, path
);
298 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
304 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
306 assert(path
&& path
->lock
> 0);
309 if (path
->lock
== 0) {
310 bgp_path_info_free(path
);
317 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
318 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
321 struct bgp_path_info
*old_pi
, *nextpi
;
322 bool set_flag
= false;
323 struct bgp
*bgp
= NULL
;
324 struct bgp_table
*table
= NULL
;
328 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
329 * then the route selection is deferred
331 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
334 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
335 if (BGP_DEBUG(update
, UPDATE_OUT
))
337 "Route %pBD is in workqueue and being processed, not deferred.",
343 table
= bgp_dest_table(dest
);
350 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
351 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
352 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
355 /* Route selection is deferred if there is a stale path which
356 * which indicates peer is in restart mode
358 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
359 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
362 /* If the peer is graceful restart capable and peer is
363 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
366 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
367 && BGP_PEER_RESTARTING_MODE(peer
)
369 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
377 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
380 if (set_flag
&& table
) {
381 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
382 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
383 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
384 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
385 if (BGP_DEBUG(update
, UPDATE_OUT
))
386 zlog_debug("DEFER route %pBD, dest %p", dest
,
394 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
396 struct bgp_path_info
*top
;
398 top
= bgp_dest_get_bgp_path_info(dest
);
404 bgp_dest_set_bgp_path_info(dest
, pi
);
406 bgp_path_info_lock(pi
);
407 bgp_dest_lock_node(dest
);
408 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
409 bgp_dest_set_defer_flag(dest
, false);
410 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
413 /* Do the actual removal of info from RIB, for use by bgp_process
414 completion callback *only* */
415 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
418 pi
->next
->prev
= pi
->prev
;
420 pi
->prev
->next
= pi
->next
;
422 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
424 bgp_path_info_mpath_dequeue(pi
);
425 bgp_path_info_unlock(pi
);
426 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
427 bgp_dest_unlock_node(dest
);
430 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
432 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
433 /* set of previous already took care of pcount */
434 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
437 /* undo the effects of a previous call to bgp_path_info_delete; typically
438 called when a route is deleted and then quickly re-added before the
439 deletion has been processed */
440 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
442 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
443 /* unset of previous already took care of pcount */
444 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
447 /* Adjust pcount as required */
448 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
450 struct bgp_table
*table
;
452 assert(dest
&& bgp_dest_table(dest
));
453 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
455 table
= bgp_dest_table(dest
);
457 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
460 if (!BGP_PATH_COUNTABLE(pi
)
461 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
463 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
465 /* slight hack, but more robust against errors. */
466 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
467 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
469 flog_err(EC_LIB_DEVELOPMENT
,
470 "Asked to decrement 0 prefix count for peer");
471 } else if (BGP_PATH_COUNTABLE(pi
)
472 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
473 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
474 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
478 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
479 struct bgp_path_info
*pi2
)
481 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
484 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
485 * This is here primarily to keep prefix-count in check.
487 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
490 SET_FLAG(pi
->flags
, flag
);
492 /* early bath if we know it's not a flag that changes countability state
494 if (!CHECK_FLAG(flag
,
495 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
498 bgp_pcount_adjust(dest
, pi
);
501 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
504 UNSET_FLAG(pi
->flags
, flag
);
506 /* early bath if we know it's not a flag that changes countability state
508 if (!CHECK_FLAG(flag
,
509 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
512 bgp_pcount_adjust(dest
, pi
);
515 /* Get MED value. If MED value is missing and "bgp bestpath
516 missing-as-worst" is specified, treat it as the worst value. */
517 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
519 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
522 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
529 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
532 if (pi
->addpath_rx_id
)
533 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
534 pi
->peer
->host
, pi
->addpath_rx_id
);
536 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
541 * Get the ultimate path info.
543 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
545 struct bgp_path_info
*bpi_ultimate
;
547 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
550 for (bpi_ultimate
= info
;
551 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
552 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
558 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
560 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
561 struct bgp_path_info
*exist
, int *paths_eq
,
562 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
563 char *pfx_buf
, afi_t afi
, safi_t safi
,
564 enum bgp_path_selection_reason
*reason
)
566 const struct prefix
*new_p
;
567 struct prefix exist_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
;
600 struct bgp_orr_group
*orr_group
= NULL
;
601 struct listnode
*node
;
602 struct bgp_orr_igp_metric
*igp_metric
= NULL
;
603 struct list
*orr_group_igp_metric_info
= NULL
;
609 *reason
= bgp_path_selection_none
;
611 zlog_debug("%s: new is NULL", pfx_buf
);
616 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
617 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
622 *reason
= bgp_path_selection_first
;
624 zlog_debug("%s(%s): %s is the initial bestpath",
625 pfx_buf
, bgp
->name_pretty
, new_buf
);
630 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
631 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
633 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
634 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
635 exist_buf
, exist
->flags
);
639 existattr
= exist
->attr
;
641 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
642 * Capability" to a neighbor MUST perform the following upon receiving
643 * a route from that neighbor with the "LLGR_STALE" community, or upon
644 * attaching the "LLGR_STALE" community itself per Section 4.2:
646 * Treat the route as the least-preferred in route selection (see
647 * below). See the Risks of Depreferencing Routes section (Section 5.2)
648 * for a discussion of potential risks inherent in doing this.
650 if (bgp_attr_get_community(newattr
) &&
651 community_include(bgp_attr_get_community(newattr
),
652 COMMUNITY_LLGR_STALE
)) {
655 "%s: %s wins over %s due to LLGR_STALE community",
656 pfx_buf
, new_buf
, exist_buf
);
660 if (bgp_attr_get_community(existattr
) &&
661 community_include(bgp_attr_get_community(existattr
),
662 COMMUNITY_LLGR_STALE
)) {
665 "%s: %s loses to %s due to LLGR_STALE community",
666 pfx_buf
, new_buf
, exist_buf
);
670 new_p
= bgp_dest_get_prefix(new->net
);
672 /* For EVPN routes, we cannot just go by local vs remote, we have to
673 * look at the MAC mobility sequence number, if present.
675 if ((safi
== SAFI_EVPN
)
676 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
677 /* This is an error condition described in RFC 7432 Section
679 * states that in this scenario "the PE MUST alert the operator"
681 * does not state what other action to take. In order to provide
683 * consistency in this scenario we are going to prefer the path
687 if (newattr
->sticky
!= existattr
->sticky
) {
689 prefix2str(new_p
, pfx_buf
,
691 * PREFIX2STR_BUFFER
);
692 bgp_path_info_path_with_addpath_rx_str(
693 new, new_buf
, sizeof(new_buf
));
694 bgp_path_info_path_with_addpath_rx_str(
695 exist
, exist_buf
, sizeof(exist_buf
));
698 if (newattr
->sticky
&& !existattr
->sticky
) {
699 *reason
= bgp_path_selection_evpn_sticky_mac
;
702 "%s: %s wins over %s due to sticky MAC flag",
703 pfx_buf
, new_buf
, exist_buf
);
707 if (!newattr
->sticky
&& existattr
->sticky
) {
708 *reason
= bgp_path_selection_evpn_sticky_mac
;
711 "%s: %s loses to %s due to sticky MAC flag",
712 pfx_buf
, new_buf
, exist_buf
);
717 new_esi
= bgp_evpn_attr_get_esi(newattr
);
718 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
719 if (bgp_evpn_is_esi_valid(new_esi
) &&
720 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
726 /* If both paths have the same non-zero ES and
727 * one path is local it wins.
728 * PS: Note the local path wins even if the remote
729 * has the higher MM seq. The local path's
730 * MM seq will be fixed up to match the highest
731 * rem seq, subsequently.
734 char esi_buf
[ESI_STR_LEN
];
736 if (bgp_evpn_is_path_local(bgp
, new)) {
737 *reason
= bgp_path_selection_evpn_local_path
;
740 "%s: %s wins over %s as ES %s is same and local",
741 pfx_buf
, new_buf
, exist_buf
,
742 esi_to_str(new_esi
, esi_buf
,
746 if (bgp_evpn_is_path_local(bgp
, exist
)) {
747 *reason
= bgp_path_selection_evpn_local_path
;
750 "%s: %s loses to %s as ES %s is same and local",
751 pfx_buf
, new_buf
, exist_buf
,
752 esi_to_str(new_esi
, esi_buf
,
758 new_mm_seq
= mac_mobility_seqnum(newattr
);
759 exist_mm_seq
= mac_mobility_seqnum(existattr
);
761 if (new_mm_seq
> exist_mm_seq
) {
762 *reason
= bgp_path_selection_evpn_seq
;
765 "%s: %s wins over %s due to MM seq %u > %u",
766 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
771 if (new_mm_seq
< exist_mm_seq
) {
772 *reason
= bgp_path_selection_evpn_seq
;
775 "%s: %s loses to %s due to MM seq %u < %u",
776 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
781 /* if the sequence numbers and ESI are the same and one path
782 * is non-proxy it wins (over proxy)
784 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
785 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
786 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
787 old_proxy
!= new_proxy
) {
789 *reason
= bgp_path_selection_evpn_non_proxy
;
792 "%s: %s wins over %s, same seq/es and non-proxy",
793 pfx_buf
, new_buf
, exist_buf
);
797 *reason
= bgp_path_selection_evpn_non_proxy
;
800 "%s: %s loses to %s, same seq/es and non-proxy",
801 pfx_buf
, new_buf
, exist_buf
);
806 * if sequence numbers are the same path with the lowest IP
809 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
811 *reason
= bgp_path_selection_evpn_lower_ip
;
814 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
815 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
816 &new->attr
->nexthop
);
820 *reason
= bgp_path_selection_evpn_lower_ip
;
823 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
824 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
825 &new->attr
->nexthop
);
830 /* 1. Weight check. */
831 new_weight
= newattr
->weight
;
832 exist_weight
= existattr
->weight
;
834 if (new_weight
> exist_weight
) {
835 *reason
= bgp_path_selection_weight
;
837 zlog_debug("%s: %s wins over %s due to weight %d > %d",
838 pfx_buf
, new_buf
, exist_buf
, new_weight
,
843 if (new_weight
< exist_weight
) {
844 *reason
= bgp_path_selection_weight
;
846 zlog_debug("%s: %s loses to %s due to weight %d < %d",
847 pfx_buf
, new_buf
, exist_buf
, new_weight
,
852 /* 2. Local preference check. */
853 new_pref
= exist_pref
= bgp
->default_local_pref
;
855 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
856 new_pref
= newattr
->local_pref
;
857 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
858 exist_pref
= existattr
->local_pref
;
860 if (new_pref
> exist_pref
) {
861 *reason
= bgp_path_selection_local_pref
;
864 "%s: %s wins over %s due to localpref %d > %d",
865 pfx_buf
, new_buf
, exist_buf
, new_pref
,
870 if (new_pref
< exist_pref
) {
871 *reason
= bgp_path_selection_local_pref
;
874 "%s: %s loses to %s due to localpref %d < %d",
875 pfx_buf
, new_buf
, exist_buf
, new_pref
,
880 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
881 * extensions defined in this document, the following step is inserted
882 * after the LOCAL_PREF comparison step in the BGP decision process:
883 * When comparing a pair of routes for a BGP destination, the
884 * route with the ACCEPT_OWN community attached is preferred over
885 * the route that does not have the community.
886 * This extra step MUST only be invoked during the best path selection
887 * process of VPN-IP routes.
889 if (safi
== SAFI_MPLS_VPN
&&
890 (CHECK_FLAG(new->peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
) ||
891 CHECK_FLAG(exist
->peer
->af_flags
[afi
][safi
],
892 PEER_FLAG_ACCEPT_OWN
))) {
893 bool new_accept_own
= false;
894 bool exist_accept_own
= false;
895 uint32_t accept_own
= COMMUNITY_ACCEPT_OWN
;
897 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
898 new_accept_own
= community_include(
899 bgp_attr_get_community(newattr
), accept_own
);
900 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
901 exist_accept_own
= community_include(
902 bgp_attr_get_community(existattr
), accept_own
);
904 if (new_accept_own
&& !exist_accept_own
) {
905 *reason
= bgp_path_selection_accept_own
;
908 "%s: %s wins over %s due to accept-own",
909 pfx_buf
, new_buf
, exist_buf
);
913 if (!new_accept_own
&& exist_accept_own
) {
914 *reason
= bgp_path_selection_accept_own
;
917 "%s: %s loses to %s due to accept-own",
918 pfx_buf
, new_buf
, exist_buf
);
923 /* 3. Local route check. We prefer:
925 * - BGP_ROUTE_AGGREGATE
926 * - BGP_ROUTE_REDISTRIBUTE
928 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
929 new->sub_type
== BGP_ROUTE_IMPORTED
);
930 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
931 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
933 if (new_origin
&& !exist_origin
) {
934 *reason
= bgp_path_selection_local_route
;
937 "%s: %s wins over %s due to preferred BGP_ROUTE type",
938 pfx_buf
, new_buf
, exist_buf
);
942 if (!new_origin
&& exist_origin
) {
943 *reason
= bgp_path_selection_local_route
;
946 "%s: %s loses to %s due to preferred BGP_ROUTE type",
947 pfx_buf
, new_buf
, exist_buf
);
951 /* Here if these are imported routes then get ultimate pi for
954 new = bgp_get_imported_bpi_ultimate(new);
955 exist
= bgp_get_imported_bpi_ultimate(exist
);
957 existattr
= exist
->attr
;
959 /* 4. AS path length check. */
960 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
961 int exist_hops
= aspath_count_hops(existattr
->aspath
);
962 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
964 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
967 aspath_hops
= aspath_count_hops(newattr
->aspath
);
968 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
970 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
971 *reason
= bgp_path_selection_confed_as_path
;
974 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
975 pfx_buf
, new_buf
, exist_buf
,
977 (exist_hops
+ exist_confeds
));
981 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
982 *reason
= bgp_path_selection_confed_as_path
;
985 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
986 pfx_buf
, new_buf
, exist_buf
,
988 (exist_hops
+ exist_confeds
));
992 int newhops
= aspath_count_hops(newattr
->aspath
);
994 if (newhops
< exist_hops
) {
995 *reason
= bgp_path_selection_as_path
;
998 "%s: %s wins over %s due to aspath hopcount %d < %d",
999 pfx_buf
, new_buf
, exist_buf
,
1000 newhops
, exist_hops
);
1004 if (newhops
> exist_hops
) {
1005 *reason
= bgp_path_selection_as_path
;
1008 "%s: %s loses to %s due to aspath hopcount %d > %d",
1009 pfx_buf
, new_buf
, exist_buf
,
1010 newhops
, exist_hops
);
1016 /* 5. Origin check. */
1017 if (newattr
->origin
< existattr
->origin
) {
1018 *reason
= bgp_path_selection_origin
;
1020 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1021 pfx_buf
, new_buf
, exist_buf
,
1022 bgp_origin_long_str
[newattr
->origin
],
1023 bgp_origin_long_str
[existattr
->origin
]);
1027 if (newattr
->origin
> existattr
->origin
) {
1028 *reason
= bgp_path_selection_origin
;
1030 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1031 pfx_buf
, new_buf
, exist_buf
,
1032 bgp_origin_long_str
[newattr
->origin
],
1033 bgp_origin_long_str
[existattr
->origin
]);
1038 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
1039 && aspath_count_hops(existattr
->aspath
) == 0);
1040 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
1041 && aspath_count_confeds(existattr
->aspath
) > 0
1042 && aspath_count_hops(newattr
->aspath
) == 0
1043 && aspath_count_hops(existattr
->aspath
) == 0);
1045 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1046 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1047 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1048 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1049 || internal_as_route
) {
1050 new_med
= bgp_med_value(new->attr
, bgp
);
1051 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1053 if (new_med
< exist_med
) {
1054 *reason
= bgp_path_selection_med
;
1057 "%s: %s wins over %s due to MED %d < %d",
1058 pfx_buf
, new_buf
, exist_buf
, new_med
,
1063 if (new_med
> exist_med
) {
1064 *reason
= bgp_path_selection_med
;
1067 "%s: %s loses to %s due to MED %d > %d",
1068 pfx_buf
, new_buf
, exist_buf
, new_med
,
1074 /* 7. Peer type check. */
1075 new_sort
= new->peer
->sort
;
1076 exist_sort
= exist
->peer
->sort
;
1078 if (new_sort
== BGP_PEER_EBGP
1079 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1080 *reason
= bgp_path_selection_peer
;
1083 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1084 pfx_buf
, new_buf
, exist_buf
);
1085 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1090 if (exist_sort
== BGP_PEER_EBGP
1091 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1092 *reason
= bgp_path_selection_peer
;
1095 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1096 pfx_buf
, new_buf
, exist_buf
);
1097 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1102 /* 8. IGP metric check. */
1106 newm
= new->extra
->igpmetric
;
1108 existm
= exist
->extra
->igpmetric
;
1110 if (new->peer
->orr_group_name
[afi
][safi
]) {
1111 ret
= str2prefix(new->peer
->host
, &exist_p
);
1112 orr_group
= bgp_orr_group_lookup_by_name(
1113 bgp
, afi
, safi
, new->peer
->orr_group_name
[afi
][safi
]);
1115 orr_group_igp_metric_info
= orr_group
->igp_metric_info
;
1116 if (orr_group_igp_metric_info
) {
1117 for (ALL_LIST_ELEMENTS_RO(
1118 orr_group_igp_metric_info
, node
,
1121 prefix_cmp(&exist_p
,
1122 &igp_metric
->prefix
) ==
1124 newm
= igp_metric
->igp_metric
;
1131 if (exist
->peer
->orr_group_name
[afi
][safi
]) {
1132 ret
= str2prefix(exist
->peer
->host
, &exist_p
);
1133 orr_group
= bgp_orr_group_lookup_by_name(
1134 bgp
, afi
, safi
, exist
->peer
->orr_group_name
[afi
][safi
]);
1136 orr_group_igp_metric_info
= orr_group
->igp_metric_info
;
1137 if (orr_group_igp_metric_info
) {
1138 for (ALL_LIST_ELEMENTS_RO(
1139 orr_group_igp_metric_info
, node
,
1142 prefix_cmp(&exist_p
,
1143 &igp_metric
->prefix
) ==
1145 existm
= igp_metric
->igp_metric
;
1153 if (newm
< existm
) {
1154 if (debug
&& peer_sort_ret
< 0)
1156 "%s: %s wins over %s due to IGP metric %u < %u",
1157 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1161 if (newm
> existm
) {
1162 if (debug
&& peer_sort_ret
< 0)
1164 "%s: %s loses to %s due to IGP metric %u > %u",
1165 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1169 /* 9. Same IGP metric. Compare the cluster list length as
1170 representative of IGP hops metric. Rewrite the metric value
1171 pair (newm, existm) with the cluster list length. Prefer the
1172 path with smaller cluster list length. */
1173 if (newm
== existm
) {
1174 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
&&
1175 peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
&&
1176 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1177 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1178 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1180 if (newm
< existm
) {
1181 if (debug
&& peer_sort_ret
< 0)
1183 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1184 pfx_buf
, new_buf
, exist_buf
,
1189 if (newm
> existm
) {
1190 if (debug
&& peer_sort_ret
< 0)
1192 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1193 pfx_buf
, new_buf
, exist_buf
,
1200 /* 10. confed-external vs. confed-internal */
1201 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1202 if (new_sort
== BGP_PEER_CONFED
1203 && exist_sort
== BGP_PEER_IBGP
) {
1204 *reason
= bgp_path_selection_confed
;
1207 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1208 pfx_buf
, new_buf
, exist_buf
);
1209 if (!CHECK_FLAG(bgp
->flags
,
1210 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1215 if (exist_sort
== BGP_PEER_CONFED
1216 && new_sort
== BGP_PEER_IBGP
) {
1217 *reason
= bgp_path_selection_confed
;
1220 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1221 pfx_buf
, new_buf
, exist_buf
);
1222 if (!CHECK_FLAG(bgp
->flags
,
1223 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1229 /* 11. Maximum path check. */
1230 if (newm
== existm
) {
1231 /* If one path has a label but the other does not, do not treat
1232 * them as equals for multipath
1234 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1236 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1239 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1240 pfx_buf
, new_buf
, exist_buf
);
1241 } else if (CHECK_FLAG(bgp
->flags
,
1242 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1245 * For the two paths, all comparison steps till IGP
1247 * have succeeded - including AS_PATH hop count. Since
1249 * bestpath as-path multipath-relax' knob is on, we
1251 * an exact match of AS_PATH. Thus, mark the paths are
1253 * That will trigger both these paths to get into the
1261 "%s: %s and %s are equal via multipath-relax",
1262 pfx_buf
, new_buf
, exist_buf
);
1263 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1264 if (aspath_cmp(new->attr
->aspath
,
1265 exist
->attr
->aspath
)) {
1270 "%s: %s and %s are equal via matching aspaths",
1271 pfx_buf
, new_buf
, exist_buf
);
1273 } else if (new->peer
->as
== exist
->peer
->as
) {
1278 "%s: %s and %s are equal via same remote-as",
1279 pfx_buf
, new_buf
, exist_buf
);
1283 * TODO: If unequal cost ibgp multipath is enabled we can
1284 * mark the paths as equal here instead of returning
1287 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1288 * if either step 7 or 10 (peer type checks) yielded a winner,
1289 * that result was returned immediately. Returning from step 10
1290 * ignored the return value computed in steps 8 and 9 (IGP
1291 * metric checks). In order to preserve that behavior, if
1292 * peer_sort_ret is set, return that rather than igp_metric_ret.
1294 ret
= peer_sort_ret
;
1295 if (peer_sort_ret
< 0) {
1296 ret
= igp_metric_ret
;
1300 "%s: %s wins over %s after IGP metric comparison",
1301 pfx_buf
, new_buf
, exist_buf
);
1304 "%s: %s loses to %s after IGP metric comparison",
1305 pfx_buf
, new_buf
, exist_buf
);
1307 *reason
= bgp_path_selection_igp_metric
;
1313 * At this point, the decision whether to set *paths_eq = 1 has been
1314 * completed. If we deferred returning because of bestpath peer-type
1315 * relax configuration, return now.
1317 if (peer_sort_ret
>= 0)
1318 return peer_sort_ret
;
1320 /* 12. If both paths are external, prefer the path that was received
1321 first (the oldest one). This step minimizes route-flap, since a
1322 newer path won't displace an older one, even if it was the
1323 preferred route based on the additional decision criteria below. */
1324 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1325 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1326 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1327 *reason
= bgp_path_selection_older
;
1330 "%s: %s wins over %s due to oldest external",
1331 pfx_buf
, new_buf
, exist_buf
);
1335 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1336 *reason
= bgp_path_selection_older
;
1339 "%s: %s loses to %s due to oldest external",
1340 pfx_buf
, new_buf
, exist_buf
);
1345 /* 13. Router-ID comparison. */
1346 /* If one of the paths is "stale", the corresponding peer router-id will
1347 * be 0 and would always win over the other path. If originator id is
1348 * used for the comparison, it will decide which path is better.
1350 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1351 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1353 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1354 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1355 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1357 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1359 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1360 *reason
= bgp_path_selection_router_id
;
1363 "%s: %s wins over %s due to Router-ID comparison",
1364 pfx_buf
, new_buf
, exist_buf
);
1368 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1369 *reason
= bgp_path_selection_router_id
;
1372 "%s: %s loses to %s due to Router-ID comparison",
1373 pfx_buf
, new_buf
, exist_buf
);
1377 /* 14. Cluster length comparison. */
1378 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1379 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1381 if (new_cluster
< exist_cluster
) {
1382 *reason
= bgp_path_selection_cluster_length
;
1385 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1386 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1391 if (new_cluster
> exist_cluster
) {
1392 *reason
= bgp_path_selection_cluster_length
;
1395 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1396 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1401 /* 15. Neighbor address comparison. */
1402 /* Do this only if neither path is "stale" as stale paths do not have
1403 * valid peer information (as the connection may or may not be up).
1405 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1406 *reason
= bgp_path_selection_stale
;
1409 "%s: %s wins over %s due to latter path being STALE",
1410 pfx_buf
, new_buf
, exist_buf
);
1414 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1415 *reason
= bgp_path_selection_stale
;
1418 "%s: %s loses to %s due to former path being STALE",
1419 pfx_buf
, new_buf
, exist_buf
);
1423 /* locally configured routes to advertise do not have su_remote */
1424 if (new->peer
->su_remote
== NULL
) {
1425 *reason
= bgp_path_selection_local_configured
;
1428 if (exist
->peer
->su_remote
== NULL
) {
1429 *reason
= bgp_path_selection_local_configured
;
1433 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1436 *reason
= bgp_path_selection_neighbor_ip
;
1439 "%s: %s loses to %s due to Neighor IP comparison",
1440 pfx_buf
, new_buf
, exist_buf
);
1445 *reason
= bgp_path_selection_neighbor_ip
;
1448 "%s: %s wins over %s due to Neighor IP comparison",
1449 pfx_buf
, new_buf
, exist_buf
);
1453 *reason
= bgp_path_selection_default
;
1455 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1456 pfx_buf
, new_buf
, exist_buf
);
1462 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1463 struct bgp_path_info
*exist
, int *paths_eq
)
1465 enum bgp_path_selection_reason reason
;
1466 char pfx_buf
[PREFIX2STR_BUFFER
];
1468 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1469 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1472 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1473 * is preferred, or 0 if they are the same (usually will only occur if
1474 * multipath is enabled
1475 * This version is compatible with */
1476 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1477 struct bgp_path_info
*exist
, char *pfx_buf
,
1478 afi_t afi
, safi_t safi
,
1479 enum bgp_path_selection_reason
*reason
)
1483 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1497 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1498 const struct prefix
*p
,
1499 struct attr
*attr
, afi_t afi
,
1502 struct bgp_filter
*filter
;
1503 enum filter_type ret
= FILTER_PERMIT
;
1505 filter
= &peer
->filter
[afi
][safi
];
1507 #define FILTER_EXIST_WARN(F, f, filter) \
1508 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1509 zlog_debug("%s: Could not find configured input %s-list %s!", \
1510 peer->host, #f, F##_IN_NAME(filter));
1512 if (DISTRIBUTE_IN_NAME(filter
)) {
1513 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1515 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1522 if (PREFIX_LIST_IN_NAME(filter
)) {
1523 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1525 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1532 if (FILTER_LIST_IN_NAME(filter
)) {
1533 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1535 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1536 == AS_FILTER_DENY
) {
1543 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1544 char pfxprint
[PREFIX2STR_BUFFER
];
1546 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1547 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1548 ret
== FILTER_PERMIT
? "permit" : "deny");
1552 #undef FILTER_EXIST_WARN
1555 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1556 const struct prefix
*p
,
1557 struct attr
*attr
, afi_t afi
,
1560 struct bgp_filter
*filter
;
1561 enum filter_type ret
= FILTER_PERMIT
;
1563 filter
= &peer
->filter
[afi
][safi
];
1565 #define FILTER_EXIST_WARN(F, f, filter) \
1566 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1567 zlog_debug("%s: Could not find configured output %s-list %s!", \
1568 peer->host, #f, F##_OUT_NAME(filter));
1570 if (DISTRIBUTE_OUT_NAME(filter
)) {
1571 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1573 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1580 if (PREFIX_LIST_OUT_NAME(filter
)) {
1581 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1583 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1590 if (FILTER_LIST_OUT_NAME(filter
)) {
1591 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1593 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1594 == AS_FILTER_DENY
) {
1600 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1601 char pfxprint
[PREFIX2STR_BUFFER
];
1603 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1604 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1605 ret
== FILTER_PERMIT
? "permit" : "deny");
1610 #undef FILTER_EXIST_WARN
1613 /* If community attribute includes no_export then return 1. */
1614 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1616 if (bgp_attr_get_community(attr
)) {
1617 /* NO_ADVERTISE check. */
1618 if (community_include(bgp_attr_get_community(attr
),
1619 COMMUNITY_NO_ADVERTISE
))
1622 /* NO_EXPORT check. */
1623 if (peer
->sort
== BGP_PEER_EBGP
&&
1624 community_include(bgp_attr_get_community(attr
),
1625 COMMUNITY_NO_EXPORT
))
1628 /* NO_EXPORT_SUBCONFED check. */
1629 if (peer
->sort
== BGP_PEER_EBGP
1630 || peer
->sort
== BGP_PEER_CONFED
)
1631 if (community_include(bgp_attr_get_community(attr
),
1632 COMMUNITY_NO_EXPORT_SUBCONFED
))
1638 /* Route reflection loop check. */
1639 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1641 struct in_addr cluster_id
;
1642 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1645 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1646 cluster_id
= peer
->bgp
->cluster_id
;
1648 cluster_id
= peer
->bgp
->router_id
;
1650 if (cluster_loop_check(cluster
, cluster_id
))
1656 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1658 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1659 if (peer
->local_role
== ROLE_PROVIDER
||
1660 peer
->local_role
== ROLE_RS_SERVER
)
1662 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1666 if (peer
->local_role
== ROLE_CUSTOMER
||
1667 peer
->local_role
== ROLE_PEER
||
1668 peer
->local_role
== ROLE_RS_CLIENT
) {
1669 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1670 attr
->otc
= peer
->as
;
1675 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1677 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1678 if (peer
->local_role
== ROLE_CUSTOMER
||
1679 peer
->local_role
== ROLE_RS_CLIENT
||
1680 peer
->local_role
== ROLE_PEER
)
1684 if (peer
->local_role
== ROLE_PROVIDER
||
1685 peer
->local_role
== ROLE_PEER
||
1686 peer
->local_role
== ROLE_RS_SERVER
) {
1687 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1688 attr
->otc
= peer
->bgp
->as
;
1693 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1695 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1698 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1699 struct attr
*attr
, afi_t afi
, safi_t safi
,
1700 const char *rmap_name
, mpls_label_t
*label
,
1701 uint32_t num_labels
, struct bgp_dest
*dest
)
1703 struct bgp_filter
*filter
;
1704 struct bgp_path_info rmap_path
= { 0 };
1705 struct bgp_path_info_extra extra
= { 0 };
1706 route_map_result_t ret
;
1707 struct route_map
*rmap
= NULL
;
1709 filter
= &peer
->filter
[afi
][safi
];
1711 /* Apply default weight value. */
1712 if (peer
->weight
[afi
][safi
])
1713 attr
->weight
= peer
->weight
[afi
][safi
];
1716 rmap
= route_map_lookup_by_name(rmap_name
);
1721 if (ROUTE_MAP_IN_NAME(filter
)) {
1722 rmap
= ROUTE_MAP_IN(filter
);
1729 /* Route map apply. */
1731 memset(&rmap_path
, 0, sizeof(rmap_path
));
1732 /* Duplicate current value to new structure for modification. */
1733 rmap_path
.peer
= peer
;
1734 rmap_path
.attr
= attr
;
1735 rmap_path
.extra
= &extra
;
1736 rmap_path
.net
= dest
;
1738 extra
.num_labels
= num_labels
;
1739 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1740 memcpy(extra
.label
, label
,
1741 num_labels
* sizeof(mpls_label_t
));
1743 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1745 /* Apply BGP route map to the attribute. */
1746 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1748 peer
->rmap_type
= 0;
1750 if (ret
== RMAP_DENYMATCH
)
1756 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1757 struct attr
*attr
, afi_t afi
, safi_t safi
,
1758 const char *rmap_name
)
1760 struct bgp_path_info rmap_path
;
1761 route_map_result_t ret
;
1762 struct route_map
*rmap
= NULL
;
1766 * So if we get to this point and have no rmap_name
1767 * we want to just show the output as it currently
1773 /* Apply default weight value. */
1774 if (peer
->weight
[afi
][safi
])
1775 attr
->weight
= peer
->weight
[afi
][safi
];
1777 rmap
= route_map_lookup_by_name(rmap_name
);
1780 * If we have a route map name and we do not find
1781 * the routemap that means we have an implicit
1787 memset(&rmap_path
, 0, sizeof(rmap_path
));
1788 /* Route map apply. */
1789 /* Duplicate current value to new structure for modification. */
1790 rmap_path
.peer
= peer
;
1791 rmap_path
.attr
= attr
;
1793 rmap_type
= peer
->rmap_type
;
1794 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1796 /* Apply BGP route map to the attribute. */
1797 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1799 peer
->rmap_type
= rmap_type
;
1801 if (ret
== RMAP_DENYMATCH
)
1803 * caller has multiple error paths with bgp_attr_flush()
1810 /* If this is an EBGP peer with remove-private-AS */
1811 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1812 struct peer
*peer
, struct attr
*attr
)
1814 if (peer
->sort
== BGP_PEER_EBGP
1815 && (peer_af_flag_check(peer
, afi
, safi
,
1816 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1817 || peer_af_flag_check(peer
, afi
, safi
,
1818 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1819 || peer_af_flag_check(peer
, afi
, safi
,
1820 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1821 || peer_af_flag_check(peer
, afi
, safi
,
1822 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1823 // Take action on the entire aspath
1824 if (peer_af_flag_check(peer
, afi
, safi
,
1825 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1826 || peer_af_flag_check(peer
, afi
, safi
,
1827 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1828 if (peer_af_flag_check(
1830 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1831 attr
->aspath
= aspath_replace_private_asns(
1832 attr
->aspath
, bgp
->as
, peer
->as
);
1835 * Even if the aspath consists of just private ASNs we
1836 * need to walk the AS-Path to maintain all instances
1837 * of the peer's ASN to break possible loops.
1840 attr
->aspath
= aspath_remove_private_asns(
1841 attr
->aspath
, peer
->as
);
1844 // 'all' was not specified so the entire aspath must be private
1846 // for us to do anything
1847 else if (aspath_private_as_check(attr
->aspath
)) {
1848 if (peer_af_flag_check(
1850 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1851 attr
->aspath
= aspath_replace_private_asns(
1852 attr
->aspath
, bgp
->as
, peer
->as
);
1855 * Walk the aspath to retain any instances of
1858 attr
->aspath
= aspath_remove_private_asns(
1859 attr
->aspath
, peer
->as
);
1864 /* If this is an EBGP peer with as-override */
1865 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1866 struct peer
*peer
, struct attr
*attr
)
1868 struct aspath
*aspath
;
1870 if (peer
->sort
== BGP_PEER_EBGP
&&
1871 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1872 if (attr
->aspath
->refcnt
)
1873 aspath
= aspath_dup(attr
->aspath
);
1875 aspath
= attr
->aspath
;
1877 attr
->aspath
= aspath_intern(
1878 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1880 aspath_free(aspath
);
1884 void bgp_attr_add_llgr_community(struct attr
*attr
)
1886 struct community
*old
;
1887 struct community
*new;
1888 struct community
*merge
;
1889 struct community
*llgr
;
1891 old
= bgp_attr_get_community(attr
);
1892 llgr
= community_str2com("llgr-stale");
1897 merge
= community_merge(community_dup(old
), llgr
);
1899 if (old
->refcnt
== 0)
1900 community_free(&old
);
1902 new = community_uniq_sort(merge
);
1903 community_free(&merge
);
1905 new = community_dup(llgr
);
1908 community_free(&llgr
);
1910 bgp_attr_set_community(attr
, new);
1913 void bgp_attr_add_gshut_community(struct attr
*attr
)
1915 struct community
*old
;
1916 struct community
*new;
1917 struct community
*merge
;
1918 struct community
*gshut
;
1920 old
= bgp_attr_get_community(attr
);
1921 gshut
= community_str2com("graceful-shutdown");
1926 merge
= community_merge(community_dup(old
), gshut
);
1928 if (old
->refcnt
== 0)
1929 community_free(&old
);
1931 new = community_uniq_sort(merge
);
1932 community_free(&merge
);
1934 new = community_dup(gshut
);
1937 community_free(&gshut
);
1938 bgp_attr_set_community(attr
, new);
1940 /* When we add the graceful-shutdown community we must also
1941 * lower the local-preference */
1942 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1943 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1947 /* Notify BGP Conditional advertisement scanner process. */
1948 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1950 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1951 afi_t afi
= SUBGRP_AFI(subgrp
);
1952 safi_t safi
= SUBGRP_SAFI(subgrp
);
1953 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1955 if (!ADVERTISE_MAP_NAME(filter
))
1958 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1961 peer
->advmap_table_change
= true;
1965 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1967 if (family
== AF_INET
) {
1968 attr
->nexthop
.s_addr
= INADDR_ANY
;
1969 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1971 if (family
== AF_INET6
)
1972 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1973 if (family
== AF_EVPN
)
1974 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1977 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1978 struct update_subgroup
*subgrp
,
1979 const struct prefix
*p
, struct attr
*attr
,
1980 struct attr
*post_attr
)
1982 struct bgp_filter
*filter
;
1985 struct peer
*onlypeer
;
1987 struct attr
*piattr
;
1988 route_map_result_t ret
;
1993 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1994 bool nh_reset
= false;
1997 if (DISABLE_BGP_ANNOUNCE
)
2000 afi
= SUBGRP_AFI(subgrp
);
2001 safi
= SUBGRP_SAFI(subgrp
);
2002 peer
= SUBGRP_PEER(subgrp
);
2004 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
2005 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
2008 filter
= &peer
->filter
[afi
][safi
];
2009 bgp
= SUBGRP_INST(subgrp
);
2010 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
2013 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
2014 peer
->pmax_out
[afi
][safi
] != 0 &&
2015 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
2016 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
2017 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
2018 zlog_debug("%s reached maximum prefix to be send (%u)",
2019 peer
->host
, peer
->pmax_out
[afi
][safi
]);
2024 #ifdef ENABLE_BGP_VNC
2025 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
2026 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
2027 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
2030 * direct and direct_ext type routes originate internally even
2031 * though they can have peer pointers that reference other
2034 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2040 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
2041 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
2042 && (pi
->type
== ZEBRA_ROUTE_BGP
)
2043 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2045 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2050 /* With addpath we may be asked to TX all kinds of paths so make sure
2052 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
2053 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
2054 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
2058 /* If this is not the bestpath then check to see if there is an enabled
2060 * feature that requires us to advertise it */
2061 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2062 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
2067 /* Aggregate-address suppress check. */
2068 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
2072 * If we are doing VRF 2 VRF leaking via the import
2073 * statement, we want to prevent the route going
2074 * off box as that the RT and RD created are localy
2075 * significant and globaly useless.
2077 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
2078 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
2081 /* If it's labeled safi, make sure the route has a valid label. */
2082 if (safi
== SAFI_LABELED_UNICAST
) {
2083 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
2084 if (!bgp_is_valid_label(&label
)) {
2085 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2086 zlog_debug("u%" PRIu64
":s%" PRIu64
2087 " %pFX is filtered - no label (%p)",
2088 subgrp
->update_group
->id
, subgrp
->id
,
2094 /* Do not send back route to sender. */
2095 if (onlypeer
&& from
== onlypeer
) {
2099 /* Do not send the default route in the BGP table if the neighbor is
2100 * configured for default-originate */
2101 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2102 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2103 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2105 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2109 /* Transparency check. */
2110 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2111 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2116 /* If community is not disabled check the no-export and local. */
2117 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2118 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2119 zlog_debug("%s: community filter check fail for %pFX",
2124 /* If the attribute has originator-id and it is same as remote
2126 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2127 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2128 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2130 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2135 /* ORF prefix-list filter check */
2136 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2137 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2138 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2139 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2140 if (peer
->orf_plist
[afi
][safi
]) {
2141 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2143 if (bgp_debug_update(NULL
, p
,
2144 subgrp
->update_group
, 0))
2146 "%pBP [Update:SEND] %pFX is filtered via ORF",
2152 /* Output filter check. */
2153 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2154 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2155 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2160 /* AS path loop check. */
2161 if (onlypeer
&& onlypeer
->as_path_loop_detection
2162 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
2163 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2165 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2166 onlypeer
, onlypeer
->as
);
2170 /* If we're a CONFED we need to loop check the CONFED ID too */
2171 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2172 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
2173 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2175 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2176 peer
, bgp
->confed_id
);
2181 /* Route-Reflect check. */
2182 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2187 /* IBGP reflection check. */
2188 if (reflect
&& !samepeer_safe
) {
2189 /* A route from a Client peer. */
2190 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2191 PEER_FLAG_REFLECTOR_CLIENT
)) {
2192 /* Reflect to all the Non-Client peers and also to the
2193 Client peers other than the originator. Originator
2195 is already done. So there is noting to do. */
2196 /* no bgp client-to-client reflection check. */
2197 if (CHECK_FLAG(bgp
->flags
,
2198 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2199 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2200 PEER_FLAG_REFLECTOR_CLIENT
))
2203 /* A route from a Non-client peer. Reflect to all other
2205 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2206 PEER_FLAG_REFLECTOR_CLIENT
))
2211 /* For modify attribute, copy it to temporary structure.
2212 * post_attr comes from BGP conditional advertisements, where
2213 * attributes are already processed by advertise-map route-map,
2214 * and this needs to be saved instead of overwriting from the
2222 /* If local-preference is not set. */
2223 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2224 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2225 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2226 attr
->local_pref
= bgp
->default_local_pref
;
2229 /* If originator-id is not set and the route is to be reflected,
2230 set the originator id */
2232 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2233 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2234 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2237 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2239 if (peer
->sort
== BGP_PEER_EBGP
2240 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2241 if (from
!= bgp
->peer_self
&& !transparent
2242 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2243 PEER_FLAG_MED_UNCHANGED
))
2245 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2248 /* Since the nexthop attribute can vary per peer, it is not explicitly
2250 * in announce check, only certain flags and length (or number of
2252 * -- for IPv6/MP_REACH) are set here in order to guide the update
2254 * code in setting the nexthop(s) on a per peer basis in
2256 * Typically, the source nexthop in the attribute is preserved but in
2258 * scenarios where we know it will always be overwritten, we reset the
2259 * nexthop to "0" in an attempt to achieve better Update packing. An
2260 * example of this is when a prefix from each of 2 IBGP peers needs to
2262 * announced to an EBGP peer (and they have the same attributes barring
2266 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2268 #define NEXTHOP_IS_V6 \
2269 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2270 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2271 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2272 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2274 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2276 * the peer (group) is configured to receive link-local nexthop
2278 * and it is available in the prefix OR we're not reflecting the route,
2279 * link-local nexthop address is valid and
2280 * the peer (group) to whom we're going to announce is on a shared
2282 * and this is either a self-originated route or the peer is EBGP.
2283 * By checking if nexthop LL address is valid we are sure that
2284 * we do not announce LL address as `::`.
2286 if (NEXTHOP_IS_V6
) {
2287 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2288 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2289 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2290 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2291 || (!reflect
&& !transparent
2292 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2293 && peer
->shared_network
2294 && (from
== bgp
->peer_self
2295 || peer
->sort
== BGP_PEER_EBGP
))) {
2296 attr
->mp_nexthop_len
=
2297 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2300 /* Clear off link-local nexthop in source, whenever it is not
2302 * ensure more prefixes share the same attribute for
2305 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2306 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2307 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2310 if (bgp_check_role_applicability(afi
, safi
) &&
2311 bgp_otc_egress(peer
, attr
))
2314 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2315 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2317 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2318 filter
->advmap
.aname
&&
2319 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2320 struct bgp_path_info rmap_path
= {0};
2321 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2322 struct attr dummy_attr
= *attr
;
2324 /* Fill temp path_info */
2325 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2326 pi
, peer
, &dummy_attr
);
2328 struct route_map
*amap
=
2329 route_map_lookup_by_name(filter
->advmap
.aname
);
2331 ret
= route_map_apply(amap
, p
, &rmap_path
);
2333 bgp_attr_flush(&dummy_attr
);
2336 * The conditional advertisement mode is Withdraw and this
2337 * prefix is a conditional prefix. Don't advertise it
2339 if (ret
== RMAP_PERMITMATCH
)
2343 /* Route map & unsuppress-map apply. */
2345 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2346 struct bgp_path_info rmap_path
= {0};
2347 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2348 struct attr dummy_attr
= {0};
2350 /* Fill temp path_info */
2351 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2354 /* don't confuse inbound and outbound setting */
2355 RESET_FLAG(attr
->rmap_change_flags
);
2358 * The route reflector is not allowed to modify the attributes
2359 * of the reflected IBGP routes unless explicitly allowed.
2361 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2362 && !CHECK_FLAG(bgp
->flags
,
2363 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2365 rmap_path
.attr
= &dummy_attr
;
2368 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2370 if (bgp_path_suppressed(pi
))
2371 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2374 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2377 bgp_attr_flush(&dummy_attr
);
2378 peer
->rmap_type
= 0;
2380 if (ret
== RMAP_DENYMATCH
) {
2381 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2383 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2384 peer
, p
, ROUTE_MAP_OUT_NAME(filter
));
2385 bgp_attr_flush(rmap_path
.attr
);
2390 /* RFC 8212 to prevent route leaks.
2391 * This specification intends to improve this situation by requiring the
2392 * explicit configuration of both BGP Import and Export Policies for any
2393 * External BGP (EBGP) session such as customers, peers, or
2394 * confederation boundaries for all enabled address families. Through
2395 * codification of the aforementioned requirement, operators will
2396 * benefit from consistent behavior across different BGP
2399 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2400 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2401 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2402 NULL
) > FIFTEENMINUTE2USEC
||
2403 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2405 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2406 monotime(&bgp
->ebgprequirespolicywarning
);
2411 /* draft-ietf-idr-deprecate-as-set-confed-set
2412 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2413 * Eventually, This document (if approved) updates RFC 4271
2414 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2415 * and obsoletes RFC 6472.
2417 if (peer
->bgp
->reject_as_sets
)
2418 if (aspath_check_as_sets(attr
->aspath
))
2421 /* If neighbor sso is configured, then check if the route has
2422 * SoO extended community and validate against the configured
2423 * one. If they match, do not announce, to prevent routing
2426 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2427 peer
->soo
[afi
][safi
]) {
2428 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2429 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2431 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2432 ECOMMUNITY_SITE_ORIGIN
) ||
2433 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2434 ECOMMUNITY_SITE_ORIGIN
)) &&
2435 ecommunity_include(ecomm
, ecomm_soo
)) {
2436 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2438 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2439 peer
, p
, ecommunity_str(ecomm_soo
));
2444 /* Codification of AS 0 Processing */
2445 if (aspath_check_as_zero(attr
->aspath
))
2448 if (bgp_in_graceful_shutdown(bgp
)) {
2449 if (peer
->sort
== BGP_PEER_IBGP
2450 || peer
->sort
== BGP_PEER_CONFED
) {
2451 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2452 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2454 bgp_attr_add_gshut_community(attr
);
2458 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2459 * Capability" to a neighbor MUST perform the following upon receiving
2460 * a route from that neighbor with the "LLGR_STALE" community, or upon
2461 * attaching the "LLGR_STALE" community itself per Section 4.2:
2463 * The route SHOULD NOT be advertised to any neighbor from which the
2464 * Long-lived Graceful Restart Capability has not been received.
2466 if (bgp_attr_get_community(attr
) &&
2467 community_include(bgp_attr_get_community(attr
),
2468 COMMUNITY_LLGR_STALE
) &&
2469 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2470 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2473 /* After route-map has been applied, we check to see if the nexthop to
2474 * be carried in the attribute (that is used for the announcement) can
2475 * be cleared off or not. We do this in all cases where we would be
2476 * setting the nexthop to "ourselves". For IPv6, we only need to
2478 * the global nexthop here; the link-local nexthop would have been
2480 * already, and if not, it is required by the update formation code.
2481 * Also see earlier comments in this function.
2484 * If route-map has performed some operation on the nexthop or the peer
2485 * configuration says to pass it unchanged, we cannot reset the nexthop
2486 * here, so only attempt to do it if these aren't true. Note that the
2487 * route-map handler itself might have cleared the nexthop, if for
2489 * it is configured as 'peer-address'.
2491 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2492 piattr
->rmap_change_flags
)
2494 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2495 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2496 /* We can reset the nexthop, if setting (or forcing) it to
2498 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2499 PEER_FLAG_NEXTHOP_SELF
)
2500 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2501 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2503 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2504 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2505 subgroup_announce_reset_nhop(
2506 (peer_cap_enhe(peer
, afi
, safi
)
2512 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2513 /* Can also reset the nexthop if announcing to EBGP, but
2515 * no peer in the subgroup is on a shared subnet.
2516 * Note: 3rd party nexthop currently implemented for
2519 if ((p
->family
== AF_INET
) &&
2520 (!bgp_subgrp_multiaccess_check_v4(
2523 subgroup_announce_reset_nhop(
2524 (peer_cap_enhe(peer
, afi
, safi
)
2531 if ((p
->family
== AF_INET6
) &&
2532 (!bgp_subgrp_multiaccess_check_v6(
2533 piattr
->mp_nexthop_global
,
2535 subgroup_announce_reset_nhop(
2536 (peer_cap_enhe(peer
, afi
, safi
)
2545 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2547 * This flag is used for leaked vpn-vrf routes
2549 int family
= p
->family
;
2551 if (peer_cap_enhe(peer
, afi
, safi
))
2554 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2556 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2557 __func__
, family2str(family
));
2558 subgroup_announce_reset_nhop(family
, attr
);
2563 /* If IPv6/MP and nexthop does not have any override and happens
2565 * be a link-local address, reset it so that we don't pass along
2567 * source's link-local IPv6 address to recipients who may not be
2569 * the same interface.
2571 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2572 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2573 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2578 /* If this is an iBGP, send Origin Validation State (OVS)
2579 * extended community (rfc8097).
2581 if (peer
->sort
== BGP_PEER_IBGP
) {
2582 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2584 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2586 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2587 bgp_attr_set_ecommunity(
2588 attr
, ecommunity_add_origin_validation_state(
2590 bgp_attr_get_ecommunity(attr
)));
2594 * When the next hop is set to ourselves, if all multipaths have
2595 * link-bandwidth announce the cumulative bandwidth as that makes
2596 * the most sense. However, don't modify if the link-bandwidth has
2597 * been explicitly set by user policy.
2600 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2601 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2602 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2603 bgp_attr_set_ecommunity(
2605 ecommunity_replace_linkbw(
2606 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2609 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2614 static void bgp_route_select_timer_expire(struct thread
*thread
)
2616 struct afi_safi_info
*info
;
2621 info
= THREAD_ARG(thread
);
2626 if (BGP_DEBUG(update
, UPDATE_OUT
))
2627 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2630 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2632 XFREE(MTYPE_TMP
, info
);
2634 /* Best path selection */
2635 bgp_best_path_select_defer(bgp
, afi
, safi
);
2638 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2639 struct bgp_maxpaths_cfg
*mpath_cfg
,
2640 struct bgp_path_info_pair
*result
, afi_t afi
,
2643 struct bgp_path_info
*new_select
;
2644 struct bgp_path_info
*old_select
;
2645 struct bgp_path_info
*pi
;
2646 struct bgp_path_info
*pi1
;
2647 struct bgp_path_info
*pi2
;
2648 struct bgp_path_info
*nextpi
= NULL
;
2649 int paths_eq
, do_mpath
, debug
;
2650 struct list mp_list
;
2651 char pfx_buf
[PREFIX2STR_BUFFER
];
2652 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2654 bgp_mp_list_init(&mp_list
);
2656 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2658 debug
= bgp_debug_bestpath(dest
);
2661 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2663 dest
->reason
= bgp_path_selection_none
;
2664 /* bgp deterministic-med */
2666 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2668 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2669 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2671 bgp_path_info_unset_flag(dest
, pi1
,
2672 BGP_PATH_DMED_SELECTED
);
2674 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2676 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2678 if (BGP_PATH_HOLDDOWN(pi1
))
2680 if (pi1
->peer
!= bgp
->peer_self
)
2681 if (!peer_established(pi1
->peer
))
2686 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2687 if (CHECK_FLAG(pi2
->flags
,
2688 BGP_PATH_DMED_CHECK
))
2690 if (BGP_PATH_HOLDDOWN(pi2
))
2692 if (pi2
->peer
!= bgp
->peer_self
2695 PEER_STATUS_NSF_WAIT
))
2696 if (pi2
->peer
->status
2700 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2702 && !aspath_cmp_left_confed(
2707 if (bgp_path_info_cmp(
2708 bgp
, pi2
, new_select
,
2709 &paths_eq
, mpath_cfg
, debug
,
2712 bgp_path_info_unset_flag(
2714 BGP_PATH_DMED_SELECTED
);
2718 bgp_path_info_set_flag(
2719 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2722 bgp_path_info_set_flag(dest
, new_select
,
2723 BGP_PATH_DMED_CHECK
);
2724 bgp_path_info_set_flag(dest
, new_select
,
2725 BGP_PATH_DMED_SELECTED
);
2728 bgp_path_info_path_with_addpath_rx_str(
2729 new_select
, path_buf
, sizeof(path_buf
));
2731 "%pBD(%s): %s is the bestpath from AS %u",
2732 dest
, bgp
->name_pretty
, path_buf
,
2733 aspath_get_first_as(
2734 new_select
->attr
->aspath
));
2739 /* Check old selected route and new selected route. */
2742 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2743 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2744 enum bgp_path_selection_reason reason
;
2746 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2749 if (BGP_PATH_HOLDDOWN(pi
)) {
2750 /* reap REMOVED routes, if needs be
2751 * selected route must stay for a while longer though
2753 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2754 && (pi
!= old_select
))
2755 bgp_path_info_reap(dest
, pi
);
2758 zlog_debug("%s: pi %p in holddown", __func__
,
2764 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2765 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2766 if (!peer_established(pi
->peer
)) {
2770 "%s: pi %p non self peer %s not estab state",
2771 __func__
, pi
, pi
->peer
->host
);
2776 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2777 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2778 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2780 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2784 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2786 reason
= dest
->reason
;
2787 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2788 debug
, pfx_buf
, afi
, safi
,
2790 if (new_select
== NULL
&&
2791 reason
!= bgp_path_selection_none
)
2792 dest
->reason
= reason
;
2797 /* Now that we know which path is the bestpath see if any of the other
2799 * qualify as multipaths
2803 bgp_path_info_path_with_addpath_rx_str(
2804 new_select
, path_buf
, sizeof(path_buf
));
2806 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2808 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2809 dest
, bgp
->name_pretty
, path_buf
,
2810 old_select
? old_select
->peer
->host
: "NONE");
2813 if (do_mpath
&& new_select
) {
2814 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2815 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2818 bgp_path_info_path_with_addpath_rx_str(
2819 pi
, path_buf
, sizeof(path_buf
));
2821 if (pi
== new_select
) {
2824 "%pBD(%s): %s is the bestpath, add to the multipath list",
2825 dest
, bgp
->name_pretty
,
2827 bgp_mp_list_add(&mp_list
, pi
);
2831 if (BGP_PATH_HOLDDOWN(pi
))
2834 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2835 && !CHECK_FLAG(pi
->peer
->sflags
,
2836 PEER_STATUS_NSF_WAIT
))
2837 if (!peer_established(pi
->peer
))
2840 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2843 "%pBD: %s has the same nexthop as the bestpath, skip it",
2848 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2849 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2855 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2857 bgp_mp_list_add(&mp_list
, pi
);
2862 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2864 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2865 bgp_mp_list_clear(&mp_list
);
2867 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2869 result
->old
= old_select
;
2870 result
->new = new_select
;
2876 * A new route/change in bestpath of an existing route. Evaluate the path
2877 * for advertisement to the subgroup.
2879 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2880 struct bgp_path_info
*selected
,
2881 struct bgp_dest
*dest
,
2882 uint32_t addpath_tx_id
)
2884 const struct prefix
*p
;
2885 struct peer
*onlypeer
;
2892 p
= bgp_dest_get_prefix(dest
);
2893 afi
= SUBGRP_AFI(subgrp
);
2894 safi
= SUBGRP_SAFI(subgrp
);
2895 bgp
= SUBGRP_INST(subgrp
);
2896 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2899 if (BGP_DEBUG(update
, UPDATE_OUT
))
2900 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2902 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2903 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2904 PEER_STATUS_ORF_WAIT_REFRESH
))
2907 memset(&attr
, 0, sizeof(attr
));
2908 /* It's initialized in bgp_announce_check() */
2910 /* Announcement to the subgroup. If the route is filtered withdraw it.
2911 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2912 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2915 advertise
= bgp_check_advertise(bgp
, dest
);
2918 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2920 /* Route is selected, if the route is already installed
2921 * in FIB, then it is advertised
2924 if (!bgp_check_withdrawal(bgp
, dest
))
2925 bgp_adj_out_set_subgroup(
2926 dest
, subgrp
, &attr
, selected
);
2928 bgp_adj_out_unset_subgroup(
2929 dest
, subgrp
, 1, addpath_tx_id
);
2932 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2936 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2938 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2943 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2944 * This is called at the end of route processing.
2946 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2948 struct bgp_path_info
*pi
;
2950 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2951 if (BGP_PATH_HOLDDOWN(pi
))
2953 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2954 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2959 * Has the route changed from the RIB's perspective? This is invoked only
2960 * if the route selection returns the same best route as earlier - to
2961 * determine if we need to update zebra or not.
2963 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2965 struct bgp_path_info
*mpinfo
;
2967 /* If this is multipath, check all selected paths for any nexthop
2968 * change or attribute change. Some attribute changes (e.g., community)
2969 * aren't of relevance to the RIB, but we'll update zebra to ensure
2970 * we handle the case of BGP nexthop change. This is the behavior
2971 * when the best path has an attribute change anyway.
2973 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2974 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2975 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2979 * If this is multipath, check all selected paths for any nexthop change
2981 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2982 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2983 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2984 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2988 /* Nothing has changed from the RIB's perspective. */
2992 struct bgp_process_queue
{
2994 STAILQ_HEAD(, bgp_dest
) pqueue
;
2995 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2997 unsigned int queued
;
3000 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
3001 safi_t safi
, struct bgp_dest
*dest
,
3002 struct bgp_path_info
*new_select
,
3003 struct bgp_path_info
*old_select
)
3005 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3007 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
3010 if (advertise_type5_routes(bgp
, afi
) && new_select
3011 && is_route_injectable_into_evpn(new_select
)) {
3013 /* apply the route-map */
3014 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
3015 route_map_result_t ret
;
3016 struct bgp_path_info rmap_path
;
3017 struct bgp_path_info_extra rmap_path_extra
;
3018 struct attr dummy_attr
;
3020 dummy_attr
= *new_select
->attr
;
3022 /* Fill temp path_info */
3023 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3024 new_select
, new_select
->peer
,
3027 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3029 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3032 if (ret
== RMAP_DENYMATCH
) {
3033 bgp_attr_flush(&dummy_attr
);
3034 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3037 bgp_evpn_advertise_type5_route(
3038 bgp
, p
, &dummy_attr
, afi
, safi
);
3040 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3043 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3044 && is_route_injectable_into_evpn(old_select
))
3045 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3049 * Utility to determine whether a particular path_info should use
3050 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3051 * in a path where we basically _know_ this is a BGP-LU route.
3053 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
3055 /* Certain types get imp null; so do paths where the nexthop is
3058 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3059 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3060 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3062 else if (new_select
->extra
== NULL
||
3063 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
3064 /* TODO -- should be configurable? */
3071 * old_select = The old best path
3072 * new_select = the new best path
3074 * if (!old_select && new_select)
3075 * We are sending new information on.
3077 * if (old_select && new_select) {
3078 * if (new_select != old_select)
3079 * We have a new best path send a change
3081 * We've received a update with new attributes that needs
3085 * if (old_select && !new_select)
3086 * We have no eligible route that we can announce or the rn
3089 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3090 afi_t afi
, safi_t safi
)
3092 struct bgp_path_info
*new_select
;
3093 struct bgp_path_info
*old_select
;
3094 struct bgp_path_info_pair old_and_new
;
3097 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3099 debug
= bgp_debug_bestpath(dest
);
3102 "%s: bgp delete in progress, ignoring event, p=%pBD",
3106 /* Is it end of initial update? (after startup) */
3108 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3109 sizeof(bgp
->update_delay_zebra_resume_time
));
3111 bgp
->main_zebra_update_hold
= 0;
3112 FOREACH_AFI_SAFI (afi
, safi
) {
3113 if (bgp_fibupd_safi(safi
))
3114 bgp_zebra_announce_table(bgp
, afi
, safi
);
3116 bgp
->main_peers_update_hold
= 0;
3118 bgp_start_routeadv(bgp
);
3122 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3124 debug
= bgp_debug_bestpath(dest
);
3126 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__
,
3127 dest
, bgp
->name_pretty
, afi2str(afi
),
3130 /* The best path calculation for the route is deferred if
3131 * BGP_NODE_SELECT_DEFER is set
3133 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3134 if (BGP_DEBUG(update
, UPDATE_OUT
))
3135 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
3139 /* Best path selection. */
3140 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3142 old_select
= old_and_new
.old
;
3143 new_select
= old_and_new
.new;
3145 /* Do we need to allocate or free labels?
3146 * Right now, since we only deal with per-prefix labels, it is not
3147 * necessary to do this upon changes to best path. Exceptions:
3148 * - label index has changed -> recalculate resulting label
3149 * - path_info sub_type changed -> switch to/from implicit-null
3150 * - no valid label (due to removed static label binding) -> get new one
3152 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3155 || bgp_label_index_differs(new_select
, old_select
)
3156 || new_select
->sub_type
!= old_select
->sub_type
3157 || !bgp_is_valid_label(&dest
->local_label
)) {
3158 /* Enforced penultimate hop popping:
3159 * implicit-null for local routes, aggregate
3160 * and redistributed routes
3162 if (bgp_lu_need_imp_null(new_select
)) {
3165 BGP_NODE_REGISTERED_FOR_LABEL
)
3168 BGP_NODE_LABEL_REQUESTED
))
3169 bgp_unregister_for_label(dest
);
3170 dest
->local_label
= mpls_lse_encode(
3171 MPLS_LABEL_IMPLICIT_NULL
, 0, 0,
3173 bgp_set_valid_label(&dest
->local_label
);
3175 bgp_register_for_label(dest
,
3178 } else if (CHECK_FLAG(dest
->flags
,
3179 BGP_NODE_REGISTERED_FOR_LABEL
)
3180 || CHECK_FLAG(dest
->flags
,
3181 BGP_NODE_LABEL_REQUESTED
)) {
3182 bgp_unregister_for_label(dest
);
3184 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3185 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3186 bgp_unregister_for_label(dest
);
3191 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3192 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3193 safi2str(safi
), old_select
, new_select
);
3195 /* If best route remains the same and this is not due to user-initiated
3196 * clear, see exactly what needs to be done.
3198 if (old_select
&& old_select
== new_select
3199 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3200 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3201 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3202 if (bgp_zebra_has_route_changed(old_select
)) {
3203 #ifdef ENABLE_BGP_VNC
3204 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3205 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3207 if (bgp_fibupd_safi(safi
)
3208 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3210 if (BGP_SUPPRESS_FIB_ENABLED(bgp
)
3211 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
3212 SET_FLAG(dest
->flags
,
3213 BGP_NODE_FIB_INSTALL_PENDING
);
3215 if (new_select
->type
== ZEBRA_ROUTE_BGP
3216 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3217 || new_select
->sub_type
3218 == BGP_ROUTE_IMPORTED
))
3220 bgp_zebra_announce(dest
, p
, old_select
,
3225 /* If there is a change of interest to peers, reannounce the
3227 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3228 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3229 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3230 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3232 /* unicast routes must also be annouced to
3233 * labeled-unicast update-groups */
3234 if (safi
== SAFI_UNICAST
)
3235 group_announce_route(bgp
, afi
,
3236 SAFI_LABELED_UNICAST
, dest
,
3239 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3240 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3243 /* advertise/withdraw type-5 routes */
3244 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3245 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3246 bgp_process_evpn_route_injection(
3247 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3249 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3250 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3251 bgp_zebra_clear_route_change_flags(dest
);
3252 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3256 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3258 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3260 /* bestpath has changed; bump version */
3261 if (old_select
|| new_select
) {
3262 bgp_bump_version(dest
);
3264 if (!bgp
->t_rmap_def_originate_eval
) {
3268 update_group_refresh_default_originate_route_map
,
3269 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3270 &bgp
->t_rmap_def_originate_eval
);
3275 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3278 zlog_debug("%s: setting SELECTED flag", __func__
);
3279 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3280 bgp_path_info_unset_flag(dest
, new_select
,
3281 BGP_PATH_ATTR_CHANGED
);
3282 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3283 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3286 #ifdef ENABLE_BGP_VNC
3287 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3288 if (old_select
!= new_select
) {
3290 vnc_import_bgp_exterior_del_route(bgp
, p
,
3292 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3295 vnc_import_bgp_exterior_add_route(bgp
, p
,
3297 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3303 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3305 /* unicast routes must also be annouced to labeled-unicast update-groups
3307 if (safi
== SAFI_UNICAST
)
3308 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3312 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3313 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3315 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3316 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3317 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3318 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3320 if (BGP_SUPPRESS_FIB_ENABLED(bgp
))
3321 SET_FLAG(dest
->flags
,
3322 BGP_NODE_FIB_INSTALL_PENDING
);
3324 /* if this is an evpn imported type-5 prefix,
3325 * we need to withdraw the route first to clear
3326 * the nh neigh and the RMAC entry.
3329 is_route_parent_evpn(old_select
))
3330 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3332 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3334 /* Withdraw the route from the kernel. */
3335 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3336 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3337 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3338 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3340 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3344 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3347 /* Clear any route change flags. */
3348 bgp_zebra_clear_route_change_flags(dest
);
3350 /* Reap old select bgp_path_info, if it has been removed */
3351 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3352 bgp_path_info_reap(dest
, old_select
);
3354 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3358 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3359 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3361 struct bgp_dest
*dest
;
3363 struct afi_safi_info
*thread_info
;
3365 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3366 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3368 thread_info
= THREAD_ARG(t
);
3369 XFREE(MTYPE_TMP
, thread_info
);
3370 THREAD_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3373 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3374 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3375 get_afi_safi_str(afi
, safi
, false),
3376 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3379 /* Process the route list */
3380 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3381 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3382 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3383 dest
= bgp_route_next(dest
)) {
3384 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3387 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3388 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3389 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3392 /* If iteration stopped before the entire table was traversed then the
3393 * node needs to be unlocked.
3396 bgp_dest_unlock_node(dest
);
3400 /* Send EOR message when all routes are processed */
3401 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3402 bgp_send_delayed_eor(bgp
);
3403 /* Send route processing complete message to RIB */
3404 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3405 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3409 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3411 thread_info
->afi
= afi
;
3412 thread_info
->safi
= safi
;
3413 thread_info
->bgp
= bgp
;
3415 /* If there are more routes to be processed, start the
3418 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3419 BGP_ROUTE_SELECT_DELAY
,
3420 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3423 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3425 struct bgp_process_queue
*pqnode
= data
;
3426 struct bgp
*bgp
= pqnode
->bgp
;
3427 struct bgp_table
*table
;
3428 struct bgp_dest
*dest
;
3431 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3432 bgp_process_main_one(bgp
, NULL
, 0, 0);
3433 /* should always have dedicated wq call */
3434 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3438 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3439 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3440 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3441 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3442 table
= bgp_dest_table(dest
);
3443 /* note, new DESTs may be added as part of processing */
3444 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3446 bgp_dest_unlock_node(dest
);
3447 bgp_table_unlock(table
);
3453 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3455 struct bgp_process_queue
*pqnode
= data
;
3457 bgp_unlock(pqnode
->bgp
);
3459 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3462 void bgp_process_queue_init(struct bgp
*bgp
)
3464 if (!bgp
->process_queue
) {
3467 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3468 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3471 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3472 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3473 bgp
->process_queue
->spec
.max_retries
= 0;
3474 bgp
->process_queue
->spec
.hold
= 50;
3475 /* Use a higher yield value of 50ms for main queue processing */
3476 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3479 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3481 struct bgp_process_queue
*pqnode
;
3483 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3484 sizeof(struct bgp_process_queue
));
3486 /* unlocked in bgp_processq_del */
3487 pqnode
->bgp
= bgp_lock(bgp
);
3488 STAILQ_INIT(&pqnode
->pqueue
);
3493 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3495 #define ARBITRARY_PROCESS_QLEN 10000
3496 struct work_queue
*wq
= bgp
->process_queue
;
3497 struct bgp_process_queue
*pqnode
;
3498 int pqnode_reuse
= 0;
3500 /* already scheduled for processing? */
3501 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3504 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3507 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3508 if (BGP_DEBUG(update
, UPDATE_OUT
))
3509 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3514 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3515 if (BGP_DEBUG(update
, UPDATE_OUT
))
3517 "Soft reconfigure table in progress for route %p",
3525 /* Add route nodes to an existing work queue item until reaching the
3526 limit only if is from the same BGP view and it's not an EOIU marker
3528 if (work_queue_item_count(wq
)) {
3529 struct work_queue_item
*item
= work_queue_last_item(wq
);
3530 pqnode
= item
->data
;
3532 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3533 || pqnode
->bgp
!= bgp
3534 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3535 pqnode
= bgp_processq_alloc(bgp
);
3539 pqnode
= bgp_processq_alloc(bgp
);
3540 /* all unlocked in bgp_process_wq */
3541 bgp_table_lock(bgp_dest_table(dest
));
3543 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3544 bgp_dest_lock_node(dest
);
3546 /* can't be enqueued twice */
3547 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3548 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3552 work_queue_add(wq
, pqnode
);
3557 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3559 struct bgp_process_queue
*pqnode
;
3561 if (bgp
->process_queue
== NULL
)
3564 pqnode
= bgp_processq_alloc(bgp
);
3566 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3567 work_queue_add(bgp
->process_queue
, pqnode
);
3570 static void bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3574 peer
= THREAD_ARG(thread
);
3575 peer
->t_pmax_restart
= NULL
;
3577 if (bgp_debug_neighbor_events(peer
))
3579 "%s Maximum-prefix restart timer expired, restore peering",
3582 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3583 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3586 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3590 bool filtered
= false;
3591 struct bgp_dest
*dest
;
3592 struct bgp_adj_in
*ain
;
3593 struct attr attr
= {};
3594 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3596 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3597 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3598 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3602 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3606 if (bgp_input_modifier(
3607 peer
, rn_p
, &attr
, afi
, safi
,
3608 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3616 bgp_attr_flush(&attr
);
3623 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3627 iana_safi_t pkt_safi
;
3628 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3629 PEER_FLAG_MAX_PREFIX_FORCE
))
3630 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3631 + peer
->pcount
[afi
][safi
]
3632 : peer
->pcount
[afi
][safi
];
3634 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3637 if (pcount
> peer
->pmax
[afi
][safi
]) {
3638 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3639 PEER_STATUS_PREFIX_LIMIT
)
3644 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3645 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3646 peer
->pmax
[afi
][safi
]);
3647 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3649 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3650 PEER_FLAG_MAX_PREFIX_WARNING
))
3653 /* Convert AFI, SAFI to values for packet. */
3654 pkt_afi
= afi_int2iana(afi
);
3655 pkt_safi
= safi_int2iana(safi
);
3659 ndata
[0] = (pkt_afi
>> 8);
3661 ndata
[2] = pkt_safi
;
3662 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3663 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3664 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3665 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3667 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3668 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3669 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3673 /* Dynamic peers will just close their connection. */
3674 if (peer_dynamic_neighbor(peer
))
3677 /* restart timer start */
3678 if (peer
->pmax_restart
[afi
][safi
]) {
3679 peer
->v_pmax_restart
=
3680 peer
->pmax_restart
[afi
][safi
] * 60;
3682 if (bgp_debug_neighbor_events(peer
))
3684 "%pBP Maximum-prefix restart timer started for %d secs",
3685 peer
, peer
->v_pmax_restart
);
3687 BGP_TIMER_ON(peer
->t_pmax_restart
,
3688 bgp_maximum_prefix_restart_timer
,
3689 peer
->v_pmax_restart
);
3694 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3695 PEER_STATUS_PREFIX_LIMIT
);
3698 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3699 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3700 PEER_STATUS_PREFIX_THRESHOLD
)
3705 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3706 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3707 peer
->pmax
[afi
][safi
]);
3708 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3709 PEER_STATUS_PREFIX_THRESHOLD
);
3711 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3712 PEER_STATUS_PREFIX_THRESHOLD
);
3716 /* Unconditionally remove the route from the RIB, without taking
3717 * damping into consideration (eg, because the session went down)
3719 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3720 struct peer
*peer
, afi_t afi
, safi_t safi
)
3723 struct bgp
*bgp
= NULL
;
3724 bool delete_route
= false;
3726 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3729 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3730 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3732 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3735 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3736 delete_route
= true;
3737 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3738 delete_route
= true;
3740 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3741 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3742 bgp
= pi
->peer
->bgp
;
3743 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3748 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3749 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3752 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3753 struct peer
*peer
, afi_t afi
, safi_t safi
,
3754 struct prefix_rd
*prd
)
3756 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3758 /* apply dampening, if result is suppressed, we'll be retaining
3759 * the bgp_path_info in the RIB for historical reference.
3761 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3762 && peer
->sort
== BGP_PEER_EBGP
)
3763 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3764 == BGP_DAMP_SUPPRESSED
) {
3765 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3770 #ifdef ENABLE_BGP_VNC
3771 if (safi
== SAFI_MPLS_VPN
) {
3772 struct bgp_dest
*pdest
= NULL
;
3773 struct bgp_table
*table
= NULL
;
3775 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3776 (struct prefix
*)prd
);
3777 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3778 table
= bgp_dest_get_bgp_table_info(pdest
);
3780 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3781 peer
->bgp
, prd
, table
, p
, pi
);
3783 bgp_dest_unlock_node(pdest
);
3785 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3786 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3788 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3789 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3794 /* If this is an EVPN route, process for un-import. */
3795 if (safi
== SAFI_EVPN
)
3796 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3798 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3801 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3802 struct peer
*peer
, struct attr
*attr
,
3803 struct bgp_dest
*dest
)
3805 struct bgp_path_info
*new;
3807 /* Make new BGP info. */
3808 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3810 new->instance
= instance
;
3811 new->sub_type
= sub_type
;
3814 new->uptime
= monotime(NULL
);
3819 /* Check if received nexthop is valid or not. */
3820 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3821 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3822 struct bgp_dest
*dest
)
3825 bool is_bgp_static_route
=
3826 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3830 * Only validated for unicast and multicast currently.
3831 * Also valid for EVPN where the nexthop is an IP address.
3832 * If we are a bgp static route being checked then there is
3833 * no need to check to see if the nexthop is martian as
3834 * that it should be ok.
3836 if (is_bgp_static_route
||
3837 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3840 /* If NEXT_HOP is present, validate it. */
3841 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3842 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3843 !ipv4_unicast_valid(&attr
->nexthop
) ||
3844 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3848 /* If MP_NEXTHOP is present, validate it. */
3849 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3850 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3851 * it is not an IPv6 link-local address.
3853 * If we receive an UPDATE with nexthop length set to 32 bytes
3854 * we shouldn't discard an UPDATE if it's set to (::).
3855 * The link-local (2st) is validated along the code path later.
3857 if (attr
->mp_nexthop_len
) {
3858 switch (attr
->mp_nexthop_len
) {
3859 case BGP_ATTR_NHLEN_IPV4
:
3860 case BGP_ATTR_NHLEN_VPNV4
:
3861 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3863 !ipv4_unicast_valid(
3864 &attr
->mp_nexthop_global_in
) ||
3865 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3869 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3870 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3871 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3872 &attr
->mp_nexthop_global
)
3873 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3874 || IN6_IS_ADDR_MULTICAST(
3875 &attr
->mp_nexthop_global
)
3876 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3879 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3880 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3881 || IN6_IS_ADDR_MULTICAST(
3882 &attr
->mp_nexthop_global
)
3883 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3896 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3898 struct community
*old
;
3899 struct community
*new;
3900 struct community
*merge
;
3901 struct community
*no_export
;
3903 old
= bgp_attr_get_community(attr
);
3904 no_export
= community_str2com("no-export");
3909 merge
= community_merge(community_dup(old
), no_export
);
3912 community_free(&old
);
3914 new = community_uniq_sort(merge
);
3915 community_free(&merge
);
3917 new = community_dup(no_export
);
3920 community_free(&no_export
);
3922 bgp_attr_set_community(attr
, new);
3925 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3926 struct attr
*attr
, const struct prefix
*prefix
,
3929 struct listnode
*node
, *nnode
;
3931 bool accept_own_found
= false;
3933 if (safi
!= SAFI_MPLS_VPN
)
3936 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3937 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3940 /* The route in question carries the ACCEPT_OWN community */
3941 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3942 struct community
*comm
= bgp_attr_get_community(attr
);
3944 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3945 accept_own_found
= true;
3948 /* The route in question is targeted to one or more destination VRFs
3949 * on the router (as determined by inspecting the Route Target(s)).
3951 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3952 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3955 if (accept_own_found
&&
3957 bgp
->vpn_policy
[afi
]
3958 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3959 bgp_attr_get_ecommunity(attr
))) {
3960 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3962 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3965 /* Treat this route as imported, because it's leaked
3966 * already from another VRF, and we got an updated
3967 * version from route-reflector with ACCEPT_OWN
3970 *sub_type
= BGP_ROUTE_IMPORTED
;
3979 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3980 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3981 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3982 uint32_t num_labels
, int soft_reconfig
,
3983 struct bgp_route_evpn
*evpn
)
3986 int aspath_loop_count
= 0;
3987 struct bgp_dest
*dest
;
3989 struct attr new_attr
;
3990 struct attr
*attr_new
;
3991 struct bgp_path_info
*pi
;
3992 struct bgp_path_info
*new;
3993 struct bgp_path_info_extra
*extra
;
3995 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3997 int do_loop_check
= 1;
3998 int has_valid_label
= 0;
4000 bool force_evpn_import
= false;
4001 safi_t orig_safi
= safi
;
4002 bool leak_success
= true;
4005 if (frrtrace_enabled(frr_bgp
, process_update
)) {
4006 char pfxprint
[PREFIX2STR_BUFFER
];
4008 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
4009 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
4013 #ifdef ENABLE_BGP_VNC
4014 int vnc_implicit_withdraw
= 0;
4018 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4019 if (orig_safi
== SAFI_LABELED_UNICAST
)
4020 safi
= SAFI_UNICAST
;
4022 memset(&new_attr
, 0, sizeof(new_attr
));
4023 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4024 new_attr
.label
= MPLS_INVALID_LABEL
;
4027 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4028 /* TODO: Check to see if we can get rid of "is_valid_label" */
4029 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4030 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4032 has_valid_label
= bgp_is_valid_label(label
);
4034 if (has_valid_label
)
4035 assert(label
!= NULL
);
4037 /* Update overlay index of the attribute */
4038 if (afi
== AFI_L2VPN
&& evpn
)
4039 memcpy(&attr
->evpn_overlay
, evpn
,
4040 sizeof(struct bgp_route_evpn
));
4042 /* When peer's soft reconfiguration enabled. Record input packet in
4045 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4046 && peer
!= bgp
->peer_self
)
4047 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4049 /* Update permitted loop count */
4050 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4051 allowas_in
= peer
->allowas_in
[afi
][safi
];
4053 /* Check previously received route. */
4054 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4055 if (pi
->peer
== peer
&& pi
->type
== type
4056 && pi
->sub_type
== sub_type
4057 && pi
->addpath_rx_id
== addpath_id
)
4060 /* AS path local-as loop check. */
4061 if (peer
->change_local_as
) {
4063 aspath_loop_count
= allowas_in
;
4064 else if (!CHECK_FLAG(peer
->flags
,
4065 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4066 aspath_loop_count
= 1;
4068 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4069 > aspath_loop_count
) {
4070 peer
->stat_pfx_aspath_loop
++;
4071 reason
= "as-path contains our own AS;";
4076 /* If the peer is configured for "allowas-in origin" and the last ASN in
4078 * as-path is our ASN then we do not need to call aspath_loop_check
4080 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4081 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4084 /* AS path loop check. */
4085 if (do_loop_check
) {
4086 if (aspath_loop_check(attr
->aspath
, bgp
->as
) > allowas_in
||
4087 (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) &&
4088 (aspath_loop_check(attr
->aspath
, bgp
->confed_id
) >
4090 peer
->stat_pfx_aspath_loop
++;
4091 reason
= "as-path contains our own AS;";
4096 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4097 * enabled, then take care of that too.
4099 bool accept_own
= false;
4101 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4102 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4104 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4106 peer
->stat_pfx_originator_loop
++;
4107 reason
= "originator is us;";
4112 /* Route reflector cluster ID check. */
4113 if (bgp_cluster_filter(peer
, attr
)) {
4114 peer
->stat_pfx_cluster_loop
++;
4115 reason
= "reflected from the same cluster;";
4119 /* Apply incoming filter. */
4120 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4121 peer
->stat_pfx_filter
++;
4126 /* RFC 8212 to prevent route leaks.
4127 * This specification intends to improve this situation by requiring the
4128 * explicit configuration of both BGP Import and Export Policies for any
4129 * External BGP (EBGP) session such as customers, peers, or
4130 * confederation boundaries for all enabled address families. Through
4131 * codification of the aforementioned requirement, operators will
4132 * benefit from consistent behavior across different BGP
4135 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4136 if (!bgp_inbound_policy_exists(peer
,
4137 &peer
->filter
[afi
][safi
])) {
4138 reason
= "inbound policy missing";
4139 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4140 NULL
) > FIFTEENMINUTE2USEC
||
4141 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4143 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4144 monotime(&bgp
->ebgprequirespolicywarning
);
4149 /* draft-ietf-idr-deprecate-as-set-confed-set
4150 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4151 * Eventually, This document (if approved) updates RFC 4271
4152 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4153 * and obsoletes RFC 6472.
4155 if (peer
->bgp
->reject_as_sets
)
4156 if (aspath_check_as_sets(attr
->aspath
)) {
4158 "as-path contains AS_SET or AS_CONFED_SET type;";
4164 /* Apply incoming route-map.
4165 * NB: new_attr may now contain newly allocated values from route-map
4167 * commands, so we need bgp_attr_flush in the error paths, until we
4169 * the attr (which takes over the memory references) */
4170 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4173 peer
->stat_pfx_filter
++;
4174 reason
= "route-map;";
4175 bgp_attr_flush(&new_attr
);
4179 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4180 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4181 /* remove from RIB previous entry */
4182 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4185 if (peer
->sort
== BGP_PEER_EBGP
) {
4188 * A BGP speaker receiving an announcement tagged with the
4189 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4190 * NO_EXPORT community as defined in RFC1997, or a
4191 * similar community, to prevent propagation of the
4192 * prefix outside the local AS. The community to prevent
4193 * propagation SHOULD be chosen according to the operator's
4196 if (bgp_attr_get_community(&new_attr
) &&
4197 community_include(bgp_attr_get_community(&new_attr
),
4198 COMMUNITY_BLACKHOLE
))
4199 bgp_attr_add_no_export_community(&new_attr
);
4201 /* If we receive the graceful-shutdown community from an eBGP
4202 * peer we must lower local-preference */
4203 if (bgp_attr_get_community(&new_attr
) &&
4204 community_include(bgp_attr_get_community(&new_attr
),
4206 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4207 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4209 /* If graceful-shutdown is configured then add the GSHUT
4210 * community to all paths received from eBGP peers */
4211 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
4212 bgp_attr_add_gshut_community(&new_attr
);
4215 /* next hop check. */
4216 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4217 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4219 peer
->stat_pfx_nh_invalid
++;
4220 reason
= "martian or self next-hop;";
4221 bgp_attr_flush(&new_attr
);
4225 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4226 peer
->stat_pfx_nh_invalid
++;
4227 reason
= "self mac;";
4228 bgp_attr_flush(&new_attr
);
4232 if (bgp_check_role_applicability(afi
, safi
) &&
4233 bgp_otc_filter(peer
, &new_attr
)) {
4234 reason
= "failing otc validation";
4235 bgp_attr_flush(&new_attr
);
4238 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4240 * Suppress fib is enabled
4241 * BGP_OPT_NO_FIB is not enabled
4242 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4243 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4245 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
4246 && (sub_type
== BGP_ROUTE_NORMAL
)
4247 && (!bgp_option_check(BGP_OPT_NO_FIB
))
4248 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
4249 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
4251 /* If maximum prefix count is configured and current prefix
4254 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4255 bgp_attr_flush(&new_attr
);
4259 /* If neighbor soo is configured, tag all incoming routes with
4260 * this SoO tag and then filter out advertisements in
4261 * subgroup_announce_check() if it matches the configured SoO
4262 * on the other peer.
4264 if (peer
->soo
[afi
][safi
]) {
4265 struct ecommunity
*old_ecomm
=
4266 bgp_attr_get_ecommunity(&new_attr
);
4267 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4268 struct ecommunity
*new_ecomm
;
4271 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4274 if (!old_ecomm
->refcnt
)
4275 ecommunity_free(&old_ecomm
);
4277 new_ecomm
= ecommunity_dup(ecomm_soo
);
4280 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4283 attr_new
= bgp_attr_intern(&new_attr
);
4285 /* If the update is implicit withdraw. */
4287 pi
->uptime
= monotime(NULL
);
4288 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4290 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4292 /* Same attribute comes in. */
4293 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4295 && (!has_valid_label
4296 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4297 num_labels
* sizeof(mpls_label_t
))
4299 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4300 BGP_CONFIG_DAMPENING
)
4301 && peer
->sort
== BGP_PEER_EBGP
4302 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4303 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4304 bgp_debug_rdpfxpath2str(
4305 afi
, safi
, prd
, p
, label
,
4306 num_labels
, addpath_id
? 1 : 0,
4307 addpath_id
, evpn
, pfx_buf
,
4309 zlog_debug("%pBP rcvd %s", peer
,
4313 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4314 != BGP_DAMP_SUPPRESSED
) {
4315 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4317 bgp_process(bgp
, dest
, afi
, safi
);
4319 } else /* Duplicate - odd */
4321 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4322 if (!peer
->rcvd_attr_printed
) {
4324 "%pBP rcvd UPDATE w/ attr: %s",
4326 peer
->rcvd_attr_str
);
4327 peer
->rcvd_attr_printed
= 1;
4330 bgp_debug_rdpfxpath2str(
4331 afi
, safi
, prd
, p
, label
,
4332 num_labels
, addpath_id
? 1 : 0,
4333 addpath_id
, evpn
, pfx_buf
,
4336 "%pBP rcvd %s...duplicate ignored",
4340 /* graceful restart STALE flag unset. */
4341 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4342 bgp_path_info_unset_flag(
4343 dest
, pi
, BGP_PATH_STALE
);
4344 bgp_dest_set_defer_flag(dest
, false);
4345 bgp_process(bgp
, dest
, afi
, safi
);
4349 bgp_dest_unlock_node(dest
);
4350 bgp_attr_unintern(&attr_new
);
4355 /* Withdraw/Announce before we fully processed the withdraw */
4356 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4357 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4358 bgp_debug_rdpfxpath2str(
4359 afi
, safi
, prd
, p
, label
, num_labels
,
4360 addpath_id
? 1 : 0, addpath_id
, evpn
,
4361 pfx_buf
, sizeof(pfx_buf
));
4363 "%pBP rcvd %s, flapped quicker than processing",
4367 bgp_path_info_restore(dest
, pi
);
4370 * If the BGP_PATH_REMOVED flag is set, then EVPN
4371 * routes would have been unimported already when a
4372 * prior BGP withdraw processing happened. Such routes
4373 * need to be imported again, so flag accordingly.
4375 force_evpn_import
= true;
4378 /* Received Logging. */
4379 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4380 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4381 num_labels
, addpath_id
? 1 : 0,
4382 addpath_id
, evpn
, pfx_buf
,
4384 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4387 /* graceful restart STALE flag unset. */
4388 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4389 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4390 bgp_dest_set_defer_flag(dest
, false);
4393 /* The attribute is changed. */
4394 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4396 /* implicit withdraw, decrement aggregate and pcount here.
4397 * only if update is accepted, they'll increment below.
4399 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4401 /* Update bgp route dampening information. */
4402 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4403 && peer
->sort
== BGP_PEER_EBGP
) {
4404 /* This is implicit withdraw so we should update
4407 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4408 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4410 #ifdef ENABLE_BGP_VNC
4411 if (safi
== SAFI_MPLS_VPN
) {
4412 struct bgp_dest
*pdest
= NULL
;
4413 struct bgp_table
*table
= NULL
;
4415 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4416 (struct prefix
*)prd
);
4417 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4418 table
= bgp_dest_get_bgp_table_info(pdest
);
4420 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4421 bgp
, prd
, table
, p
, pi
);
4423 bgp_dest_unlock_node(pdest
);
4425 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4426 && (safi
== SAFI_UNICAST
)) {
4427 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4429 * Implicit withdraw case.
4431 ++vnc_implicit_withdraw
;
4432 vnc_import_bgp_del_route(bgp
, p
, pi
);
4433 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4438 /* Special handling for EVPN update of an existing route. If the
4439 * extended community attribute has changed, we need to
4441 * the route using its existing extended community. It will be
4442 * subsequently processed for import with the new extended
4445 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4448 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4450 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4453 cmp
= ecommunity_cmp(
4454 bgp_attr_get_ecommunity(pi
->attr
),
4455 bgp_attr_get_ecommunity(attr_new
));
4457 if (bgp_debug_update(peer
, p
, NULL
, 1))
4459 "Change in EXT-COMM, existing %s new %s",
4461 bgp_attr_get_ecommunity(
4464 bgp_attr_get_ecommunity(
4466 if (safi
== SAFI_EVPN
)
4467 bgp_evpn_unimport_route(
4468 bgp
, afi
, safi
, p
, pi
);
4469 else /* SAFI_MPLS_VPN */
4470 vpn_leak_to_vrf_withdraw(bgp
,
4476 /* Update to new attribute. */
4477 bgp_attr_unintern(&pi
->attr
);
4478 pi
->attr
= attr_new
;
4480 /* Update MPLS label */
4481 if (has_valid_label
) {
4482 extra
= bgp_path_info_extra_get(pi
);
4483 if (extra
->label
!= label
) {
4484 memcpy(&extra
->label
, label
,
4485 num_labels
* sizeof(mpls_label_t
));
4486 extra
->num_labels
= num_labels
;
4488 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4489 bgp_set_valid_label(&extra
->label
[0]);
4492 /* Update SRv6 SID */
4493 if (attr
->srv6_l3vpn
) {
4494 extra
= bgp_path_info_extra_get(pi
);
4495 if (sid_diff(&extra
->sid
[0].sid
,
4496 &attr
->srv6_l3vpn
->sid
)) {
4497 sid_copy(&extra
->sid
[0].sid
,
4498 &attr
->srv6_l3vpn
->sid
);
4499 extra
->num_sids
= 1;
4501 extra
->sid
[0].loc_block_len
= 0;
4502 extra
->sid
[0].loc_node_len
= 0;
4503 extra
->sid
[0].func_len
= 0;
4504 extra
->sid
[0].arg_len
= 0;
4505 extra
->sid
[0].transposition_len
= 0;
4506 extra
->sid
[0].transposition_offset
= 0;
4508 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4509 extra
->sid
[0].loc_block_len
=
4510 attr
->srv6_l3vpn
->loc_block_len
;
4511 extra
->sid
[0].loc_node_len
=
4512 attr
->srv6_l3vpn
->loc_node_len
;
4513 extra
->sid
[0].func_len
=
4514 attr
->srv6_l3vpn
->func_len
;
4515 extra
->sid
[0].arg_len
=
4516 attr
->srv6_l3vpn
->arg_len
;
4517 extra
->sid
[0].transposition_len
=
4519 ->transposition_len
;
4520 extra
->sid
[0].transposition_offset
=
4522 ->transposition_offset
;
4525 } else if (attr
->srv6_vpn
) {
4526 extra
= bgp_path_info_extra_get(pi
);
4527 if (sid_diff(&extra
->sid
[0].sid
,
4528 &attr
->srv6_vpn
->sid
)) {
4529 sid_copy(&extra
->sid
[0].sid
,
4530 &attr
->srv6_vpn
->sid
);
4531 extra
->num_sids
= 1;
4535 #ifdef ENABLE_BGP_VNC
4536 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4537 && (safi
== SAFI_UNICAST
)) {
4538 if (vnc_implicit_withdraw
) {
4540 * Add back the route with its new attributes
4542 * The route is still selected, until the route
4544 * queued by bgp_process actually runs. We have
4546 * update to the VNC side immediately to avoid
4548 * configuration changes (e.g., route-map
4550 * trigger re-importation of the entire RIB.
4552 vnc_import_bgp_add_route(bgp
, p
, pi
);
4553 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4558 /* Update bgp route dampening information. */
4559 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4560 && peer
->sort
== BGP_PEER_EBGP
) {
4561 /* Now we do normal update dampening. */
4562 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4563 if (ret
== BGP_DAMP_SUPPRESSED
) {
4564 bgp_dest_unlock_node(dest
);
4569 /* Nexthop reachability check - for unicast and
4570 * labeled-unicast.. */
4571 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4572 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4573 || (safi
== SAFI_EVPN
&&
4574 bgp_evpn_is_prefix_nht_supported(p
))) {
4575 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4576 && peer
->ttl
== BGP_DEFAULT_TTL
4577 && !CHECK_FLAG(peer
->flags
,
4578 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4579 && !CHECK_FLAG(bgp
->flags
,
4580 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4585 struct bgp
*bgp_nexthop
= bgp
;
4587 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4588 bgp_nexthop
= pi
->extra
->bgp_orig
;
4590 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4592 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4593 safi
, pi
, NULL
, connected
,
4595 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4596 bgp_path_info_set_flag(dest
, pi
,
4599 if (BGP_DEBUG(nht
, NHT
)) {
4600 zlog_debug("%s(%pI4): NH unresolved",
4602 (in_addr_t
*)&attr_new
->nexthop
);
4604 bgp_path_info_unset_flag(dest
, pi
,
4609 bgp_path_info_set_flag(dest
, pi
,
4610 BGP_PATH_ACCEPT_OWN
);
4612 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4615 #ifdef ENABLE_BGP_VNC
4616 if (safi
== SAFI_MPLS_VPN
) {
4617 struct bgp_dest
*pdest
= NULL
;
4618 struct bgp_table
*table
= NULL
;
4620 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4621 (struct prefix
*)prd
);
4622 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4623 table
= bgp_dest_get_bgp_table_info(pdest
);
4625 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4626 bgp
, prd
, table
, p
, pi
);
4628 bgp_dest_unlock_node(pdest
);
4632 /* If this is an EVPN route and some attribute has changed,
4633 * or we are explicitly told to perform a route import, process
4634 * route for import. If the extended community has changed, we
4636 * have done the un-import earlier and the import would result
4638 * route getting injected into appropriate L2 VNIs. If it is
4640 * some other attribute change, the import will result in
4642 * the attributes for the route in the VNI(s).
4644 if (safi
== SAFI_EVPN
&&
4645 (!same_attr
|| force_evpn_import
) &&
4646 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4647 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4649 /* Process change. */
4650 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4652 bgp_process(bgp
, dest
, afi
, safi
);
4653 bgp_dest_unlock_node(dest
);
4655 if (SAFI_UNICAST
== safi
4656 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4657 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4659 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4661 if ((SAFI_MPLS_VPN
== safi
)
4662 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4663 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4666 #ifdef ENABLE_BGP_VNC
4667 if (SAFI_MPLS_VPN
== safi
) {
4668 mpls_label_t label_decoded
= decode_label(label
);
4670 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4671 type
, sub_type
, &label_decoded
);
4673 if (SAFI_ENCAP
== safi
) {
4674 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4675 type
, sub_type
, NULL
);
4678 if ((safi
== SAFI_MPLS_VPN
) &&
4679 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4680 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4682 bgp_unlink_nexthop(pi
);
4683 bgp_path_info_delete(dest
, pi
);
4686 } // End of implicit withdraw
4688 /* Received Logging. */
4689 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4690 if (!peer
->rcvd_attr_printed
) {
4691 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4692 peer
->rcvd_attr_str
);
4693 peer
->rcvd_attr_printed
= 1;
4696 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4697 addpath_id
? 1 : 0, addpath_id
, evpn
,
4698 pfx_buf
, sizeof(pfx_buf
));
4699 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4702 /* Make new BGP info. */
4703 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4705 /* Update MPLS label */
4706 if (has_valid_label
) {
4707 extra
= bgp_path_info_extra_get(new);
4708 if (extra
->label
!= label
) {
4709 memcpy(&extra
->label
, label
,
4710 num_labels
* sizeof(mpls_label_t
));
4711 extra
->num_labels
= num_labels
;
4713 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4714 bgp_set_valid_label(&extra
->label
[0]);
4717 /* Update SRv6 SID */
4718 if (safi
== SAFI_MPLS_VPN
) {
4719 extra
= bgp_path_info_extra_get(new);
4720 if (attr
->srv6_l3vpn
) {
4721 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4722 extra
->num_sids
= 1;
4724 extra
->sid
[0].loc_block_len
=
4725 attr
->srv6_l3vpn
->loc_block_len
;
4726 extra
->sid
[0].loc_node_len
=
4727 attr
->srv6_l3vpn
->loc_node_len
;
4728 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4729 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4730 extra
->sid
[0].transposition_len
=
4731 attr
->srv6_l3vpn
->transposition_len
;
4732 extra
->sid
[0].transposition_offset
=
4733 attr
->srv6_l3vpn
->transposition_offset
;
4734 } else if (attr
->srv6_vpn
) {
4735 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4736 extra
->num_sids
= 1;
4740 /* Nexthop reachability check. */
4741 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4742 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4743 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4744 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4745 && peer
->ttl
== BGP_DEFAULT_TTL
4746 && !CHECK_FLAG(peer
->flags
,
4747 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4748 && !CHECK_FLAG(bgp
->flags
,
4749 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4754 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4756 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4758 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4759 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4761 if (BGP_DEBUG(nht
, NHT
)) {
4762 char buf1
[INET6_ADDRSTRLEN
];
4764 (const void *)&attr_new
->nexthop
,
4765 buf1
, INET6_ADDRSTRLEN
);
4766 zlog_debug("%s(%s): NH unresolved", __func__
,
4769 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4773 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4775 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4779 new->addpath_rx_id
= addpath_id
;
4781 /* Increment prefix */
4782 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4784 /* Register new BGP information. */
4785 bgp_path_info_add(dest
, new);
4787 /* route_node_get lock */
4788 bgp_dest_unlock_node(dest
);
4790 #ifdef ENABLE_BGP_VNC
4791 if (safi
== SAFI_MPLS_VPN
) {
4792 struct bgp_dest
*pdest
= NULL
;
4793 struct bgp_table
*table
= NULL
;
4795 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4796 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4797 table
= bgp_dest_get_bgp_table_info(pdest
);
4799 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4800 bgp
, prd
, table
, p
, new);
4802 bgp_dest_unlock_node(pdest
);
4806 /* If this is an EVPN route, process for import. */
4807 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4808 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4810 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4812 /* Process change. */
4813 bgp_process(bgp
, dest
, afi
, safi
);
4815 if (SAFI_UNICAST
== safi
4816 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4817 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4818 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4820 if ((SAFI_MPLS_VPN
== safi
)
4821 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4822 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4824 #ifdef ENABLE_BGP_VNC
4825 if (SAFI_MPLS_VPN
== safi
) {
4826 mpls_label_t label_decoded
= decode_label(label
);
4828 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4829 sub_type
, &label_decoded
);
4831 if (SAFI_ENCAP
== safi
) {
4832 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4836 if ((safi
== SAFI_MPLS_VPN
) &&
4837 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4838 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4840 bgp_unlink_nexthop(new);
4841 bgp_path_info_delete(dest
, new);
4846 /* This BGP update is filtered. Log the reason then update BGP
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
);
5315 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5317 struct bgp_dest
*dest
;
5318 struct bgp_table
*table
;
5319 struct listnode
*node
, *nnode
;
5321 struct peer_af
*paf
;
5323 if (!peer_established(peer
))
5326 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5327 && (safi
!= SAFI_EVPN
)) {
5328 table
= peer
->bgp
->rib
[afi
][safi
];
5332 table
->soft_reconfig_init
= true;
5334 if (!table
->soft_reconfig_peers
)
5335 table
->soft_reconfig_peers
= list_new();
5337 /* add peer to the table soft_reconfig_peers if not already
5340 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5346 listnode_add(table
->soft_reconfig_peers
, peer
);
5348 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5349 * on table would start back at the beginning.
5351 bgp_soft_reconfig_table_flag(table
, true);
5353 if (!table
->soft_reconfig_thread
)
5354 thread_add_event(bm
->master
,
5355 bgp_soft_reconfig_table_task
, table
, 0,
5356 &table
->soft_reconfig_thread
);
5357 /* Cancel bgp_announce_route_timer_expired threads.
5358 * bgp_announce_route_timer_expired threads have been scheduled
5359 * to announce routes as soon as the soft_reconfigure process
5361 * In this case, soft_reconfigure is also scheduled by using
5362 * a thread but is planned after the
5363 * bgp_announce_route_timer_expired threads. It means that,
5364 * without cancelling the threads, the route announcement task
5365 * would run before the soft reconfiguration one. That would
5366 * useless and would block vtysh during several seconds. Route
5367 * announcements are rescheduled as soon as the soft_reconfigure
5370 paf
= peer_af_find(peer
, afi
, safi
);
5372 bgp_stop_announce_route_timer(paf
);
5374 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5375 dest
= bgp_route_next(dest
)) {
5376 table
= bgp_dest_get_bgp_table_info(dest
);
5381 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5382 struct prefix_rd prd
;
5384 prd
.family
= AF_UNSPEC
;
5386 memcpy(&prd
.val
, p
->u
.val
, 8);
5388 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5393 struct bgp_clear_node_queue
{
5394 struct bgp_dest
*dest
;
5397 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5399 struct bgp_clear_node_queue
*cnq
= data
;
5400 struct bgp_dest
*dest
= cnq
->dest
;
5401 struct peer
*peer
= wq
->spec
.data
;
5402 struct bgp_path_info
*pi
;
5404 afi_t afi
= bgp_dest_table(dest
)->afi
;
5405 safi_t safi
= bgp_dest_table(dest
)->safi
;
5407 assert(dest
&& peer
);
5410 /* It is possible that we have multiple paths for a prefix from a peer
5411 * if that peer is using AddPath.
5413 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5414 if (pi
->peer
!= peer
)
5417 /* graceful restart STALE flag set. */
5418 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5419 && peer
->nsf
[afi
][safi
])
5420 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5421 PEER_STATUS_ENHANCED_REFRESH
))
5422 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5423 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5424 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5426 /* If this is an EVPN route, process for
5428 if (safi
== SAFI_EVPN
)
5429 bgp_evpn_unimport_route(
5431 bgp_dest_get_prefix(dest
), pi
);
5432 /* Handle withdraw for VRF route-leaking and L3VPN */
5433 if (SAFI_UNICAST
== safi
5434 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5435 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5436 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5439 if (SAFI_MPLS_VPN
== safi
&&
5440 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5441 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5444 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5450 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5452 struct bgp_clear_node_queue
*cnq
= data
;
5453 struct bgp_dest
*dest
= cnq
->dest
;
5454 struct bgp_table
*table
= bgp_dest_table(dest
);
5456 bgp_dest_unlock_node(dest
);
5457 bgp_table_unlock(table
);
5458 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5461 static void bgp_clear_node_complete(struct work_queue
*wq
)
5463 struct peer
*peer
= wq
->spec
.data
;
5465 /* Tickle FSM to start moving again */
5466 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5468 peer_unlock(peer
); /* bgp_clear_route */
5471 static void bgp_clear_node_queue_init(struct peer
*peer
)
5473 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5475 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5476 #undef CLEAR_QUEUE_NAME_LEN
5478 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5479 peer
->clear_node_queue
->spec
.hold
= 10;
5480 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5481 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5482 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5483 peer
->clear_node_queue
->spec
.max_retries
= 0;
5485 /* we only 'lock' this peer reference when the queue is actually active
5487 peer
->clear_node_queue
->spec
.data
= peer
;
5490 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5491 struct bgp_table
*table
)
5493 struct bgp_dest
*dest
;
5494 int force
= peer
->bgp
->process_queue
? 0 : 1;
5497 table
= peer
->bgp
->rib
[afi
][safi
];
5499 /* If still no table => afi/safi isn't configured at all or smth. */
5503 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5504 struct bgp_path_info
*pi
, *next
;
5505 struct bgp_adj_in
*ain
;
5506 struct bgp_adj_in
*ain_next
;
5508 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5509 * queued for every clearing peer, regardless of whether it is
5510 * relevant to the peer at hand.
5512 * Overview: There are 3 different indices which need to be
5513 * scrubbed, potentially, when a peer is removed:
5515 * 1 peer's routes visible via the RIB (ie accepted routes)
5516 * 2 peer's routes visible by the (optional) peer's adj-in index
5517 * 3 other routes visible by the peer's adj-out index
5519 * 3 there is no hurry in scrubbing, once the struct peer is
5520 * removed from bgp->peer, we could just GC such deleted peer's
5521 * adj-outs at our leisure.
5523 * 1 and 2 must be 'scrubbed' in some way, at least made
5524 * invisible via RIB index before peer session is allowed to be
5525 * brought back up. So one needs to know when such a 'search' is
5530 * - there'd be a single global queue or a single RIB walker
5531 * - rather than tracking which route_nodes still need to be
5532 * examined on a peer basis, we'd track which peers still
5535 * Given that our per-peer prefix-counts now should be reliable,
5536 * this may actually be achievable. It doesn't seem to be a huge
5537 * problem at this time,
5539 * It is possible that we have multiple paths for a prefix from
5541 * if that peer is using AddPath.
5545 ain_next
= ain
->next
;
5547 if (ain
->peer
== peer
)
5548 bgp_adj_in_remove(dest
, ain
);
5553 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5555 if (pi
->peer
!= peer
)
5559 bgp_path_info_reap(dest
, pi
);
5561 struct bgp_clear_node_queue
*cnq
;
5563 /* both unlocked in bgp_clear_node_queue_del */
5564 bgp_table_lock(bgp_dest_table(dest
));
5565 bgp_dest_lock_node(dest
);
5567 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5568 sizeof(struct bgp_clear_node_queue
));
5570 work_queue_add(peer
->clear_node_queue
, cnq
);
5578 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5580 struct bgp_dest
*dest
;
5581 struct bgp_table
*table
;
5583 if (peer
->clear_node_queue
== NULL
)
5584 bgp_clear_node_queue_init(peer
);
5586 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5587 * Idle until it receives a Clearing_Completed event. This protects
5588 * against peers which flap faster than we can we clear, which could
5591 * a) race with routes from the new session being installed before
5592 * clear_route_node visits the node (to delete the route of that
5594 * b) resource exhaustion, clear_route_node likely leads to an entry
5595 * on the process_main queue. Fast-flapping could cause that queue
5599 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5600 * the unlock will happen upon work-queue completion; other wise, the
5601 * unlock happens at the end of this function.
5603 if (!peer
->clear_node_queue
->thread
)
5606 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5607 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5609 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5610 dest
= bgp_route_next(dest
)) {
5611 table
= bgp_dest_get_bgp_table_info(dest
);
5615 bgp_clear_route_table(peer
, afi
, safi
, table
);
5618 /* unlock if no nodes got added to the clear-node-queue. */
5619 if (!peer
->clear_node_queue
->thread
)
5623 void bgp_clear_route_all(struct peer
*peer
)
5628 FOREACH_AFI_SAFI (afi
, safi
)
5629 bgp_clear_route(peer
, afi
, safi
);
5631 #ifdef ENABLE_BGP_VNC
5632 rfapiProcessPeerDown(peer
);
5636 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5638 struct bgp_table
*table
;
5639 struct bgp_dest
*dest
;
5640 struct bgp_adj_in
*ain
;
5641 struct bgp_adj_in
*ain_next
;
5643 table
= peer
->bgp
->rib
[afi
][safi
];
5645 /* It is possible that we have multiple paths for a prefix from a peer
5646 * if that peer is using AddPath.
5648 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5652 ain_next
= ain
->next
;
5654 if (ain
->peer
== peer
)
5655 bgp_adj_in_remove(dest
, ain
);
5662 /* If any of the routes from the peer have been marked with the NO_LLGR
5663 * community, either as sent by the peer, or as the result of a configured
5664 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5665 * operation of [RFC4271].
5667 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5669 struct bgp_dest
*dest
;
5670 struct bgp_path_info
*pi
;
5671 struct bgp_table
*table
;
5673 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5674 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5675 dest
= bgp_route_next(dest
)) {
5676 struct bgp_dest
*rm
;
5678 /* look for neighbor in tables */
5679 table
= bgp_dest_get_bgp_table_info(dest
);
5683 for (rm
= bgp_table_top(table
); rm
;
5684 rm
= bgp_route_next(rm
))
5685 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5687 if (pi
->peer
!= peer
)
5690 peer
->af_sflags
[afi
][safi
],
5691 PEER_STATUS_LLGR_WAIT
) &&
5692 bgp_attr_get_community(pi
->attr
) &&
5694 bgp_attr_get_community(
5698 if (!CHECK_FLAG(pi
->flags
,
5703 * If this is VRF leaked route
5704 * process for withdraw.
5707 BGP_ROUTE_IMPORTED
&&
5708 peer
->bgp
->inst_type
==
5709 BGP_INSTANCE_TYPE_DEFAULT
)
5710 vpn_leak_to_vrf_withdraw(
5713 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5718 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5719 dest
= bgp_route_next(dest
))
5720 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5722 if (pi
->peer
!= peer
)
5724 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5725 PEER_STATUS_LLGR_WAIT
) &&
5726 bgp_attr_get_community(pi
->attr
) &&
5728 bgp_attr_get_community(pi
->attr
),
5731 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5733 if (safi
== SAFI_UNICAST
&&
5734 (peer
->bgp
->inst_type
==
5735 BGP_INSTANCE_TYPE_VRF
||
5736 peer
->bgp
->inst_type
==
5737 BGP_INSTANCE_TYPE_DEFAULT
))
5738 vpn_leak_from_vrf_withdraw(
5739 bgp_get_default(), peer
->bgp
,
5742 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5748 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5750 struct bgp_dest
*dest
, *ndest
;
5751 struct bgp_path_info
*pi
;
5752 struct bgp_table
*table
;
5754 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5755 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5756 dest
= bgp_route_next(dest
)) {
5757 table
= bgp_dest_get_bgp_table_info(dest
);
5761 for (ndest
= bgp_table_top(table
); ndest
;
5762 ndest
= bgp_route_next(ndest
)) {
5763 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5765 if (pi
->peer
!= peer
)
5769 peer
->af_sflags
[afi
][safi
],
5770 PEER_STATUS_ENHANCED_REFRESH
))
5771 && !CHECK_FLAG(pi
->flags
,
5775 BGP_PATH_UNUSEABLE
)) {
5776 if (bgp_debug_neighbor_events(
5779 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5783 bgp_dest_get_prefix(
5786 bgp_path_info_set_flag(
5794 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5795 dest
= bgp_route_next(dest
)) {
5796 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5798 if (pi
->peer
!= peer
)
5801 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5802 PEER_STATUS_ENHANCED_REFRESH
))
5803 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5804 && !CHECK_FLAG(pi
->flags
,
5805 BGP_PATH_UNUSEABLE
)) {
5806 if (bgp_debug_neighbor_events(peer
))
5808 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5811 bgp_dest_get_prefix(
5814 bgp_path_info_set_flag(dest
, pi
,
5822 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5824 if (peer
->sort
== BGP_PEER_IBGP
)
5827 if (peer
->sort
== BGP_PEER_EBGP
5828 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5829 || FILTER_LIST_OUT_NAME(filter
)
5830 || DISTRIBUTE_OUT_NAME(filter
)))
5835 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5837 if (peer
->sort
== BGP_PEER_IBGP
)
5840 if (peer
->sort
== BGP_PEER_EBGP
5841 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5842 || FILTER_LIST_IN_NAME(filter
)
5843 || DISTRIBUTE_IN_NAME(filter
)))
5848 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5851 struct bgp_dest
*dest
;
5852 struct bgp_path_info
*pi
;
5853 struct bgp_path_info
*next
;
5855 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5856 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5857 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5861 /* Unimport EVPN routes from VRFs */
5862 if (safi
== SAFI_EVPN
)
5863 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5866 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5867 && pi
->type
== ZEBRA_ROUTE_BGP
5868 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5869 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5870 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5872 if (bgp_fibupd_safi(safi
))
5873 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5876 bgp_path_info_reap(dest
, pi
);
5880 /* Delete all kernel routes. */
5881 void bgp_cleanup_routes(struct bgp
*bgp
)
5884 struct bgp_dest
*dest
;
5885 struct bgp_table
*table
;
5887 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5888 if (afi
== AFI_L2VPN
)
5890 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5893 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5895 if (afi
!= AFI_L2VPN
) {
5897 safi
= SAFI_MPLS_VPN
;
5898 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5899 dest
= bgp_route_next(dest
)) {
5900 table
= bgp_dest_get_bgp_table_info(dest
);
5901 if (table
!= NULL
) {
5902 bgp_cleanup_table(bgp
, table
, safi
);
5903 bgp_table_finish(&table
);
5904 bgp_dest_set_bgp_table_info(dest
, NULL
);
5905 bgp_dest_unlock_node(dest
);
5909 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5910 dest
= bgp_route_next(dest
)) {
5911 table
= bgp_dest_get_bgp_table_info(dest
);
5912 if (table
!= NULL
) {
5913 bgp_cleanup_table(bgp
, table
, safi
);
5914 bgp_table_finish(&table
);
5915 bgp_dest_set_bgp_table_info(dest
, NULL
);
5916 bgp_dest_unlock_node(dest
);
5921 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5922 dest
= bgp_route_next(dest
)) {
5923 table
= bgp_dest_get_bgp_table_info(dest
);
5924 if (table
!= NULL
) {
5925 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5926 bgp_table_finish(&table
);
5927 bgp_dest_set_bgp_table_info(dest
, NULL
);
5928 bgp_dest_unlock_node(dest
);
5933 void bgp_reset(void)
5936 bgp_zclient_reset();
5937 access_list_reset();
5938 prefix_list_reset();
5941 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5943 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5944 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5945 PEER_CAP_ADDPATH_AF_TX_RCV
));
5948 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5950 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5951 struct bgp_nlri
*packet
)
5960 bool addpath_capable
;
5961 uint32_t addpath_id
;
5964 lim
= pnt
+ packet
->length
;
5966 safi
= packet
->safi
;
5968 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5970 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5971 syntactic validity. If the field is syntactically incorrect,
5972 then the Error Subcode is set to Invalid Network Field. */
5973 for (; pnt
< lim
; pnt
+= psize
) {
5974 /* Clear prefix structure. */
5975 memset(&p
, 0, sizeof(p
));
5977 if (addpath_capable
) {
5979 /* When packet overflow occurs return immediately. */
5980 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5981 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5983 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5984 addpath_id
= ntohl(addpath_id
);
5985 pnt
+= BGP_ADDPATH_ID_LEN
;
5988 /* Fetch prefix length. */
5989 p
.prefixlen
= *pnt
++;
5990 /* afi/safi validity already verified by caller,
5991 * bgp_update_receive */
5992 p
.family
= afi2family(afi
);
5994 /* Prefix length check. */
5995 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5998 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5999 peer
->host
, p
.prefixlen
, packet
->afi
);
6000 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
6003 /* Packet size overflow check. */
6004 psize
= PSIZE(p
.prefixlen
);
6006 /* When packet overflow occur return immediately. */
6007 if (pnt
+ psize
> lim
) {
6010 "%s [Error] Update packet error (prefix length %d overflows packet)",
6011 peer
->host
, p
.prefixlen
);
6012 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6015 /* Defensive coding, double-check the psize fits in a struct
6016 * prefix for the v4 and v6 afi's and unicast/multicast */
6017 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6020 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6021 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6022 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6025 /* Fetch prefix from NLRI packet. */
6026 memcpy(p
.u
.val
, pnt
, psize
);
6028 /* Check address. */
6029 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6030 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6031 /* From RFC4271 Section 6.3:
6033 * If a prefix in the NLRI field is semantically
6035 * (e.g., an unexpected multicast IP address),
6037 * be logged locally, and the prefix SHOULD be
6042 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6043 peer
->host
, &p
.u
.prefix4
);
6048 /* Check address. */
6049 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6050 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6053 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6054 peer
->host
, &p
.u
.prefix6
);
6058 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6061 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6062 peer
->host
, &p
.u
.prefix6
);
6068 /* Normal process. */
6070 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6071 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
6072 NULL
, NULL
, 0, 0, NULL
);
6074 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
6075 safi
, ZEBRA_ROUTE_BGP
,
6076 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
6079 /* Do not send BGP notification twice when maximum-prefix count
6081 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6082 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6084 /* Address family configuration mismatch. */
6086 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
6089 /* Packet length consistency check. */
6093 "%s [Error] Update packet error (prefix length mismatch with total length)",
6095 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6098 return BGP_NLRI_PARSE_OK
;
6101 static struct bgp_static
*bgp_static_new(void)
6103 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6106 static void bgp_static_free(struct bgp_static
*bgp_static
)
6108 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6109 route_map_counter_decrement(bgp_static
->rmap
.map
);
6111 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6112 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6115 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6116 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6118 struct bgp_dest
*dest
;
6119 struct bgp_path_info
*pi
;
6120 struct bgp_path_info
*new;
6121 struct bgp_path_info rmap_path
;
6123 struct attr
*attr_new
;
6124 route_map_result_t ret
;
6125 #ifdef ENABLE_BGP_VNC
6126 int vnc_implicit_withdraw
= 0;
6131 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6133 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6135 attr
.nexthop
= bgp_static
->igpnexthop
;
6136 attr
.med
= bgp_static
->igpmetric
;
6137 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6140 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6142 if (bgp_static
->atomic
)
6143 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6145 /* Store label index, if required. */
6146 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6147 attr
.label_index
= bgp_static
->label_index
;
6148 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6151 /* Apply route-map. */
6152 if (bgp_static
->rmap
.name
) {
6153 struct attr attr_tmp
= attr
;
6155 memset(&rmap_path
, 0, sizeof(rmap_path
));
6156 rmap_path
.peer
= bgp
->peer_self
;
6157 rmap_path
.attr
= &attr_tmp
;
6159 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6161 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6163 bgp
->peer_self
->rmap_type
= 0;
6165 if (ret
== RMAP_DENYMATCH
) {
6166 /* Free uninterned attribute. */
6167 bgp_attr_flush(&attr_tmp
);
6169 /* Unintern original. */
6170 aspath_unintern(&attr
.aspath
);
6171 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6172 bgp_dest_unlock_node(dest
);
6176 if (bgp_in_graceful_shutdown(bgp
))
6177 bgp_attr_add_gshut_community(&attr_tmp
);
6179 attr_new
= bgp_attr_intern(&attr_tmp
);
6182 if (bgp_in_graceful_shutdown(bgp
))
6183 bgp_attr_add_gshut_community(&attr
);
6185 attr_new
= bgp_attr_intern(&attr
);
6188 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6189 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6190 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6194 if (attrhash_cmp(pi
->attr
, attr_new
)
6195 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6196 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6197 bgp_dest_unlock_node(dest
);
6198 bgp_attr_unintern(&attr_new
);
6199 aspath_unintern(&attr
.aspath
);
6202 /* The attribute is changed. */
6203 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6205 /* Rewrite BGP route information. */
6206 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6207 bgp_path_info_restore(dest
, pi
);
6209 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6210 #ifdef ENABLE_BGP_VNC
6211 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6212 && (safi
== SAFI_UNICAST
)) {
6213 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6215 * Implicit withdraw case.
6216 * We have to do this before pi is
6219 ++vnc_implicit_withdraw
;
6220 vnc_import_bgp_del_route(bgp
, p
, pi
);
6221 vnc_import_bgp_exterior_del_route(
6226 bgp_attr_unintern(&pi
->attr
);
6227 pi
->attr
= attr_new
;
6228 pi
->uptime
= monotime(NULL
);
6229 #ifdef ENABLE_BGP_VNC
6230 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6231 && (safi
== SAFI_UNICAST
)) {
6232 if (vnc_implicit_withdraw
) {
6233 vnc_import_bgp_add_route(bgp
, p
, pi
);
6234 vnc_import_bgp_exterior_add_route(
6240 /* Nexthop reachability check. */
6241 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6242 && (safi
== SAFI_UNICAST
6243 || safi
== SAFI_LABELED_UNICAST
)) {
6245 struct bgp
*bgp_nexthop
= bgp
;
6247 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6248 bgp_nexthop
= pi
->extra
->bgp_orig
;
6250 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6251 afi
, safi
, pi
, NULL
,
6253 bgp_path_info_set_flag(dest
, pi
,
6256 if (BGP_DEBUG(nht
, NHT
)) {
6257 char buf1
[INET6_ADDRSTRLEN
];
6258 inet_ntop(p
->family
,
6262 "%s(%s): Route not in table, not advertising",
6265 bgp_path_info_unset_flag(
6266 dest
, pi
, BGP_PATH_VALID
);
6269 /* Delete the NHT structure if any, if we're
6271 * enabling/disabling import check. We
6272 * deregister the route
6273 * from NHT to avoid overloading NHT and the
6274 * process interaction
6276 bgp_unlink_nexthop(pi
);
6277 bgp_path_info_set_flag(dest
, pi
,
6280 /* Process change. */
6281 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6282 bgp_process(bgp
, dest
, afi
, safi
);
6284 if (SAFI_UNICAST
== safi
6285 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6287 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6288 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6292 bgp_dest_unlock_node(dest
);
6293 aspath_unintern(&attr
.aspath
);
6298 /* Make new BGP info. */
6299 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6301 /* Nexthop reachability check. */
6302 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6303 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6304 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6306 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6308 if (BGP_DEBUG(nht
, NHT
)) {
6309 char buf1
[INET6_ADDRSTRLEN
];
6310 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6313 "%s(%s): Route not in table, not advertising",
6316 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6319 /* Delete the NHT structure if any, if we're toggling between
6320 * enabling/disabling import check. We deregister the route
6321 * from NHT to avoid overloading NHT and the process interaction
6323 bgp_unlink_nexthop(new);
6325 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6328 /* Aggregate address increment. */
6329 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6331 /* Register new BGP information. */
6332 bgp_path_info_add(dest
, new);
6334 /* route_node_get lock */
6335 bgp_dest_unlock_node(dest
);
6337 /* Process change. */
6338 bgp_process(bgp
, dest
, afi
, safi
);
6340 if (SAFI_UNICAST
== safi
6341 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6342 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6343 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6346 /* Unintern original. */
6347 aspath_unintern(&attr
.aspath
);
6350 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6353 struct bgp_dest
*dest
;
6354 struct bgp_path_info
*pi
;
6356 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6358 /* Check selected route and self inserted route. */
6359 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6360 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6361 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6364 /* Withdraw static BGP route from routing table. */
6366 if (SAFI_UNICAST
== safi
6367 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6368 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6369 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6371 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6372 bgp_unlink_nexthop(pi
);
6373 bgp_path_info_delete(dest
, pi
);
6374 bgp_process(bgp
, dest
, afi
, safi
);
6377 /* Unlock bgp_node_lookup. */
6378 bgp_dest_unlock_node(dest
);
6382 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6384 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6385 afi_t afi
, safi_t safi
,
6386 struct prefix_rd
*prd
)
6388 struct bgp_dest
*dest
;
6389 struct bgp_path_info
*pi
;
6391 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6393 /* Check selected route and self inserted route. */
6394 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6395 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6396 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6399 /* Withdraw static BGP route from routing table. */
6401 #ifdef ENABLE_BGP_VNC
6402 rfapiProcessWithdraw(
6403 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6404 1); /* Kill, since it is an administrative change */
6406 if (SAFI_MPLS_VPN
== safi
6407 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6408 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6410 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6411 bgp_path_info_delete(dest
, pi
);
6412 bgp_process(bgp
, dest
, afi
, safi
);
6415 /* Unlock bgp_node_lookup. */
6416 bgp_dest_unlock_node(dest
);
6419 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6420 struct bgp_static
*bgp_static
, afi_t afi
,
6423 struct bgp_dest
*dest
;
6424 struct bgp_path_info
*new;
6425 struct attr
*attr_new
;
6426 struct attr attr
= {0};
6427 struct bgp_path_info
*pi
;
6428 #ifdef ENABLE_BGP_VNC
6429 mpls_label_t label
= 0;
6431 uint32_t num_labels
= 0;
6435 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6437 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6440 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6442 attr
.nexthop
= bgp_static
->igpnexthop
;
6443 attr
.med
= bgp_static
->igpmetric
;
6444 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6446 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6447 || (safi
== SAFI_ENCAP
)) {
6448 if (afi
== AFI_IP
) {
6449 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6450 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6453 if (afi
== AFI_L2VPN
) {
6454 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6455 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6456 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6457 &bgp_static
->gatewayIp
.u
.prefix4
,
6459 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6460 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6461 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6462 &bgp_static
->gatewayIp
.u
.prefix6
,
6465 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6466 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6467 struct bgp_encap_type_vxlan bet
;
6468 memset(&bet
, 0, sizeof(bet
));
6469 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6470 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6472 if (bgp_static
->router_mac
) {
6473 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6476 /* Apply route-map. */
6477 if (bgp_static
->rmap
.name
) {
6478 struct attr attr_tmp
= attr
;
6479 struct bgp_path_info rmap_path
;
6480 route_map_result_t ret
;
6482 rmap_path
.peer
= bgp
->peer_self
;
6483 rmap_path
.attr
= &attr_tmp
;
6485 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6487 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6489 bgp
->peer_self
->rmap_type
= 0;
6491 if (ret
== RMAP_DENYMATCH
) {
6492 /* Free uninterned attribute. */
6493 bgp_attr_flush(&attr_tmp
);
6495 /* Unintern original. */
6496 aspath_unintern(&attr
.aspath
);
6497 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6499 bgp_dest_unlock_node(dest
);
6503 attr_new
= bgp_attr_intern(&attr_tmp
);
6505 attr_new
= bgp_attr_intern(&attr
);
6508 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6509 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6510 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6514 if (attrhash_cmp(pi
->attr
, attr_new
)
6515 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6516 bgp_dest_unlock_node(dest
);
6517 bgp_attr_unintern(&attr_new
);
6518 aspath_unintern(&attr
.aspath
);
6521 /* The attribute is changed. */
6522 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6524 /* Rewrite BGP route information. */
6525 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6526 bgp_path_info_restore(dest
, pi
);
6528 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6529 bgp_attr_unintern(&pi
->attr
);
6530 pi
->attr
= attr_new
;
6531 pi
->uptime
= monotime(NULL
);
6532 #ifdef ENABLE_BGP_VNC
6534 label
= decode_label(&pi
->extra
->label
[0]);
6537 /* Process change. */
6538 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6539 bgp_process(bgp
, dest
, afi
, safi
);
6541 if (SAFI_MPLS_VPN
== safi
6542 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6543 vpn_leak_to_vrf_update(bgp
, pi
,
6546 #ifdef ENABLE_BGP_VNC
6547 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6548 pi
->attr
, afi
, safi
, pi
->type
,
6549 pi
->sub_type
, &label
);
6551 bgp_dest_unlock_node(dest
);
6552 aspath_unintern(&attr
.aspath
);
6558 /* Make new BGP info. */
6559 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6561 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6562 bgp_path_info_extra_get(new);
6564 new->extra
->label
[0] = bgp_static
->label
;
6565 new->extra
->num_labels
= num_labels
;
6567 #ifdef ENABLE_BGP_VNC
6568 label
= decode_label(&bgp_static
->label
);
6571 /* Aggregate address increment. */
6572 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6574 /* Register new BGP information. */
6575 bgp_path_info_add(dest
, new);
6576 /* route_node_get lock */
6577 bgp_dest_unlock_node(dest
);
6579 /* Process change. */
6580 bgp_process(bgp
, dest
, afi
, safi
);
6582 if (SAFI_MPLS_VPN
== safi
6583 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6584 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6586 #ifdef ENABLE_BGP_VNC
6587 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6588 safi
, new->type
, new->sub_type
, &label
);
6591 /* Unintern original. */
6592 aspath_unintern(&attr
.aspath
);
6595 /* Configure static BGP network. When user don't run zebra, static
6596 route should be installed as valid. */
6597 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6598 const char *ip_str
, afi_t afi
, safi_t safi
,
6599 const char *rmap
, int backdoor
, uint32_t label_index
)
6601 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6604 struct bgp_static
*bgp_static
;
6605 struct bgp_dest
*dest
;
6606 uint8_t need_update
= 0;
6608 /* Convert IP prefix string to struct prefix. */
6609 ret
= str2prefix(ip_str
, &p
);
6611 vty_out(vty
, "%% Malformed prefix\n");
6612 return CMD_WARNING_CONFIG_FAILED
;
6614 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6615 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6616 return CMD_WARNING_CONFIG_FAILED
;
6623 /* Set BGP static route configuration. */
6624 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6627 vty_out(vty
, "%% Can't find static route specified\n");
6628 return CMD_WARNING_CONFIG_FAILED
;
6631 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6633 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6634 && (label_index
!= bgp_static
->label_index
)) {
6636 "%% label-index doesn't match static route\n");
6637 bgp_dest_unlock_node(dest
);
6638 return CMD_WARNING_CONFIG_FAILED
;
6641 if ((rmap
&& bgp_static
->rmap
.name
)
6642 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6644 "%% route-map name doesn't match static route\n");
6645 bgp_dest_unlock_node(dest
);
6646 return CMD_WARNING_CONFIG_FAILED
;
6649 /* Update BGP RIB. */
6650 if (!bgp_static
->backdoor
)
6651 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6653 /* Clear configuration. */
6654 bgp_static_free(bgp_static
);
6655 bgp_dest_set_bgp_static_info(dest
, NULL
);
6656 bgp_dest_unlock_node(dest
);
6657 bgp_dest_unlock_node(dest
);
6660 /* Set BGP static route configuration. */
6661 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6662 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6664 /* Configuration change. */
6665 /* Label index cannot be changed. */
6666 if (bgp_static
->label_index
!= label_index
) {
6667 vty_out(vty
, "%% cannot change label-index\n");
6668 bgp_dest_unlock_node(dest
);
6669 return CMD_WARNING_CONFIG_FAILED
;
6672 /* Check previous routes are installed into BGP. */
6673 if (bgp_static
->valid
6674 && bgp_static
->backdoor
!= backdoor
)
6677 bgp_static
->backdoor
= backdoor
;
6680 XFREE(MTYPE_ROUTE_MAP_NAME
,
6681 bgp_static
->rmap
.name
);
6682 route_map_counter_decrement(
6683 bgp_static
->rmap
.map
);
6684 bgp_static
->rmap
.name
=
6685 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6686 bgp_static
->rmap
.map
=
6687 route_map_lookup_by_name(rmap
);
6688 route_map_counter_increment(
6689 bgp_static
->rmap
.map
);
6691 XFREE(MTYPE_ROUTE_MAP_NAME
,
6692 bgp_static
->rmap
.name
);
6693 route_map_counter_decrement(
6694 bgp_static
->rmap
.map
);
6695 bgp_static
->rmap
.map
= NULL
;
6696 bgp_static
->valid
= 0;
6698 bgp_dest_unlock_node(dest
);
6700 /* New configuration. */
6701 bgp_static
= bgp_static_new();
6702 bgp_static
->backdoor
= backdoor
;
6703 bgp_static
->valid
= 0;
6704 bgp_static
->igpmetric
= 0;
6705 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6706 bgp_static
->label_index
= label_index
;
6709 XFREE(MTYPE_ROUTE_MAP_NAME
,
6710 bgp_static
->rmap
.name
);
6711 route_map_counter_decrement(
6712 bgp_static
->rmap
.map
);
6713 bgp_static
->rmap
.name
=
6714 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6715 bgp_static
->rmap
.map
=
6716 route_map_lookup_by_name(rmap
);
6717 route_map_counter_increment(
6718 bgp_static
->rmap
.map
);
6720 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6723 bgp_static
->valid
= 1;
6725 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6727 if (!bgp_static
->backdoor
)
6728 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6734 void bgp_static_add(struct bgp
*bgp
)
6738 struct bgp_dest
*dest
;
6739 struct bgp_dest
*rm
;
6740 struct bgp_table
*table
;
6741 struct bgp_static
*bgp_static
;
6743 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6744 FOREACH_AFI_SAFI (afi
, safi
)
6745 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6746 dest
= bgp_route_next(dest
)) {
6747 if (!bgp_dest_has_bgp_path_info_data(dest
))
6750 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6751 || (safi
== SAFI_EVPN
)) {
6752 table
= bgp_dest_get_bgp_table_info(dest
);
6754 for (rm
= bgp_table_top(table
); rm
;
6755 rm
= bgp_route_next(rm
)) {
6757 bgp_dest_get_bgp_static_info(
6759 bgp_static_update_safi(
6760 bgp
, bgp_dest_get_prefix(rm
),
6761 bgp_static
, afi
, safi
);
6765 bgp
, bgp_dest_get_prefix(dest
),
6766 bgp_dest_get_bgp_static_info(dest
), afi
,
6770 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6773 /* Called from bgp_delete(). Delete all static routes from the BGP
6775 void bgp_static_delete(struct bgp
*bgp
)
6779 struct bgp_dest
*dest
;
6780 struct bgp_dest
*rm
;
6781 struct bgp_table
*table
;
6782 struct bgp_static
*bgp_static
;
6784 FOREACH_AFI_SAFI (afi
, safi
)
6785 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6786 dest
= bgp_route_next(dest
)) {
6787 if (!bgp_dest_has_bgp_path_info_data(dest
))
6790 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6791 || (safi
== SAFI_EVPN
)) {
6792 table
= bgp_dest_get_bgp_table_info(dest
);
6794 for (rm
= bgp_table_top(table
); rm
;
6795 rm
= bgp_route_next(rm
)) {
6797 bgp_dest_get_bgp_static_info(
6802 bgp_static_withdraw_safi(
6803 bgp
, bgp_dest_get_prefix(rm
),
6805 (struct prefix_rd
*)
6806 bgp_dest_get_prefix(
6808 bgp_static_free(bgp_static
);
6809 bgp_dest_set_bgp_static_info(rm
,
6811 bgp_dest_unlock_node(rm
);
6814 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6815 bgp_static_withdraw(bgp
,
6816 bgp_dest_get_prefix(dest
),
6818 bgp_static_free(bgp_static
);
6819 bgp_dest_set_bgp_static_info(dest
, NULL
);
6820 bgp_dest_unlock_node(dest
);
6825 void bgp_static_redo_import_check(struct bgp
*bgp
)
6829 struct bgp_dest
*dest
;
6830 struct bgp_dest
*rm
;
6831 struct bgp_table
*table
;
6832 struct bgp_static
*bgp_static
;
6834 /* Use this flag to force reprocessing of the route */
6835 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6836 FOREACH_AFI_SAFI (afi
, safi
) {
6837 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6838 dest
= bgp_route_next(dest
)) {
6839 if (!bgp_dest_has_bgp_path_info_data(dest
))
6842 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6843 || (safi
== SAFI_EVPN
)) {
6844 table
= bgp_dest_get_bgp_table_info(dest
);
6846 for (rm
= bgp_table_top(table
); rm
;
6847 rm
= bgp_route_next(rm
)) {
6849 bgp_dest_get_bgp_static_info(
6851 bgp_static_update_safi(
6852 bgp
, bgp_dest_get_prefix(rm
),
6853 bgp_static
, afi
, safi
);
6856 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6857 bgp_static_update(bgp
,
6858 bgp_dest_get_prefix(dest
),
6859 bgp_static
, afi
, safi
);
6863 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6866 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6869 struct bgp_table
*table
;
6870 struct bgp_dest
*dest
;
6871 struct bgp_path_info
*pi
;
6873 /* Do not install the aggregate route if BGP is in the
6874 * process of termination.
6876 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6877 || (bgp
->peer_self
== NULL
))
6880 table
= bgp
->rib
[afi
][safi
];
6881 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6882 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6883 if (pi
->peer
== bgp
->peer_self
6884 && ((pi
->type
== ZEBRA_ROUTE_BGP
6885 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6886 || (pi
->type
!= ZEBRA_ROUTE_BGP
6888 == BGP_ROUTE_REDISTRIBUTE
))) {
6889 bgp_aggregate_decrement(
6890 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6892 bgp_unlink_nexthop(pi
);
6893 bgp_path_info_delete(dest
, pi
);
6894 bgp_process(bgp
, dest
, afi
, safi
);
6901 * Purge all networks and redistributed routes from routing table.
6902 * Invoked upon the instance going down.
6904 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6909 FOREACH_AFI_SAFI (afi
, safi
)
6910 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6915 * Currently this is used to set static routes for VPN and ENCAP.
6916 * I think it can probably be factored with bgp_static_set.
6918 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6919 const char *ip_str
, const char *rd_str
,
6920 const char *label_str
, const char *rmap_str
,
6921 int evpn_type
, const char *esi
, const char *gwip
,
6922 const char *ethtag
, const char *routermac
)
6924 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6927 struct prefix_rd prd
;
6928 struct bgp_dest
*pdest
;
6929 struct bgp_dest
*dest
;
6930 struct bgp_table
*table
;
6931 struct bgp_static
*bgp_static
;
6932 mpls_label_t label
= MPLS_INVALID_LABEL
;
6933 struct prefix gw_ip
;
6935 /* validate ip prefix */
6936 ret
= str2prefix(ip_str
, &p
);
6938 vty_out(vty
, "%% Malformed prefix\n");
6939 return CMD_WARNING_CONFIG_FAILED
;
6942 if ((afi
== AFI_L2VPN
)
6943 && (bgp_build_evpn_prefix(evpn_type
,
6944 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6945 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6946 return CMD_WARNING_CONFIG_FAILED
;
6949 ret
= str2prefix_rd(rd_str
, &prd
);
6951 vty_out(vty
, "%% Malformed rd\n");
6952 return CMD_WARNING_CONFIG_FAILED
;
6956 unsigned long label_val
;
6957 label_val
= strtoul(label_str
, NULL
, 10);
6958 encode_label(label_val
, &label
);
6961 if (safi
== SAFI_EVPN
) {
6962 if (esi
&& str2esi(esi
, NULL
) == 0) {
6963 vty_out(vty
, "%% Malformed ESI\n");
6964 return CMD_WARNING_CONFIG_FAILED
;
6966 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6967 vty_out(vty
, "%% Malformed Router MAC\n");
6968 return CMD_WARNING_CONFIG_FAILED
;
6971 memset(&gw_ip
, 0, sizeof(gw_ip
));
6972 ret
= str2prefix(gwip
, &gw_ip
);
6974 vty_out(vty
, "%% Malformed GatewayIp\n");
6975 return CMD_WARNING_CONFIG_FAILED
;
6977 if ((gw_ip
.family
== AF_INET
6978 && is_evpn_prefix_ipaddr_v6(
6979 (struct prefix_evpn
*)&p
))
6980 || (gw_ip
.family
== AF_INET6
6981 && is_evpn_prefix_ipaddr_v4(
6982 (struct prefix_evpn
*)&p
))) {
6984 "%% GatewayIp family differs with IP prefix\n");
6985 return CMD_WARNING_CONFIG_FAILED
;
6989 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6990 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6991 bgp_dest_set_bgp_table_info(pdest
,
6992 bgp_table_init(bgp
, afi
, safi
));
6993 table
= bgp_dest_get_bgp_table_info(pdest
);
6995 dest
= bgp_node_get(table
, &p
);
6997 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6998 vty_out(vty
, "%% Same network configuration exists\n");
6999 bgp_dest_unlock_node(dest
);
7001 /* New configuration. */
7002 bgp_static
= bgp_static_new();
7003 bgp_static
->backdoor
= 0;
7004 bgp_static
->valid
= 0;
7005 bgp_static
->igpmetric
= 0;
7006 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7007 bgp_static
->label
= label
;
7008 bgp_static
->prd
= prd
;
7011 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7012 route_map_counter_decrement(bgp_static
->rmap
.map
);
7013 bgp_static
->rmap
.name
=
7014 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7015 bgp_static
->rmap
.map
=
7016 route_map_lookup_by_name(rmap_str
);
7017 route_map_counter_increment(bgp_static
->rmap
.map
);
7020 if (safi
== SAFI_EVPN
) {
7022 bgp_static
->eth_s_id
=
7025 str2esi(esi
, bgp_static
->eth_s_id
);
7028 bgp_static
->router_mac
=
7029 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7030 (void)prefix_str2mac(routermac
,
7031 bgp_static
->router_mac
);
7034 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7036 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7038 bgp_static
->valid
= 1;
7039 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7045 /* Configure static BGP network. */
7046 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7047 const char *ip_str
, const char *rd_str
,
7048 const char *label_str
, int evpn_type
, const char *esi
,
7049 const char *gwip
, const char *ethtag
)
7051 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7054 struct prefix_rd prd
;
7055 struct bgp_dest
*pdest
;
7056 struct bgp_dest
*dest
;
7057 struct bgp_table
*table
;
7058 struct bgp_static
*bgp_static
;
7059 mpls_label_t label
= MPLS_INVALID_LABEL
;
7061 /* Convert IP prefix string to struct prefix. */
7062 ret
= str2prefix(ip_str
, &p
);
7064 vty_out(vty
, "%% Malformed prefix\n");
7065 return CMD_WARNING_CONFIG_FAILED
;
7068 if ((afi
== AFI_L2VPN
)
7069 && (bgp_build_evpn_prefix(evpn_type
,
7070 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7071 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7072 return CMD_WARNING_CONFIG_FAILED
;
7074 ret
= str2prefix_rd(rd_str
, &prd
);
7076 vty_out(vty
, "%% Malformed rd\n");
7077 return CMD_WARNING_CONFIG_FAILED
;
7081 unsigned long label_val
;
7082 label_val
= strtoul(label_str
, NULL
, 10);
7083 encode_label(label_val
, &label
);
7086 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7087 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7088 bgp_dest_set_bgp_table_info(pdest
,
7089 bgp_table_init(bgp
, afi
, safi
));
7091 bgp_dest_unlock_node(pdest
);
7092 table
= bgp_dest_get_bgp_table_info(pdest
);
7094 dest
= bgp_node_lookup(table
, &p
);
7097 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7099 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7100 bgp_static_free(bgp_static
);
7101 bgp_dest_set_bgp_static_info(dest
, NULL
);
7102 bgp_dest_unlock_node(dest
);
7103 bgp_dest_unlock_node(dest
);
7105 vty_out(vty
, "%% Can't find the route\n");
7110 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7111 const char *rmap_name
)
7113 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7114 struct bgp_rmap
*rmap
;
7116 rmap
= &bgp
->table_map
[afi
][safi
];
7118 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7119 route_map_counter_decrement(rmap
->map
);
7120 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7121 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7122 route_map_counter_increment(rmap
->map
);
7124 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7125 route_map_counter_decrement(rmap
->map
);
7129 if (bgp_fibupd_safi(safi
))
7130 bgp_zebra_announce_table(bgp
, afi
, safi
);
7135 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7136 const char *rmap_name
)
7138 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7139 struct bgp_rmap
*rmap
;
7141 rmap
= &bgp
->table_map
[afi
][safi
];
7142 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7143 route_map_counter_decrement(rmap
->map
);
7146 if (bgp_fibupd_safi(safi
))
7147 bgp_zebra_announce_table(bgp
, afi
, safi
);
7152 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7155 if (bgp
->table_map
[afi
][safi
].name
) {
7156 vty_out(vty
, " table-map %s\n",
7157 bgp
->table_map
[afi
][safi
].name
);
7161 DEFUN (bgp_table_map
,
7164 "BGP table to RIB route download filter\n"
7165 "Name of the route map\n")
7168 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7169 argv
[idx_word
]->arg
);
7171 DEFUN (no_bgp_table_map
,
7172 no_bgp_table_map_cmd
,
7173 "no table-map WORD",
7175 "BGP table to RIB route download filter\n"
7176 "Name of the route map\n")
7179 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7180 argv
[idx_word
]->arg
);
7186 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7187 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7188 backdoor$backdoor}]",
7190 "Specify a network to announce via BGP\n"
7195 "Route-map to modify the attributes\n"
7196 "Name of the route map\n"
7197 "Label index to associate with the prefix\n"
7198 "Label index value\n"
7199 "Specify a BGP backdoor route\n")
7201 char addr_prefix_str
[BUFSIZ
];
7206 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7208 sizeof(addr_prefix_str
));
7210 vty_out(vty
, "%% Inconsistent address and mask\n");
7211 return CMD_WARNING_CONFIG_FAILED
;
7215 return bgp_static_set(
7216 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7217 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7218 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7221 DEFPY(ipv6_bgp_network
,
7222 ipv6_bgp_network_cmd
,
7223 "[no] network X:X::X:X/M$prefix \
7224 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7226 "Specify a network to announce via BGP\n"
7228 "Route-map to modify the attributes\n"
7229 "Name of the route map\n"
7230 "Label index to associate with the prefix\n"
7231 "Label index value\n")
7233 return bgp_static_set(
7234 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7235 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7238 static struct bgp_aggregate
*bgp_aggregate_new(void)
7240 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7243 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7245 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7246 route_map_counter_decrement(aggregate
->suppress_map
);
7247 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7248 route_map_counter_decrement(aggregate
->rmap
.map
);
7249 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7253 * Helper function to avoid repeated code: prepare variables for a
7254 * `route_map_apply` call.
7256 * \returns `true` on route map match, otherwise `false`.
7258 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7259 struct bgp_aggregate
*aggregate
,
7260 struct bgp_path_info
*pi
)
7262 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7263 route_map_result_t rmr
= RMAP_DENYMATCH
;
7264 struct bgp_path_info rmap_path
= {};
7265 struct attr attr
= {};
7267 /* No route map entries created, just don't match. */
7268 if (aggregate
->suppress_map
== NULL
)
7271 /* Call route map matching and return result. */
7272 attr
.aspath
= aspath_empty();
7273 rmap_path
.peer
= bgp
->peer_self
;
7274 rmap_path
.attr
= &attr
;
7276 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7277 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7278 bgp
->peer_self
->rmap_type
= 0;
7280 bgp_attr_flush(&attr
);
7281 aspath_unintern(&attr
.aspath
);
7283 return rmr
== RMAP_PERMITMATCH
;
7286 /** Test whether the aggregation has suppressed this path or not. */
7287 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7288 struct bgp_path_info
*pi
)
7290 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7293 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7297 * Suppress this path and keep the reference.
7299 * \returns `true` if needs processing otherwise `false`.
7301 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7302 struct bgp_path_info
*pi
)
7304 struct bgp_path_info_extra
*pie
;
7306 /* Path is already suppressed by this aggregation. */
7307 if (aggr_suppress_exists(aggregate
, pi
))
7310 pie
= bgp_path_info_extra_get(pi
);
7312 /* This is the first suppression, allocate memory and list it. */
7313 if (pie
->aggr_suppressors
== NULL
)
7314 pie
->aggr_suppressors
= list_new();
7316 listnode_add(pie
->aggr_suppressors
, aggregate
);
7318 /* Only mark for processing if suppressed. */
7319 if (listcount(pie
->aggr_suppressors
) == 1) {
7320 if (BGP_DEBUG(update
, UPDATE_OUT
))
7321 zlog_debug("aggregate-address suppressing: %pFX",
7322 bgp_dest_get_prefix(pi
->net
));
7324 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7332 * Unsuppress this path and remove the reference.
7334 * \returns `true` if needs processing otherwise `false`.
7336 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7337 struct bgp_path_info
*pi
)
7339 /* Path wasn't suppressed. */
7340 if (!aggr_suppress_exists(aggregate
, pi
))
7343 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7345 /* Unsuppress and free extra memory if last item. */
7346 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7347 if (BGP_DEBUG(update
, UPDATE_OUT
))
7348 zlog_debug("aggregate-address unsuppressing: %pFX",
7349 bgp_dest_get_prefix(pi
->net
));
7351 list_delete(&pi
->extra
->aggr_suppressors
);
7352 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7359 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7360 struct aspath
*aspath
,
7361 struct community
*comm
,
7362 struct ecommunity
*ecomm
,
7363 struct lcommunity
*lcomm
)
7365 static struct aspath
*ae
= NULL
;
7368 ae
= aspath_empty();
7373 if (origin
!= pi
->attr
->origin
)
7376 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7379 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7382 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7385 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7388 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7394 static void bgp_aggregate_install(
7395 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7396 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7397 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7398 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7400 struct bgp_dest
*dest
;
7401 struct bgp_table
*table
;
7402 struct bgp_path_info
*pi
, *orig
, *new;
7405 table
= bgp
->rib
[afi
][safi
];
7407 dest
= bgp_node_get(table
, p
);
7409 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7410 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7411 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7415 * If we have paths with different MEDs, then don't install
7416 * (or uninstall) the aggregate route.
7418 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7419 goto uninstall_aggregate_route
;
7421 if (aggregate
->count
> 0) {
7423 * If the aggregate information has not changed
7424 * no need to re-install it again.
7426 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7427 ecommunity
, lcommunity
)) {
7428 bgp_dest_unlock_node(dest
);
7431 aspath_free(aspath
);
7433 community_free(&community
);
7435 ecommunity_free(&ecommunity
);
7437 lcommunity_free(&lcommunity
);
7443 * Mark the old as unusable
7446 bgp_path_info_delete(dest
, pi
);
7448 attr
= bgp_attr_aggregate_intern(
7449 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7450 aggregate
, atomic_aggregate
, p
);
7453 bgp_dest_unlock_node(dest
);
7454 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7455 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7456 zlog_debug("%s: %pFX null attribute", __func__
,
7461 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7462 bgp
->peer_self
, attr
, dest
);
7464 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7466 bgp_path_info_add(dest
, new);
7467 bgp_process(bgp
, dest
, afi
, safi
);
7469 uninstall_aggregate_route
:
7470 for (pi
= orig
; pi
; pi
= pi
->next
)
7471 if (pi
->peer
== bgp
->peer_self
7472 && pi
->type
== ZEBRA_ROUTE_BGP
7473 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7476 /* Withdraw static BGP route from routing table. */
7478 bgp_path_info_delete(dest
, pi
);
7479 bgp_process(bgp
, dest
, afi
, safi
);
7483 bgp_dest_unlock_node(dest
);
7487 * Check if the current path has different MED than other known paths.
7489 * \returns `true` if the MED matched the others else `false`.
7491 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7492 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7494 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7496 /* This is the first route being analyzed. */
7497 if (!aggregate
->med_initialized
) {
7498 aggregate
->med_initialized
= true;
7499 aggregate
->med_mismatched
= false;
7500 aggregate
->med_matched_value
= cur_med
;
7502 /* Check if routes with different MED showed up. */
7503 if (cur_med
!= aggregate
->med_matched_value
)
7504 aggregate
->med_mismatched
= true;
7507 return !aggregate
->med_mismatched
;
7511 * Initializes and tests all routes in the aggregate address path for MED
7514 * \returns `true` if all MEDs are the same otherwise `false`.
7516 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7517 struct bgp
*bgp
, const struct prefix
*p
,
7518 afi_t afi
, safi_t safi
)
7520 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7521 const struct prefix
*dest_p
;
7522 struct bgp_dest
*dest
, *top
;
7523 struct bgp_path_info
*pi
;
7524 bool med_matched
= true;
7526 aggregate
->med_initialized
= false;
7528 top
= bgp_node_get(table
, p
);
7529 for (dest
= bgp_node_get(table
, p
); dest
;
7530 dest
= bgp_route_next_until(dest
, top
)) {
7531 dest_p
= bgp_dest_get_prefix(dest
);
7532 if (dest_p
->prefixlen
<= p
->prefixlen
)
7535 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7536 if (BGP_PATH_HOLDDOWN(pi
))
7538 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7540 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7541 med_matched
= false;
7548 bgp_dest_unlock_node(top
);
7554 * Toggles the route suppression status for this aggregate address
7557 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7558 struct bgp
*bgp
, const struct prefix
*p
,
7559 afi_t afi
, safi_t safi
, bool suppress
)
7561 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7562 const struct prefix
*dest_p
;
7563 struct bgp_dest
*dest
, *top
;
7564 struct bgp_path_info
*pi
;
7565 bool toggle_suppression
;
7567 /* We've found a different MED we must revert any suppressed routes. */
7568 top
= bgp_node_get(table
, p
);
7569 for (dest
= bgp_node_get(table
, p
); dest
;
7570 dest
= bgp_route_next_until(dest
, top
)) {
7571 dest_p
= bgp_dest_get_prefix(dest
);
7572 if (dest_p
->prefixlen
<= p
->prefixlen
)
7575 toggle_suppression
= false;
7576 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7577 if (BGP_PATH_HOLDDOWN(pi
))
7579 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7582 /* We are toggling suppression back. */
7584 /* Suppress route if not suppressed already. */
7585 if (aggr_suppress_path(aggregate
, pi
))
7586 toggle_suppression
= true;
7590 /* Install route if there is no more suppression. */
7591 if (aggr_unsuppress_path(aggregate
, pi
))
7592 toggle_suppression
= true;
7595 if (toggle_suppression
)
7596 bgp_process(bgp
, dest
, afi
, safi
);
7598 bgp_dest_unlock_node(top
);
7602 * Aggregate address MED matching incremental test: this function is called
7603 * when the initial aggregation occurred and we are only testing a single
7606 * In addition to testing and setting the MED validity it also installs back
7607 * suppressed routes (if summary is configured).
7609 * Must not be called in `bgp_aggregate_route`.
7611 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7612 struct bgp
*bgp
, const struct prefix
*p
,
7613 afi_t afi
, safi_t safi
,
7614 struct bgp_path_info
*pi
)
7616 /* MED matching disabled. */
7617 if (!aggregate
->match_med
)
7620 /* Aggregation with different MED, recheck if we have got equal MEDs
7623 if (aggregate
->med_mismatched
&&
7624 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7625 aggregate
->summary_only
)
7626 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7629 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7631 /* No mismatches, just quit. */
7632 if (!aggregate
->med_mismatched
)
7635 /* Route summarization is disabled. */
7636 if (!aggregate
->summary_only
)
7639 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7642 /* Update an aggregate as routes are added/removed from the BGP table */
7643 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7644 safi_t safi
, struct bgp_aggregate
*aggregate
)
7646 struct bgp_table
*table
;
7647 struct bgp_dest
*top
;
7648 struct bgp_dest
*dest
;
7650 struct aspath
*aspath
= NULL
;
7651 struct community
*community
= NULL
;
7652 struct ecommunity
*ecommunity
= NULL
;
7653 struct lcommunity
*lcommunity
= NULL
;
7654 struct bgp_path_info
*pi
;
7655 unsigned long match
= 0;
7656 uint8_t atomic_aggregate
= 0;
7658 /* If the bgp instance is being deleted or self peer is deleted
7659 * then do not create aggregate route
7661 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7662 || (bgp
->peer_self
== NULL
))
7665 /* Initialize and test routes for MED difference. */
7666 if (aggregate
->match_med
)
7667 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7670 * Reset aggregate count: we might've been called from route map
7671 * update so in that case we must retest all more specific routes.
7673 * \see `bgp_route_map_process_update`.
7675 aggregate
->count
= 0;
7676 aggregate
->incomplete_origin_count
= 0;
7677 aggregate
->incomplete_origin_count
= 0;
7678 aggregate
->egp_origin_count
= 0;
7680 /* ORIGIN attribute: If at least one route among routes that are
7681 aggregated has ORIGIN with the value INCOMPLETE, then the
7682 aggregated route must have the ORIGIN attribute with the value
7683 INCOMPLETE. Otherwise, if at least one route among routes that
7684 are aggregated has ORIGIN with the value EGP, then the aggregated
7685 route must have the origin attribute with the value EGP. In all
7686 other case the value of the ORIGIN attribute of the aggregated
7687 route is INTERNAL. */
7688 origin
= BGP_ORIGIN_IGP
;
7690 table
= bgp
->rib
[afi
][safi
];
7692 top
= bgp_node_get(table
, p
);
7693 for (dest
= bgp_node_get(table
, p
); dest
;
7694 dest
= bgp_route_next_until(dest
, top
)) {
7695 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7697 if (dest_p
->prefixlen
<= p
->prefixlen
)
7700 /* If suppress fib is enabled and route not installed
7701 * in FIB, skip the route
7703 if (!bgp_check_advertise(bgp
, dest
))
7708 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7709 if (BGP_PATH_HOLDDOWN(pi
))
7713 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7714 atomic_aggregate
= 1;
7716 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7720 * summary-only aggregate route suppress
7721 * aggregated route announcements.
7724 * Don't create summaries if MED didn't match
7725 * otherwise neither the specific routes and the
7726 * aggregation will be announced.
7728 if (aggregate
->summary_only
7729 && AGGREGATE_MED_VALID(aggregate
)) {
7730 if (aggr_suppress_path(aggregate
, pi
))
7735 * Suppress more specific routes that match the route
7739 * Don't suppress routes if MED matching is enabled and
7740 * it mismatched otherwise we might end up with no
7741 * routes for this path.
7743 if (aggregate
->suppress_map_name
7744 && AGGREGATE_MED_VALID(aggregate
)
7745 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7746 if (aggr_suppress_path(aggregate
, pi
))
7753 * If at least one route among routes that are
7754 * aggregated has ORIGIN with the value INCOMPLETE,
7755 * then the aggregated route MUST have the ORIGIN
7756 * attribute with the value INCOMPLETE. Otherwise, if
7757 * at least one route among routes that are aggregated
7758 * has ORIGIN with the value EGP, then the aggregated
7759 * route MUST have the ORIGIN attribute with the value
7762 switch (pi
->attr
->origin
) {
7763 case BGP_ORIGIN_INCOMPLETE
:
7764 aggregate
->incomplete_origin_count
++;
7766 case BGP_ORIGIN_EGP
:
7767 aggregate
->egp_origin_count
++;
7775 if (!aggregate
->as_set
)
7779 * as-set aggregate route generate origin, as path,
7780 * and community aggregation.
7782 /* Compute aggregate route's as-path.
7784 bgp_compute_aggregate_aspath_hash(aggregate
,
7787 /* Compute aggregate route's community.
7789 if (bgp_attr_get_community(pi
->attr
))
7790 bgp_compute_aggregate_community_hash(
7792 bgp_attr_get_community(pi
->attr
));
7794 /* Compute aggregate route's extended community.
7796 if (bgp_attr_get_ecommunity(pi
->attr
))
7797 bgp_compute_aggregate_ecommunity_hash(
7799 bgp_attr_get_ecommunity(pi
->attr
));
7801 /* Compute aggregate route's large community.
7803 if (bgp_attr_get_lcommunity(pi
->attr
))
7804 bgp_compute_aggregate_lcommunity_hash(
7806 bgp_attr_get_lcommunity(pi
->attr
));
7809 bgp_process(bgp
, dest
, afi
, safi
);
7811 if (aggregate
->as_set
) {
7812 bgp_compute_aggregate_aspath_val(aggregate
);
7813 bgp_compute_aggregate_community_val(aggregate
);
7814 bgp_compute_aggregate_ecommunity_val(aggregate
);
7815 bgp_compute_aggregate_lcommunity_val(aggregate
);
7819 bgp_dest_unlock_node(top
);
7822 if (aggregate
->incomplete_origin_count
> 0)
7823 origin
= BGP_ORIGIN_INCOMPLETE
;
7824 else if (aggregate
->egp_origin_count
> 0)
7825 origin
= BGP_ORIGIN_EGP
;
7827 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7828 origin
= aggregate
->origin
;
7830 if (aggregate
->as_set
) {
7831 if (aggregate
->aspath
)
7832 /* Retrieve aggregate route's as-path.
7834 aspath
= aspath_dup(aggregate
->aspath
);
7836 if (aggregate
->community
)
7837 /* Retrieve aggregate route's community.
7839 community
= community_dup(aggregate
->community
);
7841 if (aggregate
->ecommunity
)
7842 /* Retrieve aggregate route's ecommunity.
7844 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7846 if (aggregate
->lcommunity
)
7847 /* Retrieve aggregate route's lcommunity.
7849 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7852 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7853 ecommunity
, lcommunity
, atomic_aggregate
,
7857 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7858 safi_t safi
, struct bgp_aggregate
*aggregate
)
7860 struct bgp_table
*table
;
7861 struct bgp_dest
*top
;
7862 struct bgp_dest
*dest
;
7863 struct bgp_path_info
*pi
;
7864 unsigned long match
;
7866 table
= bgp
->rib
[afi
][safi
];
7868 /* If routes exists below this node, generate aggregate routes. */
7869 top
= bgp_node_get(table
, p
);
7870 for (dest
= bgp_node_get(table
, p
); dest
;
7871 dest
= bgp_route_next_until(dest
, top
)) {
7872 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7874 if (dest_p
->prefixlen
<= p
->prefixlen
)
7878 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7879 if (BGP_PATH_HOLDDOWN(pi
))
7882 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7886 * This route is suppressed: attempt to unsuppress it.
7888 * `aggr_unsuppress_path` will fail if this particular
7889 * aggregate route was not the suppressor.
7891 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7892 listcount(pi
->extra
->aggr_suppressors
)) {
7893 if (aggr_unsuppress_path(aggregate
, pi
))
7899 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7900 aggregate
->incomplete_origin_count
--;
7901 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7902 aggregate
->egp_origin_count
--;
7904 if (aggregate
->as_set
) {
7905 /* Remove as-path from aggregate.
7907 bgp_remove_aspath_from_aggregate_hash(
7911 if (bgp_attr_get_community(pi
->attr
))
7912 /* Remove community from aggregate.
7914 bgp_remove_comm_from_aggregate_hash(
7916 bgp_attr_get_community(
7919 if (bgp_attr_get_ecommunity(pi
->attr
))
7920 /* Remove ecommunity from aggregate.
7922 bgp_remove_ecomm_from_aggregate_hash(
7924 bgp_attr_get_ecommunity(
7927 if (bgp_attr_get_lcommunity(pi
->attr
))
7928 /* Remove lcommunity from aggregate.
7930 bgp_remove_lcomm_from_aggregate_hash(
7932 bgp_attr_get_lcommunity(
7937 /* If this node was suppressed, process the change. */
7939 bgp_process(bgp
, dest
, afi
, safi
);
7941 if (aggregate
->as_set
) {
7942 aspath_free(aggregate
->aspath
);
7943 aggregate
->aspath
= NULL
;
7944 if (aggregate
->community
)
7945 community_free(&aggregate
->community
);
7946 if (aggregate
->ecommunity
)
7947 ecommunity_free(&aggregate
->ecommunity
);
7948 if (aggregate
->lcommunity
)
7949 lcommunity_free(&aggregate
->lcommunity
);
7952 bgp_dest_unlock_node(top
);
7955 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7956 const struct prefix
*aggr_p
,
7957 struct bgp_path_info
*pinew
, afi_t afi
,
7959 struct bgp_aggregate
*aggregate
)
7962 struct aspath
*aspath
= NULL
;
7963 uint8_t atomic_aggregate
= 0;
7964 struct community
*community
= NULL
;
7965 struct ecommunity
*ecommunity
= NULL
;
7966 struct lcommunity
*lcommunity
= NULL
;
7968 /* If the bgp instance is being deleted or self peer is deleted
7969 * then do not create aggregate route
7971 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7972 || (bgp
->peer_self
== NULL
))
7975 /* ORIGIN attribute: If at least one route among routes that are
7976 * aggregated has ORIGIN with the value INCOMPLETE, then the
7977 * aggregated route must have the ORIGIN attribute with the value
7978 * INCOMPLETE. Otherwise, if at least one route among routes that
7979 * are aggregated has ORIGIN with the value EGP, then the aggregated
7980 * route must have the origin attribute with the value EGP. In all
7981 * other case the value of the ORIGIN attribute of the aggregated
7982 * route is INTERNAL.
7984 origin
= BGP_ORIGIN_IGP
;
7989 * This must be called before `summary` check to avoid
7990 * "suppressing" twice.
7992 if (aggregate
->match_med
)
7993 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7996 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7997 aggr_suppress_path(aggregate
, pinew
);
7999 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8000 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8001 aggr_suppress_path(aggregate
, pinew
);
8003 switch (pinew
->attr
->origin
) {
8004 case BGP_ORIGIN_INCOMPLETE
:
8005 aggregate
->incomplete_origin_count
++;
8007 case BGP_ORIGIN_EGP
:
8008 aggregate
->egp_origin_count
++;
8016 if (aggregate
->incomplete_origin_count
> 0)
8017 origin
= BGP_ORIGIN_INCOMPLETE
;
8018 else if (aggregate
->egp_origin_count
> 0)
8019 origin
= BGP_ORIGIN_EGP
;
8021 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8022 origin
= aggregate
->origin
;
8024 if (aggregate
->as_set
) {
8025 /* Compute aggregate route's as-path.
8027 bgp_compute_aggregate_aspath(aggregate
,
8028 pinew
->attr
->aspath
);
8030 /* Compute aggregate route's community.
8032 if (bgp_attr_get_community(pinew
->attr
))
8033 bgp_compute_aggregate_community(
8034 aggregate
, bgp_attr_get_community(pinew
->attr
));
8036 /* Compute aggregate route's extended community.
8038 if (bgp_attr_get_ecommunity(pinew
->attr
))
8039 bgp_compute_aggregate_ecommunity(
8041 bgp_attr_get_ecommunity(pinew
->attr
));
8043 /* Compute aggregate route's large community.
8045 if (bgp_attr_get_lcommunity(pinew
->attr
))
8046 bgp_compute_aggregate_lcommunity(
8048 bgp_attr_get_lcommunity(pinew
->attr
));
8050 /* Retrieve aggregate route's as-path.
8052 if (aggregate
->aspath
)
8053 aspath
= aspath_dup(aggregate
->aspath
);
8055 /* Retrieve aggregate route's community.
8057 if (aggregate
->community
)
8058 community
= community_dup(aggregate
->community
);
8060 /* Retrieve aggregate route's ecommunity.
8062 if (aggregate
->ecommunity
)
8063 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8065 /* Retrieve aggregate route's lcommunity.
8067 if (aggregate
->lcommunity
)
8068 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8071 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8072 aspath
, community
, ecommunity
,
8073 lcommunity
, atomic_aggregate
, aggregate
);
8076 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8078 struct bgp_path_info
*pi
,
8079 struct bgp_aggregate
*aggregate
,
8080 const struct prefix
*aggr_p
)
8083 struct aspath
*aspath
= NULL
;
8084 uint8_t atomic_aggregate
= 0;
8085 struct community
*community
= NULL
;
8086 struct ecommunity
*ecommunity
= NULL
;
8087 struct lcommunity
*lcommunity
= NULL
;
8088 unsigned long match
= 0;
8090 /* If the bgp instance is being deleted or self peer is deleted
8091 * then do not create aggregate route
8093 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8094 || (bgp
->peer_self
== NULL
))
8097 if (BGP_PATH_HOLDDOWN(pi
))
8100 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8103 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8104 if (aggr_unsuppress_path(aggregate
, pi
))
8107 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8108 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8109 if (aggr_unsuppress_path(aggregate
, pi
))
8113 * This must be called after `summary`, `suppress-map` check to avoid
8114 * "unsuppressing" twice.
8116 if (aggregate
->match_med
)
8117 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8119 if (aggregate
->count
> 0)
8122 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8123 aggregate
->incomplete_origin_count
--;
8124 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8125 aggregate
->egp_origin_count
--;
8127 if (aggregate
->as_set
) {
8128 /* Remove as-path from aggregate.
8130 bgp_remove_aspath_from_aggregate(aggregate
,
8133 if (bgp_attr_get_community(pi
->attr
))
8134 /* Remove community from aggregate.
8136 bgp_remove_community_from_aggregate(
8137 aggregate
, bgp_attr_get_community(pi
->attr
));
8139 if (bgp_attr_get_ecommunity(pi
->attr
))
8140 /* Remove ecommunity from aggregate.
8142 bgp_remove_ecommunity_from_aggregate(
8143 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8145 if (bgp_attr_get_lcommunity(pi
->attr
))
8146 /* Remove lcommunity from aggregate.
8148 bgp_remove_lcommunity_from_aggregate(
8149 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8152 /* If this node was suppressed, process the change. */
8154 bgp_process(bgp
, pi
->net
, afi
, safi
);
8156 origin
= BGP_ORIGIN_IGP
;
8157 if (aggregate
->incomplete_origin_count
> 0)
8158 origin
= BGP_ORIGIN_INCOMPLETE
;
8159 else if (aggregate
->egp_origin_count
> 0)
8160 origin
= BGP_ORIGIN_EGP
;
8162 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8163 origin
= aggregate
->origin
;
8165 if (aggregate
->as_set
) {
8166 /* Retrieve aggregate route's as-path.
8168 if (aggregate
->aspath
)
8169 aspath
= aspath_dup(aggregate
->aspath
);
8171 /* Retrieve aggregate route's community.
8173 if (aggregate
->community
)
8174 community
= community_dup(aggregate
->community
);
8176 /* Retrieve aggregate route's ecommunity.
8178 if (aggregate
->ecommunity
)
8179 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8181 /* Retrieve aggregate route's lcommunity.
8183 if (aggregate
->lcommunity
)
8184 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8187 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8188 aspath
, community
, ecommunity
,
8189 lcommunity
, atomic_aggregate
, aggregate
);
8192 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8193 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8195 struct bgp_dest
*child
;
8196 struct bgp_dest
*dest
;
8197 struct bgp_aggregate
*aggregate
;
8198 struct bgp_table
*table
;
8200 table
= bgp
->aggregate
[afi
][safi
];
8202 /* No aggregates configured. */
8203 if (bgp_table_top_nolock(table
) == NULL
)
8206 if (p
->prefixlen
== 0)
8209 if (BGP_PATH_HOLDDOWN(pi
))
8212 /* If suppress fib is enabled and route not installed
8213 * in FIB, do not update the aggregate route
8215 if (!bgp_check_advertise(bgp
, pi
->net
))
8218 child
= bgp_node_get(table
, p
);
8220 /* Aggregate address configuration check. */
8221 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8222 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8224 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8225 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8226 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8230 bgp_dest_unlock_node(child
);
8233 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8234 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8236 struct bgp_dest
*child
;
8237 struct bgp_dest
*dest
;
8238 struct bgp_aggregate
*aggregate
;
8239 struct bgp_table
*table
;
8241 table
= bgp
->aggregate
[afi
][safi
];
8243 /* No aggregates configured. */
8244 if (bgp_table_top_nolock(table
) == NULL
)
8247 if (p
->prefixlen
== 0)
8250 child
= bgp_node_get(table
, p
);
8252 /* Aggregate address configuration check. */
8253 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8254 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8256 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8257 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8258 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8262 bgp_dest_unlock_node(child
);
8265 /* Aggregate route attribute. */
8266 #define AGGREGATE_SUMMARY_ONLY 1
8267 #define AGGREGATE_AS_SET 1
8268 #define AGGREGATE_AS_UNSET 0
8270 static const char *bgp_origin2str(uint8_t origin
)
8273 case BGP_ORIGIN_IGP
:
8275 case BGP_ORIGIN_EGP
:
8277 case BGP_ORIGIN_INCOMPLETE
:
8278 return "incomplete";
8283 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8286 case RPKI_NOT_BEING_USED
:
8296 assert(!"We should never get here this is a dev escape");
8300 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8301 afi_t afi
, safi_t safi
)
8303 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8306 struct bgp_dest
*dest
;
8307 struct bgp_aggregate
*aggregate
;
8309 /* Convert string to prefix structure. */
8310 ret
= str2prefix(prefix_str
, &p
);
8312 vty_out(vty
, "Malformed prefix\n");
8313 return CMD_WARNING_CONFIG_FAILED
;
8317 /* Old configuration check. */
8318 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8321 "%% There is no aggregate-address configuration.\n");
8322 return CMD_WARNING_CONFIG_FAILED
;
8325 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8326 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8327 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8328 NULL
, NULL
, 0, aggregate
);
8330 /* Unlock aggregate address configuration. */
8331 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8333 if (aggregate
->community
)
8334 community_free(&aggregate
->community
);
8336 if (aggregate
->community_hash
) {
8337 /* Delete all communities in the hash.
8339 hash_clean(aggregate
->community_hash
,
8340 bgp_aggr_community_remove
);
8341 /* Free up the community_hash.
8343 hash_free(aggregate
->community_hash
);
8346 if (aggregate
->ecommunity
)
8347 ecommunity_free(&aggregate
->ecommunity
);
8349 if (aggregate
->ecommunity_hash
) {
8350 /* Delete all ecommunities in the hash.
8352 hash_clean(aggregate
->ecommunity_hash
,
8353 bgp_aggr_ecommunity_remove
);
8354 /* Free up the ecommunity_hash.
8356 hash_free(aggregate
->ecommunity_hash
);
8359 if (aggregate
->lcommunity
)
8360 lcommunity_free(&aggregate
->lcommunity
);
8362 if (aggregate
->lcommunity_hash
) {
8363 /* Delete all lcommunities in the hash.
8365 hash_clean(aggregate
->lcommunity_hash
,
8366 bgp_aggr_lcommunity_remove
);
8367 /* Free up the lcommunity_hash.
8369 hash_free(aggregate
->lcommunity_hash
);
8372 if (aggregate
->aspath
)
8373 aspath_free(aggregate
->aspath
);
8375 if (aggregate
->aspath_hash
) {
8376 /* Delete all as-paths in the hash.
8378 hash_clean(aggregate
->aspath_hash
,
8379 bgp_aggr_aspath_remove
);
8380 /* Free up the aspath_hash.
8382 hash_free(aggregate
->aspath_hash
);
8385 bgp_aggregate_free(aggregate
);
8386 bgp_dest_unlock_node(dest
);
8387 bgp_dest_unlock_node(dest
);
8392 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8393 safi_t safi
, const char *rmap
,
8394 uint8_t summary_only
, uint8_t as_set
,
8395 uint8_t origin
, bool match_med
,
8396 const char *suppress_map
)
8398 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8401 struct bgp_dest
*dest
;
8402 struct bgp_aggregate
*aggregate
;
8403 uint8_t as_set_new
= as_set
;
8405 if (suppress_map
&& summary_only
) {
8407 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8408 return CMD_WARNING_CONFIG_FAILED
;
8411 /* Convert string to prefix structure. */
8412 ret
= str2prefix(prefix_str
, &p
);
8414 vty_out(vty
, "Malformed prefix\n");
8415 return CMD_WARNING_CONFIG_FAILED
;
8419 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8420 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8421 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8423 return CMD_WARNING_CONFIG_FAILED
;
8426 /* Old configuration check. */
8427 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8428 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8431 vty_out(vty
, "There is already same aggregate network.\n");
8432 /* try to remove the old entry */
8433 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8435 vty_out(vty
, "Error deleting aggregate.\n");
8436 bgp_dest_unlock_node(dest
);
8437 return CMD_WARNING_CONFIG_FAILED
;
8441 /* Make aggregate address structure. */
8442 aggregate
= bgp_aggregate_new();
8443 aggregate
->summary_only
= summary_only
;
8444 aggregate
->match_med
= match_med
;
8446 /* Network operators MUST NOT locally generate any new
8447 * announcements containing AS_SET or AS_CONFED_SET. If they have
8448 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8449 * SHOULD withdraw those routes and re-announce routes for the
8450 * aggregate or component prefixes (i.e., the more-specific routes
8451 * subsumed by the previously aggregated route) without AS_SET
8452 * or AS_CONFED_SET in the updates.
8454 if (bgp
->reject_as_sets
) {
8455 if (as_set
== AGGREGATE_AS_SET
) {
8456 as_set_new
= AGGREGATE_AS_UNSET
;
8458 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8461 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8465 aggregate
->as_set
= as_set_new
;
8466 aggregate
->safi
= safi
;
8467 /* Override ORIGIN attribute if defined.
8468 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8469 * to IGP which is not what rfc4271 says.
8470 * This enables the same behavior, optionally.
8472 aggregate
->origin
= origin
;
8475 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8476 route_map_counter_decrement(aggregate
->rmap
.map
);
8477 aggregate
->rmap
.name
=
8478 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8479 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8480 route_map_counter_increment(aggregate
->rmap
.map
);
8484 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8485 route_map_counter_decrement(aggregate
->suppress_map
);
8487 aggregate
->suppress_map_name
=
8488 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8489 aggregate
->suppress_map
=
8490 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8491 route_map_counter_increment(aggregate
->suppress_map
);
8494 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8496 /* Aggregate address insert into BGP routing table. */
8497 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8502 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8503 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8505 "|summary-only$summary_only"
8506 "|route-map RMAP_NAME$rmap_name"
8507 "|origin <egp|igp|incomplete>$origin_s"
8508 "|matching-MED-only$match_med"
8509 "|suppress-map RMAP_NAME$suppress_map"
8512 "Configure BGP aggregate entries\n"
8513 "Aggregate prefix\n"
8514 "Aggregate address\n"
8516 "Generate AS set path information\n"
8517 "Filter more specific routes from updates\n"
8518 "Apply route map to aggregate network\n"
8523 "Unknown heritage\n"
8524 "Only aggregate routes with matching MED\n"
8525 "Suppress the selected more specific routes\n"
8526 "Route map with the route selectors\n")
8528 const char *prefix_s
= NULL
;
8529 safi_t safi
= bgp_node_safi(vty
);
8530 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8531 int as_set
= AGGREGATE_AS_UNSET
;
8532 char prefix_buf
[PREFIX2STR_BUFFER
];
8535 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8538 vty_out(vty
, "%% Inconsistent address and mask\n");
8539 return CMD_WARNING_CONFIG_FAILED
;
8541 prefix_s
= prefix_buf
;
8543 prefix_s
= prefix_str
;
8546 if (strcmp(origin_s
, "egp") == 0)
8547 origin
= BGP_ORIGIN_EGP
;
8548 else if (strcmp(origin_s
, "igp") == 0)
8549 origin
= BGP_ORIGIN_IGP
;
8550 else if (strcmp(origin_s
, "incomplete") == 0)
8551 origin
= BGP_ORIGIN_INCOMPLETE
;
8555 as_set
= AGGREGATE_AS_SET
;
8557 /* Handle configuration removal, otherwise installation. */
8559 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8561 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8562 summary_only
!= NULL
, as_set
, origin
,
8563 match_med
!= NULL
, suppress_map
);
8566 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8567 "[no] aggregate-address X:X::X:X/M$prefix [{"
8569 "|summary-only$summary_only"
8570 "|route-map RMAP_NAME$rmap_name"
8571 "|origin <egp|igp|incomplete>$origin_s"
8572 "|matching-MED-only$match_med"
8573 "|suppress-map RMAP_NAME$suppress_map"
8576 "Configure BGP aggregate entries\n"
8577 "Aggregate prefix\n"
8578 "Generate AS set path information\n"
8579 "Filter more specific routes from updates\n"
8580 "Apply route map to aggregate network\n"
8585 "Unknown heritage\n"
8586 "Only aggregate routes with matching MED\n"
8587 "Suppress the selected more specific routes\n"
8588 "Route map with the route selectors\n")
8590 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8591 int as_set
= AGGREGATE_AS_UNSET
;
8594 if (strcmp(origin_s
, "egp") == 0)
8595 origin
= BGP_ORIGIN_EGP
;
8596 else if (strcmp(origin_s
, "igp") == 0)
8597 origin
= BGP_ORIGIN_IGP
;
8598 else if (strcmp(origin_s
, "incomplete") == 0)
8599 origin
= BGP_ORIGIN_INCOMPLETE
;
8603 as_set
= AGGREGATE_AS_SET
;
8605 /* Handle configuration removal, otherwise installation. */
8607 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8610 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8611 rmap_name
, summary_only
!= NULL
, as_set
,
8612 origin
, match_med
!= NULL
, suppress_map
);
8615 /* Redistribute route treatment. */
8616 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8617 const union g_addr
*nexthop
, ifindex_t ifindex
,
8618 enum nexthop_types_t nhtype
, uint8_t distance
,
8619 enum blackhole_type bhtype
, uint32_t metric
,
8620 uint8_t type
, unsigned short instance
,
8623 struct bgp_path_info
*new;
8624 struct bgp_path_info
*bpi
;
8625 struct bgp_path_info rmap_path
;
8626 struct bgp_dest
*bn
;
8628 struct attr
*new_attr
;
8630 route_map_result_t ret
;
8631 struct bgp_redist
*red
;
8633 /* Make default attribute. */
8634 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8636 * This must not be NULL to satisfy Coverity SA
8638 assert(attr
.aspath
);
8641 case NEXTHOP_TYPE_IFINDEX
:
8642 switch (p
->family
) {
8644 attr
.nexthop
.s_addr
= INADDR_ANY
;
8645 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8648 memset(&attr
.mp_nexthop_global
, 0,
8649 sizeof(attr
.mp_nexthop_global
));
8650 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8654 case NEXTHOP_TYPE_IPV4
:
8655 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8656 attr
.nexthop
= nexthop
->ipv4
;
8657 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8659 case NEXTHOP_TYPE_IPV6
:
8660 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8661 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8662 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8664 case NEXTHOP_TYPE_BLACKHOLE
:
8665 switch (p
->family
) {
8667 attr
.nexthop
.s_addr
= INADDR_ANY
;
8668 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8671 memset(&attr
.mp_nexthop_global
, 0,
8672 sizeof(attr
.mp_nexthop_global
));
8673 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8676 attr
.bh_type
= bhtype
;
8679 attr
.nh_type
= nhtype
;
8680 attr
.nh_ifindex
= ifindex
;
8683 attr
.distance
= distance
;
8684 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8687 afi
= family2afi(p
->family
);
8689 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8691 struct attr attr_new
;
8693 /* Copy attribute for modification. */
8696 if (red
->redist_metric_flag
)
8697 attr_new
.med
= red
->redist_metric
;
8699 /* Apply route-map. */
8700 if (red
->rmap
.name
) {
8701 memset(&rmap_path
, 0, sizeof(rmap_path
));
8702 rmap_path
.peer
= bgp
->peer_self
;
8703 rmap_path
.attr
= &attr_new
;
8705 SET_FLAG(bgp
->peer_self
->rmap_type
,
8706 PEER_RMAP_TYPE_REDISTRIBUTE
);
8708 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8710 bgp
->peer_self
->rmap_type
= 0;
8712 if (ret
== RMAP_DENYMATCH
) {
8713 /* Free uninterned attribute. */
8714 bgp_attr_flush(&attr_new
);
8716 /* Unintern original. */
8717 aspath_unintern(&attr
.aspath
);
8718 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8723 if (bgp_in_graceful_shutdown(bgp
))
8724 bgp_attr_add_gshut_community(&attr_new
);
8726 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8727 SAFI_UNICAST
, p
, NULL
);
8729 new_attr
= bgp_attr_intern(&attr_new
);
8731 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8732 if (bpi
->peer
== bgp
->peer_self
8733 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8737 /* Ensure the (source route) type is updated. */
8739 if (attrhash_cmp(bpi
->attr
, new_attr
)
8740 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8741 bgp_attr_unintern(&new_attr
);
8742 aspath_unintern(&attr
.aspath
);
8743 bgp_dest_unlock_node(bn
);
8746 /* The attribute is changed. */
8747 bgp_path_info_set_flag(bn
, bpi
,
8748 BGP_PATH_ATTR_CHANGED
);
8750 /* Rewrite BGP route information. */
8751 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8752 bgp_path_info_restore(bn
, bpi
);
8754 bgp_aggregate_decrement(
8755 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8756 bgp_attr_unintern(&bpi
->attr
);
8757 bpi
->attr
= new_attr
;
8758 bpi
->uptime
= monotime(NULL
);
8760 /* Process change. */
8761 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8763 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8764 bgp_dest_unlock_node(bn
);
8765 aspath_unintern(&attr
.aspath
);
8767 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8769 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8771 vpn_leak_from_vrf_update(
8772 bgp_get_default(), bgp
, bpi
);
8778 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8779 bgp
->peer_self
, new_attr
, bn
);
8780 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8782 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8783 bgp_path_info_add(bn
, new);
8784 bgp_dest_unlock_node(bn
);
8785 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8786 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8788 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8789 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8791 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8795 /* Unintern original. */
8796 aspath_unintern(&attr
.aspath
);
8799 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8800 unsigned short instance
)
8803 struct bgp_dest
*dest
;
8804 struct bgp_path_info
*pi
;
8805 struct bgp_redist
*red
;
8807 afi
= family2afi(p
->family
);
8809 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8811 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8812 SAFI_UNICAST
, p
, NULL
);
8814 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8815 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8819 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8820 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8822 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8825 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8826 bgp_path_info_delete(dest
, pi
);
8827 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8829 bgp_dest_unlock_node(dest
);
8833 /* Withdraw specified route type's route. */
8834 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8835 unsigned short instance
)
8837 struct bgp_dest
*dest
;
8838 struct bgp_path_info
*pi
;
8839 struct bgp_table
*table
;
8841 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8843 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8844 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8845 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8846 && pi
->instance
== instance
)
8850 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8851 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8853 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8856 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8857 pi
, afi
, SAFI_UNICAST
);
8858 bgp_path_info_delete(dest
, pi
);
8859 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8864 /* Static function to display route. */
8865 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8866 struct vty
*vty
, json_object
*json
, bool wide
)
8871 if (p
->family
== AF_INET
) {
8873 len
= vty_out(vty
, "%pFX", p
);
8875 json_object_string_add(json
, "prefix",
8876 inet_ntop(p
->family
,
8879 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8880 json_object_string_addf(json
, "network", "%pFX", p
);
8881 json_object_int_add(json
, "version", dest
->version
);
8883 } else if (p
->family
== AF_ETHERNET
) {
8884 len
= vty_out(vty
, "%pFX", p
);
8885 } else if (p
->family
== AF_EVPN
) {
8887 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8889 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8890 } else if (p
->family
== AF_FLOWSPEC
) {
8891 route_vty_out_flowspec(vty
, p
, NULL
,
8893 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8894 NLRI_STRING_FORMAT_MIN
, json
);
8897 len
= vty_out(vty
, "%pFX", p
);
8899 json_object_string_add(json
, "prefix",
8900 inet_ntop(p
->family
,
8903 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8904 json_object_string_addf(json
, "network", "%pFX", p
);
8905 json_object_int_add(json
, "version", dest
->version
);
8910 len
= wide
? (45 - len
) : (17 - len
);
8912 vty_out(vty
, "\n%*s", 20, " ");
8914 vty_out(vty
, "%*s", len
, " ");
8918 enum bgp_display_type
{
8922 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8925 case bgp_path_selection_none
:
8926 return "Nothing to Select";
8927 case bgp_path_selection_first
:
8928 return "First path received";
8929 case bgp_path_selection_evpn_sticky_mac
:
8930 return "EVPN Sticky Mac";
8931 case bgp_path_selection_evpn_seq
:
8932 return "EVPN sequence number";
8933 case bgp_path_selection_evpn_lower_ip
:
8934 return "EVPN lower IP";
8935 case bgp_path_selection_evpn_local_path
:
8936 return "EVPN local ES path";
8937 case bgp_path_selection_evpn_non_proxy
:
8938 return "EVPN non proxy";
8939 case bgp_path_selection_weight
:
8941 case bgp_path_selection_local_pref
:
8942 return "Local Pref";
8943 case bgp_path_selection_accept_own
:
8944 return "Accept Own";
8945 case bgp_path_selection_local_route
:
8946 return "Local Route";
8947 case bgp_path_selection_confed_as_path
:
8948 return "Confederation based AS Path";
8949 case bgp_path_selection_as_path
:
8951 case bgp_path_selection_origin
:
8953 case bgp_path_selection_med
:
8955 case bgp_path_selection_peer
:
8957 case bgp_path_selection_confed
:
8958 return "Confed Peer Type";
8959 case bgp_path_selection_igp_metric
:
8960 return "IGP Metric";
8961 case bgp_path_selection_older
:
8962 return "Older Path";
8963 case bgp_path_selection_router_id
:
8965 case bgp_path_selection_cluster_length
:
8966 return "Cluster length";
8967 case bgp_path_selection_stale
:
8968 return "Path Staleness";
8969 case bgp_path_selection_local_configured
:
8970 return "Locally configured route";
8971 case bgp_path_selection_neighbor_ip
:
8972 return "Neighbor IP";
8973 case bgp_path_selection_default
:
8974 return "Nothing left to compare";
8976 return "Invalid (internal error)";
8979 /* Print the short form route status for a bgp_path_info */
8980 static void route_vty_short_status_out(struct vty
*vty
,
8981 struct bgp_path_info
*path
,
8982 const struct prefix
*p
,
8983 json_object
*json_path
)
8985 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8989 /* Route status display. */
8990 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8991 json_object_boolean_true_add(json_path
, "removed");
8993 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8994 json_object_boolean_true_add(json_path
, "stale");
8996 if (path
->extra
&& bgp_path_suppressed(path
))
8997 json_object_boolean_true_add(json_path
, "suppressed");
8999 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9000 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9001 json_object_boolean_true_add(json_path
, "valid");
9004 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9005 json_object_boolean_true_add(json_path
, "history");
9007 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9008 json_object_boolean_true_add(json_path
, "damped");
9010 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9011 json_object_boolean_true_add(json_path
, "bestpath");
9012 json_object_string_add(json_path
, "selectionReason",
9013 bgp_path_selection_reason2str(
9014 path
->net
->reason
));
9017 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9018 json_object_boolean_true_add(json_path
, "multipath");
9020 /* Internal route. */
9021 if ((path
->peer
->as
)
9022 && (path
->peer
->as
== path
->peer
->local_as
))
9023 json_object_string_add(json_path
, "pathFrom",
9026 json_object_string_add(json_path
, "pathFrom",
9032 /* RPKI validation state */
9034 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9036 if (rpki_state
== RPKI_VALID
)
9038 else if (rpki_state
== RPKI_INVALID
)
9040 else if (rpki_state
== RPKI_NOTFOUND
)
9045 /* Route status display. */
9046 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9048 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9050 else if (bgp_path_suppressed(path
))
9052 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9053 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9059 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9061 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9063 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9065 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9070 /* Internal route. */
9071 if (path
->peer
&& (path
->peer
->as
)
9072 && (path
->peer
->as
== path
->peer
->local_as
))
9078 static char *bgp_nexthop_hostname(struct peer
*peer
,
9079 struct bgp_nexthop_cache
*bnc
)
9082 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9083 return peer
->hostname
;
9087 /* called from terminal list command */
9088 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9089 struct bgp_path_info
*path
, int display
, safi_t safi
,
9090 json_object
*json_paths
, bool wide
)
9093 struct attr
*attr
= path
->attr
;
9094 json_object
*json_path
= NULL
;
9095 json_object
*json_nexthops
= NULL
;
9096 json_object
*json_nexthop_global
= NULL
;
9097 json_object
*json_nexthop_ll
= NULL
;
9098 json_object
*json_ext_community
= NULL
;
9099 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9101 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9102 bool nexthop_othervrf
= false;
9103 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9104 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9105 char *nexthop_hostname
=
9106 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9107 char esi_buf
[ESI_STR_LEN
];
9110 json_path
= json_object_new_object();
9112 /* short status lead text */
9113 route_vty_short_status_out(vty
, path
, p
, json_path
);
9116 /* print prefix and mask */
9118 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9120 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9122 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9126 * If vrf id of nexthop is different from that of prefix,
9127 * set up printable string to append
9129 if (path
->extra
&& path
->extra
->bgp_orig
) {
9130 const char *self
= "";
9135 nexthop_othervrf
= true;
9136 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9138 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9139 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9140 "@%s%s", VRFID_NONE_STR
, self
);
9142 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9143 path
->extra
->bgp_orig
->vrf_id
, self
);
9145 if (path
->extra
->bgp_orig
->inst_type
9146 != BGP_INSTANCE_TYPE_DEFAULT
)
9148 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9150 const char *self
= "";
9155 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9159 * For ENCAP and EVPN routes, nexthop address family is not
9160 * neccessarily the same as the prefix address family.
9161 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9162 * EVPN routes are also exchanged with a MP nexthop. Currently,
9164 * is only IPv4, the value will be present in either
9166 * attr->mp_nexthop_global_in
9168 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9171 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9175 snprintf(nexthop
, sizeof(nexthop
), "%s",
9176 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
9180 snprintf(nexthop
, sizeof(nexthop
), "%s",
9181 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
9185 snprintf(nexthop
, sizeof(nexthop
), "?");
9190 json_nexthop_global
= json_object_new_object();
9192 json_object_string_add(json_nexthop_global
, "ip",
9195 if (path
->peer
->hostname
)
9196 json_object_string_add(json_nexthop_global
,
9198 path
->peer
->hostname
);
9200 json_object_string_add(json_nexthop_global
, "afi",
9201 (af
== AF_INET
) ? "ipv4"
9203 json_object_boolean_true_add(json_nexthop_global
,
9206 if (nexthop_hostname
)
9207 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9208 nexthop_hostname
, vrf_id_str
);
9210 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9212 len
= wide
? (41 - len
) : (16 - len
);
9214 vty_out(vty
, "\n%*s", 36, " ");
9216 vty_out(vty
, "%*s", len
, " ");
9218 } else if (safi
== SAFI_EVPN
) {
9220 json_nexthop_global
= json_object_new_object();
9222 json_object_string_addf(json_nexthop_global
, "ip",
9224 &attr
->mp_nexthop_global_in
);
9226 if (path
->peer
->hostname
)
9227 json_object_string_add(json_nexthop_global
,
9229 path
->peer
->hostname
);
9231 json_object_string_add(json_nexthop_global
, "afi",
9233 json_object_boolean_true_add(json_nexthop_global
,
9236 if (nexthop_hostname
)
9237 len
= vty_out(vty
, "%pI4(%s)%s",
9238 &attr
->mp_nexthop_global_in
,
9239 nexthop_hostname
, vrf_id_str
);
9241 len
= vty_out(vty
, "%pI4%s",
9242 &attr
->mp_nexthop_global_in
,
9245 len
= wide
? (41 - len
) : (16 - len
);
9247 vty_out(vty
, "\n%*s", 36, " ");
9249 vty_out(vty
, "%*s", len
, " ");
9251 } else if (safi
== SAFI_FLOWSPEC
) {
9252 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9254 json_nexthop_global
= json_object_new_object();
9256 json_object_string_add(json_nexthop_global
,
9258 json_object_string_addf(json_nexthop_global
,
9262 if (path
->peer
->hostname
)
9263 json_object_string_add(
9264 json_nexthop_global
, "hostname",
9265 path
->peer
->hostname
);
9267 json_object_boolean_true_add(
9268 json_nexthop_global
,
9271 if (nexthop_hostname
)
9272 len
= vty_out(vty
, "%pI4(%s)%s",
9277 len
= vty_out(vty
, "%pI4%s",
9281 len
= wide
? (41 - len
) : (16 - len
);
9283 vty_out(vty
, "\n%*s", 36, " ");
9285 vty_out(vty
, "%*s", len
, " ");
9288 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9290 json_nexthop_global
= json_object_new_object();
9292 json_object_string_addf(json_nexthop_global
, "ip",
9293 "%pI4", &attr
->nexthop
);
9295 if (path
->peer
->hostname
)
9296 json_object_string_add(json_nexthop_global
,
9298 path
->peer
->hostname
);
9300 json_object_string_add(json_nexthop_global
, "afi",
9302 json_object_boolean_true_add(json_nexthop_global
,
9305 if (nexthop_hostname
)
9306 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9307 nexthop_hostname
, vrf_id_str
);
9309 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9312 len
= wide
? (41 - len
) : (16 - len
);
9314 vty_out(vty
, "\n%*s", 36, " ");
9316 vty_out(vty
, "%*s", len
, " ");
9321 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9323 json_nexthop_global
= json_object_new_object();
9324 json_object_string_addf(json_nexthop_global
, "ip",
9326 &attr
->mp_nexthop_global
);
9328 if (path
->peer
->hostname
)
9329 json_object_string_add(json_nexthop_global
,
9331 path
->peer
->hostname
);
9333 json_object_string_add(json_nexthop_global
, "afi",
9335 json_object_string_add(json_nexthop_global
, "scope",
9338 /* We display both LL & GL if both have been
9340 if ((attr
->mp_nexthop_len
9341 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9342 || (path
->peer
->conf_if
)) {
9343 json_nexthop_ll
= json_object_new_object();
9344 json_object_string_addf(
9345 json_nexthop_ll
, "ip", "%pI6",
9346 &attr
->mp_nexthop_local
);
9348 if (path
->peer
->hostname
)
9349 json_object_string_add(
9350 json_nexthop_ll
, "hostname",
9351 path
->peer
->hostname
);
9353 json_object_string_add(json_nexthop_ll
, "afi",
9355 json_object_string_add(json_nexthop_ll
, "scope",
9358 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9359 &attr
->mp_nexthop_local
)
9361 && !attr
->mp_nexthop_prefer_global
)
9362 json_object_boolean_true_add(
9363 json_nexthop_ll
, "used");
9365 json_object_boolean_true_add(
9366 json_nexthop_global
, "used");
9368 json_object_boolean_true_add(
9369 json_nexthop_global
, "used");
9371 /* Display LL if LL/Global both in table unless
9372 * prefer-global is set */
9373 if (((attr
->mp_nexthop_len
9374 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9375 && !attr
->mp_nexthop_prefer_global
)
9376 || (path
->peer
->conf_if
)) {
9377 if (path
->peer
->conf_if
) {
9378 len
= vty_out(vty
, "%s",
9379 path
->peer
->conf_if
);
9380 /* len of IPv6 addr + max len of def
9382 len
= wide
? (41 - len
) : (16 - len
);
9385 vty_out(vty
, "\n%*s", 36, " ");
9387 vty_out(vty
, "%*s", len
, " ");
9389 if (nexthop_hostname
)
9392 &attr
->mp_nexthop_local
,
9398 &attr
->mp_nexthop_local
,
9401 len
= wide
? (41 - len
) : (16 - len
);
9404 vty_out(vty
, "\n%*s", 36, " ");
9406 vty_out(vty
, "%*s", len
, " ");
9409 if (nexthop_hostname
)
9410 len
= vty_out(vty
, "%pI6(%s)%s",
9411 &attr
->mp_nexthop_global
,
9415 len
= vty_out(vty
, "%pI6%s",
9416 &attr
->mp_nexthop_global
,
9419 len
= wide
? (41 - len
) : (16 - len
);
9422 vty_out(vty
, "\n%*s", 36, " ");
9424 vty_out(vty
, "%*s", len
, " ");
9430 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9432 json_object_int_add(json_path
, "metric", attr
->med
);
9434 vty_out(vty
, "%7u", attr
->med
);
9436 vty_out(vty
, "%10u", attr
->med
);
9437 else if (!json_paths
) {
9439 vty_out(vty
, "%*s", 7, " ");
9441 vty_out(vty
, "%*s", 10, " ");
9445 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9447 json_object_int_add(json_path
, "locPrf",
9450 vty_out(vty
, "%7u", attr
->local_pref
);
9451 else if (!json_paths
)
9455 json_object_int_add(json_path
, "weight", attr
->weight
);
9457 vty_out(vty
, "%7u ", attr
->weight
);
9460 json_object_string_addf(json_path
, "peerId", "%pSU",
9466 json_object_string_add(json_path
, "path",
9469 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9474 json_object_string_add(json_path
, "origin",
9475 bgp_origin_long_str
[attr
->origin
]);
9477 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9480 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9481 json_object_string_add(json_path
, "esi",
9482 esi_to_str(&attr
->esi
,
9483 esi_buf
, sizeof(esi_buf
)));
9485 if (safi
== SAFI_EVPN
&&
9486 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9487 json_ext_community
= json_object_new_object();
9488 json_object_string_add(
9489 json_ext_community
, "string",
9490 bgp_attr_get_ecommunity(attr
)->str
);
9491 json_object_object_add(json_path
,
9492 "extendedCommunity",
9493 json_ext_community
);
9497 json_object_boolean_true_add(json_path
,
9498 "announceNexthopSelf");
9499 if (nexthop_othervrf
) {
9500 json_object_string_add(json_path
, "nhVrfName",
9503 json_object_int_add(json_path
, "nhVrfId",
9504 ((nexthop_vrfid
== VRF_UNKNOWN
)
9506 : (int)nexthop_vrfid
));
9511 if (json_nexthop_global
|| json_nexthop_ll
) {
9512 json_nexthops
= json_object_new_array();
9514 if (json_nexthop_global
)
9515 json_object_array_add(json_nexthops
,
9516 json_nexthop_global
);
9518 if (json_nexthop_ll
)
9519 json_object_array_add(json_nexthops
,
9522 json_object_object_add(json_path
, "nexthops",
9526 json_object_array_add(json_paths
, json_path
);
9530 if (safi
== SAFI_EVPN
) {
9531 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9532 /* XXX - add these params to the json out */
9533 vty_out(vty
, "%*s", 20, " ");
9534 vty_out(vty
, "ESI:%s",
9535 esi_to_str(&attr
->esi
, esi_buf
,
9541 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9542 vty_out(vty
, "%*s", 20, " ");
9543 vty_out(vty
, "%s\n",
9544 bgp_attr_get_ecommunity(attr
)->str
);
9548 #ifdef ENABLE_BGP_VNC
9549 /* prints an additional line, indented, with VNC info, if
9551 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9552 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9557 /* called from terminal list command */
9558 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9559 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9560 bool use_json
, json_object
*json_ar
, bool wide
)
9562 json_object
*json_status
= NULL
;
9563 json_object
*json_net
= NULL
;
9567 /* Route status display. */
9569 json_status
= json_object_new_object();
9570 json_net
= json_object_new_object();
9577 /* print prefix and mask */
9579 if (safi
== SAFI_EVPN
)
9580 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9581 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9582 json_object_string_add(
9583 json_net
, "addrPrefix",
9584 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9586 json_object_int_add(json_net
, "prefixLen",
9588 json_object_string_addf(json_net
, "network", "%pFX", p
);
9591 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9593 /* Print attribute */
9596 if (p
->family
== AF_INET
&&
9597 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9598 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9599 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9600 json_object_string_addf(
9601 json_net
, "nextHop", "%pI4",
9602 &attr
->mp_nexthop_global_in
);
9604 json_object_string_addf(
9605 json_net
, "nextHop", "%pI4",
9607 } else if (p
->family
== AF_INET6
||
9608 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9609 json_object_string_addf(
9610 json_net
, "nextHopGlobal", "%pI6",
9611 &attr
->mp_nexthop_global
);
9612 } else if (p
->family
== AF_EVPN
&&
9613 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9614 json_object_string_addf(
9615 json_net
, "nextHop", "%pI4",
9616 &attr
->mp_nexthop_global_in
);
9620 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9621 json_object_int_add(json_net
, "metric",
9624 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9625 json_object_int_add(json_net
, "locPrf",
9628 json_object_int_add(json_net
, "weight", attr
->weight
);
9632 json_object_string_add(json_net
, "path",
9636 json_object_string_add(json_net
, "bgpOriginCode",
9637 bgp_origin_str
[attr
->origin
]);
9639 if (p
->family
== AF_INET
&&
9640 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9641 safi
== SAFI_EVPN
||
9642 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9643 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9644 || safi
== SAFI_EVPN
)
9645 vty_out(vty
, "%-16pI4",
9646 &attr
->mp_nexthop_global_in
);
9648 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9650 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9651 } else if (p
->family
== AF_INET6
||
9652 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9658 &attr
->mp_nexthop_global
, buf
,
9660 len
= wide
? (41 - len
) : (16 - len
);
9662 vty_out(vty
, "\n%*s", 36, " ");
9664 vty_out(vty
, "%*s", len
, " ");
9667 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9669 vty_out(vty
, "%7u", attr
->med
);
9671 vty_out(vty
, "%10u", attr
->med
);
9677 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9678 vty_out(vty
, "%7u", attr
->local_pref
);
9682 vty_out(vty
, "%7u ", attr
->weight
);
9686 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9689 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9693 json_object_boolean_true_add(json_status
, "*");
9694 json_object_boolean_true_add(json_status
, ">");
9695 json_object_object_add(json_net
, "appliedStatusSymbols",
9697 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9702 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9703 struct bgp_path_info
*path
, int display
, safi_t safi
,
9706 json_object
*json_out
= NULL
;
9708 mpls_label_t label
= MPLS_INVALID_LABEL
;
9714 json_out
= json_object_new_object();
9716 /* short status lead text */
9717 route_vty_short_status_out(vty
, path
, p
, json_out
);
9719 /* print prefix and mask */
9722 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9724 vty_out(vty
, "%*s", 17, " ");
9727 /* Print attribute */
9729 if (((p
->family
== AF_INET
) &&
9730 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9731 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9732 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9733 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9734 || safi
== SAFI_EVPN
) {
9736 json_object_string_addf(
9737 json_out
, "mpNexthopGlobalIn", "%pI4",
9738 &attr
->mp_nexthop_global_in
);
9740 vty_out(vty
, "%-16pI4",
9741 &attr
->mp_nexthop_global_in
);
9744 json_object_string_addf(json_out
, "nexthop",
9745 "%pI4", &attr
->nexthop
);
9747 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9749 } else if (((p
->family
== AF_INET6
) &&
9750 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9751 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9752 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9755 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9757 json_object_string_addf(
9758 json_out
, "mpNexthopGlobalIn", "%pI6",
9759 &attr
->mp_nexthop_global
);
9763 &attr
->mp_nexthop_global
,
9764 buf_a
, sizeof(buf_a
)));
9765 } else if (attr
->mp_nexthop_len
9766 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9767 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9768 &attr
->mp_nexthop_global
,
9769 &attr
->mp_nexthop_local
);
9771 json_object_string_add(json_out
,
9772 "mpNexthopGlobalLocal",
9775 vty_out(vty
, "%s", buf_a
);
9779 label
= decode_label(&path
->extra
->label
[0]);
9781 if (bgp_is_valid_label(&label
)) {
9783 json_object_int_add(json_out
, "notag", label
);
9784 json_object_array_add(json
, json_out
);
9786 vty_out(vty
, "notag/%d", label
);
9793 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9794 struct bgp_path_info
*path
, int display
,
9795 json_object
*json_paths
)
9798 json_object
*json_path
= NULL
;
9799 json_object
*json_nexthop
= NULL
;
9800 json_object
*json_overlay
= NULL
;
9806 json_path
= json_object_new_object();
9807 json_overlay
= json_object_new_object();
9808 json_nexthop
= json_object_new_object();
9811 /* short status lead text */
9812 route_vty_short_status_out(vty
, path
, p
, json_path
);
9814 /* print prefix and mask */
9816 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9818 vty_out(vty
, "%*s", 17, " ");
9820 /* Print attribute */
9822 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9827 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9829 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9830 &attr
->mp_nexthop_global_in
);
9832 json_object_string_add(json_nexthop
, "afi", "ipv4");
9834 json_object_object_add(json_path
, "nexthop",
9840 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9841 &attr
->mp_nexthop_local
);
9843 json_object_string_addf(json_nexthop
, "ipv6Global",
9845 &attr
->mp_nexthop_global
);
9847 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9849 &attr
->mp_nexthop_local
);
9851 json_object_string_add(json_nexthop
, "afi", "ipv6");
9853 json_object_object_add(json_path
, "nexthop",
9861 json_object_string_add(json_nexthop
, "Error",
9862 "Unsupported address-family");
9863 json_object_string_add(json_nexthop
, "error",
9864 "Unsupported address-family");
9868 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9871 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9873 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9875 if (bgp_attr_get_ecommunity(attr
)) {
9877 struct ecommunity_val
*routermac
= ecommunity_lookup(
9878 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9879 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9882 mac
= ecom_mac2str((char *)routermac
->val
);
9885 vty_out(vty
, "/%s", mac
);
9887 json_object_string_add(json_overlay
, "rmac",
9890 XFREE(MTYPE_TMP
, mac
);
9897 json_object_object_add(json_path
, "overlay", json_overlay
);
9899 json_object_array_add(json_paths
, json_path
);
9903 /* dampening route */
9904 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9905 struct bgp_path_info
*path
, int display
,
9906 afi_t afi
, safi_t safi
, bool use_json
,
9907 json_object
*json_paths
)
9909 struct attr
*attr
= path
->attr
;
9911 char timebuf
[BGP_UPTIME_LEN
];
9912 json_object
*json_path
= NULL
;
9915 json_path
= json_object_new_object();
9917 /* short status lead text */
9918 route_vty_short_status_out(vty
, path
, p
, json_path
);
9920 /* print prefix and mask */
9923 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9925 vty_out(vty
, "%*s", 17, " ");
9927 len
= vty_out(vty
, "%s", path
->peer
->host
);
9931 vty_out(vty
, "\n%*s", 34, " ");
9933 vty_out(vty
, "%*s", len
, " ");
9936 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9937 BGP_UPTIME_LEN
, afi
, safi
,
9941 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9943 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9947 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9948 safi
, use_json
, json_path
);
9951 json_object_string_add(json_path
, "asPath",
9954 json_object_string_add(json_path
, "origin",
9955 bgp_origin_str
[attr
->origin
]);
9956 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9958 json_object_array_add(json_paths
, json_path
);
9963 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9964 struct bgp_path_info
*path
, int display
,
9965 afi_t afi
, safi_t safi
, bool use_json
,
9966 json_object
*json_paths
)
9968 struct attr
*attr
= path
->attr
;
9969 struct bgp_damp_info
*bdi
;
9970 char timebuf
[BGP_UPTIME_LEN
];
9972 json_object
*json_path
= NULL
;
9978 json_path
= json_object_new_object();
9980 bdi
= path
->extra
->damp_info
;
9982 /* short status lead text */
9983 route_vty_short_status_out(vty
, path
, p
, json_path
);
9987 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9989 vty_out(vty
, "%*s", 17, " ");
9991 len
= vty_out(vty
, "%s", path
->peer
->host
);
9994 vty_out(vty
, "\n%*s", 33, " ");
9996 vty_out(vty
, "%*s", len
, " ");
9998 len
= vty_out(vty
, "%d", bdi
->flap
);
10003 vty_out(vty
, "%*s", len
, " ");
10005 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10006 BGP_UPTIME_LEN
, 0, NULL
));
10008 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10009 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10010 vty_out(vty
, "%s ",
10011 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10012 BGP_UPTIME_LEN
, afi
,
10013 safi
, use_json
, NULL
));
10015 vty_out(vty
, "%*s ", 8, " ");
10018 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
10020 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10022 vty_out(vty
, "\n");
10024 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10025 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10027 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10030 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10031 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10032 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10033 BGP_UPTIME_LEN
, afi
, safi
,
10034 use_json
, json_path
);
10037 json_object_string_add(json_path
, "asPath",
10038 attr
->aspath
->str
);
10040 json_object_string_add(json_path
, "origin",
10041 bgp_origin_str
[attr
->origin
]);
10043 json_object_array_add(json_paths
, json_path
);
10047 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10048 int *first
, const char *header
,
10049 json_object
*json_adv_to
)
10051 json_object
*json_peer
= NULL
;
10054 /* 'advertised-to' is a dictionary of peers we have advertised
10056 * prefix too. The key is the peer's IP or swpX, the value is
10058 * hostname if we know it and "" if not.
10060 json_peer
= json_object_new_object();
10062 if (peer
->hostname
)
10063 json_object_string_add(json_peer
, "hostname",
10067 json_object_object_add(json_adv_to
, peer
->conf_if
,
10070 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10074 vty_out(vty
, "%s", header
);
10079 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10081 vty_out(vty
, " %s(%s)", peer
->hostname
,
10084 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10088 vty_out(vty
, " %s", peer
->conf_if
);
10090 vty_out(vty
, " %pSU", &peer
->su
);
10095 static void route_vty_out_tx_ids(struct vty
*vty
,
10096 struct bgp_addpath_info_data
*d
)
10100 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10101 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10102 d
->addpath_tx_id
[i
],
10103 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10107 static void route_vty_out_detail_es_info(struct vty
*vty
,
10108 struct bgp_path_info
*pi
,
10110 json_object
*json_path
)
10112 char esi_buf
[ESI_STR_LEN
];
10113 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10114 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10115 ATTR_ES_PEER_ROUTER
);
10116 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10117 ATTR_ES_PEER_ACTIVE
);
10118 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10119 ATTR_ES_PEER_PROXY
);
10120 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10122 json_object
*json_es_info
= NULL
;
10124 json_object_string_add(
10127 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10128 json_es_info
= json_object_new_object();
10130 json_object_boolean_true_add(
10131 json_es_info
, "localEs");
10133 json_object_boolean_true_add(
10134 json_es_info
, "peerActive");
10136 json_object_boolean_true_add(
10137 json_es_info
, "peerProxy");
10139 json_object_boolean_true_add(
10140 json_es_info
, "peerRouter");
10141 if (attr
->mm_sync_seqnum
)
10142 json_object_int_add(
10143 json_es_info
, "peerSeq",
10144 attr
->mm_sync_seqnum
);
10145 json_object_object_add(
10146 json_path
, "es_info",
10150 if (bgp_evpn_attr_is_sync(attr
))
10152 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10154 es_local
? "local-es":"",
10155 peer_proxy
? "proxy " : "",
10156 peer_active
? "active ":"",
10157 peer_router
? "router ":"",
10158 attr
->mm_sync_seqnum
);
10160 vty_out(vty
, " ESI %s %s\n",
10162 es_local
? "local-es":"");
10166 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10167 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
10168 enum rpki_states rpki_curr_state
,
10169 json_object
*json_paths
)
10171 char buf
[INET6_ADDRSTRLEN
];
10173 struct attr
*attr
= path
->attr
;
10175 json_object
*json_bestpath
= NULL
;
10176 json_object
*json_cluster_list
= NULL
;
10177 json_object
*json_cluster_list_list
= NULL
;
10178 json_object
*json_ext_community
= NULL
;
10179 json_object
*json_last_update
= NULL
;
10180 json_object
*json_pmsi
= NULL
;
10181 json_object
*json_nexthop_global
= NULL
;
10182 json_object
*json_nexthop_ll
= NULL
;
10183 json_object
*json_nexthops
= NULL
;
10184 json_object
*json_path
= NULL
;
10185 json_object
*json_peer
= NULL
;
10186 json_object
*json_string
= NULL
;
10187 json_object
*json_adv_to
= NULL
;
10189 struct listnode
*node
, *nnode
;
10191 bool addpath_capable
;
10193 unsigned int first_as
;
10194 bool nexthop_self
=
10195 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10197 char *nexthop_hostname
=
10198 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10202 mpls_label_t label
= MPLS_INVALID_LABEL
;
10205 json_path
= json_object_new_object();
10206 json_peer
= json_object_new_object();
10207 json_nexthop_global
= json_object_new_object();
10210 if (safi
== SAFI_EVPN
) {
10212 vty_out(vty
, " Route %pRN", bn
);
10219 if (path
->extra
&& path
->extra
->num_labels
) {
10220 bgp_evpn_label2str(path
->extra
->label
,
10221 path
->extra
->num_labels
, tag_buf
,
10224 if (safi
== SAFI_EVPN
) {
10226 if (tag_buf
[0] != '\0')
10227 vty_out(vty
, " VNI %s", tag_buf
);
10230 json_object_string_add(json_path
, "VNI",
10232 json_object_string_add(json_path
, "vni",
10238 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10239 struct bgp_path_info
*parent_ri
;
10240 struct bgp_dest
*dest
, *pdest
;
10242 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10243 dest
= parent_ri
->net
;
10244 if (dest
&& dest
->pdest
) {
10245 pdest
= dest
->pdest
;
10246 if (is_pi_family_evpn(parent_ri
)) {
10248 " Imported from %pRD:%pFX, VNI %s",
10249 (struct prefix_rd
*)
10250 bgp_dest_get_prefix(
10252 (struct prefix_evpn
*)
10253 bgp_dest_get_prefix(
10256 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
10257 vty_out(vty
, ", L3NHG %s",
10259 & ATTR_ES_L3_NHG_ACTIVE
)
10262 vty_out(vty
, "\n");
10266 " Imported from %pRD:%pFX\n",
10267 (struct prefix_rd
*)
10268 bgp_dest_get_prefix(
10270 (struct prefix_evpn
*)
10271 bgp_dest_get_prefix(
10277 if (safi
== SAFI_EVPN
10278 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10279 char gwip_buf
[INET6_ADDRSTRLEN
];
10281 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10285 json_object_string_add(json_path
, "gatewayIP",
10288 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10291 if (safi
== SAFI_EVPN
&& !json_path
)
10292 vty_out(vty
, "\n");
10294 /* Line1 display AS-path, Aggregator */
10295 if (attr
->aspath
) {
10297 if (!attr
->aspath
->json
)
10298 aspath_str_update(attr
->aspath
, true);
10299 json_object_lock(attr
->aspath
->json
);
10300 json_object_object_add(json_path
, "aspath",
10301 attr
->aspath
->json
);
10303 if (attr
->aspath
->segments
)
10304 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
10306 vty_out(vty
, " Local");
10310 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10312 json_object_boolean_true_add(json_path
, "removed");
10314 vty_out(vty
, ", (removed)");
10317 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10319 json_object_boolean_true_add(json_path
, "stale");
10321 vty_out(vty
, ", (stale)");
10324 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10326 json_object_int_add(json_path
, "aggregatorAs",
10327 attr
->aggregator_as
);
10328 json_object_string_addf(json_path
, "aggregatorId",
10329 "%pI4", &attr
->aggregator_addr
);
10331 vty_out(vty
, ", (aggregated by %u %pI4)",
10332 attr
->aggregator_as
, &attr
->aggregator_addr
);
10336 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10337 PEER_FLAG_REFLECTOR_CLIENT
)) {
10339 json_object_boolean_true_add(json_path
,
10340 "rxedFromRrClient");
10342 vty_out(vty
, ", (Received from a RR-client)");
10345 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10346 PEER_FLAG_RSERVER_CLIENT
)) {
10348 json_object_boolean_true_add(json_path
,
10349 "rxedFromRsClient");
10351 vty_out(vty
, ", (Received from a RS-client)");
10354 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10356 json_object_boolean_true_add(json_path
,
10357 "dampeningHistoryEntry");
10359 vty_out(vty
, ", (history entry)");
10360 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10362 json_object_boolean_true_add(json_path
,
10363 "dampeningSuppressed");
10365 vty_out(vty
, ", (suppressed due to dampening)");
10369 vty_out(vty
, "\n");
10371 /* Line2 display Next-hop, Neighbor, Router-id */
10372 /* Display the nexthop */
10373 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
10375 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
||
10376 bn_p
->family
== AF_EVPN
) &&
10377 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10378 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10379 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10380 || safi
== SAFI_EVPN
) {
10382 json_object_string_addf(
10383 json_nexthop_global
, "ip", "%pI4",
10384 &attr
->mp_nexthop_global_in
);
10386 if (path
->peer
->hostname
)
10387 json_object_string_add(
10388 json_nexthop_global
, "hostname",
10389 path
->peer
->hostname
);
10391 if (nexthop_hostname
)
10392 vty_out(vty
, " %pI4(%s)",
10393 &attr
->mp_nexthop_global_in
,
10396 vty_out(vty
, " %pI4",
10397 &attr
->mp_nexthop_global_in
);
10401 json_object_string_addf(json_nexthop_global
,
10405 if (path
->peer
->hostname
)
10406 json_object_string_add(
10407 json_nexthop_global
, "hostname",
10408 path
->peer
->hostname
);
10410 if (nexthop_hostname
)
10411 vty_out(vty
, " %pI4(%s)",
10415 vty_out(vty
, " %pI4",
10421 json_object_string_add(json_nexthop_global
, "afi",
10425 json_object_string_addf(json_nexthop_global
, "ip",
10427 &attr
->mp_nexthop_global
);
10429 if (path
->peer
->hostname
)
10430 json_object_string_add(json_nexthop_global
,
10432 path
->peer
->hostname
);
10434 json_object_string_add(json_nexthop_global
, "afi",
10436 json_object_string_add(json_nexthop_global
, "scope",
10439 if (nexthop_hostname
)
10440 vty_out(vty
, " %pI6(%s)",
10441 &attr
->mp_nexthop_global
,
10444 vty_out(vty
, " %pI6",
10445 &attr
->mp_nexthop_global
);
10449 /* Display the IGP cost or 'inaccessible' */
10450 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10451 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10454 json_object_boolean_false_add(json_nexthop_global
,
10456 json_object_boolean_add(json_nexthop_global
,
10457 "importCheckEnabled", import
);
10459 vty_out(vty
, " (inaccessible%s)",
10460 import
? ", import-check enabled" : "");
10463 if (path
->extra
&& path
->extra
->igpmetric
) {
10465 json_object_int_add(json_nexthop_global
,
10467 path
->extra
->igpmetric
);
10469 vty_out(vty
, " (metric %u)",
10470 path
->extra
->igpmetric
);
10473 /* IGP cost is 0, display this only for json */
10476 json_object_int_add(json_nexthop_global
,
10481 json_object_boolean_true_add(json_nexthop_global
,
10485 /* Display peer "from" output */
10486 /* This path was originated locally */
10487 if (path
->peer
== bgp
->peer_self
) {
10489 if (safi
== SAFI_EVPN
|| (bn_p
->family
== AF_INET
&&
10490 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10492 json_object_string_add(json_peer
, "peerId",
10495 vty_out(vty
, " from 0.0.0.0 ");
10498 json_object_string_add(json_peer
, "peerId",
10501 vty_out(vty
, " from :: ");
10505 json_object_string_addf(json_peer
, "routerId", "%pI4",
10508 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10511 /* We RXed this path from one of our peers */
10515 json_object_string_addf(json_peer
, "peerId", "%pSU",
10517 json_object_string_addf(json_peer
, "routerId", "%pI4",
10518 &path
->peer
->remote_id
);
10520 if (path
->peer
->hostname
)
10521 json_object_string_add(json_peer
, "hostname",
10522 path
->peer
->hostname
);
10524 if (path
->peer
->domainname
)
10525 json_object_string_add(json_peer
, "domainname",
10526 path
->peer
->domainname
);
10528 if (path
->peer
->conf_if
)
10529 json_object_string_add(json_peer
, "interface",
10530 path
->peer
->conf_if
);
10532 if (path
->peer
->conf_if
) {
10533 if (path
->peer
->hostname
10534 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10535 BGP_FLAG_SHOW_HOSTNAME
))
10536 vty_out(vty
, " from %s(%s)",
10537 path
->peer
->hostname
,
10538 path
->peer
->conf_if
);
10540 vty_out(vty
, " from %s",
10541 path
->peer
->conf_if
);
10543 if (path
->peer
->hostname
10544 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10545 BGP_FLAG_SHOW_HOSTNAME
))
10546 vty_out(vty
, " from %s(%s)",
10547 path
->peer
->hostname
,
10550 vty_out(vty
, " from %pSU",
10554 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10555 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10557 vty_out(vty
, " (%s)",
10559 &path
->peer
->remote_id
, buf1
,
10565 * Note when vrfid of nexthop is different from that of prefix
10567 if (path
->extra
&& path
->extra
->bgp_orig
) {
10568 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10573 if (path
->extra
->bgp_orig
->inst_type
10574 == BGP_INSTANCE_TYPE_DEFAULT
)
10575 vn
= VRF_DEFAULT_NAME
;
10577 vn
= path
->extra
->bgp_orig
->name
;
10579 json_object_string_add(json_path
, "nhVrfName", vn
);
10581 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10582 json_object_int_add(json_path
, "nhVrfId", -1);
10584 json_object_int_add(json_path
, "nhVrfId",
10585 (int)nexthop_vrfid
);
10588 if (nexthop_vrfid
== VRF_UNKNOWN
)
10589 vty_out(vty
, " vrf ?");
10593 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10594 vty_out(vty
, " vrf %s(%u)",
10595 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10600 if (nexthop_self
) {
10602 json_object_boolean_true_add(json_path
,
10603 "announceNexthopSelf");
10605 vty_out(vty
, " announce-nh-self");
10610 vty_out(vty
, "\n");
10612 /* display the link-local nexthop */
10613 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10615 json_nexthop_ll
= json_object_new_object();
10616 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10617 &attr
->mp_nexthop_local
);
10619 if (path
->peer
->hostname
)
10620 json_object_string_add(json_nexthop_ll
,
10622 path
->peer
->hostname
);
10624 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10625 json_object_string_add(json_nexthop_ll
, "scope",
10628 json_object_boolean_true_add(json_nexthop_ll
,
10631 if (!attr
->mp_nexthop_prefer_global
)
10632 json_object_boolean_true_add(json_nexthop_ll
,
10635 json_object_boolean_true_add(
10636 json_nexthop_global
, "used");
10638 vty_out(vty
, " (%s) %s\n",
10639 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10640 buf
, INET6_ADDRSTRLEN
),
10641 attr
->mp_nexthop_prefer_global
10642 ? "(prefer-global)"
10646 /* If we do not have a link-local nexthop then we must flag the
10647 global as "used" */
10650 json_object_boolean_true_add(json_nexthop_global
,
10654 if (safi
== SAFI_EVPN
&&
10655 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10656 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10659 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10660 * Int/Ext/Local, Atomic, best */
10662 json_object_string_add(json_path
, "origin",
10663 bgp_origin_long_str
[attr
->origin
]);
10665 vty_out(vty
, " Origin %s",
10666 bgp_origin_long_str
[attr
->origin
]);
10668 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10670 json_object_int_add(json_path
, "metric", attr
->med
);
10672 vty_out(vty
, ", metric %u", attr
->med
);
10675 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10677 json_object_int_add(json_path
, "locPrf",
10680 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10683 if (attr
->weight
!= 0) {
10685 json_object_int_add(json_path
, "weight", attr
->weight
);
10687 vty_out(vty
, ", weight %u", attr
->weight
);
10690 if (attr
->tag
!= 0) {
10692 json_object_int_add(json_path
, "tag", attr
->tag
);
10694 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10697 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10699 json_object_boolean_false_add(json_path
, "valid");
10701 vty_out(vty
, ", invalid");
10702 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10704 json_object_boolean_true_add(json_path
, "valid");
10706 vty_out(vty
, ", valid");
10710 json_object_int_add(json_path
, "version", bn
->version
);
10712 if (path
->peer
!= bgp
->peer_self
) {
10713 if (path
->peer
->as
== path
->peer
->local_as
) {
10714 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10716 json_object_string_add(
10718 "confed-internal");
10720 vty_out(vty
, ", confed-internal");
10723 json_object_string_add(
10724 json_peer
, "type", "internal");
10726 vty_out(vty
, ", internal");
10729 if (bgp_confederation_peers_check(bgp
,
10732 json_object_string_add(
10734 "confed-external");
10736 vty_out(vty
, ", confed-external");
10739 json_object_string_add(
10740 json_peer
, "type", "external");
10742 vty_out(vty
, ", external");
10745 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10747 json_object_boolean_true_add(json_path
, "aggregated");
10748 json_object_boolean_true_add(json_path
, "local");
10750 vty_out(vty
, ", aggregated, local");
10752 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10754 json_object_boolean_true_add(json_path
, "sourced");
10756 vty_out(vty
, ", sourced");
10759 json_object_boolean_true_add(json_path
, "sourced");
10760 json_object_boolean_true_add(json_path
, "local");
10762 vty_out(vty
, ", sourced, local");
10766 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10768 json_object_boolean_true_add(json_path
,
10769 "atomicAggregate");
10771 vty_out(vty
, ", atomic-aggregate");
10774 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10776 json_object_int_add(json_path
, "otc", attr
->otc
);
10778 vty_out(vty
, ", otc %u", attr
->otc
);
10781 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10782 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10783 && bgp_path_info_mpath_count(path
))) {
10785 json_object_boolean_true_add(json_path
, "multipath");
10787 vty_out(vty
, ", multipath");
10790 // Mark the bestpath(s)
10791 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10792 first_as
= aspath_get_first_as(attr
->aspath
);
10795 if (!json_bestpath
)
10796 json_bestpath
= json_object_new_object();
10797 json_object_int_add(json_bestpath
, "bestpathFromAs",
10801 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10803 vty_out(vty
, ", bestpath-from-AS Local");
10807 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10809 if (!json_bestpath
)
10810 json_bestpath
= json_object_new_object();
10811 json_object_boolean_true_add(json_bestpath
, "overall");
10812 json_object_string_add(
10813 json_bestpath
, "selectionReason",
10814 bgp_path_selection_reason2str(bn
->reason
));
10816 vty_out(vty
, ", best");
10817 vty_out(vty
, " (%s)",
10818 bgp_path_selection_reason2str(bn
->reason
));
10822 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10824 json_object_string_add(
10825 json_path
, "rpkiValidationState",
10826 bgp_rpki_validation2str(rpki_curr_state
));
10828 vty_out(vty
, ", rpki validation-state: %s",
10829 bgp_rpki_validation2str(rpki_curr_state
));
10833 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10836 vty_out(vty
, "\n");
10838 /* Line 4 display Community */
10839 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10841 if (!bgp_attr_get_community(attr
)->json
)
10842 community_str(bgp_attr_get_community(attr
),
10844 json_object_lock(bgp_attr_get_community(attr
)->json
);
10845 json_object_object_add(
10846 json_path
, "community",
10847 bgp_attr_get_community(attr
)->json
);
10849 vty_out(vty
, " Community: %s\n",
10850 bgp_attr_get_community(attr
)->str
);
10854 /* Line 5 display Extended-community */
10855 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10857 json_ext_community
= json_object_new_object();
10858 json_object_string_add(
10859 json_ext_community
, "string",
10860 bgp_attr_get_ecommunity(attr
)->str
);
10861 json_object_object_add(json_path
, "extendedCommunity",
10862 json_ext_community
);
10864 vty_out(vty
, " Extended Community: %s\n",
10865 bgp_attr_get_ecommunity(attr
)->str
);
10869 /* Line 6 display Large community */
10870 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10872 if (!bgp_attr_get_lcommunity(attr
)->json
)
10873 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10875 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10876 json_object_object_add(
10877 json_path
, "largeCommunity",
10878 bgp_attr_get_lcommunity(attr
)->json
);
10880 vty_out(vty
, " Large Community: %s\n",
10881 bgp_attr_get_lcommunity(attr
)->str
);
10885 /* Line 7 display Originator, Cluster-id */
10886 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10887 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10888 char buf
[BUFSIZ
] = {0};
10890 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10892 json_object_string_addf(json_path
,
10893 "originatorId", "%pI4",
10894 &attr
->originator_id
);
10896 vty_out(vty
, " Originator: %pI4",
10897 &attr
->originator_id
);
10900 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10901 struct cluster_list
*cluster
=
10902 bgp_attr_get_cluster(attr
);
10906 json_cluster_list
= json_object_new_object();
10907 json_cluster_list_list
=
10908 json_object_new_array();
10910 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10911 json_string
= json_object_new_string(
10914 buf
, sizeof(buf
)));
10915 json_object_array_add(
10916 json_cluster_list_list
,
10921 * struct cluster_list does not have
10922 * "str" variable like aspath and community
10923 * do. Add this someday if someone asks
10925 * json_object_string_add(json_cluster_list,
10926 * "string", cluster->str);
10928 json_object_object_add(json_cluster_list
,
10930 json_cluster_list_list
);
10931 json_object_object_add(json_path
, "clusterList",
10932 json_cluster_list
);
10934 vty_out(vty
, ", Cluster list: ");
10936 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10937 vty_out(vty
, "%pI4 ",
10938 &cluster
->list
[i
]);
10944 vty_out(vty
, "\n");
10947 if (path
->extra
&& path
->extra
->damp_info
)
10948 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10951 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10952 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10953 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10957 json_object_int_add(json_path
, "remoteLabel", label
);
10959 vty_out(vty
, " Remote label: %d\n", label
);
10963 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10964 inet_ntop(AF_INET6
, &path
->extra
->sid
[0].sid
, buf
, sizeof(buf
));
10966 json_object_string_add(json_path
, "remoteSid", buf
);
10968 vty_out(vty
, " Remote SID: %s\n", buf
);
10972 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10974 json_object_int_add(json_path
, "labelIndex",
10975 attr
->label_index
);
10977 vty_out(vty
, " Label Index: %d\n",
10978 attr
->label_index
);
10981 /* Line 8 display Addpath IDs */
10982 if (path
->addpath_rx_id
10983 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10985 json_object_int_add(json_path
, "addpathRxId",
10986 path
->addpath_rx_id
);
10988 /* Keep backwards compatibility with the old API
10989 * by putting TX All's ID in the old field
10991 json_object_int_add(
10992 json_path
, "addpathTxId",
10994 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10996 /* ... but create a specific field for each
10999 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11000 json_object_int_add(
11002 bgp_addpath_names(i
)->id_json_name
,
11003 path
->tx_addpath
.addpath_tx_id
[i
]);
11006 vty_out(vty
, " AddPath ID: RX %u, ",
11007 path
->addpath_rx_id
);
11009 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11013 /* If we used addpath to TX a non-bestpath we need to display
11014 * "Advertised to" on a path-by-path basis
11016 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11019 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11021 bgp_addpath_encode_tx(peer
, afi
, safi
);
11022 has_adj
= bgp_adj_out_lookup(
11024 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11025 &path
->tx_addpath
));
11027 if ((addpath_capable
&& has_adj
)
11028 || (!addpath_capable
&& has_adj
11029 && CHECK_FLAG(path
->flags
,
11030 BGP_PATH_SELECTED
))) {
11031 if (json_path
&& !json_adv_to
)
11032 json_adv_to
= json_object_new_object();
11034 route_vty_out_advertised_to(
11036 " Advertised to:", json_adv_to
);
11042 json_object_object_add(
11043 json_path
, "advertisedTo", json_adv_to
);
11047 vty_out(vty
, "\n");
11052 /* Line 9 display Uptime */
11053 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11055 json_last_update
= json_object_new_object();
11056 json_object_int_add(json_last_update
, "epoch", tbuf
);
11057 json_object_string_add(json_last_update
, "string",
11059 json_object_object_add(json_path
, "lastUpdate",
11062 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11064 /* Line 10 display PMSI tunnel attribute, if present */
11065 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11066 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11067 bgp_attr_get_pmsi_tnl_type(attr
),
11068 PMSI_TNLTYPE_STR_DEFAULT
);
11071 json_pmsi
= json_object_new_object();
11072 json_object_string_add(json_pmsi
, "tunnelType", str
);
11073 json_object_int_add(json_pmsi
, "label",
11074 label2vni(&attr
->label
));
11075 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11077 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11078 str
, label2vni(&attr
->label
));
11081 if (path
->peer
->t_gr_restart
&&
11082 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11083 unsigned long gr_remaining
=
11084 thread_timer_remain_second(path
->peer
->t_gr_restart
);
11087 json_object_int_add(json_path
,
11088 "gracefulRestartSecondsRemaining",
11092 " Time until Graceful Restart stale route deleted: %lu\n",
11096 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11097 bgp_attr_get_community(attr
) &&
11098 community_include(bgp_attr_get_community(attr
),
11099 COMMUNITY_LLGR_STALE
)) {
11100 unsigned long llgr_remaining
= thread_timer_remain_second(
11101 path
->peer
->t_llgr_stale
[afi
][safi
]);
11104 json_object_int_add(json_path
, "llgrSecondsRemaining",
11108 " Time until Long-lived stale route deleted: %lu\n",
11112 /* Output some debug about internal state of the dest flags */
11114 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11115 json_object_boolean_true_add(json_path
, "processScheduled");
11116 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11117 json_object_boolean_true_add(json_path
, "userCleared");
11118 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11119 json_object_boolean_true_add(json_path
, "labelChanged");
11120 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11121 json_object_boolean_true_add(json_path
, "registeredForLabel");
11122 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11123 json_object_boolean_true_add(json_path
, "selectDefered");
11124 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11125 json_object_boolean_true_add(json_path
, "fibInstalled");
11126 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11127 json_object_boolean_true_add(json_path
, "fibPending");
11129 if (json_nexthop_global
|| json_nexthop_ll
) {
11130 json_nexthops
= json_object_new_array();
11132 if (json_nexthop_global
)
11133 json_object_array_add(json_nexthops
,
11134 json_nexthop_global
);
11136 if (json_nexthop_ll
)
11137 json_object_array_add(json_nexthops
,
11140 json_object_object_add(json_path
, "nexthops",
11144 json_object_object_add(json_path
, "peer", json_peer
);
11145 json_object_array_add(json_paths
, json_path
);
11149 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11150 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11151 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11153 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11154 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11156 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11157 const char *comstr
, int exact
, afi_t afi
,
11158 safi_t safi
, uint16_t show_flags
);
11160 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11161 struct bgp_table
*table
, enum bgp_show_type type
,
11162 void *output_arg
, const char *rd
, int is_last
,
11163 unsigned long *output_cum
, unsigned long *total_cum
,
11164 unsigned long *json_header_depth
, uint16_t show_flags
,
11165 enum rpki_states rpki_target_state
)
11167 struct bgp_path_info
*pi
;
11168 struct bgp_dest
*dest
;
11169 bool header
= true;
11170 bool json_detail_header
= false;
11172 unsigned long output_count
= 0;
11173 unsigned long total_count
= 0;
11175 json_object
*json_paths
= NULL
;
11177 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11178 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11179 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11181 if (output_cum
&& *output_cum
!= 0)
11184 if (use_json
&& !*json_header_depth
) {
11186 *json_header_depth
= 1;
11188 vty_out(vty
, "{\n");
11189 *json_header_depth
= 2;
11193 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11194 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11195 " \"localAS\": %u,\n \"routes\": { ",
11196 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11197 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11200 table
->version
, &bgp
->router_id
,
11201 bgp
->default_local_pref
, bgp
->as
);
11203 vty_out(vty
, " \"routeDistinguishers\" : {");
11204 ++*json_header_depth
;
11208 if (use_json
&& rd
) {
11209 vty_out(vty
, " \"%s\" : { ", rd
);
11212 /* Check for 'json detail', where we need header output once per dest */
11213 if (use_json
&& CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
) &&
11214 type
!= bgp_show_type_dampend_paths
&&
11215 type
!= bgp_show_type_damp_neighbor
&&
11216 type
!= bgp_show_type_flap_statistics
&&
11217 type
!= bgp_show_type_flap_neighbor
)
11218 json_detail_header
= true;
11220 /* Start processing of routes. */
11221 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11222 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11223 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11224 bool json_detail
= json_detail_header
;
11226 pi
= bgp_dest_get_bgp_path_info(dest
);
11232 json_paths
= json_object_new_array();
11236 for (; pi
; pi
= pi
->next
) {
11237 struct community
*picomm
= NULL
;
11239 picomm
= bgp_attr_get_community(pi
->attr
);
11243 if (type
== bgp_show_type_prefix_version
) {
11245 strtoul(output_arg
, NULL
, 10);
11246 if (dest
->version
< version
)
11250 if (type
== bgp_show_type_community_alias
) {
11251 char *alias
= output_arg
;
11252 char **communities
;
11254 bool found
= false;
11257 frrstr_split(picomm
->str
, " ",
11258 &communities
, &num
);
11259 for (int i
= 0; i
< num
; i
++) {
11260 const char *com2alias
=
11261 bgp_community2alias(
11264 && strcmp(alias
, com2alias
)
11270 XFREE(MTYPE_TMP
, communities
);
11274 bgp_attr_get_lcommunity(pi
->attr
)) {
11275 frrstr_split(bgp_attr_get_lcommunity(
11278 " ", &communities
, &num
);
11279 for (int i
= 0; i
< num
; i
++) {
11280 const char *com2alias
=
11281 bgp_community2alias(
11284 && strcmp(alias
, com2alias
)
11290 XFREE(MTYPE_TMP
, communities
);
11297 if (type
== bgp_show_type_rpki
) {
11298 if (dest_p
->family
== AF_INET
11299 || dest_p
->family
== AF_INET6
)
11300 rpki_curr_state
= hook_call(
11301 bgp_rpki_prefix_status
,
11302 pi
->peer
, pi
->attr
, dest_p
);
11303 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11304 && rpki_curr_state
!= rpki_target_state
)
11308 if (type
== bgp_show_type_flap_statistics
11309 || type
== bgp_show_type_flap_neighbor
11310 || type
== bgp_show_type_dampend_paths
11311 || type
== bgp_show_type_damp_neighbor
) {
11312 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11315 if (type
== bgp_show_type_regexp
) {
11316 regex_t
*regex
= output_arg
;
11318 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11322 if (type
== bgp_show_type_prefix_list
) {
11323 struct prefix_list
*plist
= output_arg
;
11325 if (prefix_list_apply(plist
, dest_p
)
11329 if (type
== bgp_show_type_access_list
) {
11330 struct access_list
*alist
= output_arg
;
11332 if (access_list_apply(alist
, dest_p
) !=
11336 if (type
== bgp_show_type_filter_list
) {
11337 struct as_list
*as_list
= output_arg
;
11339 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11340 != AS_FILTER_PERMIT
)
11343 if (type
== bgp_show_type_route_map
) {
11344 struct route_map
*rmap
= output_arg
;
11345 struct bgp_path_info path
;
11346 struct bgp_path_info_extra extra
;
11347 struct attr dummy_attr
= {};
11348 route_map_result_t ret
;
11350 dummy_attr
= *pi
->attr
;
11352 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11353 pi
->peer
, &dummy_attr
);
11355 ret
= route_map_apply(rmap
, dest_p
, &path
);
11356 bgp_attr_flush(&dummy_attr
);
11357 if (ret
== RMAP_DENYMATCH
)
11360 if (type
== bgp_show_type_neighbor
11361 || type
== bgp_show_type_flap_neighbor
11362 || type
== bgp_show_type_damp_neighbor
) {
11363 union sockunion
*su
= output_arg
;
11365 if (pi
->peer
== NULL
11366 || pi
->peer
->su_remote
== NULL
11367 || !sockunion_same(pi
->peer
->su_remote
, su
))
11370 if (type
== bgp_show_type_cidr_only
) {
11371 uint32_t destination
;
11373 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11374 if (IN_CLASSC(destination
)
11375 && dest_p
->prefixlen
== 24)
11377 if (IN_CLASSB(destination
)
11378 && dest_p
->prefixlen
== 16)
11380 if (IN_CLASSA(destination
)
11381 && dest_p
->prefixlen
== 8)
11384 if (type
== bgp_show_type_prefix_longer
) {
11386 if (!prefix_match(p
, dest_p
))
11389 if (type
== bgp_show_type_community_all
) {
11393 if (type
== bgp_show_type_community
) {
11394 struct community
*com
= output_arg
;
11396 if (!picomm
|| !community_match(picomm
, com
))
11399 if (type
== bgp_show_type_community_exact
) {
11400 struct community
*com
= output_arg
;
11402 if (!picomm
|| !community_cmp(picomm
, com
))
11405 if (type
== bgp_show_type_community_list
) {
11406 struct community_list
*list
= output_arg
;
11408 if (!community_list_match(picomm
, list
))
11411 if (type
== bgp_show_type_community_list_exact
) {
11412 struct community_list
*list
= output_arg
;
11414 if (!community_list_exact_match(picomm
, list
))
11417 if (type
== bgp_show_type_lcommunity
) {
11418 struct lcommunity
*lcom
= output_arg
;
11420 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11422 bgp_attr_get_lcommunity(pi
->attr
),
11427 if (type
== bgp_show_type_lcommunity_exact
) {
11428 struct lcommunity
*lcom
= output_arg
;
11430 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11432 bgp_attr_get_lcommunity(pi
->attr
),
11436 if (type
== bgp_show_type_lcommunity_list
) {
11437 struct community_list
*list
= output_arg
;
11439 if (!lcommunity_list_match(
11440 bgp_attr_get_lcommunity(pi
->attr
),
11445 == bgp_show_type_lcommunity_list_exact
) {
11446 struct community_list
*list
= output_arg
;
11448 if (!lcommunity_list_exact_match(
11449 bgp_attr_get_lcommunity(pi
->attr
),
11453 if (type
== bgp_show_type_lcommunity_all
) {
11454 if (!bgp_attr_get_lcommunity(pi
->attr
))
11457 if (type
== bgp_show_type_dampend_paths
11458 || type
== bgp_show_type_damp_neighbor
) {
11459 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11460 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11464 if (!use_json
&& header
) {
11466 "BGP table version is %" PRIu64
11467 ", local router ID is %pI4, vrf id ",
11468 table
->version
, &bgp
->router_id
);
11469 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11470 vty_out(vty
, "%s", VRFID_NONE_STR
);
11472 vty_out(vty
, "%u", bgp
->vrf_id
);
11473 vty_out(vty
, "\n");
11474 vty_out(vty
, "Default local pref %u, ",
11475 bgp
->default_local_pref
);
11476 vty_out(vty
, "local AS %u\n", bgp
->as
);
11477 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11478 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11479 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11480 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11481 if (type
== bgp_show_type_dampend_paths
11482 || type
== bgp_show_type_damp_neighbor
)
11483 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11484 else if (type
== bgp_show_type_flap_statistics
11485 || type
== bgp_show_type_flap_neighbor
)
11486 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11488 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11489 : BGP_SHOW_HEADER
));
11492 } else if (json_detail
&& json_paths
!= NULL
) {
11493 const struct prefix_rd
*prd
;
11494 json_object
*jtemp
;
11496 /* Use common detail header, for most types;
11497 * need a json 'object'.
11500 jtemp
= json_object_new_object();
11501 prd
= bgp_rd_from_dest(dest
, safi
);
11503 route_vty_out_detail_header(
11504 vty
, bgp
, dest
, prd
, table
->afi
,
11507 json_object_array_add(json_paths
, jtemp
);
11509 json_detail
= false;
11512 if (rd
!= NULL
&& !display
&& !output_count
) {
11515 "Route Distinguisher: %s\n",
11518 if (type
== bgp_show_type_dampend_paths
11519 || type
== bgp_show_type_damp_neighbor
)
11520 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11521 AFI_IP
, safi
, use_json
,
11523 else if (type
== bgp_show_type_flap_statistics
11524 || type
== bgp_show_type_flap_neighbor
)
11525 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11526 AFI_IP
, safi
, use_json
,
11529 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
11530 route_vty_out_detail(
11531 vty
, bgp
, dest
, pi
,
11532 family2afi(dest_p
->family
),
11533 safi
, RPKI_NOT_BEING_USED
,
11536 route_vty_out(vty
, dest_p
, pi
, display
,
11537 safi
, json_paths
, wide
);
11547 /* encode prefix */
11548 if (dest_p
->family
== AF_FLOWSPEC
) {
11549 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11552 bgp_fs_nlri_get_string(
11554 dest_p
->u
.prefix_flowspec
.ptr
,
11555 dest_p
->u
.prefix_flowspec
.prefixlen
,
11556 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11557 family2afi(dest_p
->u
11558 .prefix_flowspec
.family
));
11560 vty_out(vty
, "\"%s/%d\": ", retstr
,
11561 dest_p
->u
.prefix_flowspec
11564 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11565 dest_p
->u
.prefix_flowspec
11569 vty_out(vty
, "\"%pFX\": ", dest_p
);
11571 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11573 vty_json(vty
, json_paths
);
11577 json_object_free(json_paths
);
11581 output_count
+= *output_cum
;
11582 *output_cum
= output_count
;
11585 total_count
+= *total_cum
;
11586 *total_cum
= total_count
;
11590 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11594 for (i
= 0; i
< *json_header_depth
; ++i
)
11595 vty_out(vty
, " } ");
11597 vty_out(vty
, "\n");
11601 /* No route is displayed */
11602 if (output_count
== 0) {
11603 if (type
== bgp_show_type_normal
)
11605 "No BGP prefixes displayed, %ld exist\n",
11609 "\nDisplayed %ld routes and %ld total paths\n",
11610 output_count
, total_count
);
11614 return CMD_SUCCESS
;
11617 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11618 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11619 enum bgp_show_type type
, void *output_arg
, bool use_json
)
11621 struct bgp_dest
*dest
, *next
;
11622 unsigned long output_cum
= 0;
11623 unsigned long total_cum
= 0;
11624 unsigned long json_header_depth
= 0;
11625 struct bgp_table
*itable
;
11627 uint16_t show_flags
= 0;
11629 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11632 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11634 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11635 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11637 next
= bgp_route_next(dest
);
11638 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11641 itable
= bgp_dest_get_bgp_table_info(dest
);
11642 if (itable
!= NULL
) {
11643 struct prefix_rd prd
;
11644 char rd
[RD_ADDRSTRLEN
];
11646 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11647 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11648 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11649 rd
, next
== NULL
, &output_cum
,
11650 &total_cum
, &json_header_depth
,
11651 show_flags
, RPKI_NOT_BEING_USED
);
11657 if (output_cum
== 0)
11658 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11662 "\nDisplayed %ld routes and %ld total paths\n",
11663 output_cum
, total_cum
);
11665 return CMD_SUCCESS
;
11668 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11669 enum bgp_show_type type
, void *output_arg
,
11670 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11672 struct bgp_table
*table
;
11673 unsigned long json_header_depth
= 0;
11674 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11677 bgp
= bgp_get_default();
11682 vty_out(vty
, "No BGP process is configured\n");
11684 vty_out(vty
, "{}\n");
11685 return CMD_WARNING
;
11688 /* Labeled-unicast routes live in the unicast table. */
11689 if (safi
== SAFI_LABELED_UNICAST
)
11690 safi
= SAFI_UNICAST
;
11692 table
= bgp
->rib
[afi
][safi
];
11693 /* use MPLS and ENCAP specific shows until they are merged */
11694 if (safi
== SAFI_MPLS_VPN
) {
11695 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11696 output_arg
, use_json
);
11699 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11700 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11701 output_arg
, use_json
,
11705 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11706 NULL
, NULL
, &json_header_depth
, show_flags
,
11707 rpki_target_state
);
11710 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11711 safi_t safi
, uint16_t show_flags
)
11713 struct listnode
*node
, *nnode
;
11716 bool route_output
= false;
11717 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11720 vty_out(vty
, "{\n");
11722 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11723 route_output
= true;
11726 vty_out(vty
, ",\n");
11730 vty_out(vty
, "\"%s\":",
11731 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11735 vty_out(vty
, "\nInstance %s:\n",
11736 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11740 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11741 show_flags
, RPKI_NOT_BEING_USED
);
11745 vty_out(vty
, "}\n");
11746 else if (!route_output
)
11747 vty_out(vty
, "%% BGP instance not found\n");
11750 /* Header of detailed BGP route information */
11751 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11752 struct bgp_dest
*dest
,
11753 const struct prefix_rd
*prd
,
11754 afi_t afi
, safi_t safi
, json_object
*json
)
11756 struct bgp_path_info
*pi
;
11757 const struct prefix
*p
;
11759 struct listnode
*node
, *nnode
;
11760 char buf1
[RD_ADDRSTRLEN
];
11764 int accept_own
= 0;
11765 int route_filter_translated_v4
= 0;
11766 int route_filter_v4
= 0;
11767 int route_filter_translated_v6
= 0;
11768 int route_filter_v6
= 0;
11769 int llgr_stale
= 0;
11771 int accept_own_nexthop
= 0;
11774 int no_advertise
= 0;
11778 int has_valid_label
= 0;
11779 mpls_label_t label
= 0;
11780 json_object
*json_adv_to
= NULL
;
11785 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11787 p
= bgp_dest_get_prefix(dest
);
11788 has_valid_label
= bgp_is_valid_label(&label
);
11790 if (safi
== SAFI_EVPN
) {
11792 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11793 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11795 prd
? ":" : "", (struct prefix_evpn
*)p
);
11797 json_object_string_add(json
, "rd",
11798 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11800 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11805 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11807 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11808 ? prefix_rd2str(prd
, buf1
,
11811 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11815 json_object_string_addf(json
, "prefix", "%pFX", p
);
11816 json_object_int_add(json
, "version", dest
->version
);
11821 if (has_valid_label
) {
11823 json_object_int_add(json
, "localLabel", label
);
11825 vty_out(vty
, "Local label: %d\n", label
);
11829 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11830 vty_out(vty
, "not allocated\n");
11832 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11833 struct community
*picomm
= NULL
;
11835 picomm
= bgp_attr_get_community(pi
->attr
);
11838 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11840 if (bgp_path_suppressed(pi
))
11846 no_advertise
+= community_include(
11847 picomm
, COMMUNITY_NO_ADVERTISE
);
11849 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11851 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11853 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11854 route_filter_translated_v4
+= community_include(
11855 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11856 route_filter_translated_v6
+= community_include(
11857 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11858 route_filter_v4
+= community_include(
11859 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11860 route_filter_v6
+= community_include(
11861 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11863 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11864 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11865 accept_own_nexthop
+= community_include(
11866 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11868 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11869 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11874 vty_out(vty
, "Paths: (%d available", count
);
11876 vty_out(vty
, ", best #%d", best
);
11877 if (safi
== SAFI_UNICAST
) {
11878 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11879 vty_out(vty
, ", table %s",
11882 vty_out(vty
, ", vrf %s",
11886 vty_out(vty
, ", no best path");
11890 ", accept own local route exported and imported in different VRF");
11891 else if (route_filter_translated_v4
)
11893 ", mark translated RTs for VPNv4 route filtering");
11894 else if (route_filter_v4
)
11896 ", attach RT as-is for VPNv4 route filtering");
11897 else if (route_filter_translated_v6
)
11899 ", mark translated RTs for VPNv6 route filtering");
11900 else if (route_filter_v6
)
11902 ", attach RT as-is for VPNv6 route filtering");
11903 else if (llgr_stale
)
11905 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11908 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11909 else if (accept_own_nexthop
)
11911 ", accept local nexthop");
11912 else if (blackhole
)
11913 vty_out(vty
, ", inform peer to blackhole prefix");
11914 else if (no_export
)
11915 vty_out(vty
, ", not advertised to EBGP peer");
11916 else if (no_advertise
)
11917 vty_out(vty
, ", not advertised to any peer");
11919 vty_out(vty
, ", not advertised outside local AS");
11922 ", inform EBGP peer not to advertise to their EBGP peers");
11926 ", Advertisements suppressed by an aggregate.");
11927 vty_out(vty
, ")\n");
11930 /* If we are not using addpath then we can display Advertised to and
11932 * show what peers we advertised the bestpath to. If we are using
11934 * though then we must display Advertised to on a path-by-path basis. */
11935 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11936 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11937 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11938 if (json
&& !json_adv_to
)
11939 json_adv_to
= json_object_new_object();
11941 route_vty_out_advertised_to(
11943 " Advertised to non peer-group peers:\n ",
11950 json_object_object_add(json
, "advertisedTo",
11955 vty_out(vty
, " Not advertised to any peer");
11956 vty_out(vty
, "\n");
11961 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
11962 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11963 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11964 json_object
*json
, enum bgp_path_type pathtype
,
11965 int *display
, enum rpki_states rpki_target_state
)
11967 struct bgp_path_info
*pi
;
11969 json_object
*json_header
= NULL
;
11970 json_object
*json_paths
= NULL
;
11971 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
11973 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11974 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11976 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
11977 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
11978 pi
->peer
, pi
->attr
, p
);
11980 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11981 && rpki_curr_state
!= rpki_target_state
)
11984 if (json
&& !json_paths
) {
11985 /* Instantiate json_paths only if path is valid */
11986 json_paths
= json_object_new_array();
11988 json_header
= json_object_new_object();
11990 json_header
= json
;
11994 route_vty_out_detail_header(
11995 vty
, bgp
, bgp_node
, pfx_rd
,
11996 AFI_IP
, safi
, json_header
);
12001 if (pathtype
== BGP_PATH_SHOW_ALL
12002 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12003 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12004 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12005 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12006 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12007 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
12008 safi
, rpki_curr_state
, json_paths
);
12011 if (json
&& json_paths
) {
12012 json_object_object_add(json_header
, "paths", json_paths
);
12015 json_object_object_addf(json
, json_header
, "%pRD",
12021 * Return rd based on safi
12023 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12027 case SAFI_MPLS_VPN
:
12030 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12036 /* Display specified route of BGP table. */
12037 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12038 struct bgp_table
*rib
, const char *ip_str
,
12039 afi_t afi
, safi_t safi
,
12040 enum rpki_states rpki_target_state
,
12041 struct prefix_rd
*prd
, int prefix_check
,
12042 enum bgp_path_type pathtype
, bool use_json
)
12046 struct prefix match
;
12047 struct bgp_dest
*dest
;
12048 struct bgp_dest
*rm
;
12049 struct bgp_table
*table
;
12050 json_object
*json
= NULL
;
12051 json_object
*json_paths
= NULL
;
12053 /* Check IP address argument. */
12054 ret
= str2prefix(ip_str
, &match
);
12056 vty_out(vty
, "address is malformed\n");
12057 return CMD_WARNING
;
12060 match
.family
= afi2family(afi
);
12063 json
= json_object_new_object();
12065 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12066 for (dest
= bgp_table_top(rib
); dest
;
12067 dest
= bgp_route_next(dest
)) {
12068 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12070 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12072 table
= bgp_dest_get_bgp_table_info(dest
);
12076 rm
= bgp_node_match(table
, &match
);
12080 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12082 && rm_p
->prefixlen
!= match
.prefixlen
) {
12083 bgp_dest_unlock_node(rm
);
12087 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12088 bgp
, afi
, safi
, json
, pathtype
,
12089 &display
, rpki_target_state
);
12091 bgp_dest_unlock_node(rm
);
12093 } else if (safi
== SAFI_EVPN
) {
12094 struct bgp_dest
*longest_pfx
;
12095 bool is_exact_pfxlen_match
= false;
12097 for (dest
= bgp_table_top(rib
); dest
;
12098 dest
= bgp_route_next(dest
)) {
12099 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12101 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12103 table
= bgp_dest_get_bgp_table_info(dest
);
12107 longest_pfx
= NULL
;
12108 is_exact_pfxlen_match
= false;
12110 * Search through all the prefixes for a match. The
12111 * pfx's are enumerated in ascending order of pfxlens.
12112 * So, the last pfx match is the longest match. Set
12113 * is_exact_pfxlen_match when we get exact pfxlen match
12115 for (rm
= bgp_table_top(table
); rm
;
12116 rm
= bgp_route_next(rm
)) {
12117 const struct prefix
*rm_p
=
12118 bgp_dest_get_prefix(rm
);
12120 * Get prefixlen of the ip-prefix within type5
12123 if (evpn_type5_prefix_match(rm_p
, &match
)
12127 bgp_evpn_get_type5_prefixlen(
12129 if (type5_pfxlen
== match
.prefixlen
) {
12130 is_exact_pfxlen_match
= true;
12131 bgp_dest_unlock_node(rm
);
12140 if (prefix_check
&& !is_exact_pfxlen_match
)
12144 bgp_dest_lock_node(rm
);
12146 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12147 bgp
, afi
, safi
, json
, pathtype
,
12148 &display
, rpki_target_state
);
12150 bgp_dest_unlock_node(rm
);
12152 } else if (safi
== SAFI_FLOWSPEC
) {
12154 json_paths
= json_object_new_array();
12156 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12157 &match
, prefix_check
,
12163 json_object_object_add(json
, "paths",
12166 json_object_free(json_paths
);
12169 dest
= bgp_node_match(rib
, &match
);
12170 if (dest
!= NULL
) {
12171 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12173 || dest_p
->prefixlen
== match
.prefixlen
) {
12174 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12175 safi
, json
, pathtype
,
12176 &display
, rpki_target_state
);
12179 bgp_dest_unlock_node(dest
);
12184 vty_json(vty
, json
);
12187 vty_out(vty
, "%% Network not in table\n");
12188 return CMD_WARNING
;
12192 return CMD_SUCCESS
;
12195 /* Display specified route of Main RIB */
12196 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12197 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12198 int prefix_check
, enum bgp_path_type pathtype
,
12199 enum rpki_states rpki_target_state
, bool use_json
)
12202 bgp
= bgp_get_default();
12205 vty_out(vty
, "No BGP process is configured\n");
12207 vty_out(vty
, "{}\n");
12208 return CMD_WARNING
;
12212 /* labeled-unicast routes live in the unicast table */
12213 if (safi
== SAFI_LABELED_UNICAST
)
12214 safi
= SAFI_UNICAST
;
12216 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12217 afi
, safi
, rpki_target_state
, prd
,
12218 prefix_check
, pathtype
, use_json
);
12221 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12222 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12223 safi_t safi
, bool uj
)
12225 struct lcommunity
*lcom
;
12230 uint16_t show_flags
= 0;
12234 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12236 b
= buffer_new(1024);
12237 for (i
= 0; i
< argc
; i
++) {
12239 buffer_putc(b
, ' ');
12241 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12243 buffer_putstr(b
, argv
[i
]->arg
);
12247 buffer_putc(b
, '\0');
12249 str
= buffer_getstr(b
);
12252 lcom
= lcommunity_str2com(str
);
12253 XFREE(MTYPE_TMP
, str
);
12255 vty_out(vty
, "%% Large-community malformed\n");
12256 return CMD_WARNING
;
12259 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12260 (exact
? bgp_show_type_lcommunity_exact
12261 : bgp_show_type_lcommunity
),
12262 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12264 lcommunity_free(&lcom
);
12268 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12269 const char *lcom
, bool exact
, afi_t afi
,
12270 safi_t safi
, bool uj
)
12272 struct community_list
*list
;
12273 uint16_t show_flags
= 0;
12276 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12279 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12280 LARGE_COMMUNITY_LIST_MASTER
);
12281 if (list
== NULL
) {
12282 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12284 return CMD_WARNING
;
12287 return bgp_show(vty
, bgp
, afi
, safi
,
12288 (exact
? bgp_show_type_lcommunity_list_exact
12289 : bgp_show_type_lcommunity_list
),
12290 list
, show_flags
, RPKI_NOT_BEING_USED
);
12293 DEFUN (show_ip_bgp_large_community_list
,
12294 show_ip_bgp_large_community_list_cmd
,
12295 "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]",
12299 BGP_INSTANCE_HELP_STR
12301 BGP_SAFI_WITH_LABEL_HELP_STR
12302 "Display routes matching the large-community-list\n"
12303 "large-community-list number\n"
12304 "large-community-list name\n"
12305 "Exact match of the large-communities\n"
12308 afi_t afi
= AFI_IP6
;
12309 safi_t safi
= SAFI_UNICAST
;
12311 bool exact_match
= 0;
12312 struct bgp
*bgp
= NULL
;
12313 bool uj
= use_json(argc
, argv
);
12318 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12321 return CMD_WARNING
;
12323 argv_find(argv
, argc
, "large-community-list", &idx
);
12325 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12327 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12330 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12331 exact_match
, afi
, safi
, uj
);
12333 DEFUN (show_ip_bgp_large_community
,
12334 show_ip_bgp_large_community_cmd
,
12335 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12339 BGP_INSTANCE_HELP_STR
12341 BGP_SAFI_WITH_LABEL_HELP_STR
12342 "Display routes matching the large-communities\n"
12343 "List of large-community numbers\n"
12344 "Exact match of the large-communities\n"
12347 afi_t afi
= AFI_IP6
;
12348 safi_t safi
= SAFI_UNICAST
;
12350 bool exact_match
= 0;
12351 struct bgp
*bgp
= NULL
;
12352 bool uj
= use_json(argc
, argv
);
12353 uint16_t show_flags
= 0;
12357 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12360 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12363 return CMD_WARNING
;
12365 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12366 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12370 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12371 exact_match
, afi
, safi
, uj
);
12373 return bgp_show(vty
, bgp
, afi
, safi
,
12374 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12375 RPKI_NOT_BEING_USED
);
12378 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12379 safi_t safi
, struct json_object
*json_array
);
12380 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12381 safi_t safi
, struct json_object
*json
);
12384 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12385 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12386 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12387 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12389 bool uj
= use_json(argc
, argv
);
12390 struct bgp
*bgp
= NULL
;
12391 safi_t safi
= SAFI_UNICAST
;
12392 afi_t afi
= AFI_IP6
;
12394 struct json_object
*json_all
= NULL
;
12395 struct json_object
*json_afi_safi
= NULL
;
12397 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12400 return CMD_WARNING
;
12403 json_all
= json_object_new_object();
12405 FOREACH_AFI_SAFI (afi
, safi
) {
12407 * So limit output to those afi/safi pairs that
12408 * actually have something interesting in them
12410 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12415 json_afi_safi
= json_object_new_array();
12416 json_object_object_add(
12418 get_afi_safi_str(afi
, safi
, true),
12421 json_afi_safi
= NULL
;
12424 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12428 vty_json(vty
, json_all
);
12430 return CMD_SUCCESS
;
12433 /* BGP route print out function without JSON */
12434 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12435 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12436 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12440 BGP_INSTANCE_HELP_STR
12443 "BGP RIB advertisement statistics\n"
12446 afi_t afi
= AFI_IP6
;
12447 safi_t safi
= SAFI_UNICAST
;
12448 struct bgp
*bgp
= NULL
;
12450 bool uj
= use_json(argc
, argv
);
12451 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12453 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12456 return CMD_WARNING
;
12459 json_afi_safi
= json_object_new_array();
12461 json_afi_safi
= NULL
;
12463 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12466 json
= json_object_new_object();
12467 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12469 vty_json(vty
, json
);
12474 /* BGP route print out function without JSON */
12475 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12476 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12477 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12479 statistics [json]",
12480 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12481 BGP_SAFI_WITH_LABEL_HELP_STR
12482 "BGP RIB advertisement statistics\n" JSON_STR
)
12484 afi_t afi
= AFI_IP6
;
12485 safi_t safi
= SAFI_UNICAST
;
12486 struct bgp
*bgp
= NULL
;
12488 bool uj
= use_json(argc
, argv
);
12489 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12491 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12494 return CMD_WARNING
;
12497 json_afi_safi
= json_object_new_array();
12499 json_afi_safi
= NULL
;
12501 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12504 json
= json_object_new_object();
12505 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12507 vty_json(vty
, json
);
12512 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12513 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12514 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12515 "]] [all$all] dampening parameters [json]",
12516 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12517 BGP_SAFI_WITH_LABEL_HELP_STR
12518 "Display the entries for all address families\n"
12519 "Display detailed information about dampening\n"
12520 "Display detail of configured dampening parameters\n"
12523 afi_t afi
= AFI_IP6
;
12524 safi_t safi
= SAFI_UNICAST
;
12525 struct bgp
*bgp
= NULL
;
12527 uint16_t show_flags
= 0;
12528 bool uj
= use_json(argc
, argv
);
12532 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12535 /* [<ipv4|ipv6> [all]] */
12537 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12538 if (argv_find(argv
, argc
, "ipv4", &idx
))
12539 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12541 if (argv_find(argv
, argc
, "ipv6", &idx
))
12542 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12545 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12548 return CMD_WARNING
;
12550 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12553 /* BGP route print out function */
12554 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12555 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12556 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12560 |dampening <flap-statistics|dampened-paths>\
12561 |community [AA:NN|local-AS|no-advertise|no-export\
12562 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12563 |accept-own|accept-own-nexthop|route-filter-v6\
12564 |route-filter-v4|route-filter-translated-v6\
12565 |route-filter-translated-v4] [exact-match]\
12566 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12567 |filter-list AS_PATH_FILTER_NAME\
12569 |access-list ACCESSLIST_NAME\
12570 |route-map RMAP_NAME\
12571 |rpki <invalid|valid|notfound>\
12572 |version (1-4294967295)\
12574 |A.B.C.D/M longer-prefixes\
12575 |X:X::X:X/M longer-prefixes\
12576 |optimal-route-reflection [WORD$orr_group_name]\
12577 ] [json$uj [detail$detail] | wide$wide]",
12578 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12579 BGP_SAFI_WITH_LABEL_HELP_STR
12580 "Display the entries for all address families\n"
12581 "Display only routes with non-natural netmasks\n"
12582 "Display detailed information about dampening\n"
12583 "Display flap statistics of routes\n"
12584 "Display paths suppressed due to dampening\n"
12585 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12586 "Do not send outside local AS (well-known community)\n"
12587 "Do not advertise to any peer (well-known community)\n"
12588 "Do not export to next AS (well-known community)\n"
12589 "Graceful shutdown (well-known community)\n"
12590 "Do not export to any peer (well-known community)\n"
12591 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12592 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12593 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12594 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12595 "Should accept VPN route with local nexthop (well-known community)\n"
12596 "RT VPNv6 route filtering (well-known community)\n"
12597 "RT VPNv4 route filtering (well-known community)\n"
12598 "RT translated VPNv6 route filtering (well-known community)\n"
12599 "RT translated VPNv4 route filtering (well-known community)\n"
12600 "Exact match of the communities\n"
12601 "Community-list number\n"
12602 "Community-list name\n"
12603 "Display routes matching the community-list\n"
12604 "Exact match of the communities\n"
12605 "Display routes conforming to the filter-list\n"
12606 "Regular expression access list name\n"
12607 "Display routes conforming to the prefix-list\n"
12608 "Prefix-list name\n"
12609 "Display routes conforming to the access-list\n"
12610 "Access-list name\n"
12611 "Display routes matching the route-map\n"
12612 "A route-map to match on\n"
12613 "RPKI route types\n"
12614 "A valid path as determined by rpki\n"
12615 "A invalid path as determined by rpki\n"
12616 "A path that has no rpki data\n"
12617 "Display prefixes with matching version numbers\n"
12618 "Version number and above\n"
12619 "Display prefixes with matching BGP community alias\n"
12620 "BGP community alias\n"
12622 "Display route and more specific routes\n"
12624 "Display route and more specific routes\n"
12625 "Display Optimal Route Reflection RR Clients\n"
12628 "Display detailed version of JSON output\n"
12629 "Increase table width for longer prefixes\n")
12631 afi_t afi
= AFI_IP6
;
12632 safi_t safi
= SAFI_UNICAST
;
12633 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12634 void *output_arg
= NULL
;
12635 struct bgp
*bgp
= NULL
;
12637 int exact_match
= 0;
12638 char *community
= NULL
;
12640 uint16_t show_flags
= 0;
12641 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12643 bool orr_group
= false;
12647 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12651 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12653 /* [<ipv4|ipv6> [all]] */
12655 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12657 if (argv_find(argv
, argc
, "ipv4", &idx
))
12658 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12660 if (argv_find(argv
, argc
, "ipv6", &idx
))
12661 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12665 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12667 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12670 return CMD_WARNING
;
12672 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12673 sh_type
= bgp_show_type_cidr_only
;
12675 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12676 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12677 sh_type
= bgp_show_type_dampend_paths
;
12678 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12679 sh_type
= bgp_show_type_flap_statistics
;
12682 if (argv_find(argv
, argc
, "community", &idx
)) {
12683 char *maybecomm
= NULL
;
12685 if (idx
+ 1 < argc
) {
12686 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12687 maybecomm
= argv
[idx
+ 1]->arg
;
12689 maybecomm
= argv
[idx
+ 1]->text
;
12692 if (maybecomm
&& !strmatch(maybecomm
, "json")
12693 && !strmatch(maybecomm
, "exact-match"))
12694 community
= maybecomm
;
12696 if (argv_find(argv
, argc
, "exact-match", &idx
))
12700 sh_type
= bgp_show_type_community_all
;
12703 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12704 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12705 struct community_list
*list
;
12707 if (argv_find(argv
, argc
, "exact-match", &idx
))
12710 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12711 COMMUNITY_LIST_MASTER
);
12712 if (list
== NULL
) {
12713 vty_out(vty
, "%% %s community-list not found\n",
12714 clist_number_or_name
);
12715 return CMD_WARNING
;
12719 sh_type
= bgp_show_type_community_list_exact
;
12721 sh_type
= bgp_show_type_community_list
;
12725 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12726 const char *filter
= argv
[++idx
]->arg
;
12727 struct as_list
*as_list
;
12729 as_list
= as_list_lookup(filter
);
12730 if (as_list
== NULL
) {
12731 vty_out(vty
, "%% %s AS-path access-list not found\n",
12733 return CMD_WARNING
;
12736 sh_type
= bgp_show_type_filter_list
;
12737 output_arg
= as_list
;
12740 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12741 const char *prefix_list_str
= argv
[++idx
]->arg
;
12742 struct prefix_list
*plist
;
12744 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12745 if (plist
== NULL
) {
12746 vty_out(vty
, "%% %s prefix-list not found\n",
12748 return CMD_WARNING
;
12751 sh_type
= bgp_show_type_prefix_list
;
12752 output_arg
= plist
;
12755 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12756 const char *access_list_str
= argv
[++idx
]->arg
;
12757 struct access_list
*alist
;
12759 alist
= access_list_lookup(afi
, access_list_str
);
12761 vty_out(vty
, "%% %s access-list not found\n",
12763 return CMD_WARNING
;
12766 sh_type
= bgp_show_type_access_list
;
12767 output_arg
= alist
;
12770 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12771 const char *rmap_str
= argv
[++idx
]->arg
;
12772 struct route_map
*rmap
;
12774 rmap
= route_map_lookup_by_name(rmap_str
);
12776 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12777 return CMD_WARNING
;
12780 sh_type
= bgp_show_type_route_map
;
12784 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12785 sh_type
= bgp_show_type_rpki
;
12786 if (argv_find(argv
, argc
, "valid", &idx
))
12787 rpki_target_state
= RPKI_VALID
;
12788 else if (argv_find(argv
, argc
, "invalid", &idx
))
12789 rpki_target_state
= RPKI_INVALID
;
12792 /* Display prefixes with matching version numbers */
12793 if (argv_find(argv
, argc
, "version", &idx
)) {
12794 sh_type
= bgp_show_type_prefix_version
;
12795 output_arg
= argv
[idx
+ 1]->arg
;
12798 /* Display prefixes with matching BGP community alias */
12799 if (argv_find(argv
, argc
, "alias", &idx
)) {
12800 sh_type
= bgp_show_type_community_alias
;
12801 output_arg
= argv
[idx
+ 1]->arg
;
12804 /* prefix-longer */
12805 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12806 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12807 const char *prefix_str
= argv
[idx
]->arg
;
12809 if (!str2prefix(prefix_str
, &p
)) {
12810 vty_out(vty
, "%% Malformed Prefix\n");
12811 return CMD_WARNING
;
12814 sh_type
= bgp_show_type_prefix_longer
;
12818 if (argv_find(argv
, argc
, "optimal-route-reflection", &idx
))
12822 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12824 return bgp_show_community(vty
, bgp
, community
,
12825 exact_match
, afi
, safi
,
12827 else if (orr_group
)
12828 return bgp_show_orr(vty
, bgp
, afi
, safi
, orr_group_name
,
12831 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12832 output_arg
, show_flags
,
12833 rpki_target_state
);
12835 struct listnode
*node
;
12837 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12841 vty_out(vty
, "{\n");
12843 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12844 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12845 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12848 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12849 FOREACH_SAFI (safi
) {
12850 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12858 vty_out(vty
, ",\n");
12859 vty_out(vty
, "\"%s\":{\n",
12860 get_afi_safi_str(afi
,
12865 "\nFor address family: %s\n",
12871 bgp_show_community(
12872 vty
, abgp
, community
,
12873 exact_match
, afi
, safi
,
12875 else if (orr_group
)
12876 bgp_show_orr(vty
, bgp
, afi
,
12881 bgp_show(vty
, abgp
, afi
, safi
,
12882 sh_type
, output_arg
,
12884 rpki_target_state
);
12886 vty_out(vty
, "}\n");
12890 /* show <ip> bgp all: for each AFI and SAFI*/
12891 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12892 FOREACH_AFI_SAFI (afi
, safi
) {
12893 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12901 vty_out(vty
, ",\n");
12903 vty_out(vty
, "\"%s\":{\n",
12904 get_afi_safi_str(afi
,
12909 "\nFor address family: %s\n",
12915 bgp_show_community(
12916 vty
, abgp
, community
,
12917 exact_match
, afi
, safi
,
12919 else if (orr_group
)
12920 bgp_show_orr(vty
, bgp
, afi
,
12925 bgp_show(vty
, abgp
, afi
, safi
,
12926 sh_type
, output_arg
,
12928 rpki_target_state
);
12930 vty_out(vty
, "}\n");
12935 vty_out(vty
, "}\n");
12937 return CMD_SUCCESS
;
12940 DEFUN (show_ip_bgp_route
,
12941 show_ip_bgp_route_cmd
,
12942 "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]",
12946 BGP_INSTANCE_HELP_STR
12948 BGP_SAFI_WITH_LABEL_HELP_STR
12949 "Network in the BGP routing table to display\n"
12951 "Network in the BGP routing table to display\n"
12953 "Display only the bestpath\n"
12954 "Display only multipaths\n"
12955 "Display only paths that match the specified rpki state\n"
12956 "A valid path as determined by rpki\n"
12957 "A invalid path as determined by rpki\n"
12958 "A path that has no rpki data\n"
12961 int prefix_check
= 0;
12963 afi_t afi
= AFI_IP6
;
12964 safi_t safi
= SAFI_UNICAST
;
12965 char *prefix
= NULL
;
12966 struct bgp
*bgp
= NULL
;
12967 enum bgp_path_type path_type
;
12968 bool uj
= use_json(argc
, argv
);
12972 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12975 return CMD_WARNING
;
12979 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12980 return CMD_WARNING
;
12983 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12984 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12985 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12987 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12988 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12991 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12992 && afi
!= AFI_IP6
) {
12994 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12995 return CMD_WARNING
;
12997 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12998 && afi
!= AFI_IP
) {
13000 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13001 return CMD_WARNING
;
13004 prefix
= argv
[idx
]->arg
;
13006 /* [<bestpath|multipath>] */
13007 if (argv_find(argv
, argc
, "bestpath", &idx
))
13008 path_type
= BGP_PATH_SHOW_BESTPATH
;
13009 else if (argv_find(argv
, argc
, "multipath", &idx
))
13010 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13012 path_type
= BGP_PATH_SHOW_ALL
;
13014 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13015 path_type
, RPKI_NOT_BEING_USED
, uj
);
13018 DEFUN (show_ip_bgp_regexp
,
13019 show_ip_bgp_regexp_cmd
,
13020 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13024 BGP_INSTANCE_HELP_STR
13026 BGP_SAFI_WITH_LABEL_HELP_STR
13027 "Display routes matching the AS path regular expression\n"
13028 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13031 afi_t afi
= AFI_IP6
;
13032 safi_t safi
= SAFI_UNICAST
;
13033 struct bgp
*bgp
= NULL
;
13034 bool uj
= use_json(argc
, argv
);
13035 char *regstr
= NULL
;
13038 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13041 return CMD_WARNING
;
13043 // get index of regex
13044 if (argv_find(argv
, argc
, "REGEX", &idx
))
13045 regstr
= argv
[idx
]->arg
;
13048 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13049 bgp_show_type_regexp
, uj
);
13052 DEFPY (show_ip_bgp_instance_all
,
13053 show_ip_bgp_instance_all_cmd
,
13054 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13058 BGP_INSTANCE_ALL_HELP_STR
13060 BGP_SAFI_WITH_LABEL_HELP_STR
13062 "Increase table width for longer prefixes\n")
13064 afi_t afi
= AFI_IP6
;
13065 safi_t safi
= SAFI_UNICAST
;
13066 struct bgp
*bgp
= NULL
;
13068 uint16_t show_flags
= 0;
13072 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13076 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13078 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13081 return CMD_WARNING
;
13083 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13084 return CMD_SUCCESS
;
13087 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13088 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13093 uint16_t show_flags
= 0;
13096 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13098 if (!config_bgp_aspath_validate(regstr
)) {
13099 vty_out(vty
, "Invalid character in REGEX %s\n",
13101 return CMD_WARNING_CONFIG_FAILED
;
13104 regex
= bgp_regcomp(regstr
);
13106 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13107 return CMD_WARNING
;
13110 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13111 RPKI_NOT_BEING_USED
);
13112 bgp_regex_free(regex
);
13116 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13117 const char *comstr
, int exact
, afi_t afi
,
13118 safi_t safi
, uint16_t show_flags
)
13120 struct community
*com
;
13123 com
= community_str2com(comstr
);
13125 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13126 return CMD_WARNING
;
13129 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13130 (exact
? bgp_show_type_community_exact
13131 : bgp_show_type_community
),
13132 com
, show_flags
, RPKI_NOT_BEING_USED
);
13133 community_free(&com
);
13139 BGP_STATS_MAXBITLEN
= 0,
13141 BGP_STATS_PREFIXES
,
13143 BGP_STATS_UNAGGREGATEABLE
,
13144 BGP_STATS_MAX_AGGREGATEABLE
,
13145 BGP_STATS_AGGREGATES
,
13147 BGP_STATS_ASPATH_COUNT
,
13148 BGP_STATS_ASPATH_MAXHOPS
,
13149 BGP_STATS_ASPATH_TOTHOPS
,
13150 BGP_STATS_ASPATH_MAXSIZE
,
13151 BGP_STATS_ASPATH_TOTSIZE
,
13152 BGP_STATS_ASN_HIGHEST
,
13156 #define TABLE_STATS_IDX_VTY 0
13157 #define TABLE_STATS_IDX_JSON 1
13159 static const char *table_stats_strs
[][2] = {
13160 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13161 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13162 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13163 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13164 "unaggregateablePrefixes"},
13165 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13166 "maximumAggregateablePrefixes"},
13167 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13168 "bgpAggregateAdvertisements"},
13169 [BGP_STATS_SPACE
] = {"Address space advertised",
13170 "addressSpaceAdvertised"},
13171 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13172 "advertisementsWithPaths"},
13173 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13175 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13177 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13178 "averageAsPathLengthHops"},
13179 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13180 "averageAsPathSizeBytes"},
13181 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13182 [BGP_STATS_MAX
] = {NULL
, NULL
}
13185 struct bgp_table_stats
{
13186 struct bgp_table
*table
;
13187 unsigned long long counts
[BGP_STATS_MAX
];
13190 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13193 double total_space
;
13196 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13197 struct bgp_table_stats
*ts
, unsigned int space
)
13199 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13200 struct bgp_path_info
*pi
;
13201 const struct prefix
*rn_p
;
13203 if (!bgp_dest_has_bgp_path_info_data(dest
))
13206 rn_p
= bgp_dest_get_prefix(dest
);
13207 ts
->counts
[BGP_STATS_PREFIXES
]++;
13208 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13210 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13211 /* check if the prefix is included by any other announcements */
13212 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13213 pdest
= bgp_dest_parent_nolock(pdest
);
13215 if (pdest
== NULL
|| pdest
== top
) {
13216 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13217 /* announced address space */
13219 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13220 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13221 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13224 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13225 ts
->counts
[BGP_STATS_RIB
]++;
13227 if (CHECK_FLAG(pi
->attr
->flag
,
13228 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13229 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13231 /* as-path stats */
13232 if (pi
->attr
->aspath
) {
13233 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13234 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13235 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13237 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13239 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13240 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13242 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13243 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13245 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13246 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13247 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13248 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13253 static void bgp_table_stats_walker(struct thread
*t
)
13255 struct bgp_dest
*dest
, *ndest
;
13256 struct bgp_dest
*top
;
13257 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13258 unsigned int space
= 0;
13260 if (!(top
= bgp_table_top(ts
->table
)))
13263 switch (ts
->table
->afi
) {
13265 space
= IPV4_MAX_BITLEN
;
13268 space
= IPV6_MAX_BITLEN
;
13271 space
= EVPN_ROUTE_PREFIXLEN
;
13277 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13279 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13280 if (ts
->table
->safi
== SAFI_MPLS_VPN
13281 || ts
->table
->safi
== SAFI_ENCAP
13282 || ts
->table
->safi
== SAFI_EVPN
) {
13283 struct bgp_table
*table
;
13285 table
= bgp_dest_get_bgp_table_info(dest
);
13289 top
= bgp_table_top(table
);
13290 for (ndest
= bgp_table_top(table
); ndest
;
13291 ndest
= bgp_route_next(ndest
))
13292 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13294 bgp_table_stats_rn(dest
, top
, ts
, space
);
13299 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13300 struct json_object
*json_array
)
13302 struct listnode
*node
, *nnode
;
13305 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13306 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13309 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13310 safi_t safi
, struct json_object
*json_array
)
13312 struct bgp_table_stats ts
;
13314 int ret
= CMD_SUCCESS
;
13316 struct json_object
*json
= NULL
;
13317 uint32_t bitlen
= 0;
13318 struct json_object
*json_bitlen
;
13321 json
= json_object_new_object();
13323 if (!bgp
->rib
[afi
][safi
]) {
13324 char warning_msg
[50];
13326 snprintf(warning_msg
, sizeof(warning_msg
),
13327 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13331 vty_out(vty
, "%s\n", warning_msg
);
13333 json_object_string_add(json
, "warning", warning_msg
);
13336 goto end_table_stats
;
13340 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13341 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13343 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13345 /* labeled-unicast routes live in the unicast table */
13346 if (safi
== SAFI_LABELED_UNICAST
)
13347 safi
= SAFI_UNICAST
;
13349 memset(&ts
, 0, sizeof(ts
));
13350 ts
.table
= bgp
->rib
[afi
][safi
];
13351 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13353 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13354 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13355 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13359 case BGP_STATS_ASPATH_TOTHOPS
:
13360 case BGP_STATS_ASPATH_TOTSIZE
:
13363 temp_buf
, sizeof(temp_buf
), "%12.2f",
13365 ? (float)ts
.counts
[i
]
13367 [BGP_STATS_ASPATH_COUNT
]
13369 vty_out(vty
, "%-30s: %s",
13370 table_stats_strs
[i
]
13371 [TABLE_STATS_IDX_VTY
],
13374 json_object_double_add(
13376 table_stats_strs
[i
]
13377 [TABLE_STATS_IDX_JSON
],
13379 ? (double)ts
.counts
[i
]
13380 / (double)ts
.counts
13381 [BGP_STATS_ASPATH_COUNT
]
13385 case BGP_STATS_TOTPLEN
:
13388 temp_buf
, sizeof(temp_buf
), "%12.2f",
13390 ? (float)ts
.counts
[i
]
13392 [BGP_STATS_PREFIXES
]
13394 vty_out(vty
, "%-30s: %s",
13395 table_stats_strs
[i
]
13396 [TABLE_STATS_IDX_VTY
],
13399 json_object_double_add(
13401 table_stats_strs
[i
]
13402 [TABLE_STATS_IDX_JSON
],
13404 ? (double)ts
.counts
[i
]
13405 / (double)ts
.counts
13406 [BGP_STATS_PREFIXES
]
13410 case BGP_STATS_SPACE
:
13412 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13414 vty_out(vty
, "%-30s: %s\n",
13415 table_stats_strs
[i
]
13416 [TABLE_STATS_IDX_VTY
],
13419 json_object_double_add(
13421 table_stats_strs
[i
]
13422 [TABLE_STATS_IDX_JSON
],
13423 (double)ts
.total_space
);
13425 if (afi
== AFI_IP6
) {
13427 snprintf(temp_buf
, sizeof(temp_buf
),
13430 * pow(2.0, -128 + 32));
13431 vty_out(vty
, "%30s: %s\n",
13432 "/32 equivalent %s\n",
13435 json_object_double_add(
13436 json
, "/32equivalent",
13437 (double)(ts
.total_space
13442 snprintf(temp_buf
, sizeof(temp_buf
),
13445 * pow(2.0, -128 + 48));
13446 vty_out(vty
, "%30s: %s\n",
13447 "/48 equivalent %s\n",
13450 json_object_double_add(
13451 json
, "/48equivalent",
13452 (double)(ts
.total_space
13458 snprintf(temp_buf
, sizeof(temp_buf
),
13460 ts
.total_space
* 100.
13462 vty_out(vty
, "%30s: %s\n",
13463 "% announced ", temp_buf
);
13465 json_object_double_add(
13466 json
, "%announced",
13467 (double)(ts
.total_space
* 100.
13471 snprintf(temp_buf
, sizeof(temp_buf
),
13474 * pow(2.0, -32 + 8));
13475 vty_out(vty
, "%30s: %s\n",
13476 "/8 equivalent ", temp_buf
);
13478 json_object_double_add(
13479 json
, "/8equivalent",
13480 (double)(ts
.total_space
13481 * pow(2.0, -32 + 8)));
13484 snprintf(temp_buf
, sizeof(temp_buf
),
13487 * pow(2.0, -32 + 24));
13488 vty_out(vty
, "%30s: %s\n",
13489 "/24 equivalent ", temp_buf
);
13491 json_object_double_add(
13492 json
, "/24equivalent",
13493 (double)(ts
.total_space
13494 * pow(2.0, -32 + 24)));
13500 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13502 vty_out(vty
, "%-30s: %s",
13503 table_stats_strs
[i
]
13504 [TABLE_STATS_IDX_VTY
],
13507 json_object_int_add(
13509 table_stats_strs
[i
]
13510 [TABLE_STATS_IDX_JSON
],
13515 vty_out(vty
, "\n");
13520 bitlen
= IPV4_MAX_BITLEN
;
13523 bitlen
= IPV6_MAX_BITLEN
;
13526 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13533 json_bitlen
= json_object_new_array();
13535 for (i
= 0; i
<= bitlen
; i
++) {
13536 struct json_object
*ind_bit
= json_object_new_object();
13538 if (!ts
.prefix_len_count
[i
])
13541 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13542 json_object_int_add(ind_bit
, temp_buf
,
13543 ts
.prefix_len_count
[i
]);
13544 json_object_array_add(json_bitlen
, ind_bit
);
13546 json_object_object_add(json
, "prefixLength", json_bitlen
);
13551 json_object_array_add(json_array
, json
);
13555 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13556 safi_t safi
, struct json_object
*json_array
)
13559 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13560 return CMD_SUCCESS
;
13563 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13575 PCOUNT_BPATH_SELECTED
,
13576 PCOUNT_PFCNT
, /* the figure we display to users */
13580 static const char *const pcount_strs
[] = {
13581 [PCOUNT_ADJ_IN
] = "Adj-in",
13582 [PCOUNT_DAMPED
] = "Damped",
13583 [PCOUNT_REMOVED
] = "Removed",
13584 [PCOUNT_HISTORY
] = "History",
13585 [PCOUNT_STALE
] = "Stale",
13586 [PCOUNT_VALID
] = "Valid",
13587 [PCOUNT_ALL
] = "All RIB",
13588 [PCOUNT_COUNTED
] = "PfxCt counted",
13589 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13590 [PCOUNT_PFCNT
] = "Useable",
13591 [PCOUNT_MAX
] = NULL
,
13594 struct peer_pcounts
{
13595 unsigned int count
[PCOUNT_MAX
];
13596 const struct peer
*peer
;
13597 const struct bgp_table
*table
;
13601 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13603 const struct bgp_adj_in
*ain
;
13604 const struct bgp_path_info
*pi
;
13605 const struct peer
*peer
= pc
->peer
;
13607 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13608 if (ain
->peer
== peer
)
13609 pc
->count
[PCOUNT_ADJ_IN
]++;
13611 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13613 if (pi
->peer
!= peer
)
13616 pc
->count
[PCOUNT_ALL
]++;
13618 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13619 pc
->count
[PCOUNT_DAMPED
]++;
13620 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13621 pc
->count
[PCOUNT_HISTORY
]++;
13622 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13623 pc
->count
[PCOUNT_REMOVED
]++;
13624 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13625 pc
->count
[PCOUNT_STALE
]++;
13626 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13627 pc
->count
[PCOUNT_VALID
]++;
13628 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13629 pc
->count
[PCOUNT_PFCNT
]++;
13630 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13631 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13633 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13634 pc
->count
[PCOUNT_COUNTED
]++;
13635 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13637 EC_LIB_DEVELOPMENT
,
13638 "Attempting to count but flags say it is unusable");
13640 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13642 EC_LIB_DEVELOPMENT
,
13643 "Not counted but flags say we should");
13648 static void bgp_peer_count_walker(struct thread
*t
)
13650 struct bgp_dest
*rn
, *rm
;
13651 const struct bgp_table
*table
;
13652 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13654 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13655 || pc
->safi
== SAFI_EVPN
) {
13656 /* Special handling for 2-level routing tables. */
13657 for (rn
= bgp_table_top(pc
->table
); rn
;
13658 rn
= bgp_route_next(rn
)) {
13659 table
= bgp_dest_get_bgp_table_info(rn
);
13661 for (rm
= bgp_table_top(table
); rm
;
13662 rm
= bgp_route_next(rm
))
13663 bgp_peer_count_proc(rm
, pc
);
13666 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13667 bgp_peer_count_proc(rn
, pc
);
13670 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13671 safi_t safi
, bool use_json
)
13673 struct peer_pcounts pcounts
= {.peer
= peer
};
13675 json_object
*json
= NULL
;
13676 json_object
*json_loop
= NULL
;
13679 json
= json_object_new_object();
13680 json_loop
= json_object_new_object();
13683 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13684 || !peer
->bgp
->rib
[afi
][safi
]) {
13686 json_object_string_add(
13688 "No such neighbor or address family");
13689 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13690 json_object_free(json
);
13691 json_object_free(json_loop
);
13693 vty_out(vty
, "%% No such neighbor or address family\n");
13695 return CMD_WARNING
;
13698 memset(&pcounts
, 0, sizeof(pcounts
));
13699 pcounts
.peer
= peer
;
13700 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13701 pcounts
.safi
= safi
;
13703 /* in-place call via thread subsystem so as to record execution time
13704 * stats for the thread-walk (i.e. ensure this can't be blamed on
13705 * on just vty_read()).
13707 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13710 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13711 json_object_string_add(json
, "multiProtocol",
13712 get_afi_safi_str(afi
, safi
, true));
13713 json_object_int_add(json
, "pfxCounter",
13714 peer
->pcount
[afi
][safi
]);
13716 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13717 json_object_int_add(json_loop
, pcount_strs
[i
],
13720 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13722 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13723 json_object_string_add(json
, "pfxctDriftFor",
13725 json_object_string_add(
13726 json
, "recommended",
13727 "Please report this bug, with the above command output");
13729 vty_json(vty
, json
);
13733 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13734 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13735 peer
->hostname
, peer
->host
,
13736 get_afi_safi_str(afi
, safi
, false));
13738 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13739 get_afi_safi_str(afi
, safi
, false));
13742 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13743 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13745 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13746 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13749 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13750 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13752 "Please report this bug, with the above command output\n");
13756 return CMD_SUCCESS
;
13759 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13760 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13761 "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]",
13765 BGP_INSTANCE_HELP_STR
13768 "Detailed information on TCP and BGP neighbor connections\n"
13769 "Neighbor to display information about\n"
13770 "Neighbor to display information about\n"
13771 "Neighbor on BGP configured interface\n"
13772 "Display detailed prefix count information\n"
13775 afi_t afi
= AFI_IP6
;
13776 safi_t safi
= SAFI_UNICAST
;
13779 struct bgp
*bgp
= NULL
;
13780 bool uj
= use_json(argc
, argv
);
13785 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13788 return CMD_WARNING
;
13790 argv_find(argv
, argc
, "neighbors", &idx
);
13791 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13793 return CMD_WARNING
;
13795 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13798 #ifdef KEEP_OLD_VPN_COMMANDS
13799 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13800 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13801 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13806 "Display information about all VPNv4 NLRIs\n"
13807 "Detailed information on TCP and BGP neighbor connections\n"
13808 "Neighbor to display information about\n"
13809 "Neighbor to display information about\n"
13810 "Neighbor on BGP configured interface\n"
13811 "Display detailed prefix count information\n"
13816 bool uj
= use_json(argc
, argv
);
13818 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13820 return CMD_WARNING
;
13822 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13825 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13826 show_ip_bgp_vpn_all_route_prefix_cmd
,
13827 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13832 "Display information about all VPNv4 NLRIs\n"
13833 "Network in the BGP routing table to display\n"
13834 "Network in the BGP routing table to display\n"
13838 char *network
= NULL
;
13839 struct bgp
*bgp
= bgp_get_default();
13841 vty_out(vty
, "Can't find default instance\n");
13842 return CMD_WARNING
;
13845 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13846 network
= argv
[idx
]->arg
;
13847 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13848 network
= argv
[idx
]->arg
;
13850 vty_out(vty
, "Unable to figure out Network\n");
13851 return CMD_WARNING
;
13854 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13855 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13856 use_json(argc
, argv
));
13858 #endif /* KEEP_OLD_VPN_COMMANDS */
13860 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13861 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13862 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13867 "Network in the BGP routing table to display\n"
13868 "Network in the BGP routing table to display\n"
13869 "Network in the BGP routing table to display\n"
13870 "Network in the BGP routing table to display\n"
13874 char *network
= NULL
;
13875 int prefix_check
= 0;
13877 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13878 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13879 network
= argv
[idx
]->arg
;
13880 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13881 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13882 network
= argv
[idx
]->arg
;
13885 vty_out(vty
, "Unable to figure out Network\n");
13886 return CMD_WARNING
;
13888 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13889 prefix_check
, BGP_PATH_SHOW_ALL
,
13890 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13893 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13894 struct bgp_table
*table
, int *header1
,
13895 int *header2
, json_object
*json
,
13896 json_object
*json_scode
,
13897 json_object
*json_ocode
, bool wide
)
13899 uint64_t version
= table
? table
->version
: 0;
13903 json_object_int_add(json
, "bgpTableVersion", version
);
13904 json_object_string_addf(json
, "bgpLocalRouterId",
13905 "%pI4", &peer
->bgp
->router_id
);
13906 json_object_int_add(json
, "defaultLocPrf",
13907 peer
->bgp
->default_local_pref
);
13908 json_object_int_add(json
, "localAS",
13909 peer
->change_local_as
13910 ? peer
->change_local_as
13912 json_object_object_add(json
, "bgpStatusCodes",
13914 json_object_object_add(json
, "bgpOriginCodes",
13918 "BGP table version is %" PRIu64
13919 ", local router ID is %pI4, vrf id ",
13920 version
, &peer
->bgp
->router_id
);
13921 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
13922 vty_out(vty
, "%s", VRFID_NONE_STR
);
13924 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
13925 vty_out(vty
, "\n");
13926 vty_out(vty
, "Default local pref %u, ",
13927 peer
->bgp
->default_local_pref
);
13928 vty_out(vty
, "local AS %u\n",
13929 peer
->change_local_as
? peer
->change_local_as
13931 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13932 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13933 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13934 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13940 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13941 : BGP_SHOW_HEADER
));
13947 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13948 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13949 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13950 json_object
*json_scode
, json_object
*json_ocode
,
13951 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13952 unsigned long *output_count
, unsigned long *filtered_count
)
13954 struct bgp_adj_in
*ain
;
13955 struct bgp_adj_out
*adj
;
13956 struct bgp_dest
*dest
;
13960 struct update_subgroup
*subgrp
;
13961 struct peer_af
*paf
;
13962 bool route_filtered
;
13963 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13964 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13965 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13966 || (safi
== SAFI_EVPN
))
13972 subgrp
= peer_subgroup(peer
, afi
, safi
);
13974 if (type
== bgp_show_adj_route_advertised
&& subgrp
13975 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13977 json_object_int_add(json
, "bgpTableVersion",
13979 json_object_string_addf(json
, "bgpLocalRouterId",
13980 "%pI4", &bgp
->router_id
);
13981 json_object_int_add(json
, "defaultLocPrf",
13982 bgp
->default_local_pref
);
13983 json_object_int_add(json
, "localAS",
13984 peer
->change_local_as
13985 ? peer
->change_local_as
13987 json_object_object_add(json
, "bgpStatusCodes",
13989 json_object_object_add(json
, "bgpOriginCodes",
13991 json_object_string_add(
13992 json
, "bgpOriginatingDefaultNetwork",
13993 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13996 "BGP table version is %" PRIu64
13997 ", local router ID is %pI4, vrf id ",
13998 table
->version
, &bgp
->router_id
);
13999 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14000 vty_out(vty
, "%s", VRFID_NONE_STR
);
14002 vty_out(vty
, "%u", bgp
->vrf_id
);
14003 vty_out(vty
, "\n");
14004 vty_out(vty
, "Default local pref %u, ",
14005 bgp
->default_local_pref
);
14006 vty_out(vty
, "local AS %u\n",
14007 peer
->change_local_as
? peer
->change_local_as
14009 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14010 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14011 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14012 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14014 vty_out(vty
, "Originating default network %s\n\n",
14015 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14020 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14021 if (type
== bgp_show_adj_route_received
14022 || type
== bgp_show_adj_route_filtered
) {
14023 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14024 if (ain
->peer
!= peer
)
14027 show_adj_route_header(vty
, peer
, table
, header1
,
14028 header2
, json
, json_scode
,
14031 if ((safi
== SAFI_MPLS_VPN
)
14032 || (safi
== SAFI_ENCAP
)
14033 || (safi
== SAFI_EVPN
)) {
14035 json_object_string_add(
14036 json_ar
, "rd", rd_str
);
14037 else if (show_rd
&& rd_str
) {
14039 "Route Distinguisher: %s\n",
14046 route_filtered
= false;
14048 /* Filter prefix using distribute list,
14049 * filter list or prefix list
14051 const struct prefix
*rn_p
=
14052 bgp_dest_get_prefix(dest
);
14053 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14056 route_filtered
= true;
14058 /* Filter prefix using route-map */
14059 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14060 safi
, rmap_name
, NULL
,
14063 if (type
== bgp_show_adj_route_filtered
&&
14064 !route_filtered
&& ret
!= RMAP_DENY
) {
14065 bgp_attr_flush(&attr
);
14069 if (type
== bgp_show_adj_route_received
14070 && (route_filtered
|| ret
== RMAP_DENY
))
14071 (*filtered_count
)++;
14073 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
14074 use_json
, json_ar
, wide
);
14075 bgp_attr_flush(&attr
);
14078 } else if (type
== bgp_show_adj_route_advertised
) {
14079 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14080 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14081 if (paf
->peer
!= peer
|| !adj
->attr
)
14084 show_adj_route_header(vty
, peer
, table
,
14089 const struct prefix
*rn_p
=
14090 bgp_dest_get_prefix(dest
);
14093 ret
= bgp_output_modifier(
14094 peer
, rn_p
, &attr
, afi
, safi
,
14097 if (ret
!= RMAP_DENY
) {
14098 if ((safi
== SAFI_MPLS_VPN
)
14099 || (safi
== SAFI_ENCAP
)
14100 || (safi
== SAFI_EVPN
)) {
14102 json_object_string_add(
14109 "Route Distinguisher: %s\n",
14115 vty
, dest
, rn_p
, &attr
,
14116 safi
, use_json
, json_ar
,
14120 (*filtered_count
)++;
14123 bgp_attr_flush(&attr
);
14125 } else if (type
== bgp_show_adj_route_bestpath
) {
14126 struct bgp_path_info
*pi
;
14128 show_adj_route_header(vty
, peer
, table
, header1
,
14129 header2
, json
, json_scode
,
14132 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14134 if (pi
->peer
!= peer
)
14137 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14140 route_vty_out_tmp(vty
, dest
,
14141 bgp_dest_get_prefix(dest
),
14142 pi
->attr
, safi
, use_json
,
14150 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14151 safi_t safi
, enum bgp_show_adj_route_type type
,
14152 const char *rmap_name
, uint16_t show_flags
)
14155 struct bgp_table
*table
;
14156 json_object
*json
= NULL
;
14157 json_object
*json_scode
= NULL
;
14158 json_object
*json_ocode
= NULL
;
14159 json_object
*json_ar
= NULL
;
14160 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14162 /* Init BGP headers here so they're only displayed once
14163 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14169 * Initialize variables for each RD
14170 * All prefixes under an RD is aggregated within "json_routes"
14172 char rd_str
[BUFSIZ
] = {0};
14173 json_object
*json_routes
= NULL
;
14176 /* For 2-tier tables, prefix counts need to be
14177 * maintained across multiple runs of show_adj_route()
14179 unsigned long output_count_per_rd
;
14180 unsigned long filtered_count_per_rd
;
14181 unsigned long output_count
= 0;
14182 unsigned long filtered_count
= 0;
14185 json
= json_object_new_object();
14186 json_ar
= json_object_new_object();
14187 json_scode
= json_object_new_object();
14188 json_ocode
= json_object_new_object();
14190 json_object_string_add(json_scode
, "suppressed", "s");
14191 json_object_string_add(json_scode
, "damped", "d");
14192 json_object_string_add(json_scode
, "history", "h");
14193 json_object_string_add(json_scode
, "valid", "*");
14194 json_object_string_add(json_scode
, "best", ">");
14195 json_object_string_add(json_scode
, "multipath", "=");
14196 json_object_string_add(json_scode
, "internal", "i");
14197 json_object_string_add(json_scode
, "ribFailure", "r");
14198 json_object_string_add(json_scode
, "stale", "S");
14199 json_object_string_add(json_scode
, "removed", "R");
14201 json_object_string_add(json_ocode
, "igp", "i");
14202 json_object_string_add(json_ocode
, "egp", "e");
14203 json_object_string_add(json_ocode
, "incomplete", "?");
14206 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14208 json_object_string_add(
14210 "No such neighbor or address family");
14211 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14212 json_object_free(json
);
14213 json_object_free(json_ar
);
14214 json_object_free(json_scode
);
14215 json_object_free(json_ocode
);
14217 vty_out(vty
, "%% No such neighbor or address family\n");
14219 return CMD_WARNING
;
14222 if ((type
== bgp_show_adj_route_received
14223 || type
== bgp_show_adj_route_filtered
)
14224 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14225 PEER_FLAG_SOFT_RECONFIG
)) {
14227 json_object_string_add(
14229 "Inbound soft reconfiguration not enabled");
14230 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14231 json_object_free(json
);
14232 json_object_free(json_ar
);
14233 json_object_free(json_scode
);
14234 json_object_free(json_ocode
);
14237 "%% Inbound soft reconfiguration not enabled\n");
14239 return CMD_WARNING
;
14244 /* labeled-unicast routes live in the unicast table */
14245 if (safi
== SAFI_LABELED_UNICAST
)
14246 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14248 table
= bgp
->rib
[afi
][safi
];
14250 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14251 || (safi
== SAFI_EVPN
)) {
14253 struct bgp_dest
*dest
;
14255 for (dest
= bgp_table_top(table
); dest
;
14256 dest
= bgp_route_next(dest
)) {
14257 table
= bgp_dest_get_bgp_table_info(dest
);
14261 output_count_per_rd
= 0;
14262 filtered_count_per_rd
= 0;
14265 json_routes
= json_object_new_object();
14267 const struct prefix_rd
*prd
;
14268 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14271 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
14273 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
14274 rmap_name
, json
, json_routes
, json_scode
,
14275 json_ocode
, show_flags
, &header1
,
14276 &header2
, rd_str
, &output_count_per_rd
,
14277 &filtered_count_per_rd
);
14279 /* Don't include an empty RD in the output! */
14280 if (json_routes
&& (output_count_per_rd
> 0))
14281 json_object_object_add(json_ar
, rd_str
,
14284 output_count
+= output_count_per_rd
;
14285 filtered_count
+= filtered_count_per_rd
;
14288 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14289 json
, json_ar
, json_scode
, json_ocode
,
14290 show_flags
, &header1
, &header2
, rd_str
,
14291 &output_count
, &filtered_count
);
14294 if (type
== bgp_show_adj_route_advertised
)
14295 json_object_object_add(json
, "advertisedRoutes",
14298 json_object_object_add(json
, "receivedRoutes", json_ar
);
14299 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14300 json_object_int_add(json
, "filteredPrefixCounter",
14304 * These fields only give up ownership to `json` when `header1`
14305 * is used (set to zero). See code in `show_adj_route` and
14306 * `show_adj_route_header`.
14308 if (header1
== 1) {
14309 json_object_free(json_scode
);
14310 json_object_free(json_ocode
);
14313 vty_json(vty
, json
);
14314 } else if (output_count
> 0) {
14315 if (filtered_count
> 0)
14317 "\nTotal number of prefixes %ld (%ld filtered)\n",
14318 output_count
, filtered_count
);
14320 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14324 return CMD_SUCCESS
;
14327 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14328 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14329 "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]",
14333 BGP_INSTANCE_HELP_STR
14335 BGP_SAFI_WITH_LABEL_HELP_STR
14336 "Detailed information on TCP and BGP neighbor connections\n"
14337 "Neighbor to display information about\n"
14338 "Neighbor to display information about\n"
14339 "Neighbor on BGP configured interface\n"
14340 "Display the routes selected by best path\n"
14342 "Increase table width for longer prefixes\n")
14344 afi_t afi
= AFI_IP6
;
14345 safi_t safi
= SAFI_UNICAST
;
14346 char *rmap_name
= NULL
;
14347 char *peerstr
= NULL
;
14348 struct bgp
*bgp
= NULL
;
14350 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14352 uint16_t show_flags
= 0;
14355 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14358 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14360 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14364 return CMD_WARNING
;
14366 argv_find(argv
, argc
, "neighbors", &idx
);
14367 peerstr
= argv
[++idx
]->arg
;
14369 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14371 return CMD_WARNING
;
14373 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14377 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
14378 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14379 "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] [json$uj | wide$wide]",
14383 BGP_INSTANCE_HELP_STR
14385 BGP_SAFI_WITH_LABEL_HELP_STR
14386 "Display the entries for all address families\n"
14387 "Detailed information on TCP and BGP neighbor connections\n"
14388 "Neighbor to display information about\n"
14389 "Neighbor to display information about\n"
14390 "Neighbor on BGP configured interface\n"
14391 "Display the routes advertised to a BGP neighbor\n"
14392 "Display the received routes from neighbor\n"
14393 "Display the filtered routes received from neighbor\n"
14394 "Route-map to modify the attributes\n"
14395 "Name of the route map\n"
14397 "Increase table width for longer prefixes\n")
14399 afi_t afi
= AFI_IP6
;
14400 safi_t safi
= SAFI_UNICAST
;
14401 char *peerstr
= NULL
;
14402 struct bgp
*bgp
= NULL
;
14404 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14407 uint16_t show_flags
= 0;
14408 struct listnode
*node
;
14413 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14417 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14418 if (argv_find(argv
, argc
, "ipv4", &idx
))
14419 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14421 if (argv_find(argv
, argc
, "ipv6", &idx
))
14422 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14426 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14428 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14431 return CMD_WARNING
;
14433 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14434 argv_find(argv
, argc
, "neighbors", &idx
);
14435 peerstr
= argv
[++idx
]->arg
;
14437 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14439 return CMD_WARNING
;
14441 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14442 type
= bgp_show_adj_route_advertised
;
14443 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14444 type
= bgp_show_adj_route_received
;
14445 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14446 type
= bgp_show_adj_route_filtered
;
14449 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14452 vty_out(vty
, "{\n");
14454 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14455 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14456 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14458 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14459 FOREACH_SAFI (safi
) {
14460 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14467 vty_out(vty
, ",\n");
14468 vty_out(vty
, "\"%s\":",
14469 get_afi_safi_str(afi
, safi
,
14473 "\nFor address family: %s\n",
14474 get_afi_safi_str(afi
, safi
,
14477 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14478 route_map
, show_flags
);
14482 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14483 FOREACH_AFI_SAFI (afi
, safi
) {
14484 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14491 vty_out(vty
, ",\n");
14492 vty_out(vty
, "\"%s\":",
14493 get_afi_safi_str(afi
, safi
,
14497 "\nFor address family: %s\n",
14498 get_afi_safi_str(afi
, safi
,
14501 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14502 route_map
, show_flags
);
14507 vty_out(vty
, "}\n");
14509 return CMD_SUCCESS
;
14512 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14513 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14514 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14518 BGP_INSTANCE_HELP_STR
14521 BGP_AF_MODIFIER_STR
14522 "Detailed information on TCP and BGP neighbor connections\n"
14523 "Neighbor to display information about\n"
14524 "Neighbor to display information about\n"
14525 "Neighbor on BGP configured interface\n"
14526 "Display information received from a BGP neighbor\n"
14527 "Display the prefixlist filter\n"
14530 afi_t afi
= AFI_IP6
;
14531 safi_t safi
= SAFI_UNICAST
;
14532 char *peerstr
= NULL
;
14537 struct bgp
*bgp
= NULL
;
14538 bool uj
= use_json(argc
, argv
);
14543 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14546 return CMD_WARNING
;
14548 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14549 argv_find(argv
, argc
, "neighbors", &idx
);
14550 peerstr
= argv
[++idx
]->arg
;
14552 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14554 return CMD_WARNING
;
14556 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14557 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14560 vty_out(vty
, "Address Family: %s\n",
14561 get_afi_safi_str(afi
, safi
, false));
14562 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14565 vty_out(vty
, "{}\n");
14567 vty_out(vty
, "No functional output\n");
14570 return CMD_SUCCESS
;
14573 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14574 afi_t afi
, safi_t safi
,
14575 enum bgp_show_type type
, bool use_json
)
14577 uint16_t show_flags
= 0;
14580 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14582 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14584 json_object
*json_no
= NULL
;
14585 json_no
= json_object_new_object();
14586 json_object_string_add(
14587 json_no
, "warning",
14588 "No such neighbor or address family");
14589 vty_out(vty
, "%s\n",
14590 json_object_to_json_string(json_no
));
14591 json_object_free(json_no
);
14593 vty_out(vty
, "%% No such neighbor or address family\n");
14594 return CMD_WARNING
;
14597 /* labeled-unicast routes live in the unicast table */
14598 if (safi
== SAFI_LABELED_UNICAST
)
14599 safi
= SAFI_UNICAST
;
14601 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14602 RPKI_NOT_BEING_USED
);
14605 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14606 show_ip_bgp_flowspec_routes_detailed_cmd
,
14607 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14611 BGP_INSTANCE_HELP_STR
14614 "Detailed information on flowspec entries\n"
14617 afi_t afi
= AFI_IP6
;
14618 safi_t safi
= SAFI_UNICAST
;
14619 struct bgp
*bgp
= NULL
;
14621 bool uj
= use_json(argc
, argv
);
14622 uint16_t show_flags
= BGP_SHOW_OPT_DETAIL
;
14626 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14629 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14632 return CMD_WARNING
;
14634 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14635 show_flags
, RPKI_NOT_BEING_USED
);
14638 DEFUN (show_ip_bgp_neighbor_routes
,
14639 show_ip_bgp_neighbor_routes_cmd
,
14640 "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]",
14644 BGP_INSTANCE_HELP_STR
14646 BGP_SAFI_WITH_LABEL_HELP_STR
14647 "Detailed information on TCP and BGP neighbor connections\n"
14648 "Neighbor to display information about\n"
14649 "Neighbor to display information about\n"
14650 "Neighbor on BGP configured interface\n"
14651 "Display flap statistics of the routes learned from neighbor\n"
14652 "Display the dampened routes received from neighbor\n"
14653 "Display routes learned from neighbor\n"
14656 char *peerstr
= NULL
;
14657 struct bgp
*bgp
= NULL
;
14658 afi_t afi
= AFI_IP6
;
14659 safi_t safi
= SAFI_UNICAST
;
14661 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14663 bool uj
= use_json(argc
, argv
);
14668 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14671 return CMD_WARNING
;
14673 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14674 argv_find(argv
, argc
, "neighbors", &idx
);
14675 peerstr
= argv
[++idx
]->arg
;
14677 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14679 return CMD_WARNING
;
14681 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14682 sh_type
= bgp_show_type_flap_neighbor
;
14683 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14684 sh_type
= bgp_show_type_damp_neighbor
;
14685 else if (argv_find(argv
, argc
, "routes", &idx
))
14686 sh_type
= bgp_show_type_neighbor
;
14688 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14691 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14693 struct bgp_distance
{
14694 /* Distance value for the IP source prefix. */
14697 /* Name of the access-list to be matched. */
14701 DEFUN (show_bgp_afi_vpn_rd_route
,
14702 show_bgp_afi_vpn_rd_route_cmd
,
14703 "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]",
14707 BGP_AF_MODIFIER_STR
14708 "Display information for a route distinguisher\n"
14709 "Route Distinguisher\n"
14710 "All Route Distinguishers\n"
14711 "Network in the BGP routing table to display\n"
14712 "Network in the BGP routing table to display\n"
14716 struct prefix_rd prd
;
14717 afi_t afi
= AFI_MAX
;
14720 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14721 vty_out(vty
, "%% Malformed Address Family\n");
14722 return CMD_WARNING
;
14725 if (!strcmp(argv
[5]->arg
, "all"))
14726 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14727 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14728 RPKI_NOT_BEING_USED
,
14729 use_json(argc
, argv
));
14731 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14733 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14734 return CMD_WARNING
;
14737 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14738 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14739 use_json(argc
, argv
));
14742 static struct bgp_distance
*bgp_distance_new(void)
14744 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14747 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14749 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14752 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14753 const char *ip_str
, const char *access_list_str
)
14760 struct bgp_dest
*dest
;
14761 struct bgp_distance
*bdistance
;
14763 afi
= bgp_node_afi(vty
);
14764 safi
= bgp_node_safi(vty
);
14766 ret
= str2prefix(ip_str
, &p
);
14768 vty_out(vty
, "Malformed prefix\n");
14769 return CMD_WARNING_CONFIG_FAILED
;
14772 distance
= atoi(distance_str
);
14774 /* Get BGP distance node. */
14775 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14776 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14778 bgp_dest_unlock_node(dest
);
14780 bdistance
= bgp_distance_new();
14781 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14784 /* Set distance value. */
14785 bdistance
->distance
= distance
;
14787 /* Reset access-list configuration. */
14788 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14789 if (access_list_str
)
14790 bdistance
->access_list
=
14791 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14793 return CMD_SUCCESS
;
14796 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14797 const char *ip_str
, const char *access_list_str
)
14804 struct bgp_dest
*dest
;
14805 struct bgp_distance
*bdistance
;
14807 afi
= bgp_node_afi(vty
);
14808 safi
= bgp_node_safi(vty
);
14810 ret
= str2prefix(ip_str
, &p
);
14812 vty_out(vty
, "Malformed prefix\n");
14813 return CMD_WARNING_CONFIG_FAILED
;
14816 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14818 vty_out(vty
, "Can't find specified prefix\n");
14819 return CMD_WARNING_CONFIG_FAILED
;
14822 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14823 distance
= atoi(distance_str
);
14825 if (bdistance
->distance
!= distance
) {
14826 vty_out(vty
, "Distance does not match configured\n");
14827 bgp_dest_unlock_node(dest
);
14828 return CMD_WARNING_CONFIG_FAILED
;
14831 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14832 bgp_distance_free(bdistance
);
14834 bgp_dest_set_bgp_path_info(dest
, NULL
);
14835 bgp_dest_unlock_node(dest
);
14836 bgp_dest_unlock_node(dest
);
14838 return CMD_SUCCESS
;
14841 /* Apply BGP information to distance method. */
14842 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14843 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14845 struct bgp_dest
*dest
;
14846 struct prefix q
= {0};
14848 struct bgp_distance
*bdistance
;
14849 struct access_list
*alist
;
14850 struct bgp_static
*bgp_static
;
14855 peer
= pinfo
->peer
;
14857 if (pinfo
->attr
->distance
)
14858 return pinfo
->attr
->distance
;
14860 /* Check source address.
14861 * Note: for aggregate route, peer can have unspec af type.
14863 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14864 && !sockunion2hostprefix(&peer
->su
, &q
))
14867 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14869 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14870 bgp_dest_unlock_node(dest
);
14872 if (bdistance
->access_list
) {
14873 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14875 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14876 return bdistance
->distance
;
14878 return bdistance
->distance
;
14881 /* Backdoor check. */
14882 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14884 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14885 bgp_dest_unlock_node(dest
);
14887 if (bgp_static
->backdoor
) {
14888 if (bgp
->distance_local
[afi
][safi
])
14889 return bgp
->distance_local
[afi
][safi
];
14891 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14895 if (peer
->sort
== BGP_PEER_EBGP
) {
14896 if (bgp
->distance_ebgp
[afi
][safi
])
14897 return bgp
->distance_ebgp
[afi
][safi
];
14898 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14899 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14900 if (bgp
->distance_ibgp
[afi
][safi
])
14901 return bgp
->distance_ibgp
[afi
][safi
];
14902 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14904 if (bgp
->distance_local
[afi
][safi
])
14905 return bgp
->distance_local
[afi
][safi
];
14906 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14910 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14911 * we should tell ZEBRA update the routes for a specific
14912 * AFI/SAFI to reflect changes in RIB.
14914 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
14916 safi_t update_safi
)
14921 FOREACH_AFI_SAFI (afi
, safi
) {
14922 if (!bgp_fibupd_safi(safi
))
14925 if (afi
!= update_afi
&& safi
!= update_safi
)
14928 if (BGP_DEBUG(zebra
, ZEBRA
))
14930 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14931 __func__
, afi
, safi
);
14932 bgp_zebra_announce_table(bgp
, afi
, safi
);
14936 DEFUN (bgp_distance
,
14938 "distance bgp (1-255) (1-255) (1-255)",
14939 "Define an administrative distance\n"
14941 "Distance for routes external to the AS\n"
14942 "Distance for routes internal to the AS\n"
14943 "Distance for local routes\n")
14945 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14946 int idx_number
= 2;
14947 int idx_number_2
= 3;
14948 int idx_number_3
= 4;
14949 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
14950 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
14951 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
14955 afi
= bgp_node_afi(vty
);
14956 safi
= bgp_node_safi(vty
);
14958 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
14959 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
14960 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
14961 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
14962 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
14963 bgp
->distance_local
[afi
][safi
] = distance_local
;
14964 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14966 return CMD_SUCCESS
;
14969 DEFUN (no_bgp_distance
,
14970 no_bgp_distance_cmd
,
14971 "no distance bgp [(1-255) (1-255) (1-255)]",
14973 "Define an administrative distance\n"
14975 "Distance for routes external to the AS\n"
14976 "Distance for routes internal to the AS\n"
14977 "Distance for local routes\n")
14979 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14983 afi
= bgp_node_afi(vty
);
14984 safi
= bgp_node_safi(vty
);
14986 if (bgp
->distance_ebgp
[afi
][safi
] != 0
14987 || bgp
->distance_ibgp
[afi
][safi
] != 0
14988 || bgp
->distance_local
[afi
][safi
] != 0) {
14989 bgp
->distance_ebgp
[afi
][safi
] = 0;
14990 bgp
->distance_ibgp
[afi
][safi
] = 0;
14991 bgp
->distance_local
[afi
][safi
] = 0;
14992 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14994 return CMD_SUCCESS
;
14998 DEFUN (bgp_distance_source
,
14999 bgp_distance_source_cmd
,
15000 "distance (1-255) A.B.C.D/M",
15001 "Define an administrative distance\n"
15002 "Administrative distance\n"
15003 "IP source prefix\n")
15005 int idx_number
= 1;
15006 int idx_ipv4_prefixlen
= 2;
15007 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15008 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15009 return CMD_SUCCESS
;
15012 DEFUN (no_bgp_distance_source
,
15013 no_bgp_distance_source_cmd
,
15014 "no distance (1-255) A.B.C.D/M",
15016 "Define an administrative distance\n"
15017 "Administrative distance\n"
15018 "IP source prefix\n")
15020 int idx_number
= 2;
15021 int idx_ipv4_prefixlen
= 3;
15022 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15023 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15024 return CMD_SUCCESS
;
15027 DEFUN (bgp_distance_source_access_list
,
15028 bgp_distance_source_access_list_cmd
,
15029 "distance (1-255) A.B.C.D/M WORD",
15030 "Define an administrative distance\n"
15031 "Administrative distance\n"
15032 "IP source prefix\n"
15033 "Access list name\n")
15035 int idx_number
= 1;
15036 int idx_ipv4_prefixlen
= 2;
15038 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15039 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15040 return CMD_SUCCESS
;
15043 DEFUN (no_bgp_distance_source_access_list
,
15044 no_bgp_distance_source_access_list_cmd
,
15045 "no distance (1-255) A.B.C.D/M WORD",
15047 "Define an administrative distance\n"
15048 "Administrative distance\n"
15049 "IP source prefix\n"
15050 "Access list name\n")
15052 int idx_number
= 2;
15053 int idx_ipv4_prefixlen
= 3;
15055 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15056 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15057 return CMD_SUCCESS
;
15060 DEFUN (ipv6_bgp_distance_source
,
15061 ipv6_bgp_distance_source_cmd
,
15062 "distance (1-255) X:X::X:X/M",
15063 "Define an administrative distance\n"
15064 "Administrative distance\n"
15065 "IP source prefix\n")
15067 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15068 return CMD_SUCCESS
;
15071 DEFUN (no_ipv6_bgp_distance_source
,
15072 no_ipv6_bgp_distance_source_cmd
,
15073 "no distance (1-255) X:X::X:X/M",
15075 "Define an administrative distance\n"
15076 "Administrative distance\n"
15077 "IP source prefix\n")
15079 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15080 return CMD_SUCCESS
;
15083 DEFUN (ipv6_bgp_distance_source_access_list
,
15084 ipv6_bgp_distance_source_access_list_cmd
,
15085 "distance (1-255) X:X::X:X/M WORD",
15086 "Define an administrative distance\n"
15087 "Administrative distance\n"
15088 "IP source prefix\n"
15089 "Access list name\n")
15091 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15092 return CMD_SUCCESS
;
15095 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15096 no_ipv6_bgp_distance_source_access_list_cmd
,
15097 "no distance (1-255) X:X::X:X/M WORD",
15099 "Define an administrative distance\n"
15100 "Administrative distance\n"
15101 "IP source prefix\n"
15102 "Access list name\n")
15104 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15105 return CMD_SUCCESS
;
15108 DEFUN (bgp_damp_set
,
15110 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15111 "BGP Specific commands\n"
15112 "Enable route-flap dampening\n"
15113 "Half-life time for the penalty\n"
15114 "Value to start reusing a route\n"
15115 "Value to start suppressing a route\n"
15116 "Maximum duration to suppress a stable route\n")
15118 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15119 int idx_half_life
= 2;
15121 int idx_suppress
= 4;
15122 int idx_max_suppress
= 5;
15123 int half
= DEFAULT_HALF_LIFE
* 60;
15124 int reuse
= DEFAULT_REUSE
;
15125 int suppress
= DEFAULT_SUPPRESS
;
15126 int max
= 4 * half
;
15129 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15130 reuse
= atoi(argv
[idx_reuse
]->arg
);
15131 suppress
= atoi(argv
[idx_suppress
]->arg
);
15132 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15133 } else if (argc
== 3) {
15134 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15139 * These can't be 0 but our SA doesn't understand the
15140 * way our cli is constructed
15144 if (suppress
< reuse
) {
15146 "Suppress value cannot be less than reuse value \n");
15150 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15151 reuse
, suppress
, max
);
15154 DEFUN (bgp_damp_unset
,
15155 bgp_damp_unset_cmd
,
15156 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15158 "BGP Specific commands\n"
15159 "Enable route-flap dampening\n"
15160 "Half-life time for the penalty\n"
15161 "Value to start reusing a route\n"
15162 "Value to start suppressing a route\n"
15163 "Maximum duration to suppress a stable route\n")
15165 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15166 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15169 /* Display specified route of BGP table. */
15170 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15171 const char *ip_str
, afi_t afi
, safi_t safi
,
15172 struct prefix_rd
*prd
, int prefix_check
)
15175 struct prefix match
;
15176 struct bgp_dest
*dest
;
15177 struct bgp_dest
*rm
;
15178 struct bgp_path_info
*pi
;
15179 struct bgp_path_info
*pi_temp
;
15181 struct bgp_table
*table
;
15183 /* BGP structure lookup. */
15185 bgp
= bgp_lookup_by_name(view_name
);
15187 vty_out(vty
, "%% Can't find BGP instance %s\n",
15189 return CMD_WARNING
;
15192 bgp
= bgp_get_default();
15194 vty_out(vty
, "%% No BGP process is configured\n");
15195 return CMD_WARNING
;
15199 /* Check IP address argument. */
15200 ret
= str2prefix(ip_str
, &match
);
15202 vty_out(vty
, "%% address is malformed\n");
15203 return CMD_WARNING
;
15206 match
.family
= afi2family(afi
);
15208 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15209 || (safi
== SAFI_EVPN
)) {
15210 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15211 dest
= bgp_route_next(dest
)) {
15212 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15214 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15216 table
= bgp_dest_get_bgp_table_info(dest
);
15219 rm
= bgp_node_match(table
, &match
);
15223 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15226 || rm_p
->prefixlen
== match
.prefixlen
) {
15227 pi
= bgp_dest_get_bgp_path_info(rm
);
15229 if (pi
->extra
&& pi
->extra
->damp_info
) {
15230 pi_temp
= pi
->next
;
15231 bgp_damp_info_free(
15232 pi
->extra
->damp_info
,
15240 bgp_dest_unlock_node(rm
);
15243 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15244 if (dest
!= NULL
) {
15245 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15248 || dest_p
->prefixlen
== match
.prefixlen
) {
15249 pi
= bgp_dest_get_bgp_path_info(dest
);
15251 if (pi
->extra
&& pi
->extra
->damp_info
) {
15252 pi_temp
= pi
->next
;
15253 bgp_damp_info_free(
15254 pi
->extra
->damp_info
,
15262 bgp_dest_unlock_node(dest
);
15266 return CMD_SUCCESS
;
15269 DEFUN (clear_ip_bgp_dampening
,
15270 clear_ip_bgp_dampening_cmd
,
15271 "clear ip bgp dampening",
15275 "Clear route flap dampening information\n")
15277 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15278 return CMD_SUCCESS
;
15281 DEFUN (clear_ip_bgp_dampening_prefix
,
15282 clear_ip_bgp_dampening_prefix_cmd
,
15283 "clear ip bgp dampening A.B.C.D/M",
15287 "Clear route flap dampening information\n"
15290 int idx_ipv4_prefixlen
= 4;
15291 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15292 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15295 DEFUN (clear_ip_bgp_dampening_address
,
15296 clear_ip_bgp_dampening_address_cmd
,
15297 "clear ip bgp dampening A.B.C.D",
15301 "Clear route flap dampening information\n"
15302 "Network to clear damping information\n")
15305 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15306 SAFI_UNICAST
, NULL
, 0);
15309 DEFUN (clear_ip_bgp_dampening_address_mask
,
15310 clear_ip_bgp_dampening_address_mask_cmd
,
15311 "clear ip bgp dampening A.B.C.D A.B.C.D",
15315 "Clear route flap dampening information\n"
15316 "Network to clear damping information\n"
15320 int idx_ipv4_2
= 5;
15322 char prefix_str
[BUFSIZ
];
15324 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15325 prefix_str
, sizeof(prefix_str
));
15327 vty_out(vty
, "%% Inconsistent address and mask\n");
15328 return CMD_WARNING
;
15331 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15335 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15337 struct vty
*vty
= arg
;
15338 struct peer
*peer
= bucket
->data
;
15340 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15343 DEFUN (show_bgp_listeners
,
15344 show_bgp_listeners_cmd
,
15345 "show bgp listeners",
15348 "Display Listen Sockets and who created them\n")
15350 bgp_dump_listener_info(vty
);
15352 return CMD_SUCCESS
;
15355 DEFUN (show_bgp_peerhash
,
15356 show_bgp_peerhash_cmd
,
15357 "show bgp peerhash",
15360 "Display information about the BGP peerhash\n")
15362 struct list
*instances
= bm
->bgp
;
15363 struct listnode
*node
;
15366 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15367 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15368 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15372 return CMD_SUCCESS
;
15375 /* also used for encap safi */
15376 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15377 afi_t afi
, safi_t safi
)
15379 struct bgp_dest
*pdest
;
15380 struct bgp_dest
*dest
;
15381 struct bgp_table
*table
;
15382 const struct prefix
*p
;
15383 const struct prefix_rd
*prd
;
15384 struct bgp_static
*bgp_static
;
15385 mpls_label_t label
;
15387 /* Network configuration. */
15388 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15389 pdest
= bgp_route_next(pdest
)) {
15390 table
= bgp_dest_get_bgp_table_info(pdest
);
15394 for (dest
= bgp_table_top(table
); dest
;
15395 dest
= bgp_route_next(dest
)) {
15396 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15397 if (bgp_static
== NULL
)
15400 p
= bgp_dest_get_prefix(dest
);
15401 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
15404 /* "network" configuration display. */
15405 label
= decode_label(&bgp_static
->label
);
15407 vty_out(vty
, " network %pFX rd %pRD", p
, prd
);
15408 if (safi
== SAFI_MPLS_VPN
)
15409 vty_out(vty
, " label %u", label
);
15411 if (bgp_static
->rmap
.name
)
15412 vty_out(vty
, " route-map %s",
15413 bgp_static
->rmap
.name
);
15415 if (bgp_static
->backdoor
)
15416 vty_out(vty
, " backdoor");
15418 vty_out(vty
, "\n");
15423 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15424 afi_t afi
, safi_t safi
)
15426 struct bgp_dest
*pdest
;
15427 struct bgp_dest
*dest
;
15428 struct bgp_table
*table
;
15429 const struct prefix
*p
;
15430 const struct prefix_rd
*prd
;
15431 struct bgp_static
*bgp_static
;
15432 char buf
[PREFIX_STRLEN
* 2];
15433 char buf2
[SU_ADDRSTRLEN
];
15434 char esi_buf
[ESI_STR_LEN
];
15436 /* Network configuration. */
15437 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15438 pdest
= bgp_route_next(pdest
)) {
15439 table
= bgp_dest_get_bgp_table_info(pdest
);
15443 for (dest
= bgp_table_top(table
); dest
;
15444 dest
= bgp_route_next(dest
)) {
15445 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15446 if (bgp_static
== NULL
)
15449 char *macrouter
= NULL
;
15451 if (bgp_static
->router_mac
)
15452 macrouter
= prefix_mac2str(
15453 bgp_static
->router_mac
, NULL
, 0);
15454 if (bgp_static
->eth_s_id
)
15455 esi_to_str(bgp_static
->eth_s_id
,
15456 esi_buf
, sizeof(esi_buf
));
15457 p
= bgp_dest_get_prefix(dest
);
15458 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15460 /* "network" configuration display. */
15461 if (p
->u
.prefix_evpn
.route_type
== 5) {
15462 char local_buf
[PREFIX_STRLEN
];
15463 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15464 struct prefix_evpn
*)p
)
15468 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
15469 local_buf
, PREFIX_STRLEN
);
15470 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15471 p
->u
.prefix_evpn
.prefix_addr
15472 .ip_prefix_length
);
15474 prefix2str(p
, buf
, sizeof(buf
));
15477 if (bgp_static
->gatewayIp
.family
== AF_INET
15478 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15479 inet_ntop(bgp_static
->gatewayIp
.family
,
15480 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15483 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15484 buf
, prd
, p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15485 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15488 XFREE(MTYPE_TMP
, macrouter
);
15493 /* Configuration of static route announcement and aggregate
15495 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15498 struct bgp_dest
*dest
;
15499 const struct prefix
*p
;
15500 struct bgp_static
*bgp_static
;
15501 struct bgp_aggregate
*bgp_aggregate
;
15503 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15504 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15508 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15509 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15513 /* Network configuration. */
15514 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15515 dest
= bgp_route_next(dest
)) {
15516 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15517 if (bgp_static
== NULL
)
15520 p
= bgp_dest_get_prefix(dest
);
15522 vty_out(vty
, " network %pFX", p
);
15524 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15525 vty_out(vty
, " label-index %u",
15526 bgp_static
->label_index
);
15528 if (bgp_static
->rmap
.name
)
15529 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15531 if (bgp_static
->backdoor
)
15532 vty_out(vty
, " backdoor");
15534 vty_out(vty
, "\n");
15537 /* Aggregate-address configuration. */
15538 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15539 dest
= bgp_route_next(dest
)) {
15540 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15541 if (bgp_aggregate
== NULL
)
15544 p
= bgp_dest_get_prefix(dest
);
15546 vty_out(vty
, " aggregate-address %pFX", p
);
15548 if (bgp_aggregate
->as_set
)
15549 vty_out(vty
, " as-set");
15551 if (bgp_aggregate
->summary_only
)
15552 vty_out(vty
, " summary-only");
15554 if (bgp_aggregate
->rmap
.name
)
15555 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15557 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15558 vty_out(vty
, " origin %s",
15559 bgp_origin2str(bgp_aggregate
->origin
));
15561 if (bgp_aggregate
->match_med
)
15562 vty_out(vty
, " matching-MED-only");
15564 if (bgp_aggregate
->suppress_map_name
)
15565 vty_out(vty
, " suppress-map %s",
15566 bgp_aggregate
->suppress_map_name
);
15568 vty_out(vty
, "\n");
15572 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15575 struct bgp_dest
*dest
;
15576 struct bgp_distance
*bdistance
;
15578 /* Distance configuration. */
15579 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15580 && bgp
->distance_local
[afi
][safi
]
15581 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15582 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15583 || bgp
->distance_local
[afi
][safi
]
15584 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15585 vty_out(vty
, " distance bgp %d %d %d\n",
15586 bgp
->distance_ebgp
[afi
][safi
],
15587 bgp
->distance_ibgp
[afi
][safi
],
15588 bgp
->distance_local
[afi
][safi
]);
15591 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15592 dest
= bgp_route_next(dest
)) {
15593 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15594 if (bdistance
!= NULL
)
15595 vty_out(vty
, " distance %d %pBD %s\n",
15596 bdistance
->distance
, dest
,
15597 bdistance
->access_list
? bdistance
->access_list
15602 /* Allocate routing table structure and install commands. */
15603 void bgp_route_init(void)
15608 /* Init BGP distance table. */
15609 FOREACH_AFI_SAFI (afi
, safi
)
15610 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15612 /* IPv4 BGP commands. */
15613 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15614 install_element(BGP_NODE
, &bgp_network_cmd
);
15615 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15617 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15619 /* IPv4 unicast configuration. */
15620 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15621 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15622 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15624 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15626 /* IPv4 multicast configuration. */
15627 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15628 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15629 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15630 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15632 /* IPv4 labeled-unicast configuration. */
15633 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15634 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15636 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15637 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15638 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15639 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15640 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15641 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15642 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15643 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15645 install_element(VIEW_NODE
,
15646 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15647 install_element(VIEW_NODE
,
15648 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15649 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15650 install_element(VIEW_NODE
,
15651 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15652 #ifdef KEEP_OLD_VPN_COMMANDS
15653 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15654 #endif /* KEEP_OLD_VPN_COMMANDS */
15655 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15656 install_element(VIEW_NODE
,
15657 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15659 /* BGP dampening clear commands */
15660 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15661 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15663 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15664 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15667 install_element(ENABLE_NODE
,
15668 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15669 #ifdef KEEP_OLD_VPN_COMMANDS
15670 install_element(ENABLE_NODE
,
15671 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15672 #endif /* KEEP_OLD_VPN_COMMANDS */
15674 /* New config IPv6 BGP commands. */
15675 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15676 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15677 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15679 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15681 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15683 /* IPv6 labeled unicast address family. */
15684 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15685 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15687 install_element(BGP_NODE
, &bgp_distance_cmd
);
15688 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15689 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15690 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15691 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15692 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15693 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15694 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15695 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15696 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15697 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15698 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15699 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15700 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15701 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15702 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15703 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15704 install_element(BGP_IPV4M_NODE
,
15705 &no_bgp_distance_source_access_list_cmd
);
15706 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15707 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15708 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15709 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15710 install_element(BGP_IPV6_NODE
,
15711 &ipv6_bgp_distance_source_access_list_cmd
);
15712 install_element(BGP_IPV6_NODE
,
15713 &no_ipv6_bgp_distance_source_access_list_cmd
);
15714 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15715 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15716 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15717 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15718 install_element(BGP_IPV6M_NODE
,
15719 &ipv6_bgp_distance_source_access_list_cmd
);
15720 install_element(BGP_IPV6M_NODE
,
15721 &no_ipv6_bgp_distance_source_access_list_cmd
);
15723 /* BGP dampening */
15724 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15725 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15726 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15727 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15728 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15729 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15730 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15731 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15732 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15733 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15734 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15735 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15736 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15737 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15739 /* Large Communities */
15740 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15741 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15743 /* show bgp ipv4 flowspec detailed */
15744 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15746 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15747 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15750 void bgp_route_finish(void)
15755 FOREACH_AFI_SAFI (afi
, safi
) {
15756 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15757 bgp_distance_table
[afi
][safi
] = NULL
;