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;
4004 if (frrtrace_enabled(frr_bgp
, process_update
)) {
4005 char pfxprint
[PREFIX2STR_BUFFER
];
4007 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
4008 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
4012 #ifdef ENABLE_BGP_VNC
4013 int vnc_implicit_withdraw
= 0;
4017 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4018 if (orig_safi
== SAFI_LABELED_UNICAST
)
4019 safi
= SAFI_UNICAST
;
4021 memset(&new_attr
, 0, sizeof(new_attr
));
4022 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4023 new_attr
.label
= MPLS_INVALID_LABEL
;
4026 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4027 /* TODO: Check to see if we can get rid of "is_valid_label" */
4028 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4029 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4031 has_valid_label
= bgp_is_valid_label(label
);
4033 if (has_valid_label
)
4034 assert(label
!= NULL
);
4036 /* Update overlay index of the attribute */
4037 if (afi
== AFI_L2VPN
&& evpn
)
4038 memcpy(&attr
->evpn_overlay
, evpn
,
4039 sizeof(struct bgp_route_evpn
));
4041 /* When peer's soft reconfiguration enabled. Record input packet in
4044 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4045 && peer
!= bgp
->peer_self
)
4046 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4048 /* Check previously received route. */
4049 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4050 if (pi
->peer
== peer
&& pi
->type
== type
4051 && pi
->sub_type
== sub_type
4052 && pi
->addpath_rx_id
== addpath_id
)
4055 /* AS path local-as loop check. */
4056 if (peer
->change_local_as
) {
4057 if (peer
->allowas_in
[afi
][safi
])
4058 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
4059 else if (!CHECK_FLAG(peer
->flags
,
4060 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4061 aspath_loop_count
= 1;
4063 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4064 > aspath_loop_count
) {
4065 peer
->stat_pfx_aspath_loop
++;
4066 reason
= "as-path contains our own AS;";
4071 /* If the peer is configured for "allowas-in origin" and the last ASN in
4073 * as-path is our ASN then we do not need to call aspath_loop_check
4075 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4076 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4079 /* AS path loop check. */
4080 if (do_loop_check
) {
4081 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
4082 > peer
->allowas_in
[afi
][safi
]
4083 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
4084 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
4085 > peer
->allowas_in
[afi
][safi
])) {
4086 peer
->stat_pfx_aspath_loop
++;
4087 reason
= "as-path contains our own AS;";
4092 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4093 * enabled, then take care of that too.
4095 bool accept_own
= false;
4097 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4098 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4100 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4102 peer
->stat_pfx_originator_loop
++;
4103 reason
= "originator is us;";
4108 /* Route reflector cluster ID check. */
4109 if (bgp_cluster_filter(peer
, attr
)) {
4110 peer
->stat_pfx_cluster_loop
++;
4111 reason
= "reflected from the same cluster;";
4115 /* Apply incoming filter. */
4116 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4117 peer
->stat_pfx_filter
++;
4122 /* RFC 8212 to prevent route leaks.
4123 * This specification intends to improve this situation by requiring the
4124 * explicit configuration of both BGP Import and Export Policies for any
4125 * External BGP (EBGP) session such as customers, peers, or
4126 * confederation boundaries for all enabled address families. Through
4127 * codification of the aforementioned requirement, operators will
4128 * benefit from consistent behavior across different BGP
4131 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4132 if (!bgp_inbound_policy_exists(peer
,
4133 &peer
->filter
[afi
][safi
])) {
4134 reason
= "inbound policy missing";
4135 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4136 NULL
) > FIFTEENMINUTE2USEC
||
4137 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4139 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4140 monotime(&bgp
->ebgprequirespolicywarning
);
4145 /* draft-ietf-idr-deprecate-as-set-confed-set
4146 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4147 * Eventually, This document (if approved) updates RFC 4271
4148 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4149 * and obsoletes RFC 6472.
4151 if (peer
->bgp
->reject_as_sets
)
4152 if (aspath_check_as_sets(attr
->aspath
)) {
4154 "as-path contains AS_SET or AS_CONFED_SET type;";
4160 /* Apply incoming route-map.
4161 * NB: new_attr may now contain newly allocated values from route-map
4163 * commands, so we need bgp_attr_flush in the error paths, until we
4165 * the attr (which takes over the memory references) */
4166 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4169 peer
->stat_pfx_filter
++;
4170 reason
= "route-map;";
4171 bgp_attr_flush(&new_attr
);
4175 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4176 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4177 /* remove from RIB previous entry */
4178 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4181 if (peer
->sort
== BGP_PEER_EBGP
) {
4184 * A BGP speaker receiving an announcement tagged with the
4185 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4186 * NO_EXPORT community as defined in RFC1997, or a
4187 * similar community, to prevent propagation of the
4188 * prefix outside the local AS. The community to prevent
4189 * propagation SHOULD be chosen according to the operator's
4192 if (bgp_attr_get_community(&new_attr
) &&
4193 community_include(bgp_attr_get_community(&new_attr
),
4194 COMMUNITY_BLACKHOLE
))
4195 bgp_attr_add_no_export_community(&new_attr
);
4197 /* If we receive the graceful-shutdown community from an eBGP
4198 * peer we must lower local-preference */
4199 if (bgp_attr_get_community(&new_attr
) &&
4200 community_include(bgp_attr_get_community(&new_attr
),
4202 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4203 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4205 /* If graceful-shutdown is configured then add the GSHUT
4206 * community to all paths received from eBGP peers */
4207 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
4208 bgp_attr_add_gshut_community(&new_attr
);
4211 /* next hop check. */
4212 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4213 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4215 peer
->stat_pfx_nh_invalid
++;
4216 reason
= "martian or self next-hop;";
4217 bgp_attr_flush(&new_attr
);
4221 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4222 peer
->stat_pfx_nh_invalid
++;
4223 reason
= "self mac;";
4224 bgp_attr_flush(&new_attr
);
4228 if (bgp_check_role_applicability(afi
, safi
) &&
4229 bgp_otc_filter(peer
, &new_attr
)) {
4230 reason
= "failing otc validation";
4231 bgp_attr_flush(&new_attr
);
4234 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4236 * Suppress fib is enabled
4237 * BGP_OPT_NO_FIB is not enabled
4238 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4239 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4241 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
4242 && (sub_type
== BGP_ROUTE_NORMAL
)
4243 && (!bgp_option_check(BGP_OPT_NO_FIB
))
4244 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
4245 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
4247 /* If maximum prefix count is configured and current prefix
4250 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4251 bgp_attr_flush(&new_attr
);
4255 /* If neighbor soo is configured, tag all incoming routes with
4256 * this SoO tag and then filter out advertisements in
4257 * subgroup_announce_check() if it matches the configured SoO
4258 * on the other peer.
4260 if (peer
->soo
[afi
][safi
]) {
4261 struct ecommunity
*old_ecomm
=
4262 bgp_attr_get_ecommunity(&new_attr
);
4263 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4264 struct ecommunity
*new_ecomm
;
4267 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4270 if (!old_ecomm
->refcnt
)
4271 ecommunity_free(&old_ecomm
);
4273 new_ecomm
= ecommunity_dup(ecomm_soo
);
4276 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4279 attr_new
= bgp_attr_intern(&new_attr
);
4281 /* If the update is implicit withdraw. */
4283 pi
->uptime
= monotime(NULL
);
4284 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4286 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4288 /* Same attribute comes in. */
4289 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4291 && (!has_valid_label
4292 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4293 num_labels
* sizeof(mpls_label_t
))
4295 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4296 BGP_CONFIG_DAMPENING
)
4297 && peer
->sort
== BGP_PEER_EBGP
4298 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4299 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4300 bgp_debug_rdpfxpath2str(
4301 afi
, safi
, prd
, p
, label
,
4302 num_labels
, addpath_id
? 1 : 0,
4303 addpath_id
, evpn
, pfx_buf
,
4305 zlog_debug("%pBP rcvd %s", peer
,
4309 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4310 != BGP_DAMP_SUPPRESSED
) {
4311 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4313 bgp_process(bgp
, dest
, afi
, safi
);
4315 } else /* Duplicate - odd */
4317 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4318 if (!peer
->rcvd_attr_printed
) {
4320 "%pBP rcvd UPDATE w/ attr: %s",
4322 peer
->rcvd_attr_str
);
4323 peer
->rcvd_attr_printed
= 1;
4326 bgp_debug_rdpfxpath2str(
4327 afi
, safi
, prd
, p
, label
,
4328 num_labels
, addpath_id
? 1 : 0,
4329 addpath_id
, evpn
, pfx_buf
,
4332 "%pBP rcvd %s...duplicate ignored",
4336 /* graceful restart STALE flag unset. */
4337 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4338 bgp_path_info_unset_flag(
4339 dest
, pi
, BGP_PATH_STALE
);
4340 bgp_dest_set_defer_flag(dest
, false);
4341 bgp_process(bgp
, dest
, afi
, safi
);
4345 bgp_dest_unlock_node(dest
);
4346 bgp_attr_unintern(&attr_new
);
4351 /* Withdraw/Announce before we fully processed the withdraw */
4352 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4353 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4354 bgp_debug_rdpfxpath2str(
4355 afi
, safi
, prd
, p
, label
, num_labels
,
4356 addpath_id
? 1 : 0, addpath_id
, evpn
,
4357 pfx_buf
, sizeof(pfx_buf
));
4359 "%pBP rcvd %s, flapped quicker than processing",
4363 bgp_path_info_restore(dest
, pi
);
4366 * If the BGP_PATH_REMOVED flag is set, then EVPN
4367 * routes would have been unimported already when a
4368 * prior BGP withdraw processing happened. Such routes
4369 * need to be imported again, so flag accordingly.
4371 force_evpn_import
= true;
4374 /* Received Logging. */
4375 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4376 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4377 num_labels
, addpath_id
? 1 : 0,
4378 addpath_id
, evpn
, pfx_buf
,
4380 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4383 /* graceful restart STALE flag unset. */
4384 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4385 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4386 bgp_dest_set_defer_flag(dest
, false);
4389 /* The attribute is changed. */
4390 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4392 /* implicit withdraw, decrement aggregate and pcount here.
4393 * only if update is accepted, they'll increment below.
4395 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4397 /* Update bgp route dampening information. */
4398 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4399 && peer
->sort
== BGP_PEER_EBGP
) {
4400 /* This is implicit withdraw so we should update
4403 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4404 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4406 #ifdef ENABLE_BGP_VNC
4407 if (safi
== SAFI_MPLS_VPN
) {
4408 struct bgp_dest
*pdest
= NULL
;
4409 struct bgp_table
*table
= NULL
;
4411 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4412 (struct prefix
*)prd
);
4413 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4414 table
= bgp_dest_get_bgp_table_info(pdest
);
4416 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4417 bgp
, prd
, table
, p
, pi
);
4419 bgp_dest_unlock_node(pdest
);
4421 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4422 && (safi
== SAFI_UNICAST
)) {
4423 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4425 * Implicit withdraw case.
4427 ++vnc_implicit_withdraw
;
4428 vnc_import_bgp_del_route(bgp
, p
, pi
);
4429 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4434 /* Special handling for EVPN update of an existing route. If the
4435 * extended community attribute has changed, we need to
4437 * the route using its existing extended community. It will be
4438 * subsequently processed for import with the new extended
4441 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4444 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4446 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4449 cmp
= ecommunity_cmp(
4450 bgp_attr_get_ecommunity(pi
->attr
),
4451 bgp_attr_get_ecommunity(attr_new
));
4453 if (bgp_debug_update(peer
, p
, NULL
, 1))
4455 "Change in EXT-COMM, existing %s new %s",
4457 bgp_attr_get_ecommunity(
4460 bgp_attr_get_ecommunity(
4462 if (safi
== SAFI_EVPN
)
4463 bgp_evpn_unimport_route(
4464 bgp
, afi
, safi
, p
, pi
);
4465 else /* SAFI_MPLS_VPN */
4466 vpn_leak_to_vrf_withdraw(bgp
,
4472 /* Update to new attribute. */
4473 bgp_attr_unintern(&pi
->attr
);
4474 pi
->attr
= attr_new
;
4476 /* Update MPLS label */
4477 if (has_valid_label
) {
4478 extra
= bgp_path_info_extra_get(pi
);
4479 if (extra
->label
!= label
) {
4480 memcpy(&extra
->label
, label
,
4481 num_labels
* sizeof(mpls_label_t
));
4482 extra
->num_labels
= num_labels
;
4484 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4485 bgp_set_valid_label(&extra
->label
[0]);
4488 /* Update SRv6 SID */
4489 if (attr
->srv6_l3vpn
) {
4490 extra
= bgp_path_info_extra_get(pi
);
4491 if (sid_diff(&extra
->sid
[0].sid
,
4492 &attr
->srv6_l3vpn
->sid
)) {
4493 sid_copy(&extra
->sid
[0].sid
,
4494 &attr
->srv6_l3vpn
->sid
);
4495 extra
->num_sids
= 1;
4497 extra
->sid
[0].loc_block_len
= 0;
4498 extra
->sid
[0].loc_node_len
= 0;
4499 extra
->sid
[0].func_len
= 0;
4500 extra
->sid
[0].arg_len
= 0;
4501 extra
->sid
[0].transposition_len
= 0;
4502 extra
->sid
[0].transposition_offset
= 0;
4504 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4505 extra
->sid
[0].loc_block_len
=
4506 attr
->srv6_l3vpn
->loc_block_len
;
4507 extra
->sid
[0].loc_node_len
=
4508 attr
->srv6_l3vpn
->loc_node_len
;
4509 extra
->sid
[0].func_len
=
4510 attr
->srv6_l3vpn
->func_len
;
4511 extra
->sid
[0].arg_len
=
4512 attr
->srv6_l3vpn
->arg_len
;
4513 extra
->sid
[0].transposition_len
=
4515 ->transposition_len
;
4516 extra
->sid
[0].transposition_offset
=
4518 ->transposition_offset
;
4521 } else if (attr
->srv6_vpn
) {
4522 extra
= bgp_path_info_extra_get(pi
);
4523 if (sid_diff(&extra
->sid
[0].sid
,
4524 &attr
->srv6_vpn
->sid
)) {
4525 sid_copy(&extra
->sid
[0].sid
,
4526 &attr
->srv6_vpn
->sid
);
4527 extra
->num_sids
= 1;
4531 #ifdef ENABLE_BGP_VNC
4532 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4533 && (safi
== SAFI_UNICAST
)) {
4534 if (vnc_implicit_withdraw
) {
4536 * Add back the route with its new attributes
4538 * The route is still selected, until the route
4540 * queued by bgp_process actually runs. We have
4542 * update to the VNC side immediately to avoid
4544 * configuration changes (e.g., route-map
4546 * trigger re-importation of the entire RIB.
4548 vnc_import_bgp_add_route(bgp
, p
, pi
);
4549 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4554 /* Update bgp route dampening information. */
4555 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4556 && peer
->sort
== BGP_PEER_EBGP
) {
4557 /* Now we do normal update dampening. */
4558 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4559 if (ret
== BGP_DAMP_SUPPRESSED
) {
4560 bgp_dest_unlock_node(dest
);
4565 /* Nexthop reachability check - for unicast and
4566 * labeled-unicast.. */
4567 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4568 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4569 || (safi
== SAFI_EVPN
&&
4570 bgp_evpn_is_prefix_nht_supported(p
))) {
4571 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4572 && peer
->ttl
== BGP_DEFAULT_TTL
4573 && !CHECK_FLAG(peer
->flags
,
4574 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4575 && !CHECK_FLAG(bgp
->flags
,
4576 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4581 struct bgp
*bgp_nexthop
= bgp
;
4583 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4584 bgp_nexthop
= pi
->extra
->bgp_orig
;
4586 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4588 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4589 safi
, pi
, NULL
, connected
,
4591 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4592 bgp_path_info_set_flag(dest
, pi
,
4595 if (BGP_DEBUG(nht
, NHT
)) {
4596 zlog_debug("%s(%pI4): NH unresolved",
4598 (in_addr_t
*)&attr_new
->nexthop
);
4600 bgp_path_info_unset_flag(dest
, pi
,
4605 bgp_path_info_set_flag(dest
, pi
,
4606 BGP_PATH_ACCEPT_OWN
);
4608 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4611 #ifdef ENABLE_BGP_VNC
4612 if (safi
== SAFI_MPLS_VPN
) {
4613 struct bgp_dest
*pdest
= NULL
;
4614 struct bgp_table
*table
= NULL
;
4616 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4617 (struct prefix
*)prd
);
4618 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4619 table
= bgp_dest_get_bgp_table_info(pdest
);
4621 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4622 bgp
, prd
, table
, p
, pi
);
4624 bgp_dest_unlock_node(pdest
);
4628 /* If this is an EVPN route and some attribute has changed,
4629 * or we are explicitly told to perform a route import, process
4630 * route for import. If the extended community has changed, we
4632 * have done the un-import earlier and the import would result
4634 * route getting injected into appropriate L2 VNIs. If it is
4636 * some other attribute change, the import will result in
4638 * the attributes for the route in the VNI(s).
4640 if (safi
== SAFI_EVPN
&&
4641 (!same_attr
|| force_evpn_import
) &&
4642 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4643 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4645 /* Process change. */
4646 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4648 bgp_process(bgp
, dest
, afi
, safi
);
4649 bgp_dest_unlock_node(dest
);
4651 if (SAFI_UNICAST
== safi
4652 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4653 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4655 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4657 if ((SAFI_MPLS_VPN
== safi
)
4658 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4659 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4662 #ifdef ENABLE_BGP_VNC
4663 if (SAFI_MPLS_VPN
== safi
) {
4664 mpls_label_t label_decoded
= decode_label(label
);
4666 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4667 type
, sub_type
, &label_decoded
);
4669 if (SAFI_ENCAP
== safi
) {
4670 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4671 type
, sub_type
, NULL
);
4674 if ((safi
== SAFI_MPLS_VPN
) &&
4675 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4676 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4678 bgp_unlink_nexthop(pi
);
4679 bgp_path_info_delete(dest
, pi
);
4682 } // End of implicit withdraw
4684 /* Received Logging. */
4685 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4686 if (!peer
->rcvd_attr_printed
) {
4687 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4688 peer
->rcvd_attr_str
);
4689 peer
->rcvd_attr_printed
= 1;
4692 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4693 addpath_id
? 1 : 0, addpath_id
, evpn
,
4694 pfx_buf
, sizeof(pfx_buf
));
4695 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4698 /* Make new BGP info. */
4699 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4701 /* Update MPLS label */
4702 if (has_valid_label
) {
4703 extra
= bgp_path_info_extra_get(new);
4704 if (extra
->label
!= label
) {
4705 memcpy(&extra
->label
, label
,
4706 num_labels
* sizeof(mpls_label_t
));
4707 extra
->num_labels
= num_labels
;
4709 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4710 bgp_set_valid_label(&extra
->label
[0]);
4713 /* Update SRv6 SID */
4714 if (safi
== SAFI_MPLS_VPN
) {
4715 extra
= bgp_path_info_extra_get(new);
4716 if (attr
->srv6_l3vpn
) {
4717 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4718 extra
->num_sids
= 1;
4720 extra
->sid
[0].loc_block_len
=
4721 attr
->srv6_l3vpn
->loc_block_len
;
4722 extra
->sid
[0].loc_node_len
=
4723 attr
->srv6_l3vpn
->loc_node_len
;
4724 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4725 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4726 extra
->sid
[0].transposition_len
=
4727 attr
->srv6_l3vpn
->transposition_len
;
4728 extra
->sid
[0].transposition_offset
=
4729 attr
->srv6_l3vpn
->transposition_offset
;
4730 } else if (attr
->srv6_vpn
) {
4731 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4732 extra
->num_sids
= 1;
4736 /* Nexthop reachability check. */
4737 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4738 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4739 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4740 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4741 && peer
->ttl
== BGP_DEFAULT_TTL
4742 && !CHECK_FLAG(peer
->flags
,
4743 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4744 && !CHECK_FLAG(bgp
->flags
,
4745 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4750 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4752 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4754 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4755 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4757 if (BGP_DEBUG(nht
, NHT
)) {
4758 char buf1
[INET6_ADDRSTRLEN
];
4760 (const void *)&attr_new
->nexthop
,
4761 buf1
, INET6_ADDRSTRLEN
);
4762 zlog_debug("%s(%s): NH unresolved", __func__
,
4765 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4769 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4771 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4775 new->addpath_rx_id
= addpath_id
;
4777 /* Increment prefix */
4778 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4780 /* Register new BGP information. */
4781 bgp_path_info_add(dest
, new);
4783 /* route_node_get lock */
4784 bgp_dest_unlock_node(dest
);
4786 #ifdef ENABLE_BGP_VNC
4787 if (safi
== SAFI_MPLS_VPN
) {
4788 struct bgp_dest
*pdest
= NULL
;
4789 struct bgp_table
*table
= NULL
;
4791 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4792 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4793 table
= bgp_dest_get_bgp_table_info(pdest
);
4795 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4796 bgp
, prd
, table
, p
, new);
4798 bgp_dest_unlock_node(pdest
);
4802 /* If this is an EVPN route, process for import. */
4803 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4804 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4806 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4808 /* Process change. */
4809 bgp_process(bgp
, dest
, afi
, safi
);
4811 if (SAFI_UNICAST
== safi
4812 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4813 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4814 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4816 if ((SAFI_MPLS_VPN
== safi
)
4817 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4818 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4820 #ifdef ENABLE_BGP_VNC
4821 if (SAFI_MPLS_VPN
== safi
) {
4822 mpls_label_t label_decoded
= decode_label(label
);
4824 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4825 sub_type
, &label_decoded
);
4827 if (SAFI_ENCAP
== safi
) {
4828 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4832 if ((safi
== SAFI_MPLS_VPN
) &&
4833 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4834 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4836 bgp_unlink_nexthop(new);
4837 bgp_path_info_delete(dest
, new);
4842 /* This BGP update is filtered. Log the reason then update BGP
4845 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4847 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4848 if (!peer
->rcvd_attr_printed
) {
4849 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4850 peer
->rcvd_attr_str
);
4851 peer
->rcvd_attr_printed
= 1;
4854 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4855 addpath_id
? 1 : 0, addpath_id
, evpn
,
4856 pfx_buf
, sizeof(pfx_buf
));
4857 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4858 peer
, pfx_buf
, reason
);
4862 /* If this is an EVPN route, un-import it as it is now filtered.
4864 if (safi
== SAFI_EVPN
)
4865 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4867 if (SAFI_UNICAST
== safi
4868 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4869 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4871 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4873 if ((SAFI_MPLS_VPN
== safi
)
4874 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4876 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4879 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4882 bgp_dest_unlock_node(dest
);
4884 #ifdef ENABLE_BGP_VNC
4886 * Filtered update is treated as an implicit withdrawal (see
4888 * a few lines above)
4890 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4891 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4899 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4900 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4901 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4902 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4905 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4906 struct bgp_dest
*dest
;
4907 struct bgp_path_info
*pi
;
4909 #ifdef ENABLE_BGP_VNC
4910 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4911 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4919 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4921 /* If peer is soft reconfiguration enabled. Record input packet for
4922 * further calculation.
4924 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4925 * routes that are filtered. This tanks out Quagga RS pretty badly due
4927 * the iteration over all RS clients.
4928 * Since we need to remove the entry from adj_in anyway, do that first
4930 * if there was no entry, we don't need to do anything more.
4932 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4933 && peer
!= bgp
->peer_self
)
4934 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4935 peer
->stat_pfx_dup_withdraw
++;
4937 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4938 bgp_debug_rdpfxpath2str(
4939 afi
, safi
, prd
, p
, label
, num_labels
,
4940 addpath_id
? 1 : 0, addpath_id
, NULL
,
4941 pfx_buf
, sizeof(pfx_buf
));
4943 "%s withdrawing route %s not in adj-in",
4944 peer
->host
, pfx_buf
);
4946 bgp_dest_unlock_node(dest
);
4950 /* Lookup withdrawn route. */
4951 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4952 if (pi
->peer
== peer
&& pi
->type
== type
4953 && pi
->sub_type
== sub_type
4954 && pi
->addpath_rx_id
== addpath_id
)
4958 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4959 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4960 addpath_id
? 1 : 0, addpath_id
, NULL
,
4961 pfx_buf
, sizeof(pfx_buf
));
4962 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
4966 /* Withdraw specified route from routing table. */
4967 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4968 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4969 if (SAFI_UNICAST
== safi
4970 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4971 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4972 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4974 if ((SAFI_MPLS_VPN
== safi
)
4975 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4977 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4979 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4980 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4981 addpath_id
? 1 : 0, addpath_id
, NULL
,
4982 pfx_buf
, sizeof(pfx_buf
));
4983 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4986 /* Unlock bgp_node_get() lock. */
4987 bgp_dest_unlock_node(dest
);
4992 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4995 struct update_subgroup
*subgrp
;
4996 subgrp
= peer_subgroup(peer
, afi
, safi
);
4997 subgroup_default_originate(subgrp
, withdraw
);
5002 * bgp_stop_announce_route_timer
5004 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5006 if (!paf
->t_announce_route
)
5009 THREAD_OFF(paf
->t_announce_route
);
5013 * bgp_announce_route_timer_expired
5015 * Callback that is invoked when the route announcement timer for a
5018 static void bgp_announce_route_timer_expired(struct thread
*t
)
5020 struct peer_af
*paf
;
5023 paf
= THREAD_ARG(t
);
5026 if (!peer_established(peer
))
5029 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5032 peer_af_announce_route(paf
, 1);
5034 /* Notify BGP conditional advertisement scanner percess */
5035 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5039 * bgp_announce_route
5041 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5043 * if force is true we will force an update even if the update
5044 * limiting code is attempted to kick in.
5046 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5048 struct peer_af
*paf
;
5049 struct update_subgroup
*subgrp
;
5051 paf
= peer_af_find(peer
, afi
, safi
);
5054 subgrp
= PAF_SUBGRP(paf
);
5057 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5058 * or a refresh has already been triggered.
5060 if (!subgrp
|| paf
->t_announce_route
)
5064 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5067 * Start a timer to stagger/delay the announce. This serves
5068 * two purposes - announcement can potentially be combined for
5069 * multiple peers and the announcement doesn't happen in the
5072 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5073 (subgrp
->peer_count
== 1)
5074 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5075 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5076 &paf
->t_announce_route
);
5080 * Announce routes from all AF tables to a peer.
5082 * This should ONLY be called when there is a need to refresh the
5083 * routes to the peer based on a policy change for this peer alone
5084 * or a route refresh request received from the peer.
5085 * The operation will result in splitting the peer from its existing
5086 * subgroups and putting it in new subgroups.
5088 void bgp_announce_route_all(struct peer
*peer
)
5093 FOREACH_AFI_SAFI (afi
, safi
)
5094 bgp_announce_route(peer
, afi
, safi
, false);
5097 /* Flag or unflag bgp_dest to determine whether it should be treated by
5098 * bgp_soft_reconfig_table_task.
5099 * Flag if flag is true. Unflag if flag is false.
5101 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5103 struct bgp_dest
*dest
;
5104 struct bgp_adj_in
*ain
;
5109 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5110 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5111 if (ain
->peer
!= NULL
)
5114 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5115 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5117 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5121 static int bgp_soft_reconfig_table_update(struct peer
*peer
,
5122 struct bgp_dest
*dest
,
5123 struct bgp_adj_in
*ain
, afi_t afi
,
5124 safi_t safi
, struct prefix_rd
*prd
)
5126 struct bgp_path_info
*pi
;
5127 uint32_t num_labels
= 0;
5128 mpls_label_t
*label_pnt
= NULL
;
5129 struct bgp_route_evpn evpn
;
5131 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5132 if (pi
->peer
== peer
)
5135 if (pi
&& pi
->extra
)
5136 num_labels
= pi
->extra
->num_labels
;
5138 label_pnt
= &pi
->extra
->label
[0];
5140 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5143 memset(&evpn
, 0, sizeof(evpn
));
5145 return bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5146 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
5147 BGP_ROUTE_NORMAL
, prd
, label_pnt
, num_labels
, 1,
5151 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5152 struct bgp_table
*table
,
5153 struct prefix_rd
*prd
)
5156 struct bgp_dest
*dest
;
5157 struct bgp_adj_in
*ain
;
5160 table
= peer
->bgp
->rib
[afi
][safi
];
5162 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5163 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5164 if (ain
->peer
!= peer
)
5167 ret
= bgp_soft_reconfig_table_update(peer
, dest
, ain
,
5171 bgp_dest_unlock_node(dest
);
5177 /* Do soft reconfig table per bgp table.
5178 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5179 * when BGP_NODE_SOFT_RECONFIG is set,
5180 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5181 * Schedule a new thread to continue the job.
5182 * Without splitting the full job into several part,
5183 * vtysh waits for the job to finish before responding to a BGP command
5185 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
5187 uint32_t iter
, max_iter
;
5189 struct bgp_dest
*dest
;
5190 struct bgp_adj_in
*ain
;
5192 struct bgp_table
*table
;
5193 struct prefix_rd
*prd
;
5194 struct listnode
*node
, *nnode
;
5196 table
= THREAD_ARG(thread
);
5199 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5200 if (table
->soft_reconfig_init
) {
5201 /* first call of the function with a new srta structure.
5202 * Don't do any treatment this time on nodes
5203 * in order vtysh to respond quickly
5208 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5209 dest
= bgp_route_next(dest
)) {
5210 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5213 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5215 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5216 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5218 if (ain
->peer
!= peer
)
5221 ret
= bgp_soft_reconfig_table_update(
5222 peer
, dest
, ain
, table
->afi
,
5227 bgp_dest_unlock_node(dest
);
5229 table
->soft_reconfig_peers
,
5231 bgp_announce_route(peer
, table
->afi
,
5232 table
->safi
, false);
5234 table
->soft_reconfig_peers
)) {
5236 &table
->soft_reconfig_peers
);
5237 bgp_soft_reconfig_table_flag(
5246 /* we're either starting the initial iteration,
5247 * or we're going to continue an ongoing iteration
5249 if (dest
|| table
->soft_reconfig_init
) {
5250 table
->soft_reconfig_init
= false;
5251 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
5252 table
, 0, &table
->soft_reconfig_thread
);
5255 /* we're done, clean up the background iteration context info and
5256 schedule route annoucement
5258 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5259 listnode_delete(table
->soft_reconfig_peers
, peer
);
5260 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5263 list_delete(&table
->soft_reconfig_peers
);
5267 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5269 * - bgp cannot be NULL
5270 * - if table and peer are NULL, cancel all threads within the bgp instance
5271 * - if table is NULL and peer is not,
5272 * remove peer in all threads within the bgp instance
5273 * - if peer is NULL, cancel all threads matching table within the bgp instance
5275 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5276 const struct bgp_table
*table
,
5277 const struct peer
*peer
)
5280 struct listnode
*node
, *nnode
;
5282 struct bgp_table
*ntable
;
5287 FOREACH_AFI_SAFI (afi
, safi
) {
5288 ntable
= bgp
->rib
[afi
][safi
];
5291 if (table
&& table
!= ntable
)
5294 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5296 if (peer
&& peer
!= npeer
)
5298 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5301 if (!ntable
->soft_reconfig_peers
5302 || !list_isempty(ntable
->soft_reconfig_peers
))
5305 list_delete(&ntable
->soft_reconfig_peers
);
5306 bgp_soft_reconfig_table_flag(ntable
, false);
5307 THREAD_OFF(ntable
->soft_reconfig_thread
);
5311 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5313 struct bgp_dest
*dest
;
5314 struct bgp_table
*table
;
5315 struct listnode
*node
, *nnode
;
5317 struct peer_af
*paf
;
5319 if (!peer_established(peer
))
5322 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5323 && (safi
!= SAFI_EVPN
)) {
5324 table
= peer
->bgp
->rib
[afi
][safi
];
5328 table
->soft_reconfig_init
= true;
5330 if (!table
->soft_reconfig_peers
)
5331 table
->soft_reconfig_peers
= list_new();
5333 /* add peer to the table soft_reconfig_peers if not already
5336 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5342 listnode_add(table
->soft_reconfig_peers
, peer
);
5344 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5345 * on table would start back at the beginning.
5347 bgp_soft_reconfig_table_flag(table
, true);
5349 if (!table
->soft_reconfig_thread
)
5350 thread_add_event(bm
->master
,
5351 bgp_soft_reconfig_table_task
, table
, 0,
5352 &table
->soft_reconfig_thread
);
5353 /* Cancel bgp_announce_route_timer_expired threads.
5354 * bgp_announce_route_timer_expired threads have been scheduled
5355 * to announce routes as soon as the soft_reconfigure process
5357 * In this case, soft_reconfigure is also scheduled by using
5358 * a thread but is planned after the
5359 * bgp_announce_route_timer_expired threads. It means that,
5360 * without cancelling the threads, the route announcement task
5361 * would run before the soft reconfiguration one. That would
5362 * useless and would block vtysh during several seconds. Route
5363 * announcements are rescheduled as soon as the soft_reconfigure
5366 paf
= peer_af_find(peer
, afi
, safi
);
5368 bgp_stop_announce_route_timer(paf
);
5370 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5371 dest
= bgp_route_next(dest
)) {
5372 table
= bgp_dest_get_bgp_table_info(dest
);
5377 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5378 struct prefix_rd prd
;
5380 prd
.family
= AF_UNSPEC
;
5382 memcpy(&prd
.val
, p
->u
.val
, 8);
5384 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5389 struct bgp_clear_node_queue
{
5390 struct bgp_dest
*dest
;
5393 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5395 struct bgp_clear_node_queue
*cnq
= data
;
5396 struct bgp_dest
*dest
= cnq
->dest
;
5397 struct peer
*peer
= wq
->spec
.data
;
5398 struct bgp_path_info
*pi
;
5400 afi_t afi
= bgp_dest_table(dest
)->afi
;
5401 safi_t safi
= bgp_dest_table(dest
)->safi
;
5403 assert(dest
&& peer
);
5406 /* It is possible that we have multiple paths for a prefix from a peer
5407 * if that peer is using AddPath.
5409 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5410 if (pi
->peer
!= peer
)
5413 /* graceful restart STALE flag set. */
5414 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5415 && peer
->nsf
[afi
][safi
])
5416 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5417 PEER_STATUS_ENHANCED_REFRESH
))
5418 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5419 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5420 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5422 /* If this is an EVPN route, process for
5424 if (safi
== SAFI_EVPN
)
5425 bgp_evpn_unimport_route(
5427 bgp_dest_get_prefix(dest
), pi
);
5428 /* Handle withdraw for VRF route-leaking and L3VPN */
5429 if (SAFI_UNICAST
== safi
5430 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5431 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5432 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5435 if (SAFI_MPLS_VPN
== safi
&&
5436 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5437 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5440 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5446 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5448 struct bgp_clear_node_queue
*cnq
= data
;
5449 struct bgp_dest
*dest
= cnq
->dest
;
5450 struct bgp_table
*table
= bgp_dest_table(dest
);
5452 bgp_dest_unlock_node(dest
);
5453 bgp_table_unlock(table
);
5454 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5457 static void bgp_clear_node_complete(struct work_queue
*wq
)
5459 struct peer
*peer
= wq
->spec
.data
;
5461 /* Tickle FSM to start moving again */
5462 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5464 peer_unlock(peer
); /* bgp_clear_route */
5467 static void bgp_clear_node_queue_init(struct peer
*peer
)
5469 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5471 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5472 #undef CLEAR_QUEUE_NAME_LEN
5474 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5475 peer
->clear_node_queue
->spec
.hold
= 10;
5476 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5477 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5478 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5479 peer
->clear_node_queue
->spec
.max_retries
= 0;
5481 /* we only 'lock' this peer reference when the queue is actually active
5483 peer
->clear_node_queue
->spec
.data
= peer
;
5486 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5487 struct bgp_table
*table
)
5489 struct bgp_dest
*dest
;
5490 int force
= peer
->bgp
->process_queue
? 0 : 1;
5493 table
= peer
->bgp
->rib
[afi
][safi
];
5495 /* If still no table => afi/safi isn't configured at all or smth. */
5499 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5500 struct bgp_path_info
*pi
, *next
;
5501 struct bgp_adj_in
*ain
;
5502 struct bgp_adj_in
*ain_next
;
5504 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5505 * queued for every clearing peer, regardless of whether it is
5506 * relevant to the peer at hand.
5508 * Overview: There are 3 different indices which need to be
5509 * scrubbed, potentially, when a peer is removed:
5511 * 1 peer's routes visible via the RIB (ie accepted routes)
5512 * 2 peer's routes visible by the (optional) peer's adj-in index
5513 * 3 other routes visible by the peer's adj-out index
5515 * 3 there is no hurry in scrubbing, once the struct peer is
5516 * removed from bgp->peer, we could just GC such deleted peer's
5517 * adj-outs at our leisure.
5519 * 1 and 2 must be 'scrubbed' in some way, at least made
5520 * invisible via RIB index before peer session is allowed to be
5521 * brought back up. So one needs to know when such a 'search' is
5526 * - there'd be a single global queue or a single RIB walker
5527 * - rather than tracking which route_nodes still need to be
5528 * examined on a peer basis, we'd track which peers still
5531 * Given that our per-peer prefix-counts now should be reliable,
5532 * this may actually be achievable. It doesn't seem to be a huge
5533 * problem at this time,
5535 * It is possible that we have multiple paths for a prefix from
5537 * if that peer is using AddPath.
5541 ain_next
= ain
->next
;
5543 if (ain
->peer
== peer
)
5544 bgp_adj_in_remove(dest
, ain
);
5549 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5551 if (pi
->peer
!= peer
)
5555 bgp_path_info_reap(dest
, pi
);
5557 struct bgp_clear_node_queue
*cnq
;
5559 /* both unlocked in bgp_clear_node_queue_del */
5560 bgp_table_lock(bgp_dest_table(dest
));
5561 bgp_dest_lock_node(dest
);
5563 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5564 sizeof(struct bgp_clear_node_queue
));
5566 work_queue_add(peer
->clear_node_queue
, cnq
);
5574 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5576 struct bgp_dest
*dest
;
5577 struct bgp_table
*table
;
5579 if (peer
->clear_node_queue
== NULL
)
5580 bgp_clear_node_queue_init(peer
);
5582 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5583 * Idle until it receives a Clearing_Completed event. This protects
5584 * against peers which flap faster than we can we clear, which could
5587 * a) race with routes from the new session being installed before
5588 * clear_route_node visits the node (to delete the route of that
5590 * b) resource exhaustion, clear_route_node likely leads to an entry
5591 * on the process_main queue. Fast-flapping could cause that queue
5595 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5596 * the unlock will happen upon work-queue completion; other wise, the
5597 * unlock happens at the end of this function.
5599 if (!peer
->clear_node_queue
->thread
)
5602 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5603 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5605 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5606 dest
= bgp_route_next(dest
)) {
5607 table
= bgp_dest_get_bgp_table_info(dest
);
5611 bgp_clear_route_table(peer
, afi
, safi
, table
);
5614 /* unlock if no nodes got added to the clear-node-queue. */
5615 if (!peer
->clear_node_queue
->thread
)
5619 void bgp_clear_route_all(struct peer
*peer
)
5624 FOREACH_AFI_SAFI (afi
, safi
)
5625 bgp_clear_route(peer
, afi
, safi
);
5627 #ifdef ENABLE_BGP_VNC
5628 rfapiProcessPeerDown(peer
);
5632 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5634 struct bgp_table
*table
;
5635 struct bgp_dest
*dest
;
5636 struct bgp_adj_in
*ain
;
5637 struct bgp_adj_in
*ain_next
;
5639 table
= peer
->bgp
->rib
[afi
][safi
];
5641 /* It is possible that we have multiple paths for a prefix from a peer
5642 * if that peer is using AddPath.
5644 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5648 ain_next
= ain
->next
;
5650 if (ain
->peer
== peer
)
5651 bgp_adj_in_remove(dest
, ain
);
5658 /* If any of the routes from the peer have been marked with the NO_LLGR
5659 * community, either as sent by the peer, or as the result of a configured
5660 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5661 * operation of [RFC4271].
5663 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5665 struct bgp_dest
*dest
;
5666 struct bgp_path_info
*pi
;
5667 struct bgp_table
*table
;
5669 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5670 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5671 dest
= bgp_route_next(dest
)) {
5672 struct bgp_dest
*rm
;
5674 /* look for neighbor in tables */
5675 table
= bgp_dest_get_bgp_table_info(dest
);
5679 for (rm
= bgp_table_top(table
); rm
;
5680 rm
= bgp_route_next(rm
))
5681 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5683 if (pi
->peer
!= peer
)
5686 peer
->af_sflags
[afi
][safi
],
5687 PEER_STATUS_LLGR_WAIT
) &&
5688 bgp_attr_get_community(pi
->attr
) &&
5690 bgp_attr_get_community(
5694 if (!CHECK_FLAG(pi
->flags
,
5699 * If this is VRF leaked route
5700 * process for withdraw.
5703 BGP_ROUTE_IMPORTED
&&
5704 peer
->bgp
->inst_type
==
5705 BGP_INSTANCE_TYPE_DEFAULT
)
5706 vpn_leak_to_vrf_withdraw(
5709 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5714 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5715 dest
= bgp_route_next(dest
))
5716 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5718 if (pi
->peer
!= peer
)
5720 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5721 PEER_STATUS_LLGR_WAIT
) &&
5722 bgp_attr_get_community(pi
->attr
) &&
5724 bgp_attr_get_community(pi
->attr
),
5727 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5729 if (safi
== SAFI_UNICAST
&&
5730 (peer
->bgp
->inst_type
==
5731 BGP_INSTANCE_TYPE_VRF
||
5732 peer
->bgp
->inst_type
==
5733 BGP_INSTANCE_TYPE_DEFAULT
))
5734 vpn_leak_from_vrf_withdraw(
5735 bgp_get_default(), peer
->bgp
,
5738 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5744 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5746 struct bgp_dest
*dest
, *ndest
;
5747 struct bgp_path_info
*pi
;
5748 struct bgp_table
*table
;
5750 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5751 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5752 dest
= bgp_route_next(dest
)) {
5753 table
= bgp_dest_get_bgp_table_info(dest
);
5757 for (ndest
= bgp_table_top(table
); ndest
;
5758 ndest
= bgp_route_next(ndest
)) {
5759 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5761 if (pi
->peer
!= peer
)
5765 peer
->af_sflags
[afi
][safi
],
5766 PEER_STATUS_ENHANCED_REFRESH
))
5767 && !CHECK_FLAG(pi
->flags
,
5771 BGP_PATH_UNUSEABLE
)) {
5772 if (bgp_debug_neighbor_events(
5775 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5779 bgp_dest_get_prefix(
5782 bgp_path_info_set_flag(
5790 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5791 dest
= bgp_route_next(dest
)) {
5792 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5794 if (pi
->peer
!= peer
)
5797 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5798 PEER_STATUS_ENHANCED_REFRESH
))
5799 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5800 && !CHECK_FLAG(pi
->flags
,
5801 BGP_PATH_UNUSEABLE
)) {
5802 if (bgp_debug_neighbor_events(peer
))
5804 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5807 bgp_dest_get_prefix(
5810 bgp_path_info_set_flag(dest
, pi
,
5818 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5820 if (peer
->sort
== BGP_PEER_IBGP
)
5823 if (peer
->sort
== BGP_PEER_EBGP
5824 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5825 || FILTER_LIST_OUT_NAME(filter
)
5826 || DISTRIBUTE_OUT_NAME(filter
)))
5831 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5833 if (peer
->sort
== BGP_PEER_IBGP
)
5836 if (peer
->sort
== BGP_PEER_EBGP
5837 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5838 || FILTER_LIST_IN_NAME(filter
)
5839 || DISTRIBUTE_IN_NAME(filter
)))
5844 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5847 struct bgp_dest
*dest
;
5848 struct bgp_path_info
*pi
;
5849 struct bgp_path_info
*next
;
5851 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5852 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5853 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5857 /* Unimport EVPN routes from VRFs */
5858 if (safi
== SAFI_EVPN
)
5859 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5862 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5863 && pi
->type
== ZEBRA_ROUTE_BGP
5864 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5865 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5866 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5868 if (bgp_fibupd_safi(safi
))
5869 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5872 bgp_path_info_reap(dest
, pi
);
5876 /* Delete all kernel routes. */
5877 void bgp_cleanup_routes(struct bgp
*bgp
)
5880 struct bgp_dest
*dest
;
5881 struct bgp_table
*table
;
5883 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5884 if (afi
== AFI_L2VPN
)
5886 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5889 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5891 if (afi
!= AFI_L2VPN
) {
5893 safi
= SAFI_MPLS_VPN
;
5894 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5895 dest
= bgp_route_next(dest
)) {
5896 table
= bgp_dest_get_bgp_table_info(dest
);
5897 if (table
!= NULL
) {
5898 bgp_cleanup_table(bgp
, table
, safi
);
5899 bgp_table_finish(&table
);
5900 bgp_dest_set_bgp_table_info(dest
, NULL
);
5901 bgp_dest_unlock_node(dest
);
5905 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5906 dest
= bgp_route_next(dest
)) {
5907 table
= bgp_dest_get_bgp_table_info(dest
);
5908 if (table
!= NULL
) {
5909 bgp_cleanup_table(bgp
, table
, safi
);
5910 bgp_table_finish(&table
);
5911 bgp_dest_set_bgp_table_info(dest
, NULL
);
5912 bgp_dest_unlock_node(dest
);
5917 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5918 dest
= bgp_route_next(dest
)) {
5919 table
= bgp_dest_get_bgp_table_info(dest
);
5920 if (table
!= NULL
) {
5921 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5922 bgp_table_finish(&table
);
5923 bgp_dest_set_bgp_table_info(dest
, NULL
);
5924 bgp_dest_unlock_node(dest
);
5929 void bgp_reset(void)
5932 bgp_zclient_reset();
5933 access_list_reset();
5934 prefix_list_reset();
5937 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5939 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5940 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5941 PEER_CAP_ADDPATH_AF_TX_RCV
));
5944 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5946 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5947 struct bgp_nlri
*packet
)
5956 bool addpath_capable
;
5957 uint32_t addpath_id
;
5960 lim
= pnt
+ packet
->length
;
5962 safi
= packet
->safi
;
5964 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5966 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5967 syntactic validity. If the field is syntactically incorrect,
5968 then the Error Subcode is set to Invalid Network Field. */
5969 for (; pnt
< lim
; pnt
+= psize
) {
5970 /* Clear prefix structure. */
5971 memset(&p
, 0, sizeof(p
));
5973 if (addpath_capable
) {
5975 /* When packet overflow occurs return immediately. */
5976 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5977 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5979 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5980 addpath_id
= ntohl(addpath_id
);
5981 pnt
+= BGP_ADDPATH_ID_LEN
;
5984 /* Fetch prefix length. */
5985 p
.prefixlen
= *pnt
++;
5986 /* afi/safi validity already verified by caller,
5987 * bgp_update_receive */
5988 p
.family
= afi2family(afi
);
5990 /* Prefix length check. */
5991 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5994 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5995 peer
->host
, p
.prefixlen
, packet
->afi
);
5996 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5999 /* Packet size overflow check. */
6000 psize
= PSIZE(p
.prefixlen
);
6002 /* When packet overflow occur return immediately. */
6003 if (pnt
+ psize
> lim
) {
6006 "%s [Error] Update packet error (prefix length %d overflows packet)",
6007 peer
->host
, p
.prefixlen
);
6008 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6011 /* Defensive coding, double-check the psize fits in a struct
6012 * prefix for the v4 and v6 afi's and unicast/multicast */
6013 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6016 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6017 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6018 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6021 /* Fetch prefix from NLRI packet. */
6022 memcpy(p
.u
.val
, pnt
, psize
);
6024 /* Check address. */
6025 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6026 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6027 /* From RFC4271 Section 6.3:
6029 * If a prefix in the NLRI field is semantically
6031 * (e.g., an unexpected multicast IP address),
6033 * be logged locally, and the prefix SHOULD be
6038 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6039 peer
->host
, &p
.u
.prefix4
);
6044 /* Check address. */
6045 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6046 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6049 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6050 peer
->host
, &p
.u
.prefix6
);
6054 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6057 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6058 peer
->host
, &p
.u
.prefix6
);
6064 /* Normal process. */
6066 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6067 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
6068 NULL
, NULL
, 0, 0, NULL
);
6070 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
6071 safi
, ZEBRA_ROUTE_BGP
,
6072 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
6075 /* Do not send BGP notification twice when maximum-prefix count
6077 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6078 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6080 /* Address family configuration mismatch. */
6082 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
6085 /* Packet length consistency check. */
6089 "%s [Error] Update packet error (prefix length mismatch with total length)",
6091 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6094 return BGP_NLRI_PARSE_OK
;
6097 static struct bgp_static
*bgp_static_new(void)
6099 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6102 static void bgp_static_free(struct bgp_static
*bgp_static
)
6104 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6105 route_map_counter_decrement(bgp_static
->rmap
.map
);
6107 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6108 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6111 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6112 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6114 struct bgp_dest
*dest
;
6115 struct bgp_path_info
*pi
;
6116 struct bgp_path_info
*new;
6117 struct bgp_path_info rmap_path
;
6119 struct attr
*attr_new
;
6120 route_map_result_t ret
;
6121 #ifdef ENABLE_BGP_VNC
6122 int vnc_implicit_withdraw
= 0;
6127 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6129 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6131 attr
.nexthop
= bgp_static
->igpnexthop
;
6132 attr
.med
= bgp_static
->igpmetric
;
6133 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6136 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6138 if (bgp_static
->atomic
)
6139 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6141 /* Store label index, if required. */
6142 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6143 attr
.label_index
= bgp_static
->label_index
;
6144 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6147 /* Apply route-map. */
6148 if (bgp_static
->rmap
.name
) {
6149 struct attr attr_tmp
= attr
;
6151 memset(&rmap_path
, 0, sizeof(rmap_path
));
6152 rmap_path
.peer
= bgp
->peer_self
;
6153 rmap_path
.attr
= &attr_tmp
;
6155 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6157 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6159 bgp
->peer_self
->rmap_type
= 0;
6161 if (ret
== RMAP_DENYMATCH
) {
6162 /* Free uninterned attribute. */
6163 bgp_attr_flush(&attr_tmp
);
6165 /* Unintern original. */
6166 aspath_unintern(&attr
.aspath
);
6167 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6168 bgp_dest_unlock_node(dest
);
6172 if (bgp_in_graceful_shutdown(bgp
))
6173 bgp_attr_add_gshut_community(&attr_tmp
);
6175 attr_new
= bgp_attr_intern(&attr_tmp
);
6178 if (bgp_in_graceful_shutdown(bgp
))
6179 bgp_attr_add_gshut_community(&attr
);
6181 attr_new
= bgp_attr_intern(&attr
);
6184 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6185 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6186 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6190 if (attrhash_cmp(pi
->attr
, attr_new
)
6191 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6192 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6193 bgp_dest_unlock_node(dest
);
6194 bgp_attr_unintern(&attr_new
);
6195 aspath_unintern(&attr
.aspath
);
6198 /* The attribute is changed. */
6199 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6201 /* Rewrite BGP route information. */
6202 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6203 bgp_path_info_restore(dest
, pi
);
6205 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6206 #ifdef ENABLE_BGP_VNC
6207 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6208 && (safi
== SAFI_UNICAST
)) {
6209 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6211 * Implicit withdraw case.
6212 * We have to do this before pi is
6215 ++vnc_implicit_withdraw
;
6216 vnc_import_bgp_del_route(bgp
, p
, pi
);
6217 vnc_import_bgp_exterior_del_route(
6222 bgp_attr_unintern(&pi
->attr
);
6223 pi
->attr
= attr_new
;
6224 pi
->uptime
= monotime(NULL
);
6225 #ifdef ENABLE_BGP_VNC
6226 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6227 && (safi
== SAFI_UNICAST
)) {
6228 if (vnc_implicit_withdraw
) {
6229 vnc_import_bgp_add_route(bgp
, p
, pi
);
6230 vnc_import_bgp_exterior_add_route(
6236 /* Nexthop reachability check. */
6237 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6238 && (safi
== SAFI_UNICAST
6239 || safi
== SAFI_LABELED_UNICAST
)) {
6241 struct bgp
*bgp_nexthop
= bgp
;
6243 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6244 bgp_nexthop
= pi
->extra
->bgp_orig
;
6246 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6247 afi
, safi
, pi
, NULL
,
6249 bgp_path_info_set_flag(dest
, pi
,
6252 if (BGP_DEBUG(nht
, NHT
)) {
6253 char buf1
[INET6_ADDRSTRLEN
];
6254 inet_ntop(p
->family
,
6258 "%s(%s): Route not in table, not advertising",
6261 bgp_path_info_unset_flag(
6262 dest
, pi
, BGP_PATH_VALID
);
6265 /* Delete the NHT structure if any, if we're
6267 * enabling/disabling import check. We
6268 * deregister the route
6269 * from NHT to avoid overloading NHT and the
6270 * process interaction
6272 bgp_unlink_nexthop(pi
);
6273 bgp_path_info_set_flag(dest
, pi
,
6276 /* Process change. */
6277 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6278 bgp_process(bgp
, dest
, afi
, safi
);
6280 if (SAFI_UNICAST
== safi
6281 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6283 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6284 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6288 bgp_dest_unlock_node(dest
);
6289 aspath_unintern(&attr
.aspath
);
6294 /* Make new BGP info. */
6295 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6297 /* Nexthop reachability check. */
6298 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6299 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6300 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6302 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6304 if (BGP_DEBUG(nht
, NHT
)) {
6305 char buf1
[INET6_ADDRSTRLEN
];
6306 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6309 "%s(%s): Route not in table, not advertising",
6312 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6315 /* Delete the NHT structure if any, if we're toggling between
6316 * enabling/disabling import check. We deregister the route
6317 * from NHT to avoid overloading NHT and the process interaction
6319 bgp_unlink_nexthop(new);
6321 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6324 /* Aggregate address increment. */
6325 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6327 /* Register new BGP information. */
6328 bgp_path_info_add(dest
, new);
6330 /* route_node_get lock */
6331 bgp_dest_unlock_node(dest
);
6333 /* Process change. */
6334 bgp_process(bgp
, dest
, afi
, safi
);
6336 if (SAFI_UNICAST
== safi
6337 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6338 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6339 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6342 /* Unintern original. */
6343 aspath_unintern(&attr
.aspath
);
6346 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6349 struct bgp_dest
*dest
;
6350 struct bgp_path_info
*pi
;
6352 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6354 /* Check selected route and self inserted route. */
6355 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6356 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6357 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6360 /* Withdraw static BGP route from routing table. */
6362 if (SAFI_UNICAST
== safi
6363 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6364 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6365 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6367 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6368 bgp_unlink_nexthop(pi
);
6369 bgp_path_info_delete(dest
, pi
);
6370 bgp_process(bgp
, dest
, afi
, safi
);
6373 /* Unlock bgp_node_lookup. */
6374 bgp_dest_unlock_node(dest
);
6378 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6380 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6381 afi_t afi
, safi_t safi
,
6382 struct prefix_rd
*prd
)
6384 struct bgp_dest
*dest
;
6385 struct bgp_path_info
*pi
;
6387 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6389 /* Check selected route and self inserted route. */
6390 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6391 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6392 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6395 /* Withdraw static BGP route from routing table. */
6397 #ifdef ENABLE_BGP_VNC
6398 rfapiProcessWithdraw(
6399 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6400 1); /* Kill, since it is an administrative change */
6402 if (SAFI_MPLS_VPN
== safi
6403 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6404 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6406 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6407 bgp_path_info_delete(dest
, pi
);
6408 bgp_process(bgp
, dest
, afi
, safi
);
6411 /* Unlock bgp_node_lookup. */
6412 bgp_dest_unlock_node(dest
);
6415 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6416 struct bgp_static
*bgp_static
, afi_t afi
,
6419 struct bgp_dest
*dest
;
6420 struct bgp_path_info
*new;
6421 struct attr
*attr_new
;
6422 struct attr attr
= {0};
6423 struct bgp_path_info
*pi
;
6424 #ifdef ENABLE_BGP_VNC
6425 mpls_label_t label
= 0;
6427 uint32_t num_labels
= 0;
6431 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6433 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6436 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6438 attr
.nexthop
= bgp_static
->igpnexthop
;
6439 attr
.med
= bgp_static
->igpmetric
;
6440 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6442 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6443 || (safi
== SAFI_ENCAP
)) {
6444 if (afi
== AFI_IP
) {
6445 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6446 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6449 if (afi
== AFI_L2VPN
) {
6450 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6451 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6452 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6453 &bgp_static
->gatewayIp
.u
.prefix4
,
6455 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6456 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6457 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6458 &bgp_static
->gatewayIp
.u
.prefix6
,
6461 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6462 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6463 struct bgp_encap_type_vxlan bet
;
6464 memset(&bet
, 0, sizeof(bet
));
6465 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6466 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6468 if (bgp_static
->router_mac
) {
6469 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6472 /* Apply route-map. */
6473 if (bgp_static
->rmap
.name
) {
6474 struct attr attr_tmp
= attr
;
6475 struct bgp_path_info rmap_path
;
6476 route_map_result_t ret
;
6478 rmap_path
.peer
= bgp
->peer_self
;
6479 rmap_path
.attr
= &attr_tmp
;
6481 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6483 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6485 bgp
->peer_self
->rmap_type
= 0;
6487 if (ret
== RMAP_DENYMATCH
) {
6488 /* Free uninterned attribute. */
6489 bgp_attr_flush(&attr_tmp
);
6491 /* Unintern original. */
6492 aspath_unintern(&attr
.aspath
);
6493 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6495 bgp_dest_unlock_node(dest
);
6499 attr_new
= bgp_attr_intern(&attr_tmp
);
6501 attr_new
= bgp_attr_intern(&attr
);
6504 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6505 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6506 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6510 if (attrhash_cmp(pi
->attr
, attr_new
)
6511 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6512 bgp_dest_unlock_node(dest
);
6513 bgp_attr_unintern(&attr_new
);
6514 aspath_unintern(&attr
.aspath
);
6517 /* The attribute is changed. */
6518 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6520 /* Rewrite BGP route information. */
6521 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6522 bgp_path_info_restore(dest
, pi
);
6524 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6525 bgp_attr_unintern(&pi
->attr
);
6526 pi
->attr
= attr_new
;
6527 pi
->uptime
= monotime(NULL
);
6528 #ifdef ENABLE_BGP_VNC
6530 label
= decode_label(&pi
->extra
->label
[0]);
6533 /* Process change. */
6534 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6535 bgp_process(bgp
, dest
, afi
, safi
);
6537 if (SAFI_MPLS_VPN
== safi
6538 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6539 vpn_leak_to_vrf_update(bgp
, pi
,
6542 #ifdef ENABLE_BGP_VNC
6543 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6544 pi
->attr
, afi
, safi
, pi
->type
,
6545 pi
->sub_type
, &label
);
6547 bgp_dest_unlock_node(dest
);
6548 aspath_unintern(&attr
.aspath
);
6554 /* Make new BGP info. */
6555 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6557 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6558 bgp_path_info_extra_get(new);
6560 new->extra
->label
[0] = bgp_static
->label
;
6561 new->extra
->num_labels
= num_labels
;
6563 #ifdef ENABLE_BGP_VNC
6564 label
= decode_label(&bgp_static
->label
);
6567 /* Aggregate address increment. */
6568 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6570 /* Register new BGP information. */
6571 bgp_path_info_add(dest
, new);
6572 /* route_node_get lock */
6573 bgp_dest_unlock_node(dest
);
6575 /* Process change. */
6576 bgp_process(bgp
, dest
, afi
, safi
);
6578 if (SAFI_MPLS_VPN
== safi
6579 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6580 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6582 #ifdef ENABLE_BGP_VNC
6583 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6584 safi
, new->type
, new->sub_type
, &label
);
6587 /* Unintern original. */
6588 aspath_unintern(&attr
.aspath
);
6591 /* Configure static BGP network. When user don't run zebra, static
6592 route should be installed as valid. */
6593 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6594 const char *ip_str
, afi_t afi
, safi_t safi
,
6595 const char *rmap
, int backdoor
, uint32_t label_index
)
6597 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6600 struct bgp_static
*bgp_static
;
6601 struct bgp_dest
*dest
;
6602 uint8_t need_update
= 0;
6604 /* Convert IP prefix string to struct prefix. */
6605 ret
= str2prefix(ip_str
, &p
);
6607 vty_out(vty
, "%% Malformed prefix\n");
6608 return CMD_WARNING_CONFIG_FAILED
;
6610 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6611 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6612 return CMD_WARNING_CONFIG_FAILED
;
6619 /* Set BGP static route configuration. */
6620 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6623 vty_out(vty
, "%% Can't find static route specified\n");
6624 return CMD_WARNING_CONFIG_FAILED
;
6627 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6629 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6630 && (label_index
!= bgp_static
->label_index
)) {
6632 "%% label-index doesn't match static route\n");
6633 bgp_dest_unlock_node(dest
);
6634 return CMD_WARNING_CONFIG_FAILED
;
6637 if ((rmap
&& bgp_static
->rmap
.name
)
6638 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6640 "%% route-map name doesn't match static route\n");
6641 bgp_dest_unlock_node(dest
);
6642 return CMD_WARNING_CONFIG_FAILED
;
6645 /* Update BGP RIB. */
6646 if (!bgp_static
->backdoor
)
6647 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6649 /* Clear configuration. */
6650 bgp_static_free(bgp_static
);
6651 bgp_dest_set_bgp_static_info(dest
, NULL
);
6652 bgp_dest_unlock_node(dest
);
6653 bgp_dest_unlock_node(dest
);
6656 /* Set BGP static route configuration. */
6657 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6658 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6660 /* Configuration change. */
6661 /* Label index cannot be changed. */
6662 if (bgp_static
->label_index
!= label_index
) {
6663 vty_out(vty
, "%% cannot change label-index\n");
6664 bgp_dest_unlock_node(dest
);
6665 return CMD_WARNING_CONFIG_FAILED
;
6668 /* Check previous routes are installed into BGP. */
6669 if (bgp_static
->valid
6670 && bgp_static
->backdoor
!= backdoor
)
6673 bgp_static
->backdoor
= backdoor
;
6676 XFREE(MTYPE_ROUTE_MAP_NAME
,
6677 bgp_static
->rmap
.name
);
6678 route_map_counter_decrement(
6679 bgp_static
->rmap
.map
);
6680 bgp_static
->rmap
.name
=
6681 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6682 bgp_static
->rmap
.map
=
6683 route_map_lookup_by_name(rmap
);
6684 route_map_counter_increment(
6685 bgp_static
->rmap
.map
);
6687 XFREE(MTYPE_ROUTE_MAP_NAME
,
6688 bgp_static
->rmap
.name
);
6689 route_map_counter_decrement(
6690 bgp_static
->rmap
.map
);
6691 bgp_static
->rmap
.map
= NULL
;
6692 bgp_static
->valid
= 0;
6694 bgp_dest_unlock_node(dest
);
6696 /* New configuration. */
6697 bgp_static
= bgp_static_new();
6698 bgp_static
->backdoor
= backdoor
;
6699 bgp_static
->valid
= 0;
6700 bgp_static
->igpmetric
= 0;
6701 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6702 bgp_static
->label_index
= label_index
;
6705 XFREE(MTYPE_ROUTE_MAP_NAME
,
6706 bgp_static
->rmap
.name
);
6707 route_map_counter_decrement(
6708 bgp_static
->rmap
.map
);
6709 bgp_static
->rmap
.name
=
6710 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6711 bgp_static
->rmap
.map
=
6712 route_map_lookup_by_name(rmap
);
6713 route_map_counter_increment(
6714 bgp_static
->rmap
.map
);
6716 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6719 bgp_static
->valid
= 1;
6721 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6723 if (!bgp_static
->backdoor
)
6724 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6730 void bgp_static_add(struct bgp
*bgp
)
6734 struct bgp_dest
*dest
;
6735 struct bgp_dest
*rm
;
6736 struct bgp_table
*table
;
6737 struct bgp_static
*bgp_static
;
6739 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6740 FOREACH_AFI_SAFI (afi
, safi
)
6741 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6742 dest
= bgp_route_next(dest
)) {
6743 if (!bgp_dest_has_bgp_path_info_data(dest
))
6746 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6747 || (safi
== SAFI_EVPN
)) {
6748 table
= bgp_dest_get_bgp_table_info(dest
);
6750 for (rm
= bgp_table_top(table
); rm
;
6751 rm
= bgp_route_next(rm
)) {
6753 bgp_dest_get_bgp_static_info(
6755 bgp_static_update_safi(
6756 bgp
, bgp_dest_get_prefix(rm
),
6757 bgp_static
, afi
, safi
);
6761 bgp
, bgp_dest_get_prefix(dest
),
6762 bgp_dest_get_bgp_static_info(dest
), afi
,
6766 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6769 /* Called from bgp_delete(). Delete all static routes from the BGP
6771 void bgp_static_delete(struct bgp
*bgp
)
6775 struct bgp_dest
*dest
;
6776 struct bgp_dest
*rm
;
6777 struct bgp_table
*table
;
6778 struct bgp_static
*bgp_static
;
6780 FOREACH_AFI_SAFI (afi
, safi
)
6781 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6782 dest
= bgp_route_next(dest
)) {
6783 if (!bgp_dest_has_bgp_path_info_data(dest
))
6786 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6787 || (safi
== SAFI_EVPN
)) {
6788 table
= bgp_dest_get_bgp_table_info(dest
);
6790 for (rm
= bgp_table_top(table
); rm
;
6791 rm
= bgp_route_next(rm
)) {
6793 bgp_dest_get_bgp_static_info(
6798 bgp_static_withdraw_safi(
6799 bgp
, bgp_dest_get_prefix(rm
),
6801 (struct prefix_rd
*)
6802 bgp_dest_get_prefix(
6804 bgp_static_free(bgp_static
);
6805 bgp_dest_set_bgp_static_info(rm
,
6807 bgp_dest_unlock_node(rm
);
6810 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6811 bgp_static_withdraw(bgp
,
6812 bgp_dest_get_prefix(dest
),
6814 bgp_static_free(bgp_static
);
6815 bgp_dest_set_bgp_static_info(dest
, NULL
);
6816 bgp_dest_unlock_node(dest
);
6821 void bgp_static_redo_import_check(struct bgp
*bgp
)
6825 struct bgp_dest
*dest
;
6826 struct bgp_dest
*rm
;
6827 struct bgp_table
*table
;
6828 struct bgp_static
*bgp_static
;
6830 /* Use this flag to force reprocessing of the route */
6831 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6832 FOREACH_AFI_SAFI (afi
, safi
) {
6833 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6834 dest
= bgp_route_next(dest
)) {
6835 if (!bgp_dest_has_bgp_path_info_data(dest
))
6838 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6839 || (safi
== SAFI_EVPN
)) {
6840 table
= bgp_dest_get_bgp_table_info(dest
);
6842 for (rm
= bgp_table_top(table
); rm
;
6843 rm
= bgp_route_next(rm
)) {
6845 bgp_dest_get_bgp_static_info(
6847 bgp_static_update_safi(
6848 bgp
, bgp_dest_get_prefix(rm
),
6849 bgp_static
, afi
, safi
);
6852 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6853 bgp_static_update(bgp
,
6854 bgp_dest_get_prefix(dest
),
6855 bgp_static
, afi
, safi
);
6859 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6862 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6865 struct bgp_table
*table
;
6866 struct bgp_dest
*dest
;
6867 struct bgp_path_info
*pi
;
6869 /* Do not install the aggregate route if BGP is in the
6870 * process of termination.
6872 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6873 || (bgp
->peer_self
== NULL
))
6876 table
= bgp
->rib
[afi
][safi
];
6877 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6878 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6879 if (pi
->peer
== bgp
->peer_self
6880 && ((pi
->type
== ZEBRA_ROUTE_BGP
6881 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6882 || (pi
->type
!= ZEBRA_ROUTE_BGP
6884 == BGP_ROUTE_REDISTRIBUTE
))) {
6885 bgp_aggregate_decrement(
6886 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6888 bgp_unlink_nexthop(pi
);
6889 bgp_path_info_delete(dest
, pi
);
6890 bgp_process(bgp
, dest
, afi
, safi
);
6897 * Purge all networks and redistributed routes from routing table.
6898 * Invoked upon the instance going down.
6900 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6905 FOREACH_AFI_SAFI (afi
, safi
)
6906 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6911 * Currently this is used to set static routes for VPN and ENCAP.
6912 * I think it can probably be factored with bgp_static_set.
6914 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6915 const char *ip_str
, const char *rd_str
,
6916 const char *label_str
, const char *rmap_str
,
6917 int evpn_type
, const char *esi
, const char *gwip
,
6918 const char *ethtag
, const char *routermac
)
6920 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6923 struct prefix_rd prd
;
6924 struct bgp_dest
*pdest
;
6925 struct bgp_dest
*dest
;
6926 struct bgp_table
*table
;
6927 struct bgp_static
*bgp_static
;
6928 mpls_label_t label
= MPLS_INVALID_LABEL
;
6929 struct prefix gw_ip
;
6931 /* validate ip prefix */
6932 ret
= str2prefix(ip_str
, &p
);
6934 vty_out(vty
, "%% Malformed prefix\n");
6935 return CMD_WARNING_CONFIG_FAILED
;
6938 if ((afi
== AFI_L2VPN
)
6939 && (bgp_build_evpn_prefix(evpn_type
,
6940 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6941 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6942 return CMD_WARNING_CONFIG_FAILED
;
6945 ret
= str2prefix_rd(rd_str
, &prd
);
6947 vty_out(vty
, "%% Malformed rd\n");
6948 return CMD_WARNING_CONFIG_FAILED
;
6952 unsigned long label_val
;
6953 label_val
= strtoul(label_str
, NULL
, 10);
6954 encode_label(label_val
, &label
);
6957 if (safi
== SAFI_EVPN
) {
6958 if (esi
&& str2esi(esi
, NULL
) == 0) {
6959 vty_out(vty
, "%% Malformed ESI\n");
6960 return CMD_WARNING_CONFIG_FAILED
;
6962 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6963 vty_out(vty
, "%% Malformed Router MAC\n");
6964 return CMD_WARNING_CONFIG_FAILED
;
6967 memset(&gw_ip
, 0, sizeof(gw_ip
));
6968 ret
= str2prefix(gwip
, &gw_ip
);
6970 vty_out(vty
, "%% Malformed GatewayIp\n");
6971 return CMD_WARNING_CONFIG_FAILED
;
6973 if ((gw_ip
.family
== AF_INET
6974 && is_evpn_prefix_ipaddr_v6(
6975 (struct prefix_evpn
*)&p
))
6976 || (gw_ip
.family
== AF_INET6
6977 && is_evpn_prefix_ipaddr_v4(
6978 (struct prefix_evpn
*)&p
))) {
6980 "%% GatewayIp family differs with IP prefix\n");
6981 return CMD_WARNING_CONFIG_FAILED
;
6985 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6986 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6987 bgp_dest_set_bgp_table_info(pdest
,
6988 bgp_table_init(bgp
, afi
, safi
));
6989 table
= bgp_dest_get_bgp_table_info(pdest
);
6991 dest
= bgp_node_get(table
, &p
);
6993 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6994 vty_out(vty
, "%% Same network configuration exists\n");
6995 bgp_dest_unlock_node(dest
);
6997 /* New configuration. */
6998 bgp_static
= bgp_static_new();
6999 bgp_static
->backdoor
= 0;
7000 bgp_static
->valid
= 0;
7001 bgp_static
->igpmetric
= 0;
7002 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7003 bgp_static
->label
= label
;
7004 bgp_static
->prd
= prd
;
7007 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7008 route_map_counter_decrement(bgp_static
->rmap
.map
);
7009 bgp_static
->rmap
.name
=
7010 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7011 bgp_static
->rmap
.map
=
7012 route_map_lookup_by_name(rmap_str
);
7013 route_map_counter_increment(bgp_static
->rmap
.map
);
7016 if (safi
== SAFI_EVPN
) {
7018 bgp_static
->eth_s_id
=
7021 str2esi(esi
, bgp_static
->eth_s_id
);
7024 bgp_static
->router_mac
=
7025 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7026 (void)prefix_str2mac(routermac
,
7027 bgp_static
->router_mac
);
7030 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7032 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7034 bgp_static
->valid
= 1;
7035 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7041 /* Configure static BGP network. */
7042 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7043 const char *ip_str
, const char *rd_str
,
7044 const char *label_str
, int evpn_type
, const char *esi
,
7045 const char *gwip
, const char *ethtag
)
7047 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7050 struct prefix_rd prd
;
7051 struct bgp_dest
*pdest
;
7052 struct bgp_dest
*dest
;
7053 struct bgp_table
*table
;
7054 struct bgp_static
*bgp_static
;
7055 mpls_label_t label
= MPLS_INVALID_LABEL
;
7057 /* Convert IP prefix string to struct prefix. */
7058 ret
= str2prefix(ip_str
, &p
);
7060 vty_out(vty
, "%% Malformed prefix\n");
7061 return CMD_WARNING_CONFIG_FAILED
;
7064 if ((afi
== AFI_L2VPN
)
7065 && (bgp_build_evpn_prefix(evpn_type
,
7066 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7067 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7068 return CMD_WARNING_CONFIG_FAILED
;
7070 ret
= str2prefix_rd(rd_str
, &prd
);
7072 vty_out(vty
, "%% Malformed rd\n");
7073 return CMD_WARNING_CONFIG_FAILED
;
7077 unsigned long label_val
;
7078 label_val
= strtoul(label_str
, NULL
, 10);
7079 encode_label(label_val
, &label
);
7082 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7083 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7084 bgp_dest_set_bgp_table_info(pdest
,
7085 bgp_table_init(bgp
, afi
, safi
));
7087 bgp_dest_unlock_node(pdest
);
7088 table
= bgp_dest_get_bgp_table_info(pdest
);
7090 dest
= bgp_node_lookup(table
, &p
);
7093 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7095 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7096 bgp_static_free(bgp_static
);
7097 bgp_dest_set_bgp_static_info(dest
, NULL
);
7098 bgp_dest_unlock_node(dest
);
7099 bgp_dest_unlock_node(dest
);
7101 vty_out(vty
, "%% Can't find the route\n");
7106 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7107 const char *rmap_name
)
7109 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7110 struct bgp_rmap
*rmap
;
7112 rmap
= &bgp
->table_map
[afi
][safi
];
7114 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7115 route_map_counter_decrement(rmap
->map
);
7116 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7117 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7118 route_map_counter_increment(rmap
->map
);
7120 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7121 route_map_counter_decrement(rmap
->map
);
7125 if (bgp_fibupd_safi(safi
))
7126 bgp_zebra_announce_table(bgp
, afi
, safi
);
7131 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7132 const char *rmap_name
)
7134 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7135 struct bgp_rmap
*rmap
;
7137 rmap
= &bgp
->table_map
[afi
][safi
];
7138 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7139 route_map_counter_decrement(rmap
->map
);
7142 if (bgp_fibupd_safi(safi
))
7143 bgp_zebra_announce_table(bgp
, afi
, safi
);
7148 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7151 if (bgp
->table_map
[afi
][safi
].name
) {
7152 vty_out(vty
, " table-map %s\n",
7153 bgp
->table_map
[afi
][safi
].name
);
7157 DEFUN (bgp_table_map
,
7160 "BGP table to RIB route download filter\n"
7161 "Name of the route map\n")
7164 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7165 argv
[idx_word
]->arg
);
7167 DEFUN (no_bgp_table_map
,
7168 no_bgp_table_map_cmd
,
7169 "no table-map WORD",
7171 "BGP table to RIB route download filter\n"
7172 "Name of the route map\n")
7175 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7176 argv
[idx_word
]->arg
);
7182 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7183 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7184 backdoor$backdoor}]",
7186 "Specify a network to announce via BGP\n"
7191 "Route-map to modify the attributes\n"
7192 "Name of the route map\n"
7193 "Label index to associate with the prefix\n"
7194 "Label index value\n"
7195 "Specify a BGP backdoor route\n")
7197 char addr_prefix_str
[BUFSIZ
];
7202 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7204 sizeof(addr_prefix_str
));
7206 vty_out(vty
, "%% Inconsistent address and mask\n");
7207 return CMD_WARNING_CONFIG_FAILED
;
7211 return bgp_static_set(
7212 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7213 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7214 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7217 DEFPY(ipv6_bgp_network
,
7218 ipv6_bgp_network_cmd
,
7219 "[no] network X:X::X:X/M$prefix \
7220 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7222 "Specify a network to announce via BGP\n"
7224 "Route-map to modify the attributes\n"
7225 "Name of the route map\n"
7226 "Label index to associate with the prefix\n"
7227 "Label index value\n")
7229 return bgp_static_set(
7230 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7231 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7234 static struct bgp_aggregate
*bgp_aggregate_new(void)
7236 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7239 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7241 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7242 route_map_counter_decrement(aggregate
->suppress_map
);
7243 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7244 route_map_counter_decrement(aggregate
->rmap
.map
);
7245 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7249 * Helper function to avoid repeated code: prepare variables for a
7250 * `route_map_apply` call.
7252 * \returns `true` on route map match, otherwise `false`.
7254 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7255 struct bgp_aggregate
*aggregate
,
7256 struct bgp_path_info
*pi
)
7258 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7259 route_map_result_t rmr
= RMAP_DENYMATCH
;
7260 struct bgp_path_info rmap_path
= {};
7261 struct attr attr
= {};
7263 /* No route map entries created, just don't match. */
7264 if (aggregate
->suppress_map
== NULL
)
7267 /* Call route map matching and return result. */
7268 attr
.aspath
= aspath_empty();
7269 rmap_path
.peer
= bgp
->peer_self
;
7270 rmap_path
.attr
= &attr
;
7272 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7273 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7274 bgp
->peer_self
->rmap_type
= 0;
7276 bgp_attr_flush(&attr
);
7277 aspath_unintern(&attr
.aspath
);
7279 return rmr
== RMAP_PERMITMATCH
;
7282 /** Test whether the aggregation has suppressed this path or not. */
7283 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7284 struct bgp_path_info
*pi
)
7286 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7289 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7293 * Suppress this path and keep the reference.
7295 * \returns `true` if needs processing otherwise `false`.
7297 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7298 struct bgp_path_info
*pi
)
7300 struct bgp_path_info_extra
*pie
;
7302 /* Path is already suppressed by this aggregation. */
7303 if (aggr_suppress_exists(aggregate
, pi
))
7306 pie
= bgp_path_info_extra_get(pi
);
7308 /* This is the first suppression, allocate memory and list it. */
7309 if (pie
->aggr_suppressors
== NULL
)
7310 pie
->aggr_suppressors
= list_new();
7312 listnode_add(pie
->aggr_suppressors
, aggregate
);
7314 /* Only mark for processing if suppressed. */
7315 if (listcount(pie
->aggr_suppressors
) == 1) {
7316 if (BGP_DEBUG(update
, UPDATE_OUT
))
7317 zlog_debug("aggregate-address suppressing: %pFX",
7318 bgp_dest_get_prefix(pi
->net
));
7320 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7328 * Unsuppress this path and remove the reference.
7330 * \returns `true` if needs processing otherwise `false`.
7332 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7333 struct bgp_path_info
*pi
)
7335 /* Path wasn't suppressed. */
7336 if (!aggr_suppress_exists(aggregate
, pi
))
7339 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7341 /* Unsuppress and free extra memory if last item. */
7342 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7343 if (BGP_DEBUG(update
, UPDATE_OUT
))
7344 zlog_debug("aggregate-address unsuppressing: %pFX",
7345 bgp_dest_get_prefix(pi
->net
));
7347 list_delete(&pi
->extra
->aggr_suppressors
);
7348 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7355 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7356 struct aspath
*aspath
,
7357 struct community
*comm
,
7358 struct ecommunity
*ecomm
,
7359 struct lcommunity
*lcomm
)
7361 static struct aspath
*ae
= NULL
;
7364 ae
= aspath_empty();
7369 if (origin
!= pi
->attr
->origin
)
7372 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7375 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7378 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7381 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7384 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7390 static void bgp_aggregate_install(
7391 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7392 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7393 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7394 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7396 struct bgp_dest
*dest
;
7397 struct bgp_table
*table
;
7398 struct bgp_path_info
*pi
, *orig
, *new;
7401 table
= bgp
->rib
[afi
][safi
];
7403 dest
= bgp_node_get(table
, p
);
7405 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7406 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7407 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7411 * If we have paths with different MEDs, then don't install
7412 * (or uninstall) the aggregate route.
7414 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7415 goto uninstall_aggregate_route
;
7417 if (aggregate
->count
> 0) {
7419 * If the aggregate information has not changed
7420 * no need to re-install it again.
7422 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7423 ecommunity
, lcommunity
)) {
7424 bgp_dest_unlock_node(dest
);
7427 aspath_free(aspath
);
7429 community_free(&community
);
7431 ecommunity_free(&ecommunity
);
7433 lcommunity_free(&lcommunity
);
7439 * Mark the old as unusable
7442 bgp_path_info_delete(dest
, pi
);
7444 attr
= bgp_attr_aggregate_intern(
7445 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7446 aggregate
, atomic_aggregate
, p
);
7449 bgp_dest_unlock_node(dest
);
7450 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7451 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7452 zlog_debug("%s: %pFX null attribute", __func__
,
7457 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7458 bgp
->peer_self
, attr
, dest
);
7460 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7462 bgp_path_info_add(dest
, new);
7463 bgp_process(bgp
, dest
, afi
, safi
);
7465 uninstall_aggregate_route
:
7466 for (pi
= orig
; pi
; pi
= pi
->next
)
7467 if (pi
->peer
== bgp
->peer_self
7468 && pi
->type
== ZEBRA_ROUTE_BGP
7469 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7472 /* Withdraw static BGP route from routing table. */
7474 bgp_path_info_delete(dest
, pi
);
7475 bgp_process(bgp
, dest
, afi
, safi
);
7479 bgp_dest_unlock_node(dest
);
7483 * Check if the current path has different MED than other known paths.
7485 * \returns `true` if the MED matched the others else `false`.
7487 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7488 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7490 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7492 /* This is the first route being analyzed. */
7493 if (!aggregate
->med_initialized
) {
7494 aggregate
->med_initialized
= true;
7495 aggregate
->med_mismatched
= false;
7496 aggregate
->med_matched_value
= cur_med
;
7498 /* Check if routes with different MED showed up. */
7499 if (cur_med
!= aggregate
->med_matched_value
)
7500 aggregate
->med_mismatched
= true;
7503 return !aggregate
->med_mismatched
;
7507 * Initializes and tests all routes in the aggregate address path for MED
7510 * \returns `true` if all MEDs are the same otherwise `false`.
7512 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7513 struct bgp
*bgp
, const struct prefix
*p
,
7514 afi_t afi
, safi_t safi
)
7516 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7517 const struct prefix
*dest_p
;
7518 struct bgp_dest
*dest
, *top
;
7519 struct bgp_path_info
*pi
;
7520 bool med_matched
= true;
7522 aggregate
->med_initialized
= false;
7524 top
= bgp_node_get(table
, p
);
7525 for (dest
= bgp_node_get(table
, p
); dest
;
7526 dest
= bgp_route_next_until(dest
, top
)) {
7527 dest_p
= bgp_dest_get_prefix(dest
);
7528 if (dest_p
->prefixlen
<= p
->prefixlen
)
7531 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7532 if (BGP_PATH_HOLDDOWN(pi
))
7534 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7536 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7537 med_matched
= false;
7544 bgp_dest_unlock_node(top
);
7550 * Toggles the route suppression status for this aggregate address
7553 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7554 struct bgp
*bgp
, const struct prefix
*p
,
7555 afi_t afi
, safi_t safi
, bool suppress
)
7557 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7558 const struct prefix
*dest_p
;
7559 struct bgp_dest
*dest
, *top
;
7560 struct bgp_path_info
*pi
;
7561 bool toggle_suppression
;
7563 /* We've found a different MED we must revert any suppressed routes. */
7564 top
= bgp_node_get(table
, p
);
7565 for (dest
= bgp_node_get(table
, p
); dest
;
7566 dest
= bgp_route_next_until(dest
, top
)) {
7567 dest_p
= bgp_dest_get_prefix(dest
);
7568 if (dest_p
->prefixlen
<= p
->prefixlen
)
7571 toggle_suppression
= false;
7572 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7573 if (BGP_PATH_HOLDDOWN(pi
))
7575 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7578 /* We are toggling suppression back. */
7580 /* Suppress route if not suppressed already. */
7581 if (aggr_suppress_path(aggregate
, pi
))
7582 toggle_suppression
= true;
7586 /* Install route if there is no more suppression. */
7587 if (aggr_unsuppress_path(aggregate
, pi
))
7588 toggle_suppression
= true;
7591 if (toggle_suppression
)
7592 bgp_process(bgp
, dest
, afi
, safi
);
7594 bgp_dest_unlock_node(top
);
7598 * Aggregate address MED matching incremental test: this function is called
7599 * when the initial aggregation occurred and we are only testing a single
7602 * In addition to testing and setting the MED validity it also installs back
7603 * suppressed routes (if summary is configured).
7605 * Must not be called in `bgp_aggregate_route`.
7607 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7608 struct bgp
*bgp
, const struct prefix
*p
,
7609 afi_t afi
, safi_t safi
,
7610 struct bgp_path_info
*pi
)
7612 /* MED matching disabled. */
7613 if (!aggregate
->match_med
)
7616 /* Aggregation with different MED, recheck if we have got equal MEDs
7619 if (aggregate
->med_mismatched
&&
7620 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7621 aggregate
->summary_only
)
7622 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7625 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7627 /* No mismatches, just quit. */
7628 if (!aggregate
->med_mismatched
)
7631 /* Route summarization is disabled. */
7632 if (!aggregate
->summary_only
)
7635 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7638 /* Update an aggregate as routes are added/removed from the BGP table */
7639 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7640 safi_t safi
, struct bgp_aggregate
*aggregate
)
7642 struct bgp_table
*table
;
7643 struct bgp_dest
*top
;
7644 struct bgp_dest
*dest
;
7646 struct aspath
*aspath
= NULL
;
7647 struct community
*community
= NULL
;
7648 struct ecommunity
*ecommunity
= NULL
;
7649 struct lcommunity
*lcommunity
= NULL
;
7650 struct bgp_path_info
*pi
;
7651 unsigned long match
= 0;
7652 uint8_t atomic_aggregate
= 0;
7654 /* If the bgp instance is being deleted or self peer is deleted
7655 * then do not create aggregate route
7657 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7658 || (bgp
->peer_self
== NULL
))
7661 /* Initialize and test routes for MED difference. */
7662 if (aggregate
->match_med
)
7663 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7666 * Reset aggregate count: we might've been called from route map
7667 * update so in that case we must retest all more specific routes.
7669 * \see `bgp_route_map_process_update`.
7671 aggregate
->count
= 0;
7672 aggregate
->incomplete_origin_count
= 0;
7673 aggregate
->incomplete_origin_count
= 0;
7674 aggregate
->egp_origin_count
= 0;
7676 /* ORIGIN attribute: If at least one route among routes that are
7677 aggregated has ORIGIN with the value INCOMPLETE, then the
7678 aggregated route must have the ORIGIN attribute with the value
7679 INCOMPLETE. Otherwise, if at least one route among routes that
7680 are aggregated has ORIGIN with the value EGP, then the aggregated
7681 route must have the origin attribute with the value EGP. In all
7682 other case the value of the ORIGIN attribute of the aggregated
7683 route is INTERNAL. */
7684 origin
= BGP_ORIGIN_IGP
;
7686 table
= bgp
->rib
[afi
][safi
];
7688 top
= bgp_node_get(table
, p
);
7689 for (dest
= bgp_node_get(table
, p
); dest
;
7690 dest
= bgp_route_next_until(dest
, top
)) {
7691 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7693 if (dest_p
->prefixlen
<= p
->prefixlen
)
7696 /* If suppress fib is enabled and route not installed
7697 * in FIB, skip the route
7699 if (!bgp_check_advertise(bgp
, dest
))
7704 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7705 if (BGP_PATH_HOLDDOWN(pi
))
7709 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7710 atomic_aggregate
= 1;
7712 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7716 * summary-only aggregate route suppress
7717 * aggregated route announcements.
7720 * Don't create summaries if MED didn't match
7721 * otherwise neither the specific routes and the
7722 * aggregation will be announced.
7724 if (aggregate
->summary_only
7725 && AGGREGATE_MED_VALID(aggregate
)) {
7726 if (aggr_suppress_path(aggregate
, pi
))
7731 * Suppress more specific routes that match the route
7735 * Don't suppress routes if MED matching is enabled and
7736 * it mismatched otherwise we might end up with no
7737 * routes for this path.
7739 if (aggregate
->suppress_map_name
7740 && AGGREGATE_MED_VALID(aggregate
)
7741 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7742 if (aggr_suppress_path(aggregate
, pi
))
7749 * If at least one route among routes that are
7750 * aggregated has ORIGIN with the value INCOMPLETE,
7751 * then the aggregated route MUST have the ORIGIN
7752 * attribute with the value INCOMPLETE. Otherwise, if
7753 * at least one route among routes that are aggregated
7754 * has ORIGIN with the value EGP, then the aggregated
7755 * route MUST have the ORIGIN attribute with the value
7758 switch (pi
->attr
->origin
) {
7759 case BGP_ORIGIN_INCOMPLETE
:
7760 aggregate
->incomplete_origin_count
++;
7762 case BGP_ORIGIN_EGP
:
7763 aggregate
->egp_origin_count
++;
7771 if (!aggregate
->as_set
)
7775 * as-set aggregate route generate origin, as path,
7776 * and community aggregation.
7778 /* Compute aggregate route's as-path.
7780 bgp_compute_aggregate_aspath_hash(aggregate
,
7783 /* Compute aggregate route's community.
7785 if (bgp_attr_get_community(pi
->attr
))
7786 bgp_compute_aggregate_community_hash(
7788 bgp_attr_get_community(pi
->attr
));
7790 /* Compute aggregate route's extended community.
7792 if (bgp_attr_get_ecommunity(pi
->attr
))
7793 bgp_compute_aggregate_ecommunity_hash(
7795 bgp_attr_get_ecommunity(pi
->attr
));
7797 /* Compute aggregate route's large community.
7799 if (bgp_attr_get_lcommunity(pi
->attr
))
7800 bgp_compute_aggregate_lcommunity_hash(
7802 bgp_attr_get_lcommunity(pi
->attr
));
7805 bgp_process(bgp
, dest
, afi
, safi
);
7807 if (aggregate
->as_set
) {
7808 bgp_compute_aggregate_aspath_val(aggregate
);
7809 bgp_compute_aggregate_community_val(aggregate
);
7810 bgp_compute_aggregate_ecommunity_val(aggregate
);
7811 bgp_compute_aggregate_lcommunity_val(aggregate
);
7815 bgp_dest_unlock_node(top
);
7818 if (aggregate
->incomplete_origin_count
> 0)
7819 origin
= BGP_ORIGIN_INCOMPLETE
;
7820 else if (aggregate
->egp_origin_count
> 0)
7821 origin
= BGP_ORIGIN_EGP
;
7823 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7824 origin
= aggregate
->origin
;
7826 if (aggregate
->as_set
) {
7827 if (aggregate
->aspath
)
7828 /* Retrieve aggregate route's as-path.
7830 aspath
= aspath_dup(aggregate
->aspath
);
7832 if (aggregate
->community
)
7833 /* Retrieve aggregate route's community.
7835 community
= community_dup(aggregate
->community
);
7837 if (aggregate
->ecommunity
)
7838 /* Retrieve aggregate route's ecommunity.
7840 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7842 if (aggregate
->lcommunity
)
7843 /* Retrieve aggregate route's lcommunity.
7845 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7848 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7849 ecommunity
, lcommunity
, atomic_aggregate
,
7853 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7854 safi_t safi
, struct bgp_aggregate
*aggregate
)
7856 struct bgp_table
*table
;
7857 struct bgp_dest
*top
;
7858 struct bgp_dest
*dest
;
7859 struct bgp_path_info
*pi
;
7860 unsigned long match
;
7862 table
= bgp
->rib
[afi
][safi
];
7864 /* If routes exists below this node, generate aggregate routes. */
7865 top
= bgp_node_get(table
, p
);
7866 for (dest
= bgp_node_get(table
, p
); dest
;
7867 dest
= bgp_route_next_until(dest
, top
)) {
7868 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7870 if (dest_p
->prefixlen
<= p
->prefixlen
)
7874 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7875 if (BGP_PATH_HOLDDOWN(pi
))
7878 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7882 * This route is suppressed: attempt to unsuppress it.
7884 * `aggr_unsuppress_path` will fail if this particular
7885 * aggregate route was not the suppressor.
7887 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7888 listcount(pi
->extra
->aggr_suppressors
)) {
7889 if (aggr_unsuppress_path(aggregate
, pi
))
7895 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7896 aggregate
->incomplete_origin_count
--;
7897 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7898 aggregate
->egp_origin_count
--;
7900 if (aggregate
->as_set
) {
7901 /* Remove as-path from aggregate.
7903 bgp_remove_aspath_from_aggregate_hash(
7907 if (bgp_attr_get_community(pi
->attr
))
7908 /* Remove community from aggregate.
7910 bgp_remove_comm_from_aggregate_hash(
7912 bgp_attr_get_community(
7915 if (bgp_attr_get_ecommunity(pi
->attr
))
7916 /* Remove ecommunity from aggregate.
7918 bgp_remove_ecomm_from_aggregate_hash(
7920 bgp_attr_get_ecommunity(
7923 if (bgp_attr_get_lcommunity(pi
->attr
))
7924 /* Remove lcommunity from aggregate.
7926 bgp_remove_lcomm_from_aggregate_hash(
7928 bgp_attr_get_lcommunity(
7933 /* If this node was suppressed, process the change. */
7935 bgp_process(bgp
, dest
, afi
, safi
);
7937 if (aggregate
->as_set
) {
7938 aspath_free(aggregate
->aspath
);
7939 aggregate
->aspath
= NULL
;
7940 if (aggregate
->community
)
7941 community_free(&aggregate
->community
);
7942 if (aggregate
->ecommunity
)
7943 ecommunity_free(&aggregate
->ecommunity
);
7944 if (aggregate
->lcommunity
)
7945 lcommunity_free(&aggregate
->lcommunity
);
7948 bgp_dest_unlock_node(top
);
7951 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7952 const struct prefix
*aggr_p
,
7953 struct bgp_path_info
*pinew
, afi_t afi
,
7955 struct bgp_aggregate
*aggregate
)
7958 struct aspath
*aspath
= NULL
;
7959 uint8_t atomic_aggregate
= 0;
7960 struct community
*community
= NULL
;
7961 struct ecommunity
*ecommunity
= NULL
;
7962 struct lcommunity
*lcommunity
= NULL
;
7964 /* If the bgp instance is being deleted or self peer is deleted
7965 * then do not create aggregate route
7967 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7968 || (bgp
->peer_self
== NULL
))
7971 /* ORIGIN attribute: If at least one route among routes that are
7972 * aggregated has ORIGIN with the value INCOMPLETE, then the
7973 * aggregated route must have the ORIGIN attribute with the value
7974 * INCOMPLETE. Otherwise, if at least one route among routes that
7975 * are aggregated has ORIGIN with the value EGP, then the aggregated
7976 * route must have the origin attribute with the value EGP. In all
7977 * other case the value of the ORIGIN attribute of the aggregated
7978 * route is INTERNAL.
7980 origin
= BGP_ORIGIN_IGP
;
7985 * This must be called before `summary` check to avoid
7986 * "suppressing" twice.
7988 if (aggregate
->match_med
)
7989 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7992 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7993 aggr_suppress_path(aggregate
, pinew
);
7995 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7996 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7997 aggr_suppress_path(aggregate
, pinew
);
7999 switch (pinew
->attr
->origin
) {
8000 case BGP_ORIGIN_INCOMPLETE
:
8001 aggregate
->incomplete_origin_count
++;
8003 case BGP_ORIGIN_EGP
:
8004 aggregate
->egp_origin_count
++;
8012 if (aggregate
->incomplete_origin_count
> 0)
8013 origin
= BGP_ORIGIN_INCOMPLETE
;
8014 else if (aggregate
->egp_origin_count
> 0)
8015 origin
= BGP_ORIGIN_EGP
;
8017 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8018 origin
= aggregate
->origin
;
8020 if (aggregate
->as_set
) {
8021 /* Compute aggregate route's as-path.
8023 bgp_compute_aggregate_aspath(aggregate
,
8024 pinew
->attr
->aspath
);
8026 /* Compute aggregate route's community.
8028 if (bgp_attr_get_community(pinew
->attr
))
8029 bgp_compute_aggregate_community(
8030 aggregate
, bgp_attr_get_community(pinew
->attr
));
8032 /* Compute aggregate route's extended community.
8034 if (bgp_attr_get_ecommunity(pinew
->attr
))
8035 bgp_compute_aggregate_ecommunity(
8037 bgp_attr_get_ecommunity(pinew
->attr
));
8039 /* Compute aggregate route's large community.
8041 if (bgp_attr_get_lcommunity(pinew
->attr
))
8042 bgp_compute_aggregate_lcommunity(
8044 bgp_attr_get_lcommunity(pinew
->attr
));
8046 /* Retrieve aggregate route's as-path.
8048 if (aggregate
->aspath
)
8049 aspath
= aspath_dup(aggregate
->aspath
);
8051 /* Retrieve aggregate route's community.
8053 if (aggregate
->community
)
8054 community
= community_dup(aggregate
->community
);
8056 /* Retrieve aggregate route's ecommunity.
8058 if (aggregate
->ecommunity
)
8059 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8061 /* Retrieve aggregate route's lcommunity.
8063 if (aggregate
->lcommunity
)
8064 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8067 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8068 aspath
, community
, ecommunity
,
8069 lcommunity
, atomic_aggregate
, aggregate
);
8072 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8074 struct bgp_path_info
*pi
,
8075 struct bgp_aggregate
*aggregate
,
8076 const struct prefix
*aggr_p
)
8079 struct aspath
*aspath
= NULL
;
8080 uint8_t atomic_aggregate
= 0;
8081 struct community
*community
= NULL
;
8082 struct ecommunity
*ecommunity
= NULL
;
8083 struct lcommunity
*lcommunity
= NULL
;
8084 unsigned long match
= 0;
8086 /* If the bgp instance is being deleted or self peer is deleted
8087 * then do not create aggregate route
8089 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8090 || (bgp
->peer_self
== NULL
))
8093 if (BGP_PATH_HOLDDOWN(pi
))
8096 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8099 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8100 if (aggr_unsuppress_path(aggregate
, pi
))
8103 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8104 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8105 if (aggr_unsuppress_path(aggregate
, pi
))
8109 * This must be called after `summary`, `suppress-map` check to avoid
8110 * "unsuppressing" twice.
8112 if (aggregate
->match_med
)
8113 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8115 if (aggregate
->count
> 0)
8118 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8119 aggregate
->incomplete_origin_count
--;
8120 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8121 aggregate
->egp_origin_count
--;
8123 if (aggregate
->as_set
) {
8124 /* Remove as-path from aggregate.
8126 bgp_remove_aspath_from_aggregate(aggregate
,
8129 if (bgp_attr_get_community(pi
->attr
))
8130 /* Remove community from aggregate.
8132 bgp_remove_community_from_aggregate(
8133 aggregate
, bgp_attr_get_community(pi
->attr
));
8135 if (bgp_attr_get_ecommunity(pi
->attr
))
8136 /* Remove ecommunity from aggregate.
8138 bgp_remove_ecommunity_from_aggregate(
8139 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8141 if (bgp_attr_get_lcommunity(pi
->attr
))
8142 /* Remove lcommunity from aggregate.
8144 bgp_remove_lcommunity_from_aggregate(
8145 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8148 /* If this node was suppressed, process the change. */
8150 bgp_process(bgp
, pi
->net
, afi
, safi
);
8152 origin
= BGP_ORIGIN_IGP
;
8153 if (aggregate
->incomplete_origin_count
> 0)
8154 origin
= BGP_ORIGIN_INCOMPLETE
;
8155 else if (aggregate
->egp_origin_count
> 0)
8156 origin
= BGP_ORIGIN_EGP
;
8158 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8159 origin
= aggregate
->origin
;
8161 if (aggregate
->as_set
) {
8162 /* Retrieve aggregate route's as-path.
8164 if (aggregate
->aspath
)
8165 aspath
= aspath_dup(aggregate
->aspath
);
8167 /* Retrieve aggregate route's community.
8169 if (aggregate
->community
)
8170 community
= community_dup(aggregate
->community
);
8172 /* Retrieve aggregate route's ecommunity.
8174 if (aggregate
->ecommunity
)
8175 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8177 /* Retrieve aggregate route's lcommunity.
8179 if (aggregate
->lcommunity
)
8180 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8183 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8184 aspath
, community
, ecommunity
,
8185 lcommunity
, atomic_aggregate
, aggregate
);
8188 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8189 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8191 struct bgp_dest
*child
;
8192 struct bgp_dest
*dest
;
8193 struct bgp_aggregate
*aggregate
;
8194 struct bgp_table
*table
;
8196 table
= bgp
->aggregate
[afi
][safi
];
8198 /* No aggregates configured. */
8199 if (bgp_table_top_nolock(table
) == NULL
)
8202 if (p
->prefixlen
== 0)
8205 if (BGP_PATH_HOLDDOWN(pi
))
8208 /* If suppress fib is enabled and route not installed
8209 * in FIB, do not update the aggregate route
8211 if (!bgp_check_advertise(bgp
, pi
->net
))
8214 child
= bgp_node_get(table
, p
);
8216 /* Aggregate address configuration check. */
8217 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8218 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8220 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8221 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8222 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8226 bgp_dest_unlock_node(child
);
8229 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8230 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8232 struct bgp_dest
*child
;
8233 struct bgp_dest
*dest
;
8234 struct bgp_aggregate
*aggregate
;
8235 struct bgp_table
*table
;
8237 table
= bgp
->aggregate
[afi
][safi
];
8239 /* No aggregates configured. */
8240 if (bgp_table_top_nolock(table
) == NULL
)
8243 if (p
->prefixlen
== 0)
8246 child
= bgp_node_get(table
, p
);
8248 /* Aggregate address configuration check. */
8249 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8250 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8252 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8253 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8254 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8258 bgp_dest_unlock_node(child
);
8261 /* Aggregate route attribute. */
8262 #define AGGREGATE_SUMMARY_ONLY 1
8263 #define AGGREGATE_AS_SET 1
8264 #define AGGREGATE_AS_UNSET 0
8266 static const char *bgp_origin2str(uint8_t origin
)
8269 case BGP_ORIGIN_IGP
:
8271 case BGP_ORIGIN_EGP
:
8273 case BGP_ORIGIN_INCOMPLETE
:
8274 return "incomplete";
8279 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8282 case RPKI_NOT_BEING_USED
:
8292 assert(!"We should never get here this is a dev escape");
8296 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8297 afi_t afi
, safi_t safi
)
8299 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8302 struct bgp_dest
*dest
;
8303 struct bgp_aggregate
*aggregate
;
8305 /* Convert string to prefix structure. */
8306 ret
= str2prefix(prefix_str
, &p
);
8308 vty_out(vty
, "Malformed prefix\n");
8309 return CMD_WARNING_CONFIG_FAILED
;
8313 /* Old configuration check. */
8314 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8317 "%% There is no aggregate-address configuration.\n");
8318 return CMD_WARNING_CONFIG_FAILED
;
8321 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8322 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8323 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8324 NULL
, NULL
, 0, aggregate
);
8326 /* Unlock aggregate address configuration. */
8327 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8329 if (aggregate
->community
)
8330 community_free(&aggregate
->community
);
8332 if (aggregate
->community_hash
) {
8333 /* Delete all communities in the hash.
8335 hash_clean(aggregate
->community_hash
,
8336 bgp_aggr_community_remove
);
8337 /* Free up the community_hash.
8339 hash_free(aggregate
->community_hash
);
8342 if (aggregate
->ecommunity
)
8343 ecommunity_free(&aggregate
->ecommunity
);
8345 if (aggregate
->ecommunity_hash
) {
8346 /* Delete all ecommunities in the hash.
8348 hash_clean(aggregate
->ecommunity_hash
,
8349 bgp_aggr_ecommunity_remove
);
8350 /* Free up the ecommunity_hash.
8352 hash_free(aggregate
->ecommunity_hash
);
8355 if (aggregate
->lcommunity
)
8356 lcommunity_free(&aggregate
->lcommunity
);
8358 if (aggregate
->lcommunity_hash
) {
8359 /* Delete all lcommunities in the hash.
8361 hash_clean(aggregate
->lcommunity_hash
,
8362 bgp_aggr_lcommunity_remove
);
8363 /* Free up the lcommunity_hash.
8365 hash_free(aggregate
->lcommunity_hash
);
8368 if (aggregate
->aspath
)
8369 aspath_free(aggregate
->aspath
);
8371 if (aggregate
->aspath_hash
) {
8372 /* Delete all as-paths in the hash.
8374 hash_clean(aggregate
->aspath_hash
,
8375 bgp_aggr_aspath_remove
);
8376 /* Free up the aspath_hash.
8378 hash_free(aggregate
->aspath_hash
);
8381 bgp_aggregate_free(aggregate
);
8382 bgp_dest_unlock_node(dest
);
8383 bgp_dest_unlock_node(dest
);
8388 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8389 safi_t safi
, const char *rmap
,
8390 uint8_t summary_only
, uint8_t as_set
,
8391 uint8_t origin
, bool match_med
,
8392 const char *suppress_map
)
8394 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8397 struct bgp_dest
*dest
;
8398 struct bgp_aggregate
*aggregate
;
8399 uint8_t as_set_new
= as_set
;
8401 if (suppress_map
&& summary_only
) {
8403 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8404 return CMD_WARNING_CONFIG_FAILED
;
8407 /* Convert string to prefix structure. */
8408 ret
= str2prefix(prefix_str
, &p
);
8410 vty_out(vty
, "Malformed prefix\n");
8411 return CMD_WARNING_CONFIG_FAILED
;
8415 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8416 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8417 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8419 return CMD_WARNING_CONFIG_FAILED
;
8422 /* Old configuration check. */
8423 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8424 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8427 vty_out(vty
, "There is already same aggregate network.\n");
8428 /* try to remove the old entry */
8429 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8431 vty_out(vty
, "Error deleting aggregate.\n");
8432 bgp_dest_unlock_node(dest
);
8433 return CMD_WARNING_CONFIG_FAILED
;
8437 /* Make aggregate address structure. */
8438 aggregate
= bgp_aggregate_new();
8439 aggregate
->summary_only
= summary_only
;
8440 aggregate
->match_med
= match_med
;
8442 /* Network operators MUST NOT locally generate any new
8443 * announcements containing AS_SET or AS_CONFED_SET. If they have
8444 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8445 * SHOULD withdraw those routes and re-announce routes for the
8446 * aggregate or component prefixes (i.e., the more-specific routes
8447 * subsumed by the previously aggregated route) without AS_SET
8448 * or AS_CONFED_SET in the updates.
8450 if (bgp
->reject_as_sets
) {
8451 if (as_set
== AGGREGATE_AS_SET
) {
8452 as_set_new
= AGGREGATE_AS_UNSET
;
8454 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8457 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8461 aggregate
->as_set
= as_set_new
;
8462 aggregate
->safi
= safi
;
8463 /* Override ORIGIN attribute if defined.
8464 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8465 * to IGP which is not what rfc4271 says.
8466 * This enables the same behavior, optionally.
8468 aggregate
->origin
= origin
;
8471 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8472 route_map_counter_decrement(aggregate
->rmap
.map
);
8473 aggregate
->rmap
.name
=
8474 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8475 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8476 route_map_counter_increment(aggregate
->rmap
.map
);
8480 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8481 route_map_counter_decrement(aggregate
->suppress_map
);
8483 aggregate
->suppress_map_name
=
8484 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8485 aggregate
->suppress_map
=
8486 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8487 route_map_counter_increment(aggregate
->suppress_map
);
8490 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8492 /* Aggregate address insert into BGP routing table. */
8493 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8498 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8499 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8501 "|summary-only$summary_only"
8502 "|route-map RMAP_NAME$rmap_name"
8503 "|origin <egp|igp|incomplete>$origin_s"
8504 "|matching-MED-only$match_med"
8505 "|suppress-map RMAP_NAME$suppress_map"
8508 "Configure BGP aggregate entries\n"
8509 "Aggregate prefix\n"
8510 "Aggregate address\n"
8512 "Generate AS set path information\n"
8513 "Filter more specific routes from updates\n"
8514 "Apply route map to aggregate network\n"
8519 "Unknown heritage\n"
8520 "Only aggregate routes with matching MED\n"
8521 "Suppress the selected more specific routes\n"
8522 "Route map with the route selectors\n")
8524 const char *prefix_s
= NULL
;
8525 safi_t safi
= bgp_node_safi(vty
);
8526 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8527 int as_set
= AGGREGATE_AS_UNSET
;
8528 char prefix_buf
[PREFIX2STR_BUFFER
];
8531 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8534 vty_out(vty
, "%% Inconsistent address and mask\n");
8535 return CMD_WARNING_CONFIG_FAILED
;
8537 prefix_s
= prefix_buf
;
8539 prefix_s
= prefix_str
;
8542 if (strcmp(origin_s
, "egp") == 0)
8543 origin
= BGP_ORIGIN_EGP
;
8544 else if (strcmp(origin_s
, "igp") == 0)
8545 origin
= BGP_ORIGIN_IGP
;
8546 else if (strcmp(origin_s
, "incomplete") == 0)
8547 origin
= BGP_ORIGIN_INCOMPLETE
;
8551 as_set
= AGGREGATE_AS_SET
;
8553 /* Handle configuration removal, otherwise installation. */
8555 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8557 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8558 summary_only
!= NULL
, as_set
, origin
,
8559 match_med
!= NULL
, suppress_map
);
8562 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8563 "[no] aggregate-address X:X::X:X/M$prefix [{"
8565 "|summary-only$summary_only"
8566 "|route-map RMAP_NAME$rmap_name"
8567 "|origin <egp|igp|incomplete>$origin_s"
8568 "|matching-MED-only$match_med"
8569 "|suppress-map RMAP_NAME$suppress_map"
8572 "Configure BGP aggregate entries\n"
8573 "Aggregate prefix\n"
8574 "Generate AS set path information\n"
8575 "Filter more specific routes from updates\n"
8576 "Apply route map to aggregate network\n"
8581 "Unknown heritage\n"
8582 "Only aggregate routes with matching MED\n"
8583 "Suppress the selected more specific routes\n"
8584 "Route map with the route selectors\n")
8586 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8587 int as_set
= AGGREGATE_AS_UNSET
;
8590 if (strcmp(origin_s
, "egp") == 0)
8591 origin
= BGP_ORIGIN_EGP
;
8592 else if (strcmp(origin_s
, "igp") == 0)
8593 origin
= BGP_ORIGIN_IGP
;
8594 else if (strcmp(origin_s
, "incomplete") == 0)
8595 origin
= BGP_ORIGIN_INCOMPLETE
;
8599 as_set
= AGGREGATE_AS_SET
;
8601 /* Handle configuration removal, otherwise installation. */
8603 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8606 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8607 rmap_name
, summary_only
!= NULL
, as_set
,
8608 origin
, match_med
!= NULL
, suppress_map
);
8611 /* Redistribute route treatment. */
8612 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8613 const union g_addr
*nexthop
, ifindex_t ifindex
,
8614 enum nexthop_types_t nhtype
, uint8_t distance
,
8615 enum blackhole_type bhtype
, uint32_t metric
,
8616 uint8_t type
, unsigned short instance
,
8619 struct bgp_path_info
*new;
8620 struct bgp_path_info
*bpi
;
8621 struct bgp_path_info rmap_path
;
8622 struct bgp_dest
*bn
;
8624 struct attr
*new_attr
;
8626 route_map_result_t ret
;
8627 struct bgp_redist
*red
;
8629 /* Make default attribute. */
8630 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8632 * This must not be NULL to satisfy Coverity SA
8634 assert(attr
.aspath
);
8637 case NEXTHOP_TYPE_IFINDEX
:
8638 switch (p
->family
) {
8640 attr
.nexthop
.s_addr
= INADDR_ANY
;
8641 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8644 memset(&attr
.mp_nexthop_global
, 0,
8645 sizeof(attr
.mp_nexthop_global
));
8646 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8650 case NEXTHOP_TYPE_IPV4
:
8651 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8652 attr
.nexthop
= nexthop
->ipv4
;
8653 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8655 case NEXTHOP_TYPE_IPV6
:
8656 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8657 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8658 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8660 case NEXTHOP_TYPE_BLACKHOLE
:
8661 switch (p
->family
) {
8663 attr
.nexthop
.s_addr
= INADDR_ANY
;
8664 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8667 memset(&attr
.mp_nexthop_global
, 0,
8668 sizeof(attr
.mp_nexthop_global
));
8669 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8672 attr
.bh_type
= bhtype
;
8675 attr
.nh_type
= nhtype
;
8676 attr
.nh_ifindex
= ifindex
;
8679 attr
.distance
= distance
;
8680 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8683 afi
= family2afi(p
->family
);
8685 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8687 struct attr attr_new
;
8689 /* Copy attribute for modification. */
8692 if (red
->redist_metric_flag
)
8693 attr_new
.med
= red
->redist_metric
;
8695 /* Apply route-map. */
8696 if (red
->rmap
.name
) {
8697 memset(&rmap_path
, 0, sizeof(rmap_path
));
8698 rmap_path
.peer
= bgp
->peer_self
;
8699 rmap_path
.attr
= &attr_new
;
8701 SET_FLAG(bgp
->peer_self
->rmap_type
,
8702 PEER_RMAP_TYPE_REDISTRIBUTE
);
8704 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8706 bgp
->peer_self
->rmap_type
= 0;
8708 if (ret
== RMAP_DENYMATCH
) {
8709 /* Free uninterned attribute. */
8710 bgp_attr_flush(&attr_new
);
8712 /* Unintern original. */
8713 aspath_unintern(&attr
.aspath
);
8714 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8719 if (bgp_in_graceful_shutdown(bgp
))
8720 bgp_attr_add_gshut_community(&attr_new
);
8722 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8723 SAFI_UNICAST
, p
, NULL
);
8725 new_attr
= bgp_attr_intern(&attr_new
);
8727 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8728 if (bpi
->peer
== bgp
->peer_self
8729 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8733 /* Ensure the (source route) type is updated. */
8735 if (attrhash_cmp(bpi
->attr
, new_attr
)
8736 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8737 bgp_attr_unintern(&new_attr
);
8738 aspath_unintern(&attr
.aspath
);
8739 bgp_dest_unlock_node(bn
);
8742 /* The attribute is changed. */
8743 bgp_path_info_set_flag(bn
, bpi
,
8744 BGP_PATH_ATTR_CHANGED
);
8746 /* Rewrite BGP route information. */
8747 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8748 bgp_path_info_restore(bn
, bpi
);
8750 bgp_aggregate_decrement(
8751 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8752 bgp_attr_unintern(&bpi
->attr
);
8753 bpi
->attr
= new_attr
;
8754 bpi
->uptime
= monotime(NULL
);
8756 /* Process change. */
8757 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8759 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8760 bgp_dest_unlock_node(bn
);
8761 aspath_unintern(&attr
.aspath
);
8763 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8765 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8767 vpn_leak_from_vrf_update(
8768 bgp_get_default(), bgp
, bpi
);
8774 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8775 bgp
->peer_self
, new_attr
, bn
);
8776 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8778 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8779 bgp_path_info_add(bn
, new);
8780 bgp_dest_unlock_node(bn
);
8781 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8782 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8784 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8785 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8787 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8791 /* Unintern original. */
8792 aspath_unintern(&attr
.aspath
);
8795 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8796 unsigned short instance
)
8799 struct bgp_dest
*dest
;
8800 struct bgp_path_info
*pi
;
8801 struct bgp_redist
*red
;
8803 afi
= family2afi(p
->family
);
8805 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8807 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8808 SAFI_UNICAST
, p
, NULL
);
8810 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8811 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8815 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8816 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8818 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8821 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8822 bgp_path_info_delete(dest
, pi
);
8823 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8825 bgp_dest_unlock_node(dest
);
8829 /* Withdraw specified route type's route. */
8830 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8831 unsigned short instance
)
8833 struct bgp_dest
*dest
;
8834 struct bgp_path_info
*pi
;
8835 struct bgp_table
*table
;
8837 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8839 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8840 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8841 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8842 && pi
->instance
== instance
)
8846 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8847 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8849 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8852 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8853 pi
, afi
, SAFI_UNICAST
);
8854 bgp_path_info_delete(dest
, pi
);
8855 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8860 /* Static function to display route. */
8861 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8862 struct vty
*vty
, json_object
*json
, bool wide
)
8867 if (p
->family
== AF_INET
) {
8869 len
= vty_out(vty
, "%pFX", p
);
8871 json_object_string_add(json
, "prefix",
8872 inet_ntop(p
->family
,
8875 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8876 json_object_string_addf(json
, "network", "%pFX", p
);
8877 json_object_int_add(json
, "version", dest
->version
);
8879 } else if (p
->family
== AF_ETHERNET
) {
8880 len
= vty_out(vty
, "%pFX", p
);
8881 } else if (p
->family
== AF_EVPN
) {
8883 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8885 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8886 } else if (p
->family
== AF_FLOWSPEC
) {
8887 route_vty_out_flowspec(vty
, p
, NULL
,
8889 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8890 NLRI_STRING_FORMAT_MIN
, json
);
8893 len
= vty_out(vty
, "%pFX", p
);
8895 json_object_string_add(json
, "prefix",
8896 inet_ntop(p
->family
,
8899 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8900 json_object_string_addf(json
, "network", "%pFX", p
);
8901 json_object_int_add(json
, "version", dest
->version
);
8906 len
= wide
? (45 - len
) : (17 - len
);
8908 vty_out(vty
, "\n%*s", 20, " ");
8910 vty_out(vty
, "%*s", len
, " ");
8914 enum bgp_display_type
{
8918 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8921 case bgp_path_selection_none
:
8922 return "Nothing to Select";
8923 case bgp_path_selection_first
:
8924 return "First path received";
8925 case bgp_path_selection_evpn_sticky_mac
:
8926 return "EVPN Sticky Mac";
8927 case bgp_path_selection_evpn_seq
:
8928 return "EVPN sequence number";
8929 case bgp_path_selection_evpn_lower_ip
:
8930 return "EVPN lower IP";
8931 case bgp_path_selection_evpn_local_path
:
8932 return "EVPN local ES path";
8933 case bgp_path_selection_evpn_non_proxy
:
8934 return "EVPN non proxy";
8935 case bgp_path_selection_weight
:
8937 case bgp_path_selection_local_pref
:
8938 return "Local Pref";
8939 case bgp_path_selection_accept_own
:
8940 return "Accept Own";
8941 case bgp_path_selection_local_route
:
8942 return "Local Route";
8943 case bgp_path_selection_confed_as_path
:
8944 return "Confederation based AS Path";
8945 case bgp_path_selection_as_path
:
8947 case bgp_path_selection_origin
:
8949 case bgp_path_selection_med
:
8951 case bgp_path_selection_peer
:
8953 case bgp_path_selection_confed
:
8954 return "Confed Peer Type";
8955 case bgp_path_selection_igp_metric
:
8956 return "IGP Metric";
8957 case bgp_path_selection_older
:
8958 return "Older Path";
8959 case bgp_path_selection_router_id
:
8961 case bgp_path_selection_cluster_length
:
8962 return "Cluster length";
8963 case bgp_path_selection_stale
:
8964 return "Path Staleness";
8965 case bgp_path_selection_local_configured
:
8966 return "Locally configured route";
8967 case bgp_path_selection_neighbor_ip
:
8968 return "Neighbor IP";
8969 case bgp_path_selection_default
:
8970 return "Nothing left to compare";
8972 return "Invalid (internal error)";
8975 /* Print the short form route status for a bgp_path_info */
8976 static void route_vty_short_status_out(struct vty
*vty
,
8977 struct bgp_path_info
*path
,
8978 const struct prefix
*p
,
8979 json_object
*json_path
)
8981 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8985 /* Route status display. */
8986 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8987 json_object_boolean_true_add(json_path
, "removed");
8989 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8990 json_object_boolean_true_add(json_path
, "stale");
8992 if (path
->extra
&& bgp_path_suppressed(path
))
8993 json_object_boolean_true_add(json_path
, "suppressed");
8995 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8996 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8997 json_object_boolean_true_add(json_path
, "valid");
9000 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9001 json_object_boolean_true_add(json_path
, "history");
9003 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9004 json_object_boolean_true_add(json_path
, "damped");
9006 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9007 json_object_boolean_true_add(json_path
, "bestpath");
9008 json_object_string_add(json_path
, "selectionReason",
9009 bgp_path_selection_reason2str(
9010 path
->net
->reason
));
9013 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9014 json_object_boolean_true_add(json_path
, "multipath");
9016 /* Internal route. */
9017 if ((path
->peer
->as
)
9018 && (path
->peer
->as
== path
->peer
->local_as
))
9019 json_object_string_add(json_path
, "pathFrom",
9022 json_object_string_add(json_path
, "pathFrom",
9028 /* RPKI validation state */
9030 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9032 if (rpki_state
== RPKI_VALID
)
9034 else if (rpki_state
== RPKI_INVALID
)
9036 else if (rpki_state
== RPKI_NOTFOUND
)
9039 /* Route status display. */
9040 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9042 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9044 else if (bgp_path_suppressed(path
))
9046 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9047 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9053 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9055 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9057 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9059 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9064 /* Internal route. */
9065 if (path
->peer
&& (path
->peer
->as
)
9066 && (path
->peer
->as
== path
->peer
->local_as
))
9072 static char *bgp_nexthop_hostname(struct peer
*peer
,
9073 struct bgp_nexthop_cache
*bnc
)
9076 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9077 return peer
->hostname
;
9081 /* called from terminal list command */
9082 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9083 struct bgp_path_info
*path
, int display
, safi_t safi
,
9084 json_object
*json_paths
, bool wide
)
9087 struct attr
*attr
= path
->attr
;
9088 json_object
*json_path
= NULL
;
9089 json_object
*json_nexthops
= NULL
;
9090 json_object
*json_nexthop_global
= NULL
;
9091 json_object
*json_nexthop_ll
= NULL
;
9092 json_object
*json_ext_community
= NULL
;
9093 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9095 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9096 bool nexthop_othervrf
= false;
9097 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9098 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9099 char *nexthop_hostname
=
9100 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9101 char esi_buf
[ESI_STR_LEN
];
9104 json_path
= json_object_new_object();
9106 /* short status lead text */
9107 route_vty_short_status_out(vty
, path
, p
, json_path
);
9110 /* print prefix and mask */
9112 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9114 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9116 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9120 * If vrf id of nexthop is different from that of prefix,
9121 * set up printable string to append
9123 if (path
->extra
&& path
->extra
->bgp_orig
) {
9124 const char *self
= "";
9129 nexthop_othervrf
= true;
9130 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9132 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9133 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9134 "@%s%s", VRFID_NONE_STR
, self
);
9136 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9137 path
->extra
->bgp_orig
->vrf_id
, self
);
9139 if (path
->extra
->bgp_orig
->inst_type
9140 != BGP_INSTANCE_TYPE_DEFAULT
)
9142 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9144 const char *self
= "";
9149 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9153 * For ENCAP and EVPN routes, nexthop address family is not
9154 * neccessarily the same as the prefix address family.
9155 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9156 * EVPN routes are also exchanged with a MP nexthop. Currently,
9158 * is only IPv4, the value will be present in either
9160 * attr->mp_nexthop_global_in
9162 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9165 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9169 snprintf(nexthop
, sizeof(nexthop
), "%s",
9170 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
9174 snprintf(nexthop
, sizeof(nexthop
), "%s",
9175 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
9179 snprintf(nexthop
, sizeof(nexthop
), "?");
9184 json_nexthop_global
= json_object_new_object();
9186 json_object_string_add(json_nexthop_global
, "ip",
9189 if (path
->peer
->hostname
)
9190 json_object_string_add(json_nexthop_global
,
9192 path
->peer
->hostname
);
9194 json_object_string_add(json_nexthop_global
, "afi",
9195 (af
== AF_INET
) ? "ipv4"
9197 json_object_boolean_true_add(json_nexthop_global
,
9200 if (nexthop_hostname
)
9201 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9202 nexthop_hostname
, vrf_id_str
);
9204 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9206 len
= wide
? (41 - len
) : (16 - len
);
9208 vty_out(vty
, "\n%*s", 36, " ");
9210 vty_out(vty
, "%*s", len
, " ");
9212 } else if (safi
== SAFI_EVPN
) {
9214 json_nexthop_global
= json_object_new_object();
9216 json_object_string_addf(json_nexthop_global
, "ip",
9218 &attr
->mp_nexthop_global_in
);
9220 if (path
->peer
->hostname
)
9221 json_object_string_add(json_nexthop_global
,
9223 path
->peer
->hostname
);
9225 json_object_string_add(json_nexthop_global
, "afi",
9227 json_object_boolean_true_add(json_nexthop_global
,
9230 if (nexthop_hostname
)
9231 len
= vty_out(vty
, "%pI4(%s)%s",
9232 &attr
->mp_nexthop_global_in
,
9233 nexthop_hostname
, vrf_id_str
);
9235 len
= vty_out(vty
, "%pI4%s",
9236 &attr
->mp_nexthop_global_in
,
9239 len
= wide
? (41 - len
) : (16 - len
);
9241 vty_out(vty
, "\n%*s", 36, " ");
9243 vty_out(vty
, "%*s", len
, " ");
9245 } else if (safi
== SAFI_FLOWSPEC
) {
9246 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9248 json_nexthop_global
= json_object_new_object();
9250 json_object_string_add(json_nexthop_global
,
9252 json_object_string_addf(json_nexthop_global
,
9256 if (path
->peer
->hostname
)
9257 json_object_string_add(
9258 json_nexthop_global
, "hostname",
9259 path
->peer
->hostname
);
9261 json_object_boolean_true_add(
9262 json_nexthop_global
,
9265 if (nexthop_hostname
)
9266 len
= vty_out(vty
, "%pI4(%s)%s",
9271 len
= vty_out(vty
, "%pI4%s",
9275 len
= wide
? (41 - len
) : (16 - len
);
9277 vty_out(vty
, "\n%*s", 36, " ");
9279 vty_out(vty
, "%*s", len
, " ");
9282 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9284 json_nexthop_global
= json_object_new_object();
9286 json_object_string_addf(json_nexthop_global
, "ip",
9287 "%pI4", &attr
->nexthop
);
9289 if (path
->peer
->hostname
)
9290 json_object_string_add(json_nexthop_global
,
9292 path
->peer
->hostname
);
9294 json_object_string_add(json_nexthop_global
, "afi",
9296 json_object_boolean_true_add(json_nexthop_global
,
9299 if (nexthop_hostname
)
9300 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9301 nexthop_hostname
, vrf_id_str
);
9303 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9306 len
= wide
? (41 - len
) : (16 - len
);
9308 vty_out(vty
, "\n%*s", 36, " ");
9310 vty_out(vty
, "%*s", len
, " ");
9315 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9317 json_nexthop_global
= json_object_new_object();
9318 json_object_string_addf(json_nexthop_global
, "ip",
9320 &attr
->mp_nexthop_global
);
9322 if (path
->peer
->hostname
)
9323 json_object_string_add(json_nexthop_global
,
9325 path
->peer
->hostname
);
9327 json_object_string_add(json_nexthop_global
, "afi",
9329 json_object_string_add(json_nexthop_global
, "scope",
9332 /* We display both LL & GL if both have been
9334 if ((attr
->mp_nexthop_len
9335 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9336 || (path
->peer
->conf_if
)) {
9337 json_nexthop_ll
= json_object_new_object();
9338 json_object_string_addf(
9339 json_nexthop_ll
, "ip", "%pI6",
9340 &attr
->mp_nexthop_local
);
9342 if (path
->peer
->hostname
)
9343 json_object_string_add(
9344 json_nexthop_ll
, "hostname",
9345 path
->peer
->hostname
);
9347 json_object_string_add(json_nexthop_ll
, "afi",
9349 json_object_string_add(json_nexthop_ll
, "scope",
9352 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9353 &attr
->mp_nexthop_local
)
9355 && !attr
->mp_nexthop_prefer_global
)
9356 json_object_boolean_true_add(
9357 json_nexthop_ll
, "used");
9359 json_object_boolean_true_add(
9360 json_nexthop_global
, "used");
9362 json_object_boolean_true_add(
9363 json_nexthop_global
, "used");
9365 /* Display LL if LL/Global both in table unless
9366 * prefer-global is set */
9367 if (((attr
->mp_nexthop_len
9368 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9369 && !attr
->mp_nexthop_prefer_global
)
9370 || (path
->peer
->conf_if
)) {
9371 if (path
->peer
->conf_if
) {
9372 len
= vty_out(vty
, "%s",
9373 path
->peer
->conf_if
);
9374 /* len of IPv6 addr + max len of def
9376 len
= wide
? (41 - len
) : (16 - len
);
9379 vty_out(vty
, "\n%*s", 36, " ");
9381 vty_out(vty
, "%*s", len
, " ");
9383 if (nexthop_hostname
)
9386 &attr
->mp_nexthop_local
,
9392 &attr
->mp_nexthop_local
,
9395 len
= wide
? (41 - len
) : (16 - len
);
9398 vty_out(vty
, "\n%*s", 36, " ");
9400 vty_out(vty
, "%*s", len
, " ");
9403 if (nexthop_hostname
)
9404 len
= vty_out(vty
, "%pI6(%s)%s",
9405 &attr
->mp_nexthop_global
,
9409 len
= vty_out(vty
, "%pI6%s",
9410 &attr
->mp_nexthop_global
,
9413 len
= wide
? (41 - len
) : (16 - len
);
9416 vty_out(vty
, "\n%*s", 36, " ");
9418 vty_out(vty
, "%*s", len
, " ");
9424 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9426 json_object_int_add(json_path
, "metric", attr
->med
);
9428 vty_out(vty
, "%7u", attr
->med
);
9430 vty_out(vty
, "%10u", attr
->med
);
9431 else if (!json_paths
) {
9433 vty_out(vty
, "%*s", 7, " ");
9435 vty_out(vty
, "%*s", 10, " ");
9439 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9441 json_object_int_add(json_path
, "locPrf",
9444 vty_out(vty
, "%7u", attr
->local_pref
);
9445 else if (!json_paths
)
9449 json_object_int_add(json_path
, "weight", attr
->weight
);
9451 vty_out(vty
, "%7u ", attr
->weight
);
9454 json_object_string_addf(json_path
, "peerId", "%pSU",
9460 json_object_string_add(json_path
, "path",
9463 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9468 json_object_string_add(json_path
, "origin",
9469 bgp_origin_long_str
[attr
->origin
]);
9471 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9474 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9475 json_object_string_add(json_path
, "esi",
9476 esi_to_str(&attr
->esi
,
9477 esi_buf
, sizeof(esi_buf
)));
9479 if (safi
== SAFI_EVPN
&&
9480 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9481 json_ext_community
= json_object_new_object();
9482 json_object_string_add(
9483 json_ext_community
, "string",
9484 bgp_attr_get_ecommunity(attr
)->str
);
9485 json_object_object_add(json_path
,
9486 "extendedCommunity",
9487 json_ext_community
);
9491 json_object_boolean_true_add(json_path
,
9492 "announceNexthopSelf");
9493 if (nexthop_othervrf
) {
9494 json_object_string_add(json_path
, "nhVrfName",
9497 json_object_int_add(json_path
, "nhVrfId",
9498 ((nexthop_vrfid
== VRF_UNKNOWN
)
9500 : (int)nexthop_vrfid
));
9505 if (json_nexthop_global
|| json_nexthop_ll
) {
9506 json_nexthops
= json_object_new_array();
9508 if (json_nexthop_global
)
9509 json_object_array_add(json_nexthops
,
9510 json_nexthop_global
);
9512 if (json_nexthop_ll
)
9513 json_object_array_add(json_nexthops
,
9516 json_object_object_add(json_path
, "nexthops",
9520 json_object_array_add(json_paths
, json_path
);
9524 if (safi
== SAFI_EVPN
) {
9525 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9526 /* XXX - add these params to the json out */
9527 vty_out(vty
, "%*s", 20, " ");
9528 vty_out(vty
, "ESI:%s",
9529 esi_to_str(&attr
->esi
, esi_buf
,
9535 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9536 vty_out(vty
, "%*s", 20, " ");
9537 vty_out(vty
, "%s\n",
9538 bgp_attr_get_ecommunity(attr
)->str
);
9542 #ifdef ENABLE_BGP_VNC
9543 /* prints an additional line, indented, with VNC info, if
9545 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9546 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9551 /* called from terminal list command */
9552 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9553 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9554 bool use_json
, json_object
*json_ar
, bool wide
)
9556 json_object
*json_status
= NULL
;
9557 json_object
*json_net
= NULL
;
9561 /* Route status display. */
9563 json_status
= json_object_new_object();
9564 json_net
= json_object_new_object();
9571 /* print prefix and mask */
9573 if (safi
== SAFI_EVPN
)
9574 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9575 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9576 json_object_string_add(
9577 json_net
, "addrPrefix",
9578 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9580 json_object_int_add(json_net
, "prefixLen",
9582 json_object_string_addf(json_net
, "network", "%pFX", p
);
9585 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9587 /* Print attribute */
9590 if (p
->family
== AF_INET
&&
9591 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9592 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9593 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9594 json_object_string_addf(
9595 json_net
, "nextHop", "%pI4",
9596 &attr
->mp_nexthop_global_in
);
9598 json_object_string_addf(
9599 json_net
, "nextHop", "%pI4",
9601 } else if (p
->family
== AF_INET6
||
9602 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9603 json_object_string_addf(
9604 json_net
, "nextHopGlobal", "%pI6",
9605 &attr
->mp_nexthop_global
);
9606 } else if (p
->family
== AF_EVPN
&&
9607 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9608 json_object_string_addf(
9609 json_net
, "nextHop", "%pI4",
9610 &attr
->mp_nexthop_global_in
);
9614 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9615 json_object_int_add(json_net
, "metric",
9618 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9619 json_object_int_add(json_net
, "locPrf",
9622 json_object_int_add(json_net
, "weight", attr
->weight
);
9626 json_object_string_add(json_net
, "path",
9630 json_object_string_add(json_net
, "bgpOriginCode",
9631 bgp_origin_str
[attr
->origin
]);
9633 if (p
->family
== AF_INET
&&
9634 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9635 safi
== SAFI_EVPN
||
9636 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9637 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9638 || safi
== SAFI_EVPN
)
9639 vty_out(vty
, "%-16pI4",
9640 &attr
->mp_nexthop_global_in
);
9642 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9644 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9645 } else if (p
->family
== AF_INET6
||
9646 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9652 &attr
->mp_nexthop_global
, buf
,
9654 len
= wide
? (41 - len
) : (16 - len
);
9656 vty_out(vty
, "\n%*s", 36, " ");
9658 vty_out(vty
, "%*s", len
, " ");
9661 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9663 vty_out(vty
, "%7u", attr
->med
);
9665 vty_out(vty
, "%10u", attr
->med
);
9671 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9672 vty_out(vty
, "%7u", attr
->local_pref
);
9676 vty_out(vty
, "%7u ", attr
->weight
);
9680 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9683 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9687 json_object_boolean_true_add(json_status
, "*");
9688 json_object_boolean_true_add(json_status
, ">");
9689 json_object_object_add(json_net
, "appliedStatusSymbols",
9691 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9696 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9697 struct bgp_path_info
*path
, int display
, safi_t safi
,
9700 json_object
*json_out
= NULL
;
9702 mpls_label_t label
= MPLS_INVALID_LABEL
;
9708 json_out
= json_object_new_object();
9710 /* short status lead text */
9711 route_vty_short_status_out(vty
, path
, p
, json_out
);
9713 /* print prefix and mask */
9716 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9718 vty_out(vty
, "%*s", 17, " ");
9721 /* Print attribute */
9723 if (((p
->family
== AF_INET
) &&
9724 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9725 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9726 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9727 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9728 || safi
== SAFI_EVPN
) {
9730 json_object_string_addf(
9731 json_out
, "mpNexthopGlobalIn", "%pI4",
9732 &attr
->mp_nexthop_global_in
);
9734 vty_out(vty
, "%-16pI4",
9735 &attr
->mp_nexthop_global_in
);
9738 json_object_string_addf(json_out
, "nexthop",
9739 "%pI4", &attr
->nexthop
);
9741 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9743 } else if (((p
->family
== AF_INET6
) &&
9744 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9745 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9746 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9749 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9751 json_object_string_addf(
9752 json_out
, "mpNexthopGlobalIn", "%pI6",
9753 &attr
->mp_nexthop_global
);
9757 &attr
->mp_nexthop_global
,
9758 buf_a
, sizeof(buf_a
)));
9759 } else if (attr
->mp_nexthop_len
9760 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9761 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9762 &attr
->mp_nexthop_global
,
9763 &attr
->mp_nexthop_local
);
9765 json_object_string_add(json_out
,
9766 "mpNexthopGlobalLocal",
9769 vty_out(vty
, "%s", buf_a
);
9773 label
= decode_label(&path
->extra
->label
[0]);
9775 if (bgp_is_valid_label(&label
)) {
9777 json_object_int_add(json_out
, "notag", label
);
9778 json_object_array_add(json
, json_out
);
9780 vty_out(vty
, "notag/%d", label
);
9787 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9788 struct bgp_path_info
*path
, int display
,
9789 json_object
*json_paths
)
9792 json_object
*json_path
= NULL
;
9793 json_object
*json_nexthop
= NULL
;
9794 json_object
*json_overlay
= NULL
;
9800 json_path
= json_object_new_object();
9801 json_overlay
= json_object_new_object();
9802 json_nexthop
= json_object_new_object();
9805 /* short status lead text */
9806 route_vty_short_status_out(vty
, path
, p
, json_path
);
9808 /* print prefix and mask */
9810 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9812 vty_out(vty
, "%*s", 17, " ");
9814 /* Print attribute */
9816 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9821 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9823 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9824 &attr
->mp_nexthop_global_in
);
9826 json_object_string_add(json_nexthop
, "afi", "ipv4");
9828 json_object_object_add(json_path
, "nexthop",
9834 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9835 &attr
->mp_nexthop_local
);
9837 json_object_string_addf(json_nexthop
, "ipv6Global",
9839 &attr
->mp_nexthop_global
);
9841 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9843 &attr
->mp_nexthop_local
);
9845 json_object_string_add(json_nexthop
, "afi", "ipv6");
9847 json_object_object_add(json_path
, "nexthop",
9855 json_object_string_add(json_nexthop
, "Error",
9856 "Unsupported address-family");
9857 json_object_string_add(json_nexthop
, "error",
9858 "Unsupported address-family");
9862 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9865 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9867 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9869 if (bgp_attr_get_ecommunity(attr
)) {
9871 struct ecommunity_val
*routermac
= ecommunity_lookup(
9872 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9873 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9876 mac
= ecom_mac2str((char *)routermac
->val
);
9879 vty_out(vty
, "/%s", mac
);
9881 json_object_string_add(json_overlay
, "rmac",
9884 XFREE(MTYPE_TMP
, mac
);
9891 json_object_object_add(json_path
, "overlay", json_overlay
);
9893 json_object_array_add(json_paths
, json_path
);
9897 /* dampening route */
9898 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9899 struct bgp_path_info
*path
, int display
,
9900 afi_t afi
, safi_t safi
, bool use_json
,
9901 json_object
*json_paths
)
9903 struct attr
*attr
= path
->attr
;
9905 char timebuf
[BGP_UPTIME_LEN
];
9906 json_object
*json_path
= NULL
;
9909 json_path
= json_object_new_object();
9911 /* short status lead text */
9912 route_vty_short_status_out(vty
, path
, p
, json_path
);
9914 /* print prefix and mask */
9917 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9919 vty_out(vty
, "%*s", 17, " ");
9921 len
= vty_out(vty
, "%s", path
->peer
->host
);
9925 vty_out(vty
, "\n%*s", 34, " ");
9927 vty_out(vty
, "%*s", len
, " ");
9930 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9931 BGP_UPTIME_LEN
, afi
, safi
,
9935 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9937 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9941 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9942 safi
, use_json
, json_path
);
9945 json_object_string_add(json_path
, "asPath",
9948 json_object_string_add(json_path
, "origin",
9949 bgp_origin_str
[attr
->origin
]);
9950 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9952 json_object_array_add(json_paths
, json_path
);
9957 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9958 struct bgp_path_info
*path
, int display
,
9959 afi_t afi
, safi_t safi
, bool use_json
,
9960 json_object
*json_paths
)
9962 struct attr
*attr
= path
->attr
;
9963 struct bgp_damp_info
*bdi
;
9964 char timebuf
[BGP_UPTIME_LEN
];
9966 json_object
*json_path
= NULL
;
9972 json_path
= json_object_new_object();
9974 bdi
= path
->extra
->damp_info
;
9976 /* short status lead text */
9977 route_vty_short_status_out(vty
, path
, p
, json_path
);
9981 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9983 vty_out(vty
, "%*s", 17, " ");
9985 len
= vty_out(vty
, "%s", path
->peer
->host
);
9988 vty_out(vty
, "\n%*s", 33, " ");
9990 vty_out(vty
, "%*s", len
, " ");
9992 len
= vty_out(vty
, "%d", bdi
->flap
);
9997 vty_out(vty
, "%*s", len
, " ");
9999 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10000 BGP_UPTIME_LEN
, 0, NULL
));
10002 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10003 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10004 vty_out(vty
, "%s ",
10005 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10006 BGP_UPTIME_LEN
, afi
,
10007 safi
, use_json
, NULL
));
10009 vty_out(vty
, "%*s ", 8, " ");
10012 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
10014 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10016 vty_out(vty
, "\n");
10018 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10019 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10021 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10024 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10025 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10026 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10027 BGP_UPTIME_LEN
, afi
, safi
,
10028 use_json
, json_path
);
10031 json_object_string_add(json_path
, "asPath",
10032 attr
->aspath
->str
);
10034 json_object_string_add(json_path
, "origin",
10035 bgp_origin_str
[attr
->origin
]);
10037 json_object_array_add(json_paths
, json_path
);
10041 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10042 int *first
, const char *header
,
10043 json_object
*json_adv_to
)
10045 json_object
*json_peer
= NULL
;
10048 /* 'advertised-to' is a dictionary of peers we have advertised
10050 * prefix too. The key is the peer's IP or swpX, the value is
10052 * hostname if we know it and "" if not.
10054 json_peer
= json_object_new_object();
10056 if (peer
->hostname
)
10057 json_object_string_add(json_peer
, "hostname",
10061 json_object_object_add(json_adv_to
, peer
->conf_if
,
10064 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10068 vty_out(vty
, "%s", header
);
10073 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10075 vty_out(vty
, " %s(%s)", peer
->hostname
,
10078 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10082 vty_out(vty
, " %s", peer
->conf_if
);
10084 vty_out(vty
, " %pSU", &peer
->su
);
10089 static void route_vty_out_tx_ids(struct vty
*vty
,
10090 struct bgp_addpath_info_data
*d
)
10094 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10095 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10096 d
->addpath_tx_id
[i
],
10097 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10101 static void route_vty_out_detail_es_info(struct vty
*vty
,
10102 struct bgp_path_info
*pi
,
10104 json_object
*json_path
)
10106 char esi_buf
[ESI_STR_LEN
];
10107 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10108 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10109 ATTR_ES_PEER_ROUTER
);
10110 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10111 ATTR_ES_PEER_ACTIVE
);
10112 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10113 ATTR_ES_PEER_PROXY
);
10114 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10116 json_object
*json_es_info
= NULL
;
10118 json_object_string_add(
10121 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10122 json_es_info
= json_object_new_object();
10124 json_object_boolean_true_add(
10125 json_es_info
, "localEs");
10127 json_object_boolean_true_add(
10128 json_es_info
, "peerActive");
10130 json_object_boolean_true_add(
10131 json_es_info
, "peerProxy");
10133 json_object_boolean_true_add(
10134 json_es_info
, "peerRouter");
10135 if (attr
->mm_sync_seqnum
)
10136 json_object_int_add(
10137 json_es_info
, "peerSeq",
10138 attr
->mm_sync_seqnum
);
10139 json_object_object_add(
10140 json_path
, "es_info",
10144 if (bgp_evpn_attr_is_sync(attr
))
10146 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10148 es_local
? "local-es":"",
10149 peer_proxy
? "proxy " : "",
10150 peer_active
? "active ":"",
10151 peer_router
? "router ":"",
10152 attr
->mm_sync_seqnum
);
10154 vty_out(vty
, " ESI %s %s\n",
10156 es_local
? "local-es":"");
10160 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10161 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
10162 enum rpki_states rpki_curr_state
,
10163 json_object
*json_paths
)
10165 char buf
[INET6_ADDRSTRLEN
];
10167 struct attr
*attr
= path
->attr
;
10169 json_object
*json_bestpath
= NULL
;
10170 json_object
*json_cluster_list
= NULL
;
10171 json_object
*json_cluster_list_list
= NULL
;
10172 json_object
*json_ext_community
= NULL
;
10173 json_object
*json_last_update
= NULL
;
10174 json_object
*json_pmsi
= NULL
;
10175 json_object
*json_nexthop_global
= NULL
;
10176 json_object
*json_nexthop_ll
= NULL
;
10177 json_object
*json_nexthops
= NULL
;
10178 json_object
*json_path
= NULL
;
10179 json_object
*json_peer
= NULL
;
10180 json_object
*json_string
= NULL
;
10181 json_object
*json_adv_to
= NULL
;
10183 struct listnode
*node
, *nnode
;
10185 bool addpath_capable
;
10187 unsigned int first_as
;
10188 bool nexthop_self
=
10189 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10191 char *nexthop_hostname
=
10192 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10196 mpls_label_t label
= MPLS_INVALID_LABEL
;
10199 json_path
= json_object_new_object();
10200 json_peer
= json_object_new_object();
10201 json_nexthop_global
= json_object_new_object();
10204 if (safi
== SAFI_EVPN
) {
10206 vty_out(vty
, " Route %pRN", bn
);
10213 if (path
->extra
&& path
->extra
->num_labels
) {
10214 bgp_evpn_label2str(path
->extra
->label
,
10215 path
->extra
->num_labels
, tag_buf
,
10218 if (safi
== SAFI_EVPN
) {
10220 if (tag_buf
[0] != '\0')
10221 vty_out(vty
, " VNI %s", tag_buf
);
10224 json_object_string_add(json_path
, "VNI",
10226 json_object_string_add(json_path
, "vni",
10232 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10233 struct bgp_path_info
*parent_ri
;
10234 struct bgp_dest
*dest
, *pdest
;
10236 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10237 dest
= parent_ri
->net
;
10238 if (dest
&& dest
->pdest
) {
10239 pdest
= dest
->pdest
;
10240 if (is_pi_family_evpn(parent_ri
)) {
10242 " Imported from %pRD:%pFX, VNI %s",
10243 (struct prefix_rd
*)
10244 bgp_dest_get_prefix(
10246 (struct prefix_evpn
*)
10247 bgp_dest_get_prefix(
10250 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
10251 vty_out(vty
, ", L3NHG %s",
10253 & ATTR_ES_L3_NHG_ACTIVE
)
10256 vty_out(vty
, "\n");
10260 " Imported from %pRD:%pFX\n",
10261 (struct prefix_rd
*)
10262 bgp_dest_get_prefix(
10264 (struct prefix_evpn
*)
10265 bgp_dest_get_prefix(
10271 if (safi
== SAFI_EVPN
10272 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10273 char gwip_buf
[INET6_ADDRSTRLEN
];
10275 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10279 json_object_string_add(json_path
, "gatewayIP",
10282 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10285 if (safi
== SAFI_EVPN
&& !json_path
)
10286 vty_out(vty
, "\n");
10288 /* Line1 display AS-path, Aggregator */
10289 if (attr
->aspath
) {
10291 if (!attr
->aspath
->json
)
10292 aspath_str_update(attr
->aspath
, true);
10293 json_object_lock(attr
->aspath
->json
);
10294 json_object_object_add(json_path
, "aspath",
10295 attr
->aspath
->json
);
10297 if (attr
->aspath
->segments
)
10298 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
10300 vty_out(vty
, " Local");
10304 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10306 json_object_boolean_true_add(json_path
, "removed");
10308 vty_out(vty
, ", (removed)");
10311 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10313 json_object_boolean_true_add(json_path
, "stale");
10315 vty_out(vty
, ", (stale)");
10318 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10320 json_object_int_add(json_path
, "aggregatorAs",
10321 attr
->aggregator_as
);
10322 json_object_string_addf(json_path
, "aggregatorId",
10323 "%pI4", &attr
->aggregator_addr
);
10325 vty_out(vty
, ", (aggregated by %u %pI4)",
10326 attr
->aggregator_as
, &attr
->aggregator_addr
);
10330 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10331 PEER_FLAG_REFLECTOR_CLIENT
)) {
10333 json_object_boolean_true_add(json_path
,
10334 "rxedFromRrClient");
10336 vty_out(vty
, ", (Received from a RR-client)");
10339 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10340 PEER_FLAG_RSERVER_CLIENT
)) {
10342 json_object_boolean_true_add(json_path
,
10343 "rxedFromRsClient");
10345 vty_out(vty
, ", (Received from a RS-client)");
10348 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10350 json_object_boolean_true_add(json_path
,
10351 "dampeningHistoryEntry");
10353 vty_out(vty
, ", (history entry)");
10354 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10356 json_object_boolean_true_add(json_path
,
10357 "dampeningSuppressed");
10359 vty_out(vty
, ", (suppressed due to dampening)");
10363 vty_out(vty
, "\n");
10365 /* Line2 display Next-hop, Neighbor, Router-id */
10366 /* Display the nexthop */
10367 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
10369 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
||
10370 bn_p
->family
== AF_EVPN
) &&
10371 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10372 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10373 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10374 || safi
== SAFI_EVPN
) {
10376 json_object_string_addf(
10377 json_nexthop_global
, "ip", "%pI4",
10378 &attr
->mp_nexthop_global_in
);
10380 if (path
->peer
->hostname
)
10381 json_object_string_add(
10382 json_nexthop_global
, "hostname",
10383 path
->peer
->hostname
);
10385 if (nexthop_hostname
)
10386 vty_out(vty
, " %pI4(%s)",
10387 &attr
->mp_nexthop_global_in
,
10390 vty_out(vty
, " %pI4",
10391 &attr
->mp_nexthop_global_in
);
10395 json_object_string_addf(json_nexthop_global
,
10399 if (path
->peer
->hostname
)
10400 json_object_string_add(
10401 json_nexthop_global
, "hostname",
10402 path
->peer
->hostname
);
10404 if (nexthop_hostname
)
10405 vty_out(vty
, " %pI4(%s)",
10409 vty_out(vty
, " %pI4",
10415 json_object_string_add(json_nexthop_global
, "afi",
10419 json_object_string_addf(json_nexthop_global
, "ip",
10421 &attr
->mp_nexthop_global
);
10423 if (path
->peer
->hostname
)
10424 json_object_string_add(json_nexthop_global
,
10426 path
->peer
->hostname
);
10428 json_object_string_add(json_nexthop_global
, "afi",
10430 json_object_string_add(json_nexthop_global
, "scope",
10433 if (nexthop_hostname
)
10434 vty_out(vty
, " %pI6(%s)",
10435 &attr
->mp_nexthop_global
,
10438 vty_out(vty
, " %pI6",
10439 &attr
->mp_nexthop_global
);
10443 /* Display the IGP cost or 'inaccessible' */
10444 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10445 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10448 json_object_boolean_false_add(json_nexthop_global
,
10450 json_object_boolean_add(json_nexthop_global
,
10451 "importCheckEnabled", import
);
10453 vty_out(vty
, " (inaccessible%s)",
10454 import
? ", import-check enabled" : "");
10457 if (path
->extra
&& path
->extra
->igpmetric
) {
10459 json_object_int_add(json_nexthop_global
,
10461 path
->extra
->igpmetric
);
10463 vty_out(vty
, " (metric %u)",
10464 path
->extra
->igpmetric
);
10467 /* IGP cost is 0, display this only for json */
10470 json_object_int_add(json_nexthop_global
,
10475 json_object_boolean_true_add(json_nexthop_global
,
10479 /* Display peer "from" output */
10480 /* This path was originated locally */
10481 if (path
->peer
== bgp
->peer_self
) {
10483 if (safi
== SAFI_EVPN
|| (bn_p
->family
== AF_INET
&&
10484 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10486 json_object_string_add(json_peer
, "peerId",
10489 vty_out(vty
, " from 0.0.0.0 ");
10492 json_object_string_add(json_peer
, "peerId",
10495 vty_out(vty
, " from :: ");
10499 json_object_string_addf(json_peer
, "routerId", "%pI4",
10502 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10505 /* We RXed this path from one of our peers */
10509 json_object_string_addf(json_peer
, "peerId", "%pSU",
10511 json_object_string_addf(json_peer
, "routerId", "%pI4",
10512 &path
->peer
->remote_id
);
10514 if (path
->peer
->hostname
)
10515 json_object_string_add(json_peer
, "hostname",
10516 path
->peer
->hostname
);
10518 if (path
->peer
->domainname
)
10519 json_object_string_add(json_peer
, "domainname",
10520 path
->peer
->domainname
);
10522 if (path
->peer
->conf_if
)
10523 json_object_string_add(json_peer
, "interface",
10524 path
->peer
->conf_if
);
10526 if (path
->peer
->conf_if
) {
10527 if (path
->peer
->hostname
10528 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10529 BGP_FLAG_SHOW_HOSTNAME
))
10530 vty_out(vty
, " from %s(%s)",
10531 path
->peer
->hostname
,
10532 path
->peer
->conf_if
);
10534 vty_out(vty
, " from %s",
10535 path
->peer
->conf_if
);
10537 if (path
->peer
->hostname
10538 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10539 BGP_FLAG_SHOW_HOSTNAME
))
10540 vty_out(vty
, " from %s(%s)",
10541 path
->peer
->hostname
,
10544 vty_out(vty
, " from %pSU",
10548 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10549 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10551 vty_out(vty
, " (%s)",
10553 &path
->peer
->remote_id
, buf1
,
10559 * Note when vrfid of nexthop is different from that of prefix
10561 if (path
->extra
&& path
->extra
->bgp_orig
) {
10562 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10567 if (path
->extra
->bgp_orig
->inst_type
10568 == BGP_INSTANCE_TYPE_DEFAULT
)
10569 vn
= VRF_DEFAULT_NAME
;
10571 vn
= path
->extra
->bgp_orig
->name
;
10573 json_object_string_add(json_path
, "nhVrfName", vn
);
10575 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10576 json_object_int_add(json_path
, "nhVrfId", -1);
10578 json_object_int_add(json_path
, "nhVrfId",
10579 (int)nexthop_vrfid
);
10582 if (nexthop_vrfid
== VRF_UNKNOWN
)
10583 vty_out(vty
, " vrf ?");
10587 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10588 vty_out(vty
, " vrf %s(%u)",
10589 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10594 if (nexthop_self
) {
10596 json_object_boolean_true_add(json_path
,
10597 "announceNexthopSelf");
10599 vty_out(vty
, " announce-nh-self");
10604 vty_out(vty
, "\n");
10606 /* display the link-local nexthop */
10607 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10609 json_nexthop_ll
= json_object_new_object();
10610 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10611 &attr
->mp_nexthop_local
);
10613 if (path
->peer
->hostname
)
10614 json_object_string_add(json_nexthop_ll
,
10616 path
->peer
->hostname
);
10618 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10619 json_object_string_add(json_nexthop_ll
, "scope",
10622 json_object_boolean_true_add(json_nexthop_ll
,
10625 if (!attr
->mp_nexthop_prefer_global
)
10626 json_object_boolean_true_add(json_nexthop_ll
,
10629 json_object_boolean_true_add(
10630 json_nexthop_global
, "used");
10632 vty_out(vty
, " (%s) %s\n",
10633 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10634 buf
, INET6_ADDRSTRLEN
),
10635 attr
->mp_nexthop_prefer_global
10636 ? "(prefer-global)"
10640 /* If we do not have a link-local nexthop then we must flag the
10641 global as "used" */
10644 json_object_boolean_true_add(json_nexthop_global
,
10648 if (safi
== SAFI_EVPN
&&
10649 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10650 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10653 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10654 * Int/Ext/Local, Atomic, best */
10656 json_object_string_add(json_path
, "origin",
10657 bgp_origin_long_str
[attr
->origin
]);
10659 vty_out(vty
, " Origin %s",
10660 bgp_origin_long_str
[attr
->origin
]);
10662 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10664 json_object_int_add(json_path
, "metric", attr
->med
);
10666 vty_out(vty
, ", metric %u", attr
->med
);
10669 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10671 json_object_int_add(json_path
, "locPrf",
10674 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10677 if (attr
->weight
!= 0) {
10679 json_object_int_add(json_path
, "weight", attr
->weight
);
10681 vty_out(vty
, ", weight %u", attr
->weight
);
10684 if (attr
->tag
!= 0) {
10686 json_object_int_add(json_path
, "tag", attr
->tag
);
10688 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10691 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10693 json_object_boolean_false_add(json_path
, "valid");
10695 vty_out(vty
, ", invalid");
10696 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10698 json_object_boolean_true_add(json_path
, "valid");
10700 vty_out(vty
, ", valid");
10704 json_object_int_add(json_path
, "version", bn
->version
);
10706 if (path
->peer
!= bgp
->peer_self
) {
10707 if (path
->peer
->as
== path
->peer
->local_as
) {
10708 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10710 json_object_string_add(
10712 "confed-internal");
10714 vty_out(vty
, ", confed-internal");
10717 json_object_string_add(
10718 json_peer
, "type", "internal");
10720 vty_out(vty
, ", internal");
10723 if (bgp_confederation_peers_check(bgp
,
10726 json_object_string_add(
10728 "confed-external");
10730 vty_out(vty
, ", confed-external");
10733 json_object_string_add(
10734 json_peer
, "type", "external");
10736 vty_out(vty
, ", external");
10739 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10741 json_object_boolean_true_add(json_path
, "aggregated");
10742 json_object_boolean_true_add(json_path
, "local");
10744 vty_out(vty
, ", aggregated, local");
10746 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10748 json_object_boolean_true_add(json_path
, "sourced");
10750 vty_out(vty
, ", sourced");
10753 json_object_boolean_true_add(json_path
, "sourced");
10754 json_object_boolean_true_add(json_path
, "local");
10756 vty_out(vty
, ", sourced, local");
10760 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10762 json_object_boolean_true_add(json_path
,
10763 "atomicAggregate");
10765 vty_out(vty
, ", atomic-aggregate");
10768 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10770 json_object_int_add(json_path
, "otc", attr
->otc
);
10772 vty_out(vty
, ", otc %u", attr
->otc
);
10775 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10776 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10777 && bgp_path_info_mpath_count(path
))) {
10779 json_object_boolean_true_add(json_path
, "multipath");
10781 vty_out(vty
, ", multipath");
10784 // Mark the bestpath(s)
10785 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10786 first_as
= aspath_get_first_as(attr
->aspath
);
10789 if (!json_bestpath
)
10790 json_bestpath
= json_object_new_object();
10791 json_object_int_add(json_bestpath
, "bestpathFromAs",
10795 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10797 vty_out(vty
, ", bestpath-from-AS Local");
10801 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10803 if (!json_bestpath
)
10804 json_bestpath
= json_object_new_object();
10805 json_object_boolean_true_add(json_bestpath
, "overall");
10806 json_object_string_add(
10807 json_bestpath
, "selectionReason",
10808 bgp_path_selection_reason2str(bn
->reason
));
10810 vty_out(vty
, ", best");
10811 vty_out(vty
, " (%s)",
10812 bgp_path_selection_reason2str(bn
->reason
));
10816 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10818 json_object_string_add(
10819 json_path
, "rpkiValidationState",
10820 bgp_rpki_validation2str(rpki_curr_state
));
10822 vty_out(vty
, ", rpki validation-state: %s",
10823 bgp_rpki_validation2str(rpki_curr_state
));
10827 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10830 vty_out(vty
, "\n");
10832 /* Line 4 display Community */
10833 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10835 if (!bgp_attr_get_community(attr
)->json
)
10836 community_str(bgp_attr_get_community(attr
),
10838 json_object_lock(bgp_attr_get_community(attr
)->json
);
10839 json_object_object_add(
10840 json_path
, "community",
10841 bgp_attr_get_community(attr
)->json
);
10843 vty_out(vty
, " Community: %s\n",
10844 bgp_attr_get_community(attr
)->str
);
10848 /* Line 5 display Extended-community */
10849 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10851 json_ext_community
= json_object_new_object();
10852 json_object_string_add(
10853 json_ext_community
, "string",
10854 bgp_attr_get_ecommunity(attr
)->str
);
10855 json_object_object_add(json_path
, "extendedCommunity",
10856 json_ext_community
);
10858 vty_out(vty
, " Extended Community: %s\n",
10859 bgp_attr_get_ecommunity(attr
)->str
);
10863 /* Line 6 display Large community */
10864 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10866 if (!bgp_attr_get_lcommunity(attr
)->json
)
10867 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10869 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10870 json_object_object_add(
10871 json_path
, "largeCommunity",
10872 bgp_attr_get_lcommunity(attr
)->json
);
10874 vty_out(vty
, " Large Community: %s\n",
10875 bgp_attr_get_lcommunity(attr
)->str
);
10879 /* Line 7 display Originator, Cluster-id */
10880 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10881 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10882 char buf
[BUFSIZ
] = {0};
10884 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10886 json_object_string_addf(json_path
,
10887 "originatorId", "%pI4",
10888 &attr
->originator_id
);
10890 vty_out(vty
, " Originator: %pI4",
10891 &attr
->originator_id
);
10894 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10895 struct cluster_list
*cluster
=
10896 bgp_attr_get_cluster(attr
);
10900 json_cluster_list
= json_object_new_object();
10901 json_cluster_list_list
=
10902 json_object_new_array();
10904 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10905 json_string
= json_object_new_string(
10908 buf
, sizeof(buf
)));
10909 json_object_array_add(
10910 json_cluster_list_list
,
10915 * struct cluster_list does not have
10916 * "str" variable like aspath and community
10917 * do. Add this someday if someone asks
10919 * json_object_string_add(json_cluster_list,
10920 * "string", cluster->str);
10922 json_object_object_add(json_cluster_list
,
10924 json_cluster_list_list
);
10925 json_object_object_add(json_path
, "clusterList",
10926 json_cluster_list
);
10928 vty_out(vty
, ", Cluster list: ");
10930 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10931 vty_out(vty
, "%pI4 ",
10932 &cluster
->list
[i
]);
10938 vty_out(vty
, "\n");
10941 if (path
->extra
&& path
->extra
->damp_info
)
10942 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10945 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10946 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10947 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10951 json_object_int_add(json_path
, "remoteLabel", label
);
10953 vty_out(vty
, " Remote label: %d\n", label
);
10957 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10958 inet_ntop(AF_INET6
, &path
->extra
->sid
[0].sid
, buf
, sizeof(buf
));
10960 json_object_string_add(json_path
, "remoteSid", buf
);
10962 vty_out(vty
, " Remote SID: %s\n", buf
);
10966 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10968 json_object_int_add(json_path
, "labelIndex",
10969 attr
->label_index
);
10971 vty_out(vty
, " Label Index: %d\n",
10972 attr
->label_index
);
10975 /* Line 8 display Addpath IDs */
10976 if (path
->addpath_rx_id
10977 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10979 json_object_int_add(json_path
, "addpathRxId",
10980 path
->addpath_rx_id
);
10982 /* Keep backwards compatibility with the old API
10983 * by putting TX All's ID in the old field
10985 json_object_int_add(
10986 json_path
, "addpathTxId",
10988 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10990 /* ... but create a specific field for each
10993 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10994 json_object_int_add(
10996 bgp_addpath_names(i
)->id_json_name
,
10997 path
->tx_addpath
.addpath_tx_id
[i
]);
11000 vty_out(vty
, " AddPath ID: RX %u, ",
11001 path
->addpath_rx_id
);
11003 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11007 /* If we used addpath to TX a non-bestpath we need to display
11008 * "Advertised to" on a path-by-path basis
11010 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11013 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11015 bgp_addpath_encode_tx(peer
, afi
, safi
);
11016 has_adj
= bgp_adj_out_lookup(
11018 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11019 &path
->tx_addpath
));
11021 if ((addpath_capable
&& has_adj
)
11022 || (!addpath_capable
&& has_adj
11023 && CHECK_FLAG(path
->flags
,
11024 BGP_PATH_SELECTED
))) {
11025 if (json_path
&& !json_adv_to
)
11026 json_adv_to
= json_object_new_object();
11028 route_vty_out_advertised_to(
11030 " Advertised to:", json_adv_to
);
11036 json_object_object_add(
11037 json_path
, "advertisedTo", json_adv_to
);
11041 vty_out(vty
, "\n");
11046 /* Line 9 display Uptime */
11047 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11049 json_last_update
= json_object_new_object();
11050 json_object_int_add(json_last_update
, "epoch", tbuf
);
11051 json_object_string_add(json_last_update
, "string",
11053 json_object_object_add(json_path
, "lastUpdate",
11056 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11058 /* Line 10 display PMSI tunnel attribute, if present */
11059 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11060 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11061 bgp_attr_get_pmsi_tnl_type(attr
),
11062 PMSI_TNLTYPE_STR_DEFAULT
);
11065 json_pmsi
= json_object_new_object();
11066 json_object_string_add(json_pmsi
, "tunnelType", str
);
11067 json_object_int_add(json_pmsi
, "label",
11068 label2vni(&attr
->label
));
11069 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11071 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11072 str
, label2vni(&attr
->label
));
11075 if (path
->peer
->t_gr_restart
&&
11076 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11077 unsigned long gr_remaining
=
11078 thread_timer_remain_second(path
->peer
->t_gr_restart
);
11081 json_object_int_add(json_path
,
11082 "gracefulRestartSecondsRemaining",
11086 " Time until Graceful Restart stale route deleted: %lu\n",
11090 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11091 bgp_attr_get_community(attr
) &&
11092 community_include(bgp_attr_get_community(attr
),
11093 COMMUNITY_LLGR_STALE
)) {
11094 unsigned long llgr_remaining
= thread_timer_remain_second(
11095 path
->peer
->t_llgr_stale
[afi
][safi
]);
11098 json_object_int_add(json_path
, "llgrSecondsRemaining",
11102 " Time until Long-lived stale route deleted: %lu\n",
11106 /* Output some debug about internal state of the dest flags */
11108 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11109 json_object_boolean_true_add(json_path
, "processScheduled");
11110 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11111 json_object_boolean_true_add(json_path
, "userCleared");
11112 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11113 json_object_boolean_true_add(json_path
, "labelChanged");
11114 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11115 json_object_boolean_true_add(json_path
, "registeredForLabel");
11116 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11117 json_object_boolean_true_add(json_path
, "selectDefered");
11118 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11119 json_object_boolean_true_add(json_path
, "fibInstalled");
11120 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11121 json_object_boolean_true_add(json_path
, "fibPending");
11123 if (json_nexthop_global
|| json_nexthop_ll
) {
11124 json_nexthops
= json_object_new_array();
11126 if (json_nexthop_global
)
11127 json_object_array_add(json_nexthops
,
11128 json_nexthop_global
);
11130 if (json_nexthop_ll
)
11131 json_object_array_add(json_nexthops
,
11134 json_object_object_add(json_path
, "nexthops",
11138 json_object_object_add(json_path
, "peer", json_peer
);
11139 json_object_array_add(json_paths
, json_path
);
11143 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11144 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11145 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11147 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11148 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11150 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11151 const char *comstr
, int exact
, afi_t afi
,
11152 safi_t safi
, uint16_t show_flags
);
11154 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11155 struct bgp_table
*table
, enum bgp_show_type type
,
11156 void *output_arg
, const char *rd
, int is_last
,
11157 unsigned long *output_cum
, unsigned long *total_cum
,
11158 unsigned long *json_header_depth
, uint16_t show_flags
,
11159 enum rpki_states rpki_target_state
)
11161 struct bgp_path_info
*pi
;
11162 struct bgp_dest
*dest
;
11163 bool header
= true;
11164 bool json_detail_header
= false;
11166 unsigned long output_count
= 0;
11167 unsigned long total_count
= 0;
11169 json_object
*json_paths
= NULL
;
11171 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11172 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11173 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11175 if (output_cum
&& *output_cum
!= 0)
11178 if (use_json
&& !*json_header_depth
) {
11180 *json_header_depth
= 1;
11182 vty_out(vty
, "{\n");
11183 *json_header_depth
= 2;
11187 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11188 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11189 " \"localAS\": %u,\n \"routes\": { ",
11190 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11191 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11194 table
->version
, &bgp
->router_id
,
11195 bgp
->default_local_pref
, bgp
->as
);
11197 vty_out(vty
, " \"routeDistinguishers\" : {");
11198 ++*json_header_depth
;
11202 if (use_json
&& rd
) {
11203 vty_out(vty
, " \"%s\" : { ", rd
);
11206 /* Check for 'json detail', where we need header output once per dest */
11207 if (use_json
&& CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
) &&
11208 type
!= bgp_show_type_dampend_paths
&&
11209 type
!= bgp_show_type_damp_neighbor
&&
11210 type
!= bgp_show_type_flap_statistics
&&
11211 type
!= bgp_show_type_flap_neighbor
)
11212 json_detail_header
= true;
11214 /* Start processing of routes. */
11215 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11216 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11217 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11218 bool json_detail
= json_detail_header
;
11220 pi
= bgp_dest_get_bgp_path_info(dest
);
11226 json_paths
= json_object_new_array();
11230 for (; pi
; pi
= pi
->next
) {
11231 struct community
*picomm
= NULL
;
11233 picomm
= bgp_attr_get_community(pi
->attr
);
11237 if (type
== bgp_show_type_prefix_version
) {
11239 strtoul(output_arg
, NULL
, 10);
11240 if (dest
->version
< version
)
11244 if (type
== bgp_show_type_community_alias
) {
11245 char *alias
= output_arg
;
11246 char **communities
;
11248 bool found
= false;
11251 frrstr_split(picomm
->str
, " ",
11252 &communities
, &num
);
11253 for (int i
= 0; i
< num
; i
++) {
11254 const char *com2alias
=
11255 bgp_community2alias(
11258 && strcmp(alias
, com2alias
)
11264 XFREE(MTYPE_TMP
, communities
);
11268 bgp_attr_get_lcommunity(pi
->attr
)) {
11269 frrstr_split(bgp_attr_get_lcommunity(
11272 " ", &communities
, &num
);
11273 for (int i
= 0; i
< num
; i
++) {
11274 const char *com2alias
=
11275 bgp_community2alias(
11278 && strcmp(alias
, com2alias
)
11284 XFREE(MTYPE_TMP
, communities
);
11291 if (type
== bgp_show_type_rpki
) {
11292 if (dest_p
->family
== AF_INET
11293 || dest_p
->family
== AF_INET6
)
11294 rpki_curr_state
= hook_call(
11295 bgp_rpki_prefix_status
,
11296 pi
->peer
, pi
->attr
, dest_p
);
11297 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11298 && rpki_curr_state
!= rpki_target_state
)
11302 if (type
== bgp_show_type_flap_statistics
11303 || type
== bgp_show_type_flap_neighbor
11304 || type
== bgp_show_type_dampend_paths
11305 || type
== bgp_show_type_damp_neighbor
) {
11306 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11309 if (type
== bgp_show_type_regexp
) {
11310 regex_t
*regex
= output_arg
;
11312 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11316 if (type
== bgp_show_type_prefix_list
) {
11317 struct prefix_list
*plist
= output_arg
;
11319 if (prefix_list_apply(plist
, dest_p
)
11323 if (type
== bgp_show_type_access_list
) {
11324 struct access_list
*alist
= output_arg
;
11326 if (access_list_apply(alist
, dest_p
) !=
11330 if (type
== bgp_show_type_filter_list
) {
11331 struct as_list
*as_list
= output_arg
;
11333 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11334 != AS_FILTER_PERMIT
)
11337 if (type
== bgp_show_type_route_map
) {
11338 struct route_map
*rmap
= output_arg
;
11339 struct bgp_path_info path
;
11340 struct bgp_path_info_extra extra
;
11341 struct attr dummy_attr
= {};
11342 route_map_result_t ret
;
11344 dummy_attr
= *pi
->attr
;
11346 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11347 pi
->peer
, &dummy_attr
);
11349 ret
= route_map_apply(rmap
, dest_p
, &path
);
11350 bgp_attr_flush(&dummy_attr
);
11351 if (ret
== RMAP_DENYMATCH
)
11354 if (type
== bgp_show_type_neighbor
11355 || type
== bgp_show_type_flap_neighbor
11356 || type
== bgp_show_type_damp_neighbor
) {
11357 union sockunion
*su
= output_arg
;
11359 if (pi
->peer
== NULL
11360 || pi
->peer
->su_remote
== NULL
11361 || !sockunion_same(pi
->peer
->su_remote
, su
))
11364 if (type
== bgp_show_type_cidr_only
) {
11365 uint32_t destination
;
11367 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11368 if (IN_CLASSC(destination
)
11369 && dest_p
->prefixlen
== 24)
11371 if (IN_CLASSB(destination
)
11372 && dest_p
->prefixlen
== 16)
11374 if (IN_CLASSA(destination
)
11375 && dest_p
->prefixlen
== 8)
11378 if (type
== bgp_show_type_prefix_longer
) {
11380 if (!prefix_match(p
, dest_p
))
11383 if (type
== bgp_show_type_community_all
) {
11387 if (type
== bgp_show_type_community
) {
11388 struct community
*com
= output_arg
;
11390 if (!picomm
|| !community_match(picomm
, com
))
11393 if (type
== bgp_show_type_community_exact
) {
11394 struct community
*com
= output_arg
;
11396 if (!picomm
|| !community_cmp(picomm
, com
))
11399 if (type
== bgp_show_type_community_list
) {
11400 struct community_list
*list
= output_arg
;
11402 if (!community_list_match(picomm
, list
))
11405 if (type
== bgp_show_type_community_list_exact
) {
11406 struct community_list
*list
= output_arg
;
11408 if (!community_list_exact_match(picomm
, list
))
11411 if (type
== bgp_show_type_lcommunity
) {
11412 struct lcommunity
*lcom
= output_arg
;
11414 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11416 bgp_attr_get_lcommunity(pi
->attr
),
11421 if (type
== bgp_show_type_lcommunity_exact
) {
11422 struct lcommunity
*lcom
= output_arg
;
11424 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11426 bgp_attr_get_lcommunity(pi
->attr
),
11430 if (type
== bgp_show_type_lcommunity_list
) {
11431 struct community_list
*list
= output_arg
;
11433 if (!lcommunity_list_match(
11434 bgp_attr_get_lcommunity(pi
->attr
),
11439 == bgp_show_type_lcommunity_list_exact
) {
11440 struct community_list
*list
= output_arg
;
11442 if (!lcommunity_list_exact_match(
11443 bgp_attr_get_lcommunity(pi
->attr
),
11447 if (type
== bgp_show_type_lcommunity_all
) {
11448 if (!bgp_attr_get_lcommunity(pi
->attr
))
11451 if (type
== bgp_show_type_dampend_paths
11452 || type
== bgp_show_type_damp_neighbor
) {
11453 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11454 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11458 if (!use_json
&& header
) {
11460 "BGP table version is %" PRIu64
11461 ", local router ID is %pI4, vrf id ",
11462 table
->version
, &bgp
->router_id
);
11463 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11464 vty_out(vty
, "%s", VRFID_NONE_STR
);
11466 vty_out(vty
, "%u", bgp
->vrf_id
);
11467 vty_out(vty
, "\n");
11468 vty_out(vty
, "Default local pref %u, ",
11469 bgp
->default_local_pref
);
11470 vty_out(vty
, "local AS %u\n", bgp
->as
);
11471 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11472 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11473 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11474 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11475 if (type
== bgp_show_type_dampend_paths
11476 || type
== bgp_show_type_damp_neighbor
)
11477 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11478 else if (type
== bgp_show_type_flap_statistics
11479 || type
== bgp_show_type_flap_neighbor
)
11480 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11482 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11483 : BGP_SHOW_HEADER
));
11486 } else if (json_detail
&& json_paths
!= NULL
) {
11487 const struct prefix_rd
*prd
;
11488 json_object
*jtemp
;
11490 /* Use common detail header, for most types;
11491 * need a json 'object'.
11494 jtemp
= json_object_new_object();
11495 prd
= bgp_rd_from_dest(dest
, safi
);
11497 route_vty_out_detail_header(
11498 vty
, bgp
, dest
, prd
, table
->afi
,
11501 json_object_array_add(json_paths
, jtemp
);
11503 json_detail
= false;
11506 if (rd
!= NULL
&& !display
&& !output_count
) {
11509 "Route Distinguisher: %s\n",
11512 if (type
== bgp_show_type_dampend_paths
11513 || type
== bgp_show_type_damp_neighbor
)
11514 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11515 AFI_IP
, safi
, use_json
,
11517 else if (type
== bgp_show_type_flap_statistics
11518 || type
== bgp_show_type_flap_neighbor
)
11519 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11520 AFI_IP
, safi
, use_json
,
11523 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
11524 route_vty_out_detail(
11525 vty
, bgp
, dest
, pi
,
11526 family2afi(dest_p
->family
),
11527 safi
, RPKI_NOT_BEING_USED
,
11530 route_vty_out(vty
, dest_p
, pi
, display
,
11531 safi
, json_paths
, wide
);
11541 /* encode prefix */
11542 if (dest_p
->family
== AF_FLOWSPEC
) {
11543 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11546 bgp_fs_nlri_get_string(
11548 dest_p
->u
.prefix_flowspec
.ptr
,
11549 dest_p
->u
.prefix_flowspec
.prefixlen
,
11550 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11551 family2afi(dest_p
->u
11552 .prefix_flowspec
.family
));
11554 vty_out(vty
, "\"%s/%d\": ", retstr
,
11555 dest_p
->u
.prefix_flowspec
11558 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11559 dest_p
->u
.prefix_flowspec
11563 vty_out(vty
, "\"%pFX\": ", dest_p
);
11565 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11567 vty_json(vty
, json_paths
);
11571 json_object_free(json_paths
);
11575 output_count
+= *output_cum
;
11576 *output_cum
= output_count
;
11579 total_count
+= *total_cum
;
11580 *total_cum
= total_count
;
11584 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11588 for (i
= 0; i
< *json_header_depth
; ++i
)
11589 vty_out(vty
, " } ");
11591 vty_out(vty
, "\n");
11595 /* No route is displayed */
11596 if (output_count
== 0) {
11597 if (type
== bgp_show_type_normal
)
11599 "No BGP prefixes displayed, %ld exist\n",
11603 "\nDisplayed %ld routes and %ld total paths\n",
11604 output_count
, total_count
);
11608 return CMD_SUCCESS
;
11611 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11612 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11613 enum bgp_show_type type
, void *output_arg
, bool use_json
)
11615 struct bgp_dest
*dest
, *next
;
11616 unsigned long output_cum
= 0;
11617 unsigned long total_cum
= 0;
11618 unsigned long json_header_depth
= 0;
11619 struct bgp_table
*itable
;
11621 uint16_t show_flags
= 0;
11623 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11626 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11628 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11629 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11631 next
= bgp_route_next(dest
);
11632 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11635 itable
= bgp_dest_get_bgp_table_info(dest
);
11636 if (itable
!= NULL
) {
11637 struct prefix_rd prd
;
11638 char rd
[RD_ADDRSTRLEN
];
11640 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11641 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11642 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11643 rd
, next
== NULL
, &output_cum
,
11644 &total_cum
, &json_header_depth
,
11645 show_flags
, RPKI_NOT_BEING_USED
);
11651 if (output_cum
== 0)
11652 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11656 "\nDisplayed %ld routes and %ld total paths\n",
11657 output_cum
, total_cum
);
11659 return CMD_SUCCESS
;
11662 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11663 enum bgp_show_type type
, void *output_arg
,
11664 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11666 struct bgp_table
*table
;
11667 unsigned long json_header_depth
= 0;
11668 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11671 bgp
= bgp_get_default();
11676 vty_out(vty
, "No BGP process is configured\n");
11678 vty_out(vty
, "{}\n");
11679 return CMD_WARNING
;
11682 /* Labeled-unicast routes live in the unicast table. */
11683 if (safi
== SAFI_LABELED_UNICAST
)
11684 safi
= SAFI_UNICAST
;
11686 table
= bgp
->rib
[afi
][safi
];
11687 /* use MPLS and ENCAP specific shows until they are merged */
11688 if (safi
== SAFI_MPLS_VPN
) {
11689 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11690 output_arg
, use_json
);
11693 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11694 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11695 output_arg
, use_json
,
11699 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11700 NULL
, NULL
, &json_header_depth
, show_flags
,
11701 rpki_target_state
);
11704 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11705 safi_t safi
, uint16_t show_flags
)
11707 struct listnode
*node
, *nnode
;
11710 bool route_output
= false;
11711 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11714 vty_out(vty
, "{\n");
11716 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11717 route_output
= true;
11720 vty_out(vty
, ",\n");
11724 vty_out(vty
, "\"%s\":",
11725 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11729 vty_out(vty
, "\nInstance %s:\n",
11730 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11734 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11735 show_flags
, RPKI_NOT_BEING_USED
);
11739 vty_out(vty
, "}\n");
11740 else if (!route_output
)
11741 vty_out(vty
, "%% BGP instance not found\n");
11744 /* Header of detailed BGP route information */
11745 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11746 struct bgp_dest
*dest
,
11747 const struct prefix_rd
*prd
,
11748 afi_t afi
, safi_t safi
, json_object
*json
)
11750 struct bgp_path_info
*pi
;
11751 const struct prefix
*p
;
11753 struct listnode
*node
, *nnode
;
11754 char buf1
[RD_ADDRSTRLEN
];
11758 int accept_own
= 0;
11759 int route_filter_translated_v4
= 0;
11760 int route_filter_v4
= 0;
11761 int route_filter_translated_v6
= 0;
11762 int route_filter_v6
= 0;
11763 int llgr_stale
= 0;
11765 int accept_own_nexthop
= 0;
11768 int no_advertise
= 0;
11772 int has_valid_label
= 0;
11773 mpls_label_t label
= 0;
11774 json_object
*json_adv_to
= NULL
;
11779 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11781 p
= bgp_dest_get_prefix(dest
);
11782 has_valid_label
= bgp_is_valid_label(&label
);
11784 if (safi
== SAFI_EVPN
) {
11786 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11787 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11789 prd
? ":" : "", (struct prefix_evpn
*)p
);
11791 json_object_string_add(json
, "rd",
11792 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11794 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11799 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11801 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11802 ? prefix_rd2str(prd
, buf1
,
11805 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11809 json_object_string_addf(json
, "prefix", "%pFX", p
);
11810 json_object_int_add(json
, "version", dest
->version
);
11815 if (has_valid_label
) {
11817 json_object_int_add(json
, "localLabel", label
);
11819 vty_out(vty
, "Local label: %d\n", label
);
11823 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11824 vty_out(vty
, "not allocated\n");
11826 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11827 struct community
*picomm
= NULL
;
11829 picomm
= bgp_attr_get_community(pi
->attr
);
11832 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11834 if (bgp_path_suppressed(pi
))
11840 no_advertise
+= community_include(
11841 picomm
, COMMUNITY_NO_ADVERTISE
);
11843 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11845 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11847 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11848 route_filter_translated_v4
+= community_include(
11849 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11850 route_filter_translated_v6
+= community_include(
11851 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11852 route_filter_v4
+= community_include(
11853 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11854 route_filter_v6
+= community_include(
11855 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11857 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11858 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11859 accept_own_nexthop
+= community_include(
11860 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11862 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11863 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11868 vty_out(vty
, "Paths: (%d available", count
);
11870 vty_out(vty
, ", best #%d", best
);
11871 if (safi
== SAFI_UNICAST
) {
11872 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11873 vty_out(vty
, ", table %s",
11876 vty_out(vty
, ", vrf %s",
11880 vty_out(vty
, ", no best path");
11884 ", accept own local route exported and imported in different VRF");
11885 else if (route_filter_translated_v4
)
11887 ", mark translated RTs for VPNv4 route filtering");
11888 else if (route_filter_v4
)
11890 ", attach RT as-is for VPNv4 route filtering");
11891 else if (route_filter_translated_v6
)
11893 ", mark translated RTs for VPNv6 route filtering");
11894 else if (route_filter_v6
)
11896 ", attach RT as-is for VPNv6 route filtering");
11897 else if (llgr_stale
)
11899 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11902 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11903 else if (accept_own_nexthop
)
11905 ", accept local nexthop");
11906 else if (blackhole
)
11907 vty_out(vty
, ", inform peer to blackhole prefix");
11908 else if (no_export
)
11909 vty_out(vty
, ", not advertised to EBGP peer");
11910 else if (no_advertise
)
11911 vty_out(vty
, ", not advertised to any peer");
11913 vty_out(vty
, ", not advertised outside local AS");
11916 ", inform EBGP peer not to advertise to their EBGP peers");
11920 ", Advertisements suppressed by an aggregate.");
11921 vty_out(vty
, ")\n");
11924 /* If we are not using addpath then we can display Advertised to and
11926 * show what peers we advertised the bestpath to. If we are using
11928 * though then we must display Advertised to on a path-by-path basis. */
11929 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11930 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11931 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11932 if (json
&& !json_adv_to
)
11933 json_adv_to
= json_object_new_object();
11935 route_vty_out_advertised_to(
11937 " Advertised to non peer-group peers:\n ",
11944 json_object_object_add(json
, "advertisedTo",
11949 vty_out(vty
, " Not advertised to any peer");
11950 vty_out(vty
, "\n");
11955 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
11956 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11957 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11958 json_object
*json
, enum bgp_path_type pathtype
,
11959 int *display
, enum rpki_states rpki_target_state
)
11961 struct bgp_path_info
*pi
;
11963 json_object
*json_header
= NULL
;
11964 json_object
*json_paths
= NULL
;
11965 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
11967 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11968 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11970 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
11971 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
11972 pi
->peer
, pi
->attr
, p
);
11974 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11975 && rpki_curr_state
!= rpki_target_state
)
11978 if (json
&& !json_paths
) {
11979 /* Instantiate json_paths only if path is valid */
11980 json_paths
= json_object_new_array();
11982 json_header
= json_object_new_object();
11984 json_header
= json
;
11988 route_vty_out_detail_header(
11989 vty
, bgp
, bgp_node
, pfx_rd
,
11990 AFI_IP
, safi
, json_header
);
11995 if (pathtype
== BGP_PATH_SHOW_ALL
11996 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11997 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11998 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11999 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12000 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12001 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
12002 safi
, rpki_curr_state
, json_paths
);
12005 if (json
&& json_paths
) {
12006 json_object_object_add(json_header
, "paths", json_paths
);
12009 json_object_object_addf(json
, json_header
, "%pRD",
12015 * Return rd based on safi
12017 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12021 case SAFI_MPLS_VPN
:
12024 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12030 /* Display specified route of BGP table. */
12031 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12032 struct bgp_table
*rib
, const char *ip_str
,
12033 afi_t afi
, safi_t safi
,
12034 enum rpki_states rpki_target_state
,
12035 struct prefix_rd
*prd
, int prefix_check
,
12036 enum bgp_path_type pathtype
, bool use_json
)
12040 struct prefix match
;
12041 struct bgp_dest
*dest
;
12042 struct bgp_dest
*rm
;
12043 struct bgp_table
*table
;
12044 json_object
*json
= NULL
;
12045 json_object
*json_paths
= NULL
;
12047 /* Check IP address argument. */
12048 ret
= str2prefix(ip_str
, &match
);
12050 vty_out(vty
, "address is malformed\n");
12051 return CMD_WARNING
;
12054 match
.family
= afi2family(afi
);
12057 json
= json_object_new_object();
12059 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12060 for (dest
= bgp_table_top(rib
); dest
;
12061 dest
= bgp_route_next(dest
)) {
12062 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12064 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12066 table
= bgp_dest_get_bgp_table_info(dest
);
12070 rm
= bgp_node_match(table
, &match
);
12074 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12076 && rm_p
->prefixlen
!= match
.prefixlen
) {
12077 bgp_dest_unlock_node(rm
);
12081 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12082 bgp
, afi
, safi
, json
, pathtype
,
12083 &display
, rpki_target_state
);
12085 bgp_dest_unlock_node(rm
);
12087 } else if (safi
== SAFI_EVPN
) {
12088 struct bgp_dest
*longest_pfx
;
12089 bool is_exact_pfxlen_match
= false;
12091 for (dest
= bgp_table_top(rib
); dest
;
12092 dest
= bgp_route_next(dest
)) {
12093 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12095 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12097 table
= bgp_dest_get_bgp_table_info(dest
);
12101 longest_pfx
= NULL
;
12102 is_exact_pfxlen_match
= false;
12104 * Search through all the prefixes for a match. The
12105 * pfx's are enumerated in ascending order of pfxlens.
12106 * So, the last pfx match is the longest match. Set
12107 * is_exact_pfxlen_match when we get exact pfxlen match
12109 for (rm
= bgp_table_top(table
); rm
;
12110 rm
= bgp_route_next(rm
)) {
12111 const struct prefix
*rm_p
=
12112 bgp_dest_get_prefix(rm
);
12114 * Get prefixlen of the ip-prefix within type5
12117 if (evpn_type5_prefix_match(rm_p
, &match
)
12121 bgp_evpn_get_type5_prefixlen(
12123 if (type5_pfxlen
== match
.prefixlen
) {
12124 is_exact_pfxlen_match
= true;
12125 bgp_dest_unlock_node(rm
);
12134 if (prefix_check
&& !is_exact_pfxlen_match
)
12138 bgp_dest_lock_node(rm
);
12140 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12141 bgp
, afi
, safi
, json
, pathtype
,
12142 &display
, rpki_target_state
);
12144 bgp_dest_unlock_node(rm
);
12146 } else if (safi
== SAFI_FLOWSPEC
) {
12148 json_paths
= json_object_new_array();
12150 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12151 &match
, prefix_check
,
12157 json_object_object_add(json
, "paths",
12160 json_object_free(json_paths
);
12163 dest
= bgp_node_match(rib
, &match
);
12164 if (dest
!= NULL
) {
12165 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12167 || dest_p
->prefixlen
== match
.prefixlen
) {
12168 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12169 safi
, json
, pathtype
,
12170 &display
, rpki_target_state
);
12173 bgp_dest_unlock_node(dest
);
12178 vty_json(vty
, json
);
12181 vty_out(vty
, "%% Network not in table\n");
12182 return CMD_WARNING
;
12186 return CMD_SUCCESS
;
12189 /* Display specified route of Main RIB */
12190 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12191 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12192 int prefix_check
, enum bgp_path_type pathtype
,
12193 enum rpki_states rpki_target_state
, bool use_json
)
12196 bgp
= bgp_get_default();
12199 vty_out(vty
, "No BGP process is configured\n");
12201 vty_out(vty
, "{}\n");
12202 return CMD_WARNING
;
12206 /* labeled-unicast routes live in the unicast table */
12207 if (safi
== SAFI_LABELED_UNICAST
)
12208 safi
= SAFI_UNICAST
;
12210 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12211 afi
, safi
, rpki_target_state
, prd
,
12212 prefix_check
, pathtype
, use_json
);
12215 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12216 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12217 safi_t safi
, bool uj
)
12219 struct lcommunity
*lcom
;
12224 uint16_t show_flags
= 0;
12228 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12230 b
= buffer_new(1024);
12231 for (i
= 0; i
< argc
; i
++) {
12233 buffer_putc(b
, ' ');
12235 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12237 buffer_putstr(b
, argv
[i
]->arg
);
12241 buffer_putc(b
, '\0');
12243 str
= buffer_getstr(b
);
12246 lcom
= lcommunity_str2com(str
);
12247 XFREE(MTYPE_TMP
, str
);
12249 vty_out(vty
, "%% Large-community malformed\n");
12250 return CMD_WARNING
;
12253 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12254 (exact
? bgp_show_type_lcommunity_exact
12255 : bgp_show_type_lcommunity
),
12256 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12258 lcommunity_free(&lcom
);
12262 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12263 const char *lcom
, bool exact
, afi_t afi
,
12264 safi_t safi
, bool uj
)
12266 struct community_list
*list
;
12267 uint16_t show_flags
= 0;
12270 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12273 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12274 LARGE_COMMUNITY_LIST_MASTER
);
12275 if (list
== NULL
) {
12276 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12278 return CMD_WARNING
;
12281 return bgp_show(vty
, bgp
, afi
, safi
,
12282 (exact
? bgp_show_type_lcommunity_list_exact
12283 : bgp_show_type_lcommunity_list
),
12284 list
, show_flags
, RPKI_NOT_BEING_USED
);
12287 DEFUN (show_ip_bgp_large_community_list
,
12288 show_ip_bgp_large_community_list_cmd
,
12289 "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]",
12293 BGP_INSTANCE_HELP_STR
12295 BGP_SAFI_WITH_LABEL_HELP_STR
12296 "Display routes matching the large-community-list\n"
12297 "large-community-list number\n"
12298 "large-community-list name\n"
12299 "Exact match of the large-communities\n"
12302 afi_t afi
= AFI_IP6
;
12303 safi_t safi
= SAFI_UNICAST
;
12305 bool exact_match
= 0;
12306 struct bgp
*bgp
= NULL
;
12307 bool uj
= use_json(argc
, argv
);
12312 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12315 return CMD_WARNING
;
12317 argv_find(argv
, argc
, "large-community-list", &idx
);
12319 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12321 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12324 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12325 exact_match
, afi
, safi
, uj
);
12327 DEFUN (show_ip_bgp_large_community
,
12328 show_ip_bgp_large_community_cmd
,
12329 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12333 BGP_INSTANCE_HELP_STR
12335 BGP_SAFI_WITH_LABEL_HELP_STR
12336 "Display routes matching the large-communities\n"
12337 "List of large-community numbers\n"
12338 "Exact match of the large-communities\n"
12341 afi_t afi
= AFI_IP6
;
12342 safi_t safi
= SAFI_UNICAST
;
12344 bool exact_match
= 0;
12345 struct bgp
*bgp
= NULL
;
12346 bool uj
= use_json(argc
, argv
);
12347 uint16_t show_flags
= 0;
12351 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12354 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12357 return CMD_WARNING
;
12359 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12360 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12364 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12365 exact_match
, afi
, safi
, uj
);
12367 return bgp_show(vty
, bgp
, afi
, safi
,
12368 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12369 RPKI_NOT_BEING_USED
);
12372 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12373 safi_t safi
, struct json_object
*json_array
);
12374 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12375 safi_t safi
, struct json_object
*json
);
12378 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12379 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12380 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12381 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12383 bool uj
= use_json(argc
, argv
);
12384 struct bgp
*bgp
= NULL
;
12385 safi_t safi
= SAFI_UNICAST
;
12386 afi_t afi
= AFI_IP6
;
12388 struct json_object
*json_all
= NULL
;
12389 struct json_object
*json_afi_safi
= NULL
;
12391 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12394 return CMD_WARNING
;
12397 json_all
= json_object_new_object();
12399 FOREACH_AFI_SAFI (afi
, safi
) {
12401 * So limit output to those afi/safi pairs that
12402 * actually have something interesting in them
12404 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12409 json_afi_safi
= json_object_new_array();
12410 json_object_object_add(
12412 get_afi_safi_str(afi
, safi
, true),
12415 json_afi_safi
= NULL
;
12418 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12422 vty_json(vty
, json_all
);
12424 return CMD_SUCCESS
;
12427 /* BGP route print out function without JSON */
12428 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12429 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12430 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12434 BGP_INSTANCE_HELP_STR
12437 "BGP RIB advertisement statistics\n"
12440 afi_t afi
= AFI_IP6
;
12441 safi_t safi
= SAFI_UNICAST
;
12442 struct bgp
*bgp
= NULL
;
12444 bool uj
= use_json(argc
, argv
);
12445 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12447 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12450 return CMD_WARNING
;
12453 json_afi_safi
= json_object_new_array();
12455 json_afi_safi
= NULL
;
12457 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12460 json
= json_object_new_object();
12461 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12463 vty_json(vty
, json
);
12468 /* BGP route print out function without JSON */
12469 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12470 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12471 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12473 statistics [json]",
12474 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12475 BGP_SAFI_WITH_LABEL_HELP_STR
12476 "BGP RIB advertisement statistics\n" JSON_STR
)
12478 afi_t afi
= AFI_IP6
;
12479 safi_t safi
= SAFI_UNICAST
;
12480 struct bgp
*bgp
= NULL
;
12482 bool uj
= use_json(argc
, argv
);
12483 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12485 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12488 return CMD_WARNING
;
12491 json_afi_safi
= json_object_new_array();
12493 json_afi_safi
= NULL
;
12495 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12498 json
= json_object_new_object();
12499 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12501 vty_json(vty
, json
);
12506 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12507 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12508 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12509 "]] [all$all] dampening parameters [json]",
12510 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12511 BGP_SAFI_WITH_LABEL_HELP_STR
12512 "Display the entries for all address families\n"
12513 "Display detailed information about dampening\n"
12514 "Display detail of configured dampening parameters\n"
12517 afi_t afi
= AFI_IP6
;
12518 safi_t safi
= SAFI_UNICAST
;
12519 struct bgp
*bgp
= NULL
;
12521 uint16_t show_flags
= 0;
12522 bool uj
= use_json(argc
, argv
);
12526 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12529 /* [<ipv4|ipv6> [all]] */
12531 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12532 if (argv_find(argv
, argc
, "ipv4", &idx
))
12533 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12535 if (argv_find(argv
, argc
, "ipv6", &idx
))
12536 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12539 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12542 return CMD_WARNING
;
12544 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12547 /* BGP route print out function */
12548 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12549 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12550 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12554 |dampening <flap-statistics|dampened-paths>\
12555 |community [AA:NN|local-AS|no-advertise|no-export\
12556 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12557 |accept-own|accept-own-nexthop|route-filter-v6\
12558 |route-filter-v4|route-filter-translated-v6\
12559 |route-filter-translated-v4] [exact-match]\
12560 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12561 |filter-list AS_PATH_FILTER_NAME\
12563 |access-list ACCESSLIST_NAME\
12564 |route-map RMAP_NAME\
12565 |rpki <invalid|valid|notfound>\
12566 |version (1-4294967295)\
12568 |A.B.C.D/M longer-prefixes\
12569 |X:X::X:X/M longer-prefixes\
12570 |optimal-route-reflection [WORD$orr_group_name]\
12571 ] [json$uj [detail$detail] | wide$wide]",
12572 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12573 BGP_SAFI_WITH_LABEL_HELP_STR
12574 "Display the entries for all address families\n"
12575 "Display only routes with non-natural netmasks\n"
12576 "Display detailed information about dampening\n"
12577 "Display flap statistics of routes\n"
12578 "Display paths suppressed due to dampening\n"
12579 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12580 "Do not send outside local AS (well-known community)\n"
12581 "Do not advertise to any peer (well-known community)\n"
12582 "Do not export to next AS (well-known community)\n"
12583 "Graceful shutdown (well-known community)\n"
12584 "Do not export to any peer (well-known community)\n"
12585 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12586 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12587 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12588 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12589 "Should accept VPN route with local nexthop (well-known community)\n"
12590 "RT VPNv6 route filtering (well-known community)\n"
12591 "RT VPNv4 route filtering (well-known community)\n"
12592 "RT translated VPNv6 route filtering (well-known community)\n"
12593 "RT translated VPNv4 route filtering (well-known community)\n"
12594 "Exact match of the communities\n"
12595 "Community-list number\n"
12596 "Community-list name\n"
12597 "Display routes matching the community-list\n"
12598 "Exact match of the communities\n"
12599 "Display routes conforming to the filter-list\n"
12600 "Regular expression access list name\n"
12601 "Display routes conforming to the prefix-list\n"
12602 "Prefix-list name\n"
12603 "Display routes conforming to the access-list\n"
12604 "Access-list name\n"
12605 "Display routes matching the route-map\n"
12606 "A route-map to match on\n"
12607 "RPKI route types\n"
12608 "A valid path as determined by rpki\n"
12609 "A invalid path as determined by rpki\n"
12610 "A path that has no rpki data\n"
12611 "Display prefixes with matching version numbers\n"
12612 "Version number and above\n"
12613 "Display prefixes with matching BGP community alias\n"
12614 "BGP community alias\n"
12616 "Display route and more specific routes\n"
12618 "Display route and more specific routes\n"
12619 "Display Optimal Route Reflection RR Clients\n"
12622 "Display detailed version of JSON output\n"
12623 "Increase table width for longer prefixes\n")
12625 afi_t afi
= AFI_IP6
;
12626 safi_t safi
= SAFI_UNICAST
;
12627 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12628 void *output_arg
= NULL
;
12629 struct bgp
*bgp
= NULL
;
12631 int exact_match
= 0;
12632 char *community
= NULL
;
12634 uint16_t show_flags
= 0;
12635 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12637 bool orr_group
= false;
12641 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12645 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12647 /* [<ipv4|ipv6> [all]] */
12649 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12651 if (argv_find(argv
, argc
, "ipv4", &idx
))
12652 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12654 if (argv_find(argv
, argc
, "ipv6", &idx
))
12655 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12659 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12661 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12664 return CMD_WARNING
;
12666 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12667 sh_type
= bgp_show_type_cidr_only
;
12669 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12670 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12671 sh_type
= bgp_show_type_dampend_paths
;
12672 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12673 sh_type
= bgp_show_type_flap_statistics
;
12676 if (argv_find(argv
, argc
, "community", &idx
)) {
12677 char *maybecomm
= NULL
;
12679 if (idx
+ 1 < argc
) {
12680 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12681 maybecomm
= argv
[idx
+ 1]->arg
;
12683 maybecomm
= argv
[idx
+ 1]->text
;
12686 if (maybecomm
&& !strmatch(maybecomm
, "json")
12687 && !strmatch(maybecomm
, "exact-match"))
12688 community
= maybecomm
;
12690 if (argv_find(argv
, argc
, "exact-match", &idx
))
12694 sh_type
= bgp_show_type_community_all
;
12697 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12698 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12699 struct community_list
*list
;
12701 if (argv_find(argv
, argc
, "exact-match", &idx
))
12704 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12705 COMMUNITY_LIST_MASTER
);
12706 if (list
== NULL
) {
12707 vty_out(vty
, "%% %s community-list not found\n",
12708 clist_number_or_name
);
12709 return CMD_WARNING
;
12713 sh_type
= bgp_show_type_community_list_exact
;
12715 sh_type
= bgp_show_type_community_list
;
12719 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12720 const char *filter
= argv
[++idx
]->arg
;
12721 struct as_list
*as_list
;
12723 as_list
= as_list_lookup(filter
);
12724 if (as_list
== NULL
) {
12725 vty_out(vty
, "%% %s AS-path access-list not found\n",
12727 return CMD_WARNING
;
12730 sh_type
= bgp_show_type_filter_list
;
12731 output_arg
= as_list
;
12734 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12735 const char *prefix_list_str
= argv
[++idx
]->arg
;
12736 struct prefix_list
*plist
;
12738 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12739 if (plist
== NULL
) {
12740 vty_out(vty
, "%% %s prefix-list not found\n",
12742 return CMD_WARNING
;
12745 sh_type
= bgp_show_type_prefix_list
;
12746 output_arg
= plist
;
12749 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12750 const char *access_list_str
= argv
[++idx
]->arg
;
12751 struct access_list
*alist
;
12753 alist
= access_list_lookup(afi
, access_list_str
);
12755 vty_out(vty
, "%% %s access-list not found\n",
12757 return CMD_WARNING
;
12760 sh_type
= bgp_show_type_access_list
;
12761 output_arg
= alist
;
12764 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12765 const char *rmap_str
= argv
[++idx
]->arg
;
12766 struct route_map
*rmap
;
12768 rmap
= route_map_lookup_by_name(rmap_str
);
12770 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12771 return CMD_WARNING
;
12774 sh_type
= bgp_show_type_route_map
;
12778 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12779 sh_type
= bgp_show_type_rpki
;
12780 if (argv_find(argv
, argc
, "valid", &idx
))
12781 rpki_target_state
= RPKI_VALID
;
12782 else if (argv_find(argv
, argc
, "invalid", &idx
))
12783 rpki_target_state
= RPKI_INVALID
;
12786 /* Display prefixes with matching version numbers */
12787 if (argv_find(argv
, argc
, "version", &idx
)) {
12788 sh_type
= bgp_show_type_prefix_version
;
12789 output_arg
= argv
[idx
+ 1]->arg
;
12792 /* Display prefixes with matching BGP community alias */
12793 if (argv_find(argv
, argc
, "alias", &idx
)) {
12794 sh_type
= bgp_show_type_community_alias
;
12795 output_arg
= argv
[idx
+ 1]->arg
;
12798 /* prefix-longer */
12799 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12800 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12801 const char *prefix_str
= argv
[idx
]->arg
;
12803 if (!str2prefix(prefix_str
, &p
)) {
12804 vty_out(vty
, "%% Malformed Prefix\n");
12805 return CMD_WARNING
;
12808 sh_type
= bgp_show_type_prefix_longer
;
12812 if (argv_find(argv
, argc
, "optimal-route-reflection", &idx
))
12816 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12818 return bgp_show_community(vty
, bgp
, community
,
12819 exact_match
, afi
, safi
,
12821 else if (orr_group
)
12822 return bgp_show_orr(vty
, bgp
, afi
, safi
, orr_group_name
,
12825 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12826 output_arg
, show_flags
,
12827 rpki_target_state
);
12829 struct listnode
*node
;
12831 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12835 vty_out(vty
, "{\n");
12837 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12838 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12839 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12842 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12843 FOREACH_SAFI (safi
) {
12844 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12852 vty_out(vty
, ",\n");
12853 vty_out(vty
, "\"%s\":{\n",
12854 get_afi_safi_str(afi
,
12859 "\nFor address family: %s\n",
12865 bgp_show_community(
12866 vty
, abgp
, community
,
12867 exact_match
, afi
, safi
,
12869 else if (orr_group
)
12870 bgp_show_orr(vty
, bgp
, afi
,
12875 bgp_show(vty
, abgp
, afi
, safi
,
12876 sh_type
, output_arg
,
12878 rpki_target_state
);
12880 vty_out(vty
, "}\n");
12884 /* show <ip> bgp all: for each AFI and SAFI*/
12885 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12886 FOREACH_AFI_SAFI (afi
, safi
) {
12887 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12895 vty_out(vty
, ",\n");
12897 vty_out(vty
, "\"%s\":{\n",
12898 get_afi_safi_str(afi
,
12903 "\nFor address family: %s\n",
12909 bgp_show_community(
12910 vty
, abgp
, community
,
12911 exact_match
, afi
, safi
,
12913 else if (orr_group
)
12914 bgp_show_orr(vty
, bgp
, afi
,
12919 bgp_show(vty
, abgp
, afi
, safi
,
12920 sh_type
, output_arg
,
12922 rpki_target_state
);
12924 vty_out(vty
, "}\n");
12929 vty_out(vty
, "}\n");
12931 return CMD_SUCCESS
;
12934 DEFUN (show_ip_bgp_route
,
12935 show_ip_bgp_route_cmd
,
12936 "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]",
12940 BGP_INSTANCE_HELP_STR
12942 BGP_SAFI_WITH_LABEL_HELP_STR
12943 "Network in the BGP routing table to display\n"
12945 "Network in the BGP routing table to display\n"
12947 "Display only the bestpath\n"
12948 "Display only multipaths\n"
12949 "Display only paths that match the specified rpki state\n"
12950 "A valid path as determined by rpki\n"
12951 "A invalid path as determined by rpki\n"
12952 "A path that has no rpki data\n"
12955 int prefix_check
= 0;
12957 afi_t afi
= AFI_IP6
;
12958 safi_t safi
= SAFI_UNICAST
;
12959 char *prefix
= NULL
;
12960 struct bgp
*bgp
= NULL
;
12961 enum bgp_path_type path_type
;
12962 bool uj
= use_json(argc
, argv
);
12966 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12969 return CMD_WARNING
;
12973 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12974 return CMD_WARNING
;
12977 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12978 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12979 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12981 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12982 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12985 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12986 && afi
!= AFI_IP6
) {
12988 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12989 return CMD_WARNING
;
12991 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12992 && afi
!= AFI_IP
) {
12994 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12995 return CMD_WARNING
;
12998 prefix
= argv
[idx
]->arg
;
13000 /* [<bestpath|multipath>] */
13001 if (argv_find(argv
, argc
, "bestpath", &idx
))
13002 path_type
= BGP_PATH_SHOW_BESTPATH
;
13003 else if (argv_find(argv
, argc
, "multipath", &idx
))
13004 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13006 path_type
= BGP_PATH_SHOW_ALL
;
13008 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13009 path_type
, RPKI_NOT_BEING_USED
, uj
);
13012 DEFUN (show_ip_bgp_regexp
,
13013 show_ip_bgp_regexp_cmd
,
13014 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13018 BGP_INSTANCE_HELP_STR
13020 BGP_SAFI_WITH_LABEL_HELP_STR
13021 "Display routes matching the AS path regular expression\n"
13022 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13025 afi_t afi
= AFI_IP6
;
13026 safi_t safi
= SAFI_UNICAST
;
13027 struct bgp
*bgp
= NULL
;
13028 bool uj
= use_json(argc
, argv
);
13029 char *regstr
= NULL
;
13032 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13035 return CMD_WARNING
;
13037 // get index of regex
13038 if (argv_find(argv
, argc
, "REGEX", &idx
))
13039 regstr
= argv
[idx
]->arg
;
13042 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13043 bgp_show_type_regexp
, uj
);
13046 DEFPY (show_ip_bgp_instance_all
,
13047 show_ip_bgp_instance_all_cmd
,
13048 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13052 BGP_INSTANCE_ALL_HELP_STR
13054 BGP_SAFI_WITH_LABEL_HELP_STR
13056 "Increase table width for longer prefixes\n")
13058 afi_t afi
= AFI_IP6
;
13059 safi_t safi
= SAFI_UNICAST
;
13060 struct bgp
*bgp
= NULL
;
13062 uint16_t show_flags
= 0;
13066 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13070 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13072 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13075 return CMD_WARNING
;
13077 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13078 return CMD_SUCCESS
;
13081 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13082 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13087 uint16_t show_flags
= 0;
13090 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13092 if (!config_bgp_aspath_validate(regstr
)) {
13093 vty_out(vty
, "Invalid character in REGEX %s\n",
13095 return CMD_WARNING_CONFIG_FAILED
;
13098 regex
= bgp_regcomp(regstr
);
13100 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13101 return CMD_WARNING
;
13104 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13105 RPKI_NOT_BEING_USED
);
13106 bgp_regex_free(regex
);
13110 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13111 const char *comstr
, int exact
, afi_t afi
,
13112 safi_t safi
, uint16_t show_flags
)
13114 struct community
*com
;
13117 com
= community_str2com(comstr
);
13119 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13120 return CMD_WARNING
;
13123 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13124 (exact
? bgp_show_type_community_exact
13125 : bgp_show_type_community
),
13126 com
, show_flags
, RPKI_NOT_BEING_USED
);
13127 community_free(&com
);
13133 BGP_STATS_MAXBITLEN
= 0,
13135 BGP_STATS_PREFIXES
,
13137 BGP_STATS_UNAGGREGATEABLE
,
13138 BGP_STATS_MAX_AGGREGATEABLE
,
13139 BGP_STATS_AGGREGATES
,
13141 BGP_STATS_ASPATH_COUNT
,
13142 BGP_STATS_ASPATH_MAXHOPS
,
13143 BGP_STATS_ASPATH_TOTHOPS
,
13144 BGP_STATS_ASPATH_MAXSIZE
,
13145 BGP_STATS_ASPATH_TOTSIZE
,
13146 BGP_STATS_ASN_HIGHEST
,
13150 #define TABLE_STATS_IDX_VTY 0
13151 #define TABLE_STATS_IDX_JSON 1
13153 static const char *table_stats_strs
[][2] = {
13154 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13155 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13156 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13157 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13158 "unaggregateablePrefixes"},
13159 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13160 "maximumAggregateablePrefixes"},
13161 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13162 "bgpAggregateAdvertisements"},
13163 [BGP_STATS_SPACE
] = {"Address space advertised",
13164 "addressSpaceAdvertised"},
13165 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13166 "advertisementsWithPaths"},
13167 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13169 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13171 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13172 "averageAsPathLengthHops"},
13173 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13174 "averageAsPathSizeBytes"},
13175 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13176 [BGP_STATS_MAX
] = {NULL
, NULL
}
13179 struct bgp_table_stats
{
13180 struct bgp_table
*table
;
13181 unsigned long long counts
[BGP_STATS_MAX
];
13184 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13187 double total_space
;
13190 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13191 struct bgp_table_stats
*ts
, unsigned int space
)
13193 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13194 struct bgp_path_info
*pi
;
13195 const struct prefix
*rn_p
;
13197 if (!bgp_dest_has_bgp_path_info_data(dest
))
13200 rn_p
= bgp_dest_get_prefix(dest
);
13201 ts
->counts
[BGP_STATS_PREFIXES
]++;
13202 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13204 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13205 /* check if the prefix is included by any other announcements */
13206 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13207 pdest
= bgp_dest_parent_nolock(pdest
);
13209 if (pdest
== NULL
|| pdest
== top
) {
13210 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13211 /* announced address space */
13213 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13214 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13215 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13218 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13219 ts
->counts
[BGP_STATS_RIB
]++;
13221 if (CHECK_FLAG(pi
->attr
->flag
,
13222 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13223 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13225 /* as-path stats */
13226 if (pi
->attr
->aspath
) {
13227 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13228 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13229 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13231 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13233 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13234 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13236 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13237 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13239 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13240 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13241 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13242 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13247 static void bgp_table_stats_walker(struct thread
*t
)
13249 struct bgp_dest
*dest
, *ndest
;
13250 struct bgp_dest
*top
;
13251 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13252 unsigned int space
= 0;
13254 if (!(top
= bgp_table_top(ts
->table
)))
13257 switch (ts
->table
->afi
) {
13259 space
= IPV4_MAX_BITLEN
;
13262 space
= IPV6_MAX_BITLEN
;
13265 space
= EVPN_ROUTE_PREFIXLEN
;
13271 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13273 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13274 if (ts
->table
->safi
== SAFI_MPLS_VPN
13275 || ts
->table
->safi
== SAFI_ENCAP
13276 || ts
->table
->safi
== SAFI_EVPN
) {
13277 struct bgp_table
*table
;
13279 table
= bgp_dest_get_bgp_table_info(dest
);
13283 top
= bgp_table_top(table
);
13284 for (ndest
= bgp_table_top(table
); ndest
;
13285 ndest
= bgp_route_next(ndest
))
13286 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13288 bgp_table_stats_rn(dest
, top
, ts
, space
);
13293 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13294 struct json_object
*json_array
)
13296 struct listnode
*node
, *nnode
;
13299 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13300 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13303 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13304 safi_t safi
, struct json_object
*json_array
)
13306 struct bgp_table_stats ts
;
13308 int ret
= CMD_SUCCESS
;
13310 struct json_object
*json
= NULL
;
13311 uint32_t bitlen
= 0;
13312 struct json_object
*json_bitlen
;
13315 json
= json_object_new_object();
13317 if (!bgp
->rib
[afi
][safi
]) {
13318 char warning_msg
[50];
13320 snprintf(warning_msg
, sizeof(warning_msg
),
13321 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13325 vty_out(vty
, "%s\n", warning_msg
);
13327 json_object_string_add(json
, "warning", warning_msg
);
13330 goto end_table_stats
;
13334 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13335 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13337 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13339 /* labeled-unicast routes live in the unicast table */
13340 if (safi
== SAFI_LABELED_UNICAST
)
13341 safi
= SAFI_UNICAST
;
13343 memset(&ts
, 0, sizeof(ts
));
13344 ts
.table
= bgp
->rib
[afi
][safi
];
13345 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13347 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13348 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13349 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13353 case BGP_STATS_ASPATH_TOTHOPS
:
13354 case BGP_STATS_ASPATH_TOTSIZE
:
13357 temp_buf
, sizeof(temp_buf
), "%12.2f",
13359 ? (float)ts
.counts
[i
]
13361 [BGP_STATS_ASPATH_COUNT
]
13363 vty_out(vty
, "%-30s: %s",
13364 table_stats_strs
[i
]
13365 [TABLE_STATS_IDX_VTY
],
13368 json_object_double_add(
13370 table_stats_strs
[i
]
13371 [TABLE_STATS_IDX_JSON
],
13373 ? (double)ts
.counts
[i
]
13374 / (double)ts
.counts
13375 [BGP_STATS_ASPATH_COUNT
]
13379 case BGP_STATS_TOTPLEN
:
13382 temp_buf
, sizeof(temp_buf
), "%12.2f",
13384 ? (float)ts
.counts
[i
]
13386 [BGP_STATS_PREFIXES
]
13388 vty_out(vty
, "%-30s: %s",
13389 table_stats_strs
[i
]
13390 [TABLE_STATS_IDX_VTY
],
13393 json_object_double_add(
13395 table_stats_strs
[i
]
13396 [TABLE_STATS_IDX_JSON
],
13398 ? (double)ts
.counts
[i
]
13399 / (double)ts
.counts
13400 [BGP_STATS_PREFIXES
]
13404 case BGP_STATS_SPACE
:
13406 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13408 vty_out(vty
, "%-30s: %s\n",
13409 table_stats_strs
[i
]
13410 [TABLE_STATS_IDX_VTY
],
13413 json_object_double_add(
13415 table_stats_strs
[i
]
13416 [TABLE_STATS_IDX_JSON
],
13417 (double)ts
.total_space
);
13419 if (afi
== AFI_IP6
) {
13421 snprintf(temp_buf
, sizeof(temp_buf
),
13424 * pow(2.0, -128 + 32));
13425 vty_out(vty
, "%30s: %s\n",
13426 "/32 equivalent %s\n",
13429 json_object_double_add(
13430 json
, "/32equivalent",
13431 (double)(ts
.total_space
13436 snprintf(temp_buf
, sizeof(temp_buf
),
13439 * pow(2.0, -128 + 48));
13440 vty_out(vty
, "%30s: %s\n",
13441 "/48 equivalent %s\n",
13444 json_object_double_add(
13445 json
, "/48equivalent",
13446 (double)(ts
.total_space
13452 snprintf(temp_buf
, sizeof(temp_buf
),
13454 ts
.total_space
* 100.
13456 vty_out(vty
, "%30s: %s\n",
13457 "% announced ", temp_buf
);
13459 json_object_double_add(
13460 json
, "%announced",
13461 (double)(ts
.total_space
* 100.
13465 snprintf(temp_buf
, sizeof(temp_buf
),
13468 * pow(2.0, -32 + 8));
13469 vty_out(vty
, "%30s: %s\n",
13470 "/8 equivalent ", temp_buf
);
13472 json_object_double_add(
13473 json
, "/8equivalent",
13474 (double)(ts
.total_space
13475 * pow(2.0, -32 + 8)));
13478 snprintf(temp_buf
, sizeof(temp_buf
),
13481 * pow(2.0, -32 + 24));
13482 vty_out(vty
, "%30s: %s\n",
13483 "/24 equivalent ", temp_buf
);
13485 json_object_double_add(
13486 json
, "/24equivalent",
13487 (double)(ts
.total_space
13488 * pow(2.0, -32 + 24)));
13494 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13496 vty_out(vty
, "%-30s: %s",
13497 table_stats_strs
[i
]
13498 [TABLE_STATS_IDX_VTY
],
13501 json_object_int_add(
13503 table_stats_strs
[i
]
13504 [TABLE_STATS_IDX_JSON
],
13509 vty_out(vty
, "\n");
13514 bitlen
= IPV4_MAX_BITLEN
;
13517 bitlen
= IPV6_MAX_BITLEN
;
13520 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13527 json_bitlen
= json_object_new_array();
13529 for (i
= 0; i
<= bitlen
; i
++) {
13530 struct json_object
*ind_bit
= json_object_new_object();
13532 if (!ts
.prefix_len_count
[i
])
13535 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13536 json_object_int_add(ind_bit
, temp_buf
,
13537 ts
.prefix_len_count
[i
]);
13538 json_object_array_add(json_bitlen
, ind_bit
);
13540 json_object_object_add(json
, "prefixLength", json_bitlen
);
13545 json_object_array_add(json_array
, json
);
13549 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13550 safi_t safi
, struct json_object
*json_array
)
13553 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13554 return CMD_SUCCESS
;
13557 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13569 PCOUNT_BPATH_SELECTED
,
13570 PCOUNT_PFCNT
, /* the figure we display to users */
13574 static const char *const pcount_strs
[] = {
13575 [PCOUNT_ADJ_IN
] = "Adj-in",
13576 [PCOUNT_DAMPED
] = "Damped",
13577 [PCOUNT_REMOVED
] = "Removed",
13578 [PCOUNT_HISTORY
] = "History",
13579 [PCOUNT_STALE
] = "Stale",
13580 [PCOUNT_VALID
] = "Valid",
13581 [PCOUNT_ALL
] = "All RIB",
13582 [PCOUNT_COUNTED
] = "PfxCt counted",
13583 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13584 [PCOUNT_PFCNT
] = "Useable",
13585 [PCOUNT_MAX
] = NULL
,
13588 struct peer_pcounts
{
13589 unsigned int count
[PCOUNT_MAX
];
13590 const struct peer
*peer
;
13591 const struct bgp_table
*table
;
13595 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13597 const struct bgp_adj_in
*ain
;
13598 const struct bgp_path_info
*pi
;
13599 const struct peer
*peer
= pc
->peer
;
13601 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13602 if (ain
->peer
== peer
)
13603 pc
->count
[PCOUNT_ADJ_IN
]++;
13605 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13607 if (pi
->peer
!= peer
)
13610 pc
->count
[PCOUNT_ALL
]++;
13612 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13613 pc
->count
[PCOUNT_DAMPED
]++;
13614 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13615 pc
->count
[PCOUNT_HISTORY
]++;
13616 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13617 pc
->count
[PCOUNT_REMOVED
]++;
13618 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13619 pc
->count
[PCOUNT_STALE
]++;
13620 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13621 pc
->count
[PCOUNT_VALID
]++;
13622 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13623 pc
->count
[PCOUNT_PFCNT
]++;
13624 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13625 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13627 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13628 pc
->count
[PCOUNT_COUNTED
]++;
13629 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13631 EC_LIB_DEVELOPMENT
,
13632 "Attempting to count but flags say it is unusable");
13634 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13636 EC_LIB_DEVELOPMENT
,
13637 "Not counted but flags say we should");
13642 static void bgp_peer_count_walker(struct thread
*t
)
13644 struct bgp_dest
*rn
, *rm
;
13645 const struct bgp_table
*table
;
13646 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13648 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13649 || pc
->safi
== SAFI_EVPN
) {
13650 /* Special handling for 2-level routing tables. */
13651 for (rn
= bgp_table_top(pc
->table
); rn
;
13652 rn
= bgp_route_next(rn
)) {
13653 table
= bgp_dest_get_bgp_table_info(rn
);
13655 for (rm
= bgp_table_top(table
); rm
;
13656 rm
= bgp_route_next(rm
))
13657 bgp_peer_count_proc(rm
, pc
);
13660 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13661 bgp_peer_count_proc(rn
, pc
);
13664 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13665 safi_t safi
, bool use_json
)
13667 struct peer_pcounts pcounts
= {.peer
= peer
};
13669 json_object
*json
= NULL
;
13670 json_object
*json_loop
= NULL
;
13673 json
= json_object_new_object();
13674 json_loop
= json_object_new_object();
13677 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13678 || !peer
->bgp
->rib
[afi
][safi
]) {
13680 json_object_string_add(
13682 "No such neighbor or address family");
13683 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13684 json_object_free(json
);
13685 json_object_free(json_loop
);
13687 vty_out(vty
, "%% No such neighbor or address family\n");
13689 return CMD_WARNING
;
13692 memset(&pcounts
, 0, sizeof(pcounts
));
13693 pcounts
.peer
= peer
;
13694 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13695 pcounts
.safi
= safi
;
13697 /* in-place call via thread subsystem so as to record execution time
13698 * stats for the thread-walk (i.e. ensure this can't be blamed on
13699 * on just vty_read()).
13701 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13704 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13705 json_object_string_add(json
, "multiProtocol",
13706 get_afi_safi_str(afi
, safi
, true));
13707 json_object_int_add(json
, "pfxCounter",
13708 peer
->pcount
[afi
][safi
]);
13710 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13711 json_object_int_add(json_loop
, pcount_strs
[i
],
13714 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13716 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13717 json_object_string_add(json
, "pfxctDriftFor",
13719 json_object_string_add(
13720 json
, "recommended",
13721 "Please report this bug, with the above command output");
13723 vty_json(vty
, json
);
13727 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13728 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13729 peer
->hostname
, peer
->host
,
13730 get_afi_safi_str(afi
, safi
, false));
13732 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13733 get_afi_safi_str(afi
, safi
, false));
13736 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13737 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13739 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13740 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13743 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13744 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13746 "Please report this bug, with the above command output\n");
13750 return CMD_SUCCESS
;
13753 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13754 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13755 "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]",
13759 BGP_INSTANCE_HELP_STR
13762 "Detailed information on TCP and BGP neighbor connections\n"
13763 "Neighbor to display information about\n"
13764 "Neighbor to display information about\n"
13765 "Neighbor on BGP configured interface\n"
13766 "Display detailed prefix count information\n"
13769 afi_t afi
= AFI_IP6
;
13770 safi_t safi
= SAFI_UNICAST
;
13773 struct bgp
*bgp
= NULL
;
13774 bool uj
= use_json(argc
, argv
);
13779 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13782 return CMD_WARNING
;
13784 argv_find(argv
, argc
, "neighbors", &idx
);
13785 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13787 return CMD_WARNING
;
13789 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13792 #ifdef KEEP_OLD_VPN_COMMANDS
13793 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13794 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13795 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13800 "Display information about all VPNv4 NLRIs\n"
13801 "Detailed information on TCP and BGP neighbor connections\n"
13802 "Neighbor to display information about\n"
13803 "Neighbor to display information about\n"
13804 "Neighbor on BGP configured interface\n"
13805 "Display detailed prefix count information\n"
13810 bool uj
= use_json(argc
, argv
);
13812 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13814 return CMD_WARNING
;
13816 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13819 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13820 show_ip_bgp_vpn_all_route_prefix_cmd
,
13821 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13826 "Display information about all VPNv4 NLRIs\n"
13827 "Network in the BGP routing table to display\n"
13828 "Network in the BGP routing table to display\n"
13832 char *network
= NULL
;
13833 struct bgp
*bgp
= bgp_get_default();
13835 vty_out(vty
, "Can't find default instance\n");
13836 return CMD_WARNING
;
13839 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13840 network
= argv
[idx
]->arg
;
13841 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13842 network
= argv
[idx
]->arg
;
13844 vty_out(vty
, "Unable to figure out Network\n");
13845 return CMD_WARNING
;
13848 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13849 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13850 use_json(argc
, argv
));
13852 #endif /* KEEP_OLD_VPN_COMMANDS */
13854 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13855 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13856 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13861 "Network in the BGP routing table to display\n"
13862 "Network in the BGP routing table to display\n"
13863 "Network in the BGP routing table to display\n"
13864 "Network in the BGP routing table to display\n"
13868 char *network
= NULL
;
13869 int prefix_check
= 0;
13871 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13872 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13873 network
= argv
[idx
]->arg
;
13874 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13875 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13876 network
= argv
[idx
]->arg
;
13879 vty_out(vty
, "Unable to figure out Network\n");
13880 return CMD_WARNING
;
13882 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13883 prefix_check
, BGP_PATH_SHOW_ALL
,
13884 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13887 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13888 struct bgp_table
*table
, int *header1
,
13889 int *header2
, json_object
*json
,
13890 json_object
*json_scode
,
13891 json_object
*json_ocode
, bool wide
)
13893 uint64_t version
= table
? table
->version
: 0;
13897 json_object_int_add(json
, "bgpTableVersion", version
);
13898 json_object_string_addf(json
, "bgpLocalRouterId",
13899 "%pI4", &peer
->bgp
->router_id
);
13900 json_object_int_add(json
, "defaultLocPrf",
13901 peer
->bgp
->default_local_pref
);
13902 json_object_int_add(json
, "localAS",
13903 peer
->change_local_as
13904 ? peer
->change_local_as
13906 json_object_object_add(json
, "bgpStatusCodes",
13908 json_object_object_add(json
, "bgpOriginCodes",
13912 "BGP table version is %" PRIu64
13913 ", local router ID is %pI4, vrf id ",
13914 version
, &peer
->bgp
->router_id
);
13915 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
13916 vty_out(vty
, "%s", VRFID_NONE_STR
);
13918 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
13919 vty_out(vty
, "\n");
13920 vty_out(vty
, "Default local pref %u, ",
13921 peer
->bgp
->default_local_pref
);
13922 vty_out(vty
, "local AS %u\n",
13923 peer
->change_local_as
? peer
->change_local_as
13925 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13926 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13927 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13928 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13934 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13935 : BGP_SHOW_HEADER
));
13941 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13942 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13943 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13944 json_object
*json_scode
, json_object
*json_ocode
,
13945 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13946 unsigned long *output_count
, unsigned long *filtered_count
)
13948 struct bgp_adj_in
*ain
;
13949 struct bgp_adj_out
*adj
;
13950 struct bgp_dest
*dest
;
13954 struct update_subgroup
*subgrp
;
13955 struct peer_af
*paf
;
13956 bool route_filtered
;
13957 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13958 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13959 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13960 || (safi
== SAFI_EVPN
))
13966 subgrp
= peer_subgroup(peer
, afi
, safi
);
13968 if (type
== bgp_show_adj_route_advertised
&& subgrp
13969 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13971 json_object_int_add(json
, "bgpTableVersion",
13973 json_object_string_addf(json
, "bgpLocalRouterId",
13974 "%pI4", &bgp
->router_id
);
13975 json_object_int_add(json
, "defaultLocPrf",
13976 bgp
->default_local_pref
);
13977 json_object_int_add(json
, "localAS",
13978 peer
->change_local_as
13979 ? peer
->change_local_as
13981 json_object_object_add(json
, "bgpStatusCodes",
13983 json_object_object_add(json
, "bgpOriginCodes",
13985 json_object_string_add(
13986 json
, "bgpOriginatingDefaultNetwork",
13987 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13990 "BGP table version is %" PRIu64
13991 ", local router ID is %pI4, vrf id ",
13992 table
->version
, &bgp
->router_id
);
13993 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13994 vty_out(vty
, "%s", VRFID_NONE_STR
);
13996 vty_out(vty
, "%u", bgp
->vrf_id
);
13997 vty_out(vty
, "\n");
13998 vty_out(vty
, "Default local pref %u, ",
13999 bgp
->default_local_pref
);
14000 vty_out(vty
, "local AS %u\n",
14001 peer
->change_local_as
? peer
->change_local_as
14003 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14004 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14005 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14006 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14008 vty_out(vty
, "Originating default network %s\n\n",
14009 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14014 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14015 if (type
== bgp_show_adj_route_received
14016 || type
== bgp_show_adj_route_filtered
) {
14017 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14018 if (ain
->peer
!= peer
)
14021 show_adj_route_header(vty
, peer
, table
, header1
,
14022 header2
, json
, json_scode
,
14025 if ((safi
== SAFI_MPLS_VPN
)
14026 || (safi
== SAFI_ENCAP
)
14027 || (safi
== SAFI_EVPN
)) {
14029 json_object_string_add(
14030 json_ar
, "rd", rd_str
);
14031 else if (show_rd
&& rd_str
) {
14033 "Route Distinguisher: %s\n",
14040 route_filtered
= false;
14042 /* Filter prefix using distribute list,
14043 * filter list or prefix list
14045 const struct prefix
*rn_p
=
14046 bgp_dest_get_prefix(dest
);
14047 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14050 route_filtered
= true;
14052 /* Filter prefix using route-map */
14053 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14054 safi
, rmap_name
, NULL
,
14057 if (type
== bgp_show_adj_route_filtered
&&
14058 !route_filtered
&& ret
!= RMAP_DENY
) {
14059 bgp_attr_flush(&attr
);
14063 if (type
== bgp_show_adj_route_received
14064 && (route_filtered
|| ret
== RMAP_DENY
))
14065 (*filtered_count
)++;
14067 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
14068 use_json
, json_ar
, wide
);
14069 bgp_attr_flush(&attr
);
14072 } else if (type
== bgp_show_adj_route_advertised
) {
14073 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14074 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14075 if (paf
->peer
!= peer
|| !adj
->attr
)
14078 show_adj_route_header(vty
, peer
, table
,
14083 const struct prefix
*rn_p
=
14084 bgp_dest_get_prefix(dest
);
14087 ret
= bgp_output_modifier(
14088 peer
, rn_p
, &attr
, afi
, safi
,
14091 if (ret
!= RMAP_DENY
) {
14092 if ((safi
== SAFI_MPLS_VPN
)
14093 || (safi
== SAFI_ENCAP
)
14094 || (safi
== SAFI_EVPN
)) {
14096 json_object_string_add(
14103 "Route Distinguisher: %s\n",
14109 vty
, dest
, rn_p
, &attr
,
14110 safi
, use_json
, json_ar
,
14114 (*filtered_count
)++;
14117 bgp_attr_flush(&attr
);
14119 } else if (type
== bgp_show_adj_route_bestpath
) {
14120 struct bgp_path_info
*pi
;
14122 show_adj_route_header(vty
, peer
, table
, header1
,
14123 header2
, json
, json_scode
,
14126 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14128 if (pi
->peer
!= peer
)
14131 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14134 route_vty_out_tmp(vty
, dest
,
14135 bgp_dest_get_prefix(dest
),
14136 pi
->attr
, safi
, use_json
,
14144 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14145 safi_t safi
, enum bgp_show_adj_route_type type
,
14146 const char *rmap_name
, uint16_t show_flags
)
14149 struct bgp_table
*table
;
14150 json_object
*json
= NULL
;
14151 json_object
*json_scode
= NULL
;
14152 json_object
*json_ocode
= NULL
;
14153 json_object
*json_ar
= NULL
;
14154 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14156 /* Init BGP headers here so they're only displayed once
14157 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14163 * Initialize variables for each RD
14164 * All prefixes under an RD is aggregated within "json_routes"
14166 char rd_str
[BUFSIZ
] = {0};
14167 json_object
*json_routes
= NULL
;
14170 /* For 2-tier tables, prefix counts need to be
14171 * maintained across multiple runs of show_adj_route()
14173 unsigned long output_count_per_rd
;
14174 unsigned long filtered_count_per_rd
;
14175 unsigned long output_count
= 0;
14176 unsigned long filtered_count
= 0;
14179 json
= json_object_new_object();
14180 json_ar
= json_object_new_object();
14181 json_scode
= json_object_new_object();
14182 json_ocode
= json_object_new_object();
14184 json_object_string_add(json_scode
, "suppressed", "s");
14185 json_object_string_add(json_scode
, "damped", "d");
14186 json_object_string_add(json_scode
, "history", "h");
14187 json_object_string_add(json_scode
, "valid", "*");
14188 json_object_string_add(json_scode
, "best", ">");
14189 json_object_string_add(json_scode
, "multipath", "=");
14190 json_object_string_add(json_scode
, "internal", "i");
14191 json_object_string_add(json_scode
, "ribFailure", "r");
14192 json_object_string_add(json_scode
, "stale", "S");
14193 json_object_string_add(json_scode
, "removed", "R");
14195 json_object_string_add(json_ocode
, "igp", "i");
14196 json_object_string_add(json_ocode
, "egp", "e");
14197 json_object_string_add(json_ocode
, "incomplete", "?");
14200 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14202 json_object_string_add(
14204 "No such neighbor or address family");
14205 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14206 json_object_free(json
);
14207 json_object_free(json_ar
);
14208 json_object_free(json_scode
);
14209 json_object_free(json_ocode
);
14211 vty_out(vty
, "%% No such neighbor or address family\n");
14213 return CMD_WARNING
;
14216 if ((type
== bgp_show_adj_route_received
14217 || type
== bgp_show_adj_route_filtered
)
14218 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14219 PEER_FLAG_SOFT_RECONFIG
)) {
14221 json_object_string_add(
14223 "Inbound soft reconfiguration not enabled");
14224 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14225 json_object_free(json
);
14226 json_object_free(json_ar
);
14227 json_object_free(json_scode
);
14228 json_object_free(json_ocode
);
14231 "%% Inbound soft reconfiguration not enabled\n");
14233 return CMD_WARNING
;
14238 /* labeled-unicast routes live in the unicast table */
14239 if (safi
== SAFI_LABELED_UNICAST
)
14240 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14242 table
= bgp
->rib
[afi
][safi
];
14244 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14245 || (safi
== SAFI_EVPN
)) {
14247 struct bgp_dest
*dest
;
14249 for (dest
= bgp_table_top(table
); dest
;
14250 dest
= bgp_route_next(dest
)) {
14251 table
= bgp_dest_get_bgp_table_info(dest
);
14255 output_count_per_rd
= 0;
14256 filtered_count_per_rd
= 0;
14259 json_routes
= json_object_new_object();
14261 const struct prefix_rd
*prd
;
14262 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14265 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
14267 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
14268 rmap_name
, json
, json_routes
, json_scode
,
14269 json_ocode
, show_flags
, &header1
,
14270 &header2
, rd_str
, &output_count_per_rd
,
14271 &filtered_count_per_rd
);
14273 /* Don't include an empty RD in the output! */
14274 if (json_routes
&& (output_count_per_rd
> 0))
14275 json_object_object_add(json_ar
, rd_str
,
14278 output_count
+= output_count_per_rd
;
14279 filtered_count
+= filtered_count_per_rd
;
14282 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14283 json
, json_ar
, json_scode
, json_ocode
,
14284 show_flags
, &header1
, &header2
, rd_str
,
14285 &output_count
, &filtered_count
);
14288 if (type
== bgp_show_adj_route_advertised
)
14289 json_object_object_add(json
, "advertisedRoutes",
14292 json_object_object_add(json
, "receivedRoutes", json_ar
);
14293 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14294 json_object_int_add(json
, "filteredPrefixCounter",
14298 * These fields only give up ownership to `json` when `header1`
14299 * is used (set to zero). See code in `show_adj_route` and
14300 * `show_adj_route_header`.
14302 if (header1
== 1) {
14303 json_object_free(json_scode
);
14304 json_object_free(json_ocode
);
14307 vty_json(vty
, json
);
14308 } else if (output_count
> 0) {
14309 if (filtered_count
> 0)
14311 "\nTotal number of prefixes %ld (%ld filtered)\n",
14312 output_count
, filtered_count
);
14314 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14318 return CMD_SUCCESS
;
14321 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14322 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14323 "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]",
14327 BGP_INSTANCE_HELP_STR
14329 BGP_SAFI_WITH_LABEL_HELP_STR
14330 "Detailed information on TCP and BGP neighbor connections\n"
14331 "Neighbor to display information about\n"
14332 "Neighbor to display information about\n"
14333 "Neighbor on BGP configured interface\n"
14334 "Display the routes selected by best path\n"
14336 "Increase table width for longer prefixes\n")
14338 afi_t afi
= AFI_IP6
;
14339 safi_t safi
= SAFI_UNICAST
;
14340 char *rmap_name
= NULL
;
14341 char *peerstr
= NULL
;
14342 struct bgp
*bgp
= NULL
;
14344 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14346 uint16_t show_flags
= 0;
14349 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14352 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14354 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14358 return CMD_WARNING
;
14360 argv_find(argv
, argc
, "neighbors", &idx
);
14361 peerstr
= argv
[++idx
]->arg
;
14363 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14365 return CMD_WARNING
;
14367 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14371 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
14372 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14373 "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]",
14377 BGP_INSTANCE_HELP_STR
14379 BGP_SAFI_WITH_LABEL_HELP_STR
14380 "Display the entries for all address families\n"
14381 "Detailed information on TCP and BGP neighbor connections\n"
14382 "Neighbor to display information about\n"
14383 "Neighbor to display information about\n"
14384 "Neighbor on BGP configured interface\n"
14385 "Display the routes advertised to a BGP neighbor\n"
14386 "Display the received routes from neighbor\n"
14387 "Display the filtered routes received from neighbor\n"
14388 "Route-map to modify the attributes\n"
14389 "Name of the route map\n"
14391 "Increase table width for longer prefixes\n")
14393 afi_t afi
= AFI_IP6
;
14394 safi_t safi
= SAFI_UNICAST
;
14395 char *peerstr
= NULL
;
14396 struct bgp
*bgp
= NULL
;
14398 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14401 uint16_t show_flags
= 0;
14402 struct listnode
*node
;
14407 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14411 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14412 if (argv_find(argv
, argc
, "ipv4", &idx
))
14413 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14415 if (argv_find(argv
, argc
, "ipv6", &idx
))
14416 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14420 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14422 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14425 return CMD_WARNING
;
14427 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14428 argv_find(argv
, argc
, "neighbors", &idx
);
14429 peerstr
= argv
[++idx
]->arg
;
14431 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14433 return CMD_WARNING
;
14435 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14436 type
= bgp_show_adj_route_advertised
;
14437 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14438 type
= bgp_show_adj_route_received
;
14439 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14440 type
= bgp_show_adj_route_filtered
;
14443 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14446 vty_out(vty
, "{\n");
14448 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14449 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14450 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14452 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14453 FOREACH_SAFI (safi
) {
14454 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14461 vty_out(vty
, ",\n");
14462 vty_out(vty
, "\"%s\":",
14463 get_afi_safi_str(afi
, safi
,
14467 "\nFor address family: %s\n",
14468 get_afi_safi_str(afi
, safi
,
14471 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14472 route_map
, show_flags
);
14476 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14477 FOREACH_AFI_SAFI (afi
, safi
) {
14478 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14485 vty_out(vty
, ",\n");
14486 vty_out(vty
, "\"%s\":",
14487 get_afi_safi_str(afi
, safi
,
14491 "\nFor address family: %s\n",
14492 get_afi_safi_str(afi
, safi
,
14495 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14496 route_map
, show_flags
);
14501 vty_out(vty
, "}\n");
14503 return CMD_SUCCESS
;
14506 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14507 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14508 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14512 BGP_INSTANCE_HELP_STR
14515 BGP_AF_MODIFIER_STR
14516 "Detailed information on TCP and BGP neighbor connections\n"
14517 "Neighbor to display information about\n"
14518 "Neighbor to display information about\n"
14519 "Neighbor on BGP configured interface\n"
14520 "Display information received from a BGP neighbor\n"
14521 "Display the prefixlist filter\n"
14524 afi_t afi
= AFI_IP6
;
14525 safi_t safi
= SAFI_UNICAST
;
14526 char *peerstr
= NULL
;
14531 struct bgp
*bgp
= NULL
;
14532 bool uj
= use_json(argc
, argv
);
14537 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14540 return CMD_WARNING
;
14542 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14543 argv_find(argv
, argc
, "neighbors", &idx
);
14544 peerstr
= argv
[++idx
]->arg
;
14546 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14548 return CMD_WARNING
;
14550 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14551 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14554 vty_out(vty
, "Address Family: %s\n",
14555 get_afi_safi_str(afi
, safi
, false));
14556 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14559 vty_out(vty
, "{}\n");
14561 vty_out(vty
, "No functional output\n");
14564 return CMD_SUCCESS
;
14567 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14568 afi_t afi
, safi_t safi
,
14569 enum bgp_show_type type
, bool use_json
)
14571 uint16_t show_flags
= 0;
14574 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14576 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14578 json_object
*json_no
= NULL
;
14579 json_no
= json_object_new_object();
14580 json_object_string_add(
14581 json_no
, "warning",
14582 "No such neighbor or address family");
14583 vty_out(vty
, "%s\n",
14584 json_object_to_json_string(json_no
));
14585 json_object_free(json_no
);
14587 vty_out(vty
, "%% No such neighbor or address family\n");
14588 return CMD_WARNING
;
14591 /* labeled-unicast routes live in the unicast table */
14592 if (safi
== SAFI_LABELED_UNICAST
)
14593 safi
= SAFI_UNICAST
;
14595 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14596 RPKI_NOT_BEING_USED
);
14599 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14600 show_ip_bgp_flowspec_routes_detailed_cmd
,
14601 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14605 BGP_INSTANCE_HELP_STR
14608 "Detailed information on flowspec entries\n"
14611 afi_t afi
= AFI_IP6
;
14612 safi_t safi
= SAFI_UNICAST
;
14613 struct bgp
*bgp
= NULL
;
14615 bool uj
= use_json(argc
, argv
);
14616 uint16_t show_flags
= BGP_SHOW_OPT_DETAIL
;
14620 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14623 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14626 return CMD_WARNING
;
14628 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14629 show_flags
, RPKI_NOT_BEING_USED
);
14632 DEFUN (show_ip_bgp_neighbor_routes
,
14633 show_ip_bgp_neighbor_routes_cmd
,
14634 "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]",
14638 BGP_INSTANCE_HELP_STR
14640 BGP_SAFI_WITH_LABEL_HELP_STR
14641 "Detailed information on TCP and BGP neighbor connections\n"
14642 "Neighbor to display information about\n"
14643 "Neighbor to display information about\n"
14644 "Neighbor on BGP configured interface\n"
14645 "Display flap statistics of the routes learned from neighbor\n"
14646 "Display the dampened routes received from neighbor\n"
14647 "Display routes learned from neighbor\n"
14650 char *peerstr
= NULL
;
14651 struct bgp
*bgp
= NULL
;
14652 afi_t afi
= AFI_IP6
;
14653 safi_t safi
= SAFI_UNICAST
;
14655 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14657 bool uj
= use_json(argc
, argv
);
14662 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14665 return CMD_WARNING
;
14667 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14668 argv_find(argv
, argc
, "neighbors", &idx
);
14669 peerstr
= argv
[++idx
]->arg
;
14671 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14673 return CMD_WARNING
;
14675 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14676 sh_type
= bgp_show_type_flap_neighbor
;
14677 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14678 sh_type
= bgp_show_type_damp_neighbor
;
14679 else if (argv_find(argv
, argc
, "routes", &idx
))
14680 sh_type
= bgp_show_type_neighbor
;
14682 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14685 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14687 struct bgp_distance
{
14688 /* Distance value for the IP source prefix. */
14691 /* Name of the access-list to be matched. */
14695 DEFUN (show_bgp_afi_vpn_rd_route
,
14696 show_bgp_afi_vpn_rd_route_cmd
,
14697 "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]",
14701 BGP_AF_MODIFIER_STR
14702 "Display information for a route distinguisher\n"
14703 "Route Distinguisher\n"
14704 "All Route Distinguishers\n"
14705 "Network in the BGP routing table to display\n"
14706 "Network in the BGP routing table to display\n"
14710 struct prefix_rd prd
;
14711 afi_t afi
= AFI_MAX
;
14714 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14715 vty_out(vty
, "%% Malformed Address Family\n");
14716 return CMD_WARNING
;
14719 if (!strcmp(argv
[5]->arg
, "all"))
14720 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14721 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14722 RPKI_NOT_BEING_USED
,
14723 use_json(argc
, argv
));
14725 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14727 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14728 return CMD_WARNING
;
14731 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14732 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14733 use_json(argc
, argv
));
14736 static struct bgp_distance
*bgp_distance_new(void)
14738 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14741 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14743 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14746 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14747 const char *ip_str
, const char *access_list_str
)
14754 struct bgp_dest
*dest
;
14755 struct bgp_distance
*bdistance
;
14757 afi
= bgp_node_afi(vty
);
14758 safi
= bgp_node_safi(vty
);
14760 ret
= str2prefix(ip_str
, &p
);
14762 vty_out(vty
, "Malformed prefix\n");
14763 return CMD_WARNING_CONFIG_FAILED
;
14766 distance
= atoi(distance_str
);
14768 /* Get BGP distance node. */
14769 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14770 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14772 bgp_dest_unlock_node(dest
);
14774 bdistance
= bgp_distance_new();
14775 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14778 /* Set distance value. */
14779 bdistance
->distance
= distance
;
14781 /* Reset access-list configuration. */
14782 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14783 if (access_list_str
)
14784 bdistance
->access_list
=
14785 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14787 return CMD_SUCCESS
;
14790 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14791 const char *ip_str
, const char *access_list_str
)
14798 struct bgp_dest
*dest
;
14799 struct bgp_distance
*bdistance
;
14801 afi
= bgp_node_afi(vty
);
14802 safi
= bgp_node_safi(vty
);
14804 ret
= str2prefix(ip_str
, &p
);
14806 vty_out(vty
, "Malformed prefix\n");
14807 return CMD_WARNING_CONFIG_FAILED
;
14810 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14812 vty_out(vty
, "Can't find specified prefix\n");
14813 return CMD_WARNING_CONFIG_FAILED
;
14816 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14817 distance
= atoi(distance_str
);
14819 if (bdistance
->distance
!= distance
) {
14820 vty_out(vty
, "Distance does not match configured\n");
14821 bgp_dest_unlock_node(dest
);
14822 return CMD_WARNING_CONFIG_FAILED
;
14825 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14826 bgp_distance_free(bdistance
);
14828 bgp_dest_set_bgp_path_info(dest
, NULL
);
14829 bgp_dest_unlock_node(dest
);
14830 bgp_dest_unlock_node(dest
);
14832 return CMD_SUCCESS
;
14835 /* Apply BGP information to distance method. */
14836 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14837 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14839 struct bgp_dest
*dest
;
14840 struct prefix q
= {0};
14842 struct bgp_distance
*bdistance
;
14843 struct access_list
*alist
;
14844 struct bgp_static
*bgp_static
;
14849 peer
= pinfo
->peer
;
14851 if (pinfo
->attr
->distance
)
14852 return pinfo
->attr
->distance
;
14854 /* Check source address.
14855 * Note: for aggregate route, peer can have unspec af type.
14857 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14858 && !sockunion2hostprefix(&peer
->su
, &q
))
14861 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14863 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14864 bgp_dest_unlock_node(dest
);
14866 if (bdistance
->access_list
) {
14867 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14869 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14870 return bdistance
->distance
;
14872 return bdistance
->distance
;
14875 /* Backdoor check. */
14876 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14878 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14879 bgp_dest_unlock_node(dest
);
14881 if (bgp_static
->backdoor
) {
14882 if (bgp
->distance_local
[afi
][safi
])
14883 return bgp
->distance_local
[afi
][safi
];
14885 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14889 if (peer
->sort
== BGP_PEER_EBGP
) {
14890 if (bgp
->distance_ebgp
[afi
][safi
])
14891 return bgp
->distance_ebgp
[afi
][safi
];
14892 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14893 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14894 if (bgp
->distance_ibgp
[afi
][safi
])
14895 return bgp
->distance_ibgp
[afi
][safi
];
14896 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14898 if (bgp
->distance_local
[afi
][safi
])
14899 return bgp
->distance_local
[afi
][safi
];
14900 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14904 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14905 * we should tell ZEBRA update the routes for a specific
14906 * AFI/SAFI to reflect changes in RIB.
14908 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
14910 safi_t update_safi
)
14915 FOREACH_AFI_SAFI (afi
, safi
) {
14916 if (!bgp_fibupd_safi(safi
))
14919 if (afi
!= update_afi
&& safi
!= update_safi
)
14922 if (BGP_DEBUG(zebra
, ZEBRA
))
14924 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14925 __func__
, afi
, safi
);
14926 bgp_zebra_announce_table(bgp
, afi
, safi
);
14930 DEFUN (bgp_distance
,
14932 "distance bgp (1-255) (1-255) (1-255)",
14933 "Define an administrative distance\n"
14935 "Distance for routes external to the AS\n"
14936 "Distance for routes internal to the AS\n"
14937 "Distance for local routes\n")
14939 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14940 int idx_number
= 2;
14941 int idx_number_2
= 3;
14942 int idx_number_3
= 4;
14943 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
14944 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
14945 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
14949 afi
= bgp_node_afi(vty
);
14950 safi
= bgp_node_safi(vty
);
14952 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
14953 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
14954 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
14955 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
14956 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
14957 bgp
->distance_local
[afi
][safi
] = distance_local
;
14958 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14960 return CMD_SUCCESS
;
14963 DEFUN (no_bgp_distance
,
14964 no_bgp_distance_cmd
,
14965 "no distance bgp [(1-255) (1-255) (1-255)]",
14967 "Define an administrative distance\n"
14969 "Distance for routes external to the AS\n"
14970 "Distance for routes internal to the AS\n"
14971 "Distance for local routes\n")
14973 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14977 afi
= bgp_node_afi(vty
);
14978 safi
= bgp_node_safi(vty
);
14980 if (bgp
->distance_ebgp
[afi
][safi
] != 0
14981 || bgp
->distance_ibgp
[afi
][safi
] != 0
14982 || bgp
->distance_local
[afi
][safi
] != 0) {
14983 bgp
->distance_ebgp
[afi
][safi
] = 0;
14984 bgp
->distance_ibgp
[afi
][safi
] = 0;
14985 bgp
->distance_local
[afi
][safi
] = 0;
14986 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14988 return CMD_SUCCESS
;
14992 DEFUN (bgp_distance_source
,
14993 bgp_distance_source_cmd
,
14994 "distance (1-255) A.B.C.D/M",
14995 "Define an administrative distance\n"
14996 "Administrative distance\n"
14997 "IP source prefix\n")
14999 int idx_number
= 1;
15000 int idx_ipv4_prefixlen
= 2;
15001 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15002 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15003 return CMD_SUCCESS
;
15006 DEFUN (no_bgp_distance_source
,
15007 no_bgp_distance_source_cmd
,
15008 "no distance (1-255) A.B.C.D/M",
15010 "Define an administrative distance\n"
15011 "Administrative distance\n"
15012 "IP source prefix\n")
15014 int idx_number
= 2;
15015 int idx_ipv4_prefixlen
= 3;
15016 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15017 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15018 return CMD_SUCCESS
;
15021 DEFUN (bgp_distance_source_access_list
,
15022 bgp_distance_source_access_list_cmd
,
15023 "distance (1-255) A.B.C.D/M WORD",
15024 "Define an administrative distance\n"
15025 "Administrative distance\n"
15026 "IP source prefix\n"
15027 "Access list name\n")
15029 int idx_number
= 1;
15030 int idx_ipv4_prefixlen
= 2;
15032 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15033 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15034 return CMD_SUCCESS
;
15037 DEFUN (no_bgp_distance_source_access_list
,
15038 no_bgp_distance_source_access_list_cmd
,
15039 "no distance (1-255) A.B.C.D/M WORD",
15041 "Define an administrative distance\n"
15042 "Administrative distance\n"
15043 "IP source prefix\n"
15044 "Access list name\n")
15046 int idx_number
= 2;
15047 int idx_ipv4_prefixlen
= 3;
15049 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15050 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15051 return CMD_SUCCESS
;
15054 DEFUN (ipv6_bgp_distance_source
,
15055 ipv6_bgp_distance_source_cmd
,
15056 "distance (1-255) X:X::X:X/M",
15057 "Define an administrative distance\n"
15058 "Administrative distance\n"
15059 "IP source prefix\n")
15061 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15062 return CMD_SUCCESS
;
15065 DEFUN (no_ipv6_bgp_distance_source
,
15066 no_ipv6_bgp_distance_source_cmd
,
15067 "no distance (1-255) X:X::X:X/M",
15069 "Define an administrative distance\n"
15070 "Administrative distance\n"
15071 "IP source prefix\n")
15073 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15074 return CMD_SUCCESS
;
15077 DEFUN (ipv6_bgp_distance_source_access_list
,
15078 ipv6_bgp_distance_source_access_list_cmd
,
15079 "distance (1-255) X:X::X:X/M WORD",
15080 "Define an administrative distance\n"
15081 "Administrative distance\n"
15082 "IP source prefix\n"
15083 "Access list name\n")
15085 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15086 return CMD_SUCCESS
;
15089 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15090 no_ipv6_bgp_distance_source_access_list_cmd
,
15091 "no distance (1-255) X:X::X:X/M WORD",
15093 "Define an administrative distance\n"
15094 "Administrative distance\n"
15095 "IP source prefix\n"
15096 "Access list name\n")
15098 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15099 return CMD_SUCCESS
;
15102 DEFUN (bgp_damp_set
,
15104 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15105 "BGP Specific commands\n"
15106 "Enable route-flap dampening\n"
15107 "Half-life time for the penalty\n"
15108 "Value to start reusing a route\n"
15109 "Value to start suppressing a route\n"
15110 "Maximum duration to suppress a stable route\n")
15112 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15113 int idx_half_life
= 2;
15115 int idx_suppress
= 4;
15116 int idx_max_suppress
= 5;
15117 int half
= DEFAULT_HALF_LIFE
* 60;
15118 int reuse
= DEFAULT_REUSE
;
15119 int suppress
= DEFAULT_SUPPRESS
;
15120 int max
= 4 * half
;
15123 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15124 reuse
= atoi(argv
[idx_reuse
]->arg
);
15125 suppress
= atoi(argv
[idx_suppress
]->arg
);
15126 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15127 } else if (argc
== 3) {
15128 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15133 * These can't be 0 but our SA doesn't understand the
15134 * way our cli is constructed
15138 if (suppress
< reuse
) {
15140 "Suppress value cannot be less than reuse value \n");
15144 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15145 reuse
, suppress
, max
);
15148 DEFUN (bgp_damp_unset
,
15149 bgp_damp_unset_cmd
,
15150 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15152 "BGP Specific commands\n"
15153 "Enable route-flap dampening\n"
15154 "Half-life time for the penalty\n"
15155 "Value to start reusing a route\n"
15156 "Value to start suppressing a route\n"
15157 "Maximum duration to suppress a stable route\n")
15159 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15160 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15163 /* Display specified route of BGP table. */
15164 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15165 const char *ip_str
, afi_t afi
, safi_t safi
,
15166 struct prefix_rd
*prd
, int prefix_check
)
15169 struct prefix match
;
15170 struct bgp_dest
*dest
;
15171 struct bgp_dest
*rm
;
15172 struct bgp_path_info
*pi
;
15173 struct bgp_path_info
*pi_temp
;
15175 struct bgp_table
*table
;
15177 /* BGP structure lookup. */
15179 bgp
= bgp_lookup_by_name(view_name
);
15181 vty_out(vty
, "%% Can't find BGP instance %s\n",
15183 return CMD_WARNING
;
15186 bgp
= bgp_get_default();
15188 vty_out(vty
, "%% No BGP process is configured\n");
15189 return CMD_WARNING
;
15193 /* Check IP address argument. */
15194 ret
= str2prefix(ip_str
, &match
);
15196 vty_out(vty
, "%% address is malformed\n");
15197 return CMD_WARNING
;
15200 match
.family
= afi2family(afi
);
15202 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15203 || (safi
== SAFI_EVPN
)) {
15204 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15205 dest
= bgp_route_next(dest
)) {
15206 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15208 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15210 table
= bgp_dest_get_bgp_table_info(dest
);
15213 rm
= bgp_node_match(table
, &match
);
15217 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15220 || rm_p
->prefixlen
== match
.prefixlen
) {
15221 pi
= bgp_dest_get_bgp_path_info(rm
);
15223 if (pi
->extra
&& pi
->extra
->damp_info
) {
15224 pi_temp
= pi
->next
;
15225 bgp_damp_info_free(
15226 pi
->extra
->damp_info
,
15234 bgp_dest_unlock_node(rm
);
15237 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15238 if (dest
!= NULL
) {
15239 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15242 || dest_p
->prefixlen
== match
.prefixlen
) {
15243 pi
= bgp_dest_get_bgp_path_info(dest
);
15245 if (pi
->extra
&& pi
->extra
->damp_info
) {
15246 pi_temp
= pi
->next
;
15247 bgp_damp_info_free(
15248 pi
->extra
->damp_info
,
15256 bgp_dest_unlock_node(dest
);
15260 return CMD_SUCCESS
;
15263 DEFUN (clear_ip_bgp_dampening
,
15264 clear_ip_bgp_dampening_cmd
,
15265 "clear ip bgp dampening",
15269 "Clear route flap dampening information\n")
15271 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15272 return CMD_SUCCESS
;
15275 DEFUN (clear_ip_bgp_dampening_prefix
,
15276 clear_ip_bgp_dampening_prefix_cmd
,
15277 "clear ip bgp dampening A.B.C.D/M",
15281 "Clear route flap dampening information\n"
15284 int idx_ipv4_prefixlen
= 4;
15285 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15286 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15289 DEFUN (clear_ip_bgp_dampening_address
,
15290 clear_ip_bgp_dampening_address_cmd
,
15291 "clear ip bgp dampening A.B.C.D",
15295 "Clear route flap dampening information\n"
15296 "Network to clear damping information\n")
15299 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15300 SAFI_UNICAST
, NULL
, 0);
15303 DEFUN (clear_ip_bgp_dampening_address_mask
,
15304 clear_ip_bgp_dampening_address_mask_cmd
,
15305 "clear ip bgp dampening A.B.C.D A.B.C.D",
15309 "Clear route flap dampening information\n"
15310 "Network to clear damping information\n"
15314 int idx_ipv4_2
= 5;
15316 char prefix_str
[BUFSIZ
];
15318 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15319 prefix_str
, sizeof(prefix_str
));
15321 vty_out(vty
, "%% Inconsistent address and mask\n");
15322 return CMD_WARNING
;
15325 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15329 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15331 struct vty
*vty
= arg
;
15332 struct peer
*peer
= bucket
->data
;
15334 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15337 DEFUN (show_bgp_listeners
,
15338 show_bgp_listeners_cmd
,
15339 "show bgp listeners",
15342 "Display Listen Sockets and who created them\n")
15344 bgp_dump_listener_info(vty
);
15346 return CMD_SUCCESS
;
15349 DEFUN (show_bgp_peerhash
,
15350 show_bgp_peerhash_cmd
,
15351 "show bgp peerhash",
15354 "Display information about the BGP peerhash\n")
15356 struct list
*instances
= bm
->bgp
;
15357 struct listnode
*node
;
15360 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15361 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15362 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15366 return CMD_SUCCESS
;
15369 /* also used for encap safi */
15370 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15371 afi_t afi
, safi_t safi
)
15373 struct bgp_dest
*pdest
;
15374 struct bgp_dest
*dest
;
15375 struct bgp_table
*table
;
15376 const struct prefix
*p
;
15377 const struct prefix_rd
*prd
;
15378 struct bgp_static
*bgp_static
;
15379 mpls_label_t label
;
15381 /* Network configuration. */
15382 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15383 pdest
= bgp_route_next(pdest
)) {
15384 table
= bgp_dest_get_bgp_table_info(pdest
);
15388 for (dest
= bgp_table_top(table
); dest
;
15389 dest
= bgp_route_next(dest
)) {
15390 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15391 if (bgp_static
== NULL
)
15394 p
= bgp_dest_get_prefix(dest
);
15395 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
15398 /* "network" configuration display. */
15399 label
= decode_label(&bgp_static
->label
);
15401 vty_out(vty
, " network %pFX rd %pRD", p
, prd
);
15402 if (safi
== SAFI_MPLS_VPN
)
15403 vty_out(vty
, " label %u", label
);
15405 if (bgp_static
->rmap
.name
)
15406 vty_out(vty
, " route-map %s",
15407 bgp_static
->rmap
.name
);
15409 if (bgp_static
->backdoor
)
15410 vty_out(vty
, " backdoor");
15412 vty_out(vty
, "\n");
15417 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15418 afi_t afi
, safi_t safi
)
15420 struct bgp_dest
*pdest
;
15421 struct bgp_dest
*dest
;
15422 struct bgp_table
*table
;
15423 const struct prefix
*p
;
15424 const struct prefix_rd
*prd
;
15425 struct bgp_static
*bgp_static
;
15426 char buf
[PREFIX_STRLEN
* 2];
15427 char buf2
[SU_ADDRSTRLEN
];
15428 char esi_buf
[ESI_STR_LEN
];
15430 /* Network configuration. */
15431 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15432 pdest
= bgp_route_next(pdest
)) {
15433 table
= bgp_dest_get_bgp_table_info(pdest
);
15437 for (dest
= bgp_table_top(table
); dest
;
15438 dest
= bgp_route_next(dest
)) {
15439 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15440 if (bgp_static
== NULL
)
15443 char *macrouter
= NULL
;
15445 if (bgp_static
->router_mac
)
15446 macrouter
= prefix_mac2str(
15447 bgp_static
->router_mac
, NULL
, 0);
15448 if (bgp_static
->eth_s_id
)
15449 esi_to_str(bgp_static
->eth_s_id
,
15450 esi_buf
, sizeof(esi_buf
));
15451 p
= bgp_dest_get_prefix(dest
);
15452 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15454 /* "network" configuration display. */
15455 if (p
->u
.prefix_evpn
.route_type
== 5) {
15456 char local_buf
[PREFIX_STRLEN
];
15457 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15458 struct prefix_evpn
*)p
)
15462 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
15463 local_buf
, PREFIX_STRLEN
);
15464 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15465 p
->u
.prefix_evpn
.prefix_addr
15466 .ip_prefix_length
);
15468 prefix2str(p
, buf
, sizeof(buf
));
15471 if (bgp_static
->gatewayIp
.family
== AF_INET
15472 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15473 inet_ntop(bgp_static
->gatewayIp
.family
,
15474 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15477 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15478 buf
, prd
, p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15479 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15482 XFREE(MTYPE_TMP
, macrouter
);
15487 /* Configuration of static route announcement and aggregate
15489 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15492 struct bgp_dest
*dest
;
15493 const struct prefix
*p
;
15494 struct bgp_static
*bgp_static
;
15495 struct bgp_aggregate
*bgp_aggregate
;
15497 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15498 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15502 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15503 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15507 /* Network configuration. */
15508 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15509 dest
= bgp_route_next(dest
)) {
15510 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15511 if (bgp_static
== NULL
)
15514 p
= bgp_dest_get_prefix(dest
);
15516 vty_out(vty
, " network %pFX", p
);
15518 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15519 vty_out(vty
, " label-index %u",
15520 bgp_static
->label_index
);
15522 if (bgp_static
->rmap
.name
)
15523 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15525 if (bgp_static
->backdoor
)
15526 vty_out(vty
, " backdoor");
15528 vty_out(vty
, "\n");
15531 /* Aggregate-address configuration. */
15532 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15533 dest
= bgp_route_next(dest
)) {
15534 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15535 if (bgp_aggregate
== NULL
)
15538 p
= bgp_dest_get_prefix(dest
);
15540 vty_out(vty
, " aggregate-address %pFX", p
);
15542 if (bgp_aggregate
->as_set
)
15543 vty_out(vty
, " as-set");
15545 if (bgp_aggregate
->summary_only
)
15546 vty_out(vty
, " summary-only");
15548 if (bgp_aggregate
->rmap
.name
)
15549 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15551 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15552 vty_out(vty
, " origin %s",
15553 bgp_origin2str(bgp_aggregate
->origin
));
15555 if (bgp_aggregate
->match_med
)
15556 vty_out(vty
, " matching-MED-only");
15558 if (bgp_aggregate
->suppress_map_name
)
15559 vty_out(vty
, " suppress-map %s",
15560 bgp_aggregate
->suppress_map_name
);
15562 vty_out(vty
, "\n");
15566 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15569 struct bgp_dest
*dest
;
15570 struct bgp_distance
*bdistance
;
15572 /* Distance configuration. */
15573 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15574 && bgp
->distance_local
[afi
][safi
]
15575 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15576 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15577 || bgp
->distance_local
[afi
][safi
]
15578 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15579 vty_out(vty
, " distance bgp %d %d %d\n",
15580 bgp
->distance_ebgp
[afi
][safi
],
15581 bgp
->distance_ibgp
[afi
][safi
],
15582 bgp
->distance_local
[afi
][safi
]);
15585 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15586 dest
= bgp_route_next(dest
)) {
15587 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15588 if (bdistance
!= NULL
)
15589 vty_out(vty
, " distance %d %pBD %s\n",
15590 bdistance
->distance
, dest
,
15591 bdistance
->access_list
? bdistance
->access_list
15596 /* Allocate routing table structure and install commands. */
15597 void bgp_route_init(void)
15602 /* Init BGP distance table. */
15603 FOREACH_AFI_SAFI (afi
, safi
)
15604 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15606 /* IPv4 BGP commands. */
15607 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15608 install_element(BGP_NODE
, &bgp_network_cmd
);
15609 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15611 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15613 /* IPv4 unicast configuration. */
15614 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15615 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15616 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15618 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15620 /* IPv4 multicast configuration. */
15621 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15622 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15623 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15624 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15626 /* IPv4 labeled-unicast configuration. */
15627 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15628 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15630 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15631 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15632 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15633 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15634 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15635 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15636 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15637 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15639 install_element(VIEW_NODE
,
15640 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15641 install_element(VIEW_NODE
,
15642 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15643 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15644 install_element(VIEW_NODE
,
15645 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15646 #ifdef KEEP_OLD_VPN_COMMANDS
15647 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15648 #endif /* KEEP_OLD_VPN_COMMANDS */
15649 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15650 install_element(VIEW_NODE
,
15651 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15653 /* BGP dampening clear commands */
15654 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15655 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15657 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15658 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15661 install_element(ENABLE_NODE
,
15662 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15663 #ifdef KEEP_OLD_VPN_COMMANDS
15664 install_element(ENABLE_NODE
,
15665 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15666 #endif /* KEEP_OLD_VPN_COMMANDS */
15668 /* New config IPv6 BGP commands. */
15669 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15670 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15671 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15673 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15675 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15677 /* IPv6 labeled unicast address family. */
15678 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15679 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15681 install_element(BGP_NODE
, &bgp_distance_cmd
);
15682 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15683 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15684 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15685 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15686 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15687 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15688 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15689 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15690 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15691 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15692 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15693 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15694 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15695 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15696 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15697 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15698 install_element(BGP_IPV4M_NODE
,
15699 &no_bgp_distance_source_access_list_cmd
);
15700 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15701 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15702 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15703 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15704 install_element(BGP_IPV6_NODE
,
15705 &ipv6_bgp_distance_source_access_list_cmd
);
15706 install_element(BGP_IPV6_NODE
,
15707 &no_ipv6_bgp_distance_source_access_list_cmd
);
15708 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15709 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15710 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15711 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15712 install_element(BGP_IPV6M_NODE
,
15713 &ipv6_bgp_distance_source_access_list_cmd
);
15714 install_element(BGP_IPV6M_NODE
,
15715 &no_ipv6_bgp_distance_source_access_list_cmd
);
15717 /* BGP dampening */
15718 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15719 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15720 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15721 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15722 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15723 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15724 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15725 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15726 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15727 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15728 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15729 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15730 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15731 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15733 /* Large Communities */
15734 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15735 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15737 /* show bgp ipv4 flowspec detailed */
15738 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15740 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15741 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15744 void bgp_route_finish(void)
15749 FOREACH_AFI_SAFI (afi
, safi
) {
15750 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15751 bgp_distance_table
[afi
][safi
] = NULL
;