1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "sockunion.h"
39 #include "workqueue.h"
44 #include "lib_errors.h"
46 #include "bgpd/bgpd.h"
47 #include "bgpd/bgp_table.h"
48 #include "bgpd/bgp_route.h"
49 #include "bgpd/bgp_attr.h"
50 #include "bgpd/bgp_debug.h"
51 #include "bgpd/bgp_errors.h"
52 #include "bgpd/bgp_aspath.h"
53 #include "bgpd/bgp_regex.h"
54 #include "bgpd/bgp_community.h"
55 #include "bgpd/bgp_community_alias.h"
56 #include "bgpd/bgp_ecommunity.h"
57 #include "bgpd/bgp_lcommunity.h"
58 #include "bgpd/bgp_clist.h"
59 #include "bgpd/bgp_packet.h"
60 #include "bgpd/bgp_filter.h"
61 #include "bgpd/bgp_fsm.h"
62 #include "bgpd/bgp_mplsvpn.h"
63 #include "bgpd/bgp_nexthop.h"
64 #include "bgpd/bgp_damp.h"
65 #include "bgpd/bgp_advertise.h"
66 #include "bgpd/bgp_zebra.h"
67 #include "bgpd/bgp_vty.h"
68 #include "bgpd/bgp_mpath.h"
69 #include "bgpd/bgp_nht.h"
70 #include "bgpd/bgp_updgrp.h"
71 #include "bgpd/bgp_label.h"
72 #include "bgpd/bgp_addpath.h"
73 #include "bgpd/bgp_mac.h"
74 #include "bgpd/bgp_network.h"
75 #include "bgpd/bgp_trace.h"
76 #include "bgpd/bgp_rpki.h"
79 #include "bgpd/rfapi/rfapi_backend.h"
80 #include "bgpd/rfapi/vnc_import_bgp.h"
81 #include "bgpd/rfapi/vnc_export_bgp.h"
83 #include "bgpd/bgp_encap_types.h"
84 #include "bgpd/bgp_encap_tlv.h"
85 #include "bgpd/bgp_evpn.h"
86 #include "bgpd/bgp_evpn_mh.h"
87 #include "bgpd/bgp_evpn_vty.h"
88 #include "bgpd/bgp_flowspec.h"
89 #include "bgpd/bgp_flowspec_util.h"
90 #include "bgpd/bgp_pbr.h"
92 #ifndef VTYSH_EXTRACT_PL
93 #include "bgpd/bgp_route_clippy.c"
96 DEFINE_HOOK(bgp_snmp_update_stats
,
97 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
100 DEFINE_HOOK(bgp_rpki_prefix_status
,
101 (struct peer
*peer
, struct attr
*attr
,
102 const struct prefix
*prefix
),
103 (peer
, attr
, prefix
));
105 /* Render dest to prefix_rd based on safi */
106 static const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
109 /* Extern from bgp_dump.c */
110 extern const char *bgp_origin_str
[];
111 extern const char *bgp_origin_long_str
[];
114 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
115 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
116 static const struct message bgp_pmsi_tnltype_str
[] = {
117 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
118 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
119 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
120 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
121 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
122 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
123 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
124 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
128 #define VRFID_NONE_STR "-"
129 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
131 DEFINE_HOOK(bgp_process
,
132 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
133 struct peer
*peer
, bool withdraw
),
134 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
136 /** Test if path is suppressed. */
137 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
139 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
142 return listcount(pi
->extra
->aggr_suppressors
) > 0;
145 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
146 safi_t safi
, const struct prefix
*p
,
147 struct prefix_rd
*prd
)
149 struct bgp_dest
*dest
;
150 struct bgp_dest
*pdest
= NULL
;
154 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
155 || (safi
== SAFI_EVPN
)) {
156 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
158 if (!bgp_dest_has_bgp_path_info_data(pdest
))
159 bgp_dest_set_bgp_table_info(
160 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
162 bgp_dest_unlock_node(pdest
);
163 table
= bgp_dest_get_bgp_table_info(pdest
);
166 dest
= bgp_node_get(table
, p
);
168 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
169 || (safi
== SAFI_EVPN
))
175 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
176 safi_t safi
, const struct prefix
*p
,
177 struct prefix_rd
*prd
)
179 struct bgp_dest
*dest
;
180 struct bgp_dest
*pdest
= NULL
;
185 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
186 || (safi
== SAFI_EVPN
)) {
187 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
191 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
192 bgp_dest_unlock_node(pdest
);
196 table
= bgp_dest_get_bgp_table_info(pdest
);
199 dest
= bgp_node_lookup(table
, p
);
204 /* Allocate bgp_path_info_extra */
205 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
207 struct bgp_path_info_extra
*new;
208 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
209 sizeof(struct bgp_path_info_extra
));
210 new->label
[0] = MPLS_INVALID_LABEL
;
212 new->bgp_fs_pbr
= NULL
;
213 new->bgp_fs_iprule
= NULL
;
217 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
219 struct bgp_path_info_extra
*e
;
221 if (!extra
|| !*extra
)
226 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
231 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
234 /* FIXME: since multiple e may have the same e->parent
235 * and e->parent->net is holding a refcount for each
236 * of them, we need to do some fudging here.
238 * WARNING: if bpi->net->lock drops to 0, bpi may be
239 * freed as well (because bpi->net was holding the
240 * last reference to bpi) => write after free!
244 bpi
= bgp_path_info_lock(bpi
);
245 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
246 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
249 bgp_path_info_unlock(bpi
);
251 bgp_path_info_unlock(e
->parent
);
256 bgp_unlock(e
->bgp_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 attr
*newattr
, *existattr
;
568 bgp_peer_sort_t new_sort
;
569 bgp_peer_sort_t exist_sort
;
575 uint32_t exist_weight
;
576 uint32_t newm
, existm
;
577 struct in_addr new_id
;
578 struct in_addr exist_id
;
581 int internal_as_route
;
584 int igp_metric_ret
= 0;
585 int peer_sort_ret
= -1;
586 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
587 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
589 uint32_t exist_mm_seq
;
596 bool new_origin
, exist_origin
;
597 struct bgp_path_info
*bpi_ultimate
;
603 *reason
= bgp_path_selection_none
;
605 zlog_debug("%s: new is NULL", pfx_buf
);
610 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
616 *reason
= bgp_path_selection_first
;
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf
, bgp
->name_pretty
, new_buf
);
624 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
629 exist_buf
, exist
->flags
);
633 existattr
= exist
->attr
;
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
644 if (bgp_attr_get_community(newattr
) &&
645 community_include(bgp_attr_get_community(newattr
),
646 COMMUNITY_LLGR_STALE
)) {
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf
, new_buf
, exist_buf
);
654 if (bgp_attr_get_community(existattr
) &&
655 community_include(bgp_attr_get_community(existattr
),
656 COMMUNITY_LLGR_STALE
)) {
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf
, new_buf
, exist_buf
);
664 new_p
= bgp_dest_get_prefix(new->net
);
666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
669 if ((safi
== SAFI_EVPN
)
670 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
671 /* This is an error condition described in RFC 7432 Section
673 * states that in this scenario "the PE MUST alert the operator"
675 * does not state what other action to take. In order to provide
677 * consistency in this scenario we are going to prefer the path
681 if (newattr
->sticky
!= existattr
->sticky
) {
683 prefix2str(new_p
, pfx_buf
,
685 * PREFIX2STR_BUFFER
);
686 bgp_path_info_path_with_addpath_rx_str(
687 new, new_buf
, sizeof(new_buf
));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist
, exist_buf
, sizeof(exist_buf
));
692 if (newattr
->sticky
&& !existattr
->sticky
) {
693 *reason
= bgp_path_selection_evpn_sticky_mac
;
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf
, new_buf
, exist_buf
);
701 if (!newattr
->sticky
&& existattr
->sticky
) {
702 *reason
= bgp_path_selection_evpn_sticky_mac
;
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf
, new_buf
, exist_buf
);
711 new_esi
= bgp_evpn_attr_get_esi(newattr
);
712 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
713 if (bgp_evpn_is_esi_valid(new_esi
) &&
714 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
728 char esi_buf
[ESI_STR_LEN
];
730 if (bgp_evpn_is_path_local(bgp
, new)) {
731 *reason
= bgp_path_selection_evpn_local_path
;
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf
, new_buf
, exist_buf
,
736 esi_to_str(new_esi
, esi_buf
,
740 if (bgp_evpn_is_path_local(bgp
, exist
)) {
741 *reason
= bgp_path_selection_evpn_local_path
;
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf
, new_buf
, exist_buf
,
746 esi_to_str(new_esi
, esi_buf
,
752 new_mm_seq
= mac_mobility_seqnum(newattr
);
753 exist_mm_seq
= mac_mobility_seqnum(existattr
);
755 if (new_mm_seq
> exist_mm_seq
) {
756 *reason
= bgp_path_selection_evpn_seq
;
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
765 if (new_mm_seq
< exist_mm_seq
) {
766 *reason
= bgp_path_selection_evpn_seq
;
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
778 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
779 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
780 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
781 old_proxy
!= new_proxy
) {
783 *reason
= bgp_path_selection_evpn_non_proxy
;
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf
, new_buf
, exist_buf
);
791 *reason
= bgp_path_selection_evpn_non_proxy
;
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf
, new_buf
, exist_buf
);
800 * if sequence numbers are the same path with the lowest IP
803 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
805 *reason
= bgp_path_selection_evpn_lower_ip
;
808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
809 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
810 &new->attr
->nexthop
);
814 *reason
= bgp_path_selection_evpn_lower_ip
;
817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
818 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
819 &new->attr
->nexthop
);
824 /* 1. Weight check. */
825 new_weight
= newattr
->weight
;
826 exist_weight
= existattr
->weight
;
828 if (new_weight
> exist_weight
) {
829 *reason
= bgp_path_selection_weight
;
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf
, new_buf
, exist_buf
, new_weight
,
837 if (new_weight
< exist_weight
) {
838 *reason
= bgp_path_selection_weight
;
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf
, new_buf
, exist_buf
, new_weight
,
846 /* 2. Local preference check. */
847 new_pref
= exist_pref
= bgp
->default_local_pref
;
849 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
850 new_pref
= newattr
->local_pref
;
851 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
852 exist_pref
= existattr
->local_pref
;
854 if (new_pref
> exist_pref
) {
855 *reason
= bgp_path_selection_local_pref
;
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf
, new_buf
, exist_buf
, new_pref
,
864 if (new_pref
< exist_pref
) {
865 *reason
= bgp_path_selection_local_pref
;
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf
, new_buf
, exist_buf
, new_pref
,
874 /* 3. Local route check. We prefer:
876 * - BGP_ROUTE_AGGREGATE
877 * - BGP_ROUTE_REDISTRIBUTE
879 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
880 new->sub_type
== BGP_ROUTE_IMPORTED
);
881 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
882 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
884 if (new_origin
&& !exist_origin
) {
885 *reason
= bgp_path_selection_local_route
;
888 "%s: %s wins over %s due to preferred BGP_ROUTE type",
889 pfx_buf
, new_buf
, exist_buf
);
893 if (!new_origin
&& exist_origin
) {
894 *reason
= bgp_path_selection_local_route
;
897 "%s: %s loses to %s due to preferred BGP_ROUTE type",
898 pfx_buf
, new_buf
, exist_buf
);
902 /* Here if these are imported routes then get ultimate pi for
905 new = bgp_get_imported_bpi_ultimate(new);
906 exist
= bgp_get_imported_bpi_ultimate(exist
);
908 existattr
= exist
->attr
;
910 /* 4. AS path length check. */
911 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
912 int exist_hops
= aspath_count_hops(existattr
->aspath
);
913 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
915 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
918 aspath_hops
= aspath_count_hops(newattr
->aspath
);
919 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
921 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
922 *reason
= bgp_path_selection_confed_as_path
;
925 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
926 pfx_buf
, new_buf
, exist_buf
,
928 (exist_hops
+ exist_confeds
));
932 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
933 *reason
= bgp_path_selection_confed_as_path
;
936 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
937 pfx_buf
, new_buf
, exist_buf
,
939 (exist_hops
+ exist_confeds
));
943 int newhops
= aspath_count_hops(newattr
->aspath
);
945 if (newhops
< exist_hops
) {
946 *reason
= bgp_path_selection_as_path
;
949 "%s: %s wins over %s due to aspath hopcount %d < %d",
950 pfx_buf
, new_buf
, exist_buf
,
951 newhops
, exist_hops
);
955 if (newhops
> exist_hops
) {
956 *reason
= bgp_path_selection_as_path
;
959 "%s: %s loses to %s due to aspath hopcount %d > %d",
960 pfx_buf
, new_buf
, exist_buf
,
961 newhops
, exist_hops
);
967 /* 5. Origin check. */
968 if (newattr
->origin
< existattr
->origin
) {
969 *reason
= bgp_path_selection_origin
;
971 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
972 pfx_buf
, new_buf
, exist_buf
,
973 bgp_origin_long_str
[newattr
->origin
],
974 bgp_origin_long_str
[existattr
->origin
]);
978 if (newattr
->origin
> existattr
->origin
) {
979 *reason
= bgp_path_selection_origin
;
981 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
982 pfx_buf
, new_buf
, exist_buf
,
983 bgp_origin_long_str
[newattr
->origin
],
984 bgp_origin_long_str
[existattr
->origin
]);
989 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
990 && aspath_count_hops(existattr
->aspath
) == 0);
991 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
992 && aspath_count_confeds(existattr
->aspath
) > 0
993 && aspath_count_hops(newattr
->aspath
) == 0
994 && aspath_count_hops(existattr
->aspath
) == 0);
996 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
997 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
998 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
999 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1000 || internal_as_route
) {
1001 new_med
= bgp_med_value(new->attr
, bgp
);
1002 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1004 if (new_med
< exist_med
) {
1005 *reason
= bgp_path_selection_med
;
1008 "%s: %s wins over %s due to MED %d < %d",
1009 pfx_buf
, new_buf
, exist_buf
, new_med
,
1014 if (new_med
> exist_med
) {
1015 *reason
= bgp_path_selection_med
;
1018 "%s: %s loses to %s due to MED %d > %d",
1019 pfx_buf
, new_buf
, exist_buf
, new_med
,
1025 /* 7. Peer type check. */
1026 new_sort
= new->peer
->sort
;
1027 exist_sort
= exist
->peer
->sort
;
1029 if (new_sort
== BGP_PEER_EBGP
1030 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1031 *reason
= bgp_path_selection_peer
;
1034 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1035 pfx_buf
, new_buf
, exist_buf
);
1036 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1041 if (exist_sort
== BGP_PEER_EBGP
1042 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1043 *reason
= bgp_path_selection_peer
;
1046 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1047 pfx_buf
, new_buf
, exist_buf
);
1048 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1053 /* 8. IGP metric check. */
1057 newm
= new->extra
->igpmetric
;
1059 existm
= exist
->extra
->igpmetric
;
1061 if (newm
< existm
) {
1062 if (debug
&& peer_sort_ret
< 0)
1064 "%s: %s wins over %s due to IGP metric %u < %u",
1065 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1069 if (newm
> existm
) {
1070 if (debug
&& peer_sort_ret
< 0)
1072 "%s: %s loses to %s due to IGP metric %u > %u",
1073 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1077 /* 9. Same IGP metric. Compare the cluster list length as
1078 representative of IGP hops metric. Rewrite the metric value
1079 pair (newm, existm) with the cluster list length. Prefer the
1080 path with smaller cluster list length. */
1081 if (newm
== existm
) {
1082 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
1083 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
1084 && (mpath_cfg
== NULL
1086 mpath_cfg
->ibgp_flags
,
1087 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
1088 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1089 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1091 if (newm
< existm
) {
1092 if (debug
&& peer_sort_ret
< 0)
1094 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1095 pfx_buf
, new_buf
, exist_buf
,
1100 if (newm
> existm
) {
1101 if (debug
&& peer_sort_ret
< 0)
1103 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1104 pfx_buf
, new_buf
, exist_buf
,
1111 /* 10. confed-external vs. confed-internal */
1112 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1113 if (new_sort
== BGP_PEER_CONFED
1114 && exist_sort
== BGP_PEER_IBGP
) {
1115 *reason
= bgp_path_selection_confed
;
1118 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1119 pfx_buf
, new_buf
, exist_buf
);
1120 if (!CHECK_FLAG(bgp
->flags
,
1121 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1126 if (exist_sort
== BGP_PEER_CONFED
1127 && new_sort
== BGP_PEER_IBGP
) {
1128 *reason
= bgp_path_selection_confed
;
1131 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1132 pfx_buf
, new_buf
, exist_buf
);
1133 if (!CHECK_FLAG(bgp
->flags
,
1134 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1140 /* 11. Maximum path check. */
1141 if (newm
== existm
) {
1142 /* If one path has a label but the other does not, do not treat
1143 * them as equals for multipath
1145 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1147 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1150 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1151 pfx_buf
, new_buf
, exist_buf
);
1152 } else if (CHECK_FLAG(bgp
->flags
,
1153 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1156 * For the two paths, all comparison steps till IGP
1158 * have succeeded - including AS_PATH hop count. Since
1160 * bestpath as-path multipath-relax' knob is on, we
1162 * an exact match of AS_PATH. Thus, mark the paths are
1164 * That will trigger both these paths to get into the
1172 "%s: %s and %s are equal via multipath-relax",
1173 pfx_buf
, new_buf
, exist_buf
);
1174 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1175 if (aspath_cmp(new->attr
->aspath
,
1176 exist
->attr
->aspath
)) {
1181 "%s: %s and %s are equal via matching aspaths",
1182 pfx_buf
, new_buf
, exist_buf
);
1184 } else if (new->peer
->as
== exist
->peer
->as
) {
1189 "%s: %s and %s are equal via same remote-as",
1190 pfx_buf
, new_buf
, exist_buf
);
1194 * TODO: If unequal cost ibgp multipath is enabled we can
1195 * mark the paths as equal here instead of returning
1198 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1199 * if either step 7 or 10 (peer type checks) yielded a winner,
1200 * that result was returned immediately. Returning from step 10
1201 * ignored the return value computed in steps 8 and 9 (IGP
1202 * metric checks). In order to preserve that behavior, if
1203 * peer_sort_ret is set, return that rather than igp_metric_ret.
1205 ret
= peer_sort_ret
;
1206 if (peer_sort_ret
< 0) {
1207 ret
= igp_metric_ret
;
1211 "%s: %s wins over %s after IGP metric comparison",
1212 pfx_buf
, new_buf
, exist_buf
);
1215 "%s: %s loses to %s after IGP metric comparison",
1216 pfx_buf
, new_buf
, exist_buf
);
1218 *reason
= bgp_path_selection_igp_metric
;
1224 * At this point, the decision whether to set *paths_eq = 1 has been
1225 * completed. If we deferred returning because of bestpath peer-type
1226 * relax configuration, return now.
1228 if (peer_sort_ret
>= 0)
1229 return peer_sort_ret
;
1231 /* 12. If both paths are external, prefer the path that was received
1232 first (the oldest one). This step minimizes route-flap, since a
1233 newer path won't displace an older one, even if it was the
1234 preferred route based on the additional decision criteria below. */
1235 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1236 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1237 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1238 *reason
= bgp_path_selection_older
;
1241 "%s: %s wins over %s due to oldest external",
1242 pfx_buf
, new_buf
, exist_buf
);
1246 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1247 *reason
= bgp_path_selection_older
;
1250 "%s: %s loses to %s due to oldest external",
1251 pfx_buf
, new_buf
, exist_buf
);
1256 /* 13. Router-ID comparision. */
1257 /* If one of the paths is "stale", the corresponding peer router-id will
1258 * be 0 and would always win over the other path. If originator id is
1259 * used for the comparision, it will decide which path is better.
1261 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1262 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1264 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1265 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1266 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1268 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1270 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1271 *reason
= bgp_path_selection_router_id
;
1274 "%s: %s wins over %s due to Router-ID comparison",
1275 pfx_buf
, new_buf
, exist_buf
);
1279 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1280 *reason
= bgp_path_selection_router_id
;
1283 "%s: %s loses to %s due to Router-ID comparison",
1284 pfx_buf
, new_buf
, exist_buf
);
1288 /* 14. Cluster length comparision. */
1289 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1290 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1292 if (new_cluster
< exist_cluster
) {
1293 *reason
= bgp_path_selection_cluster_length
;
1296 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1297 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1302 if (new_cluster
> exist_cluster
) {
1303 *reason
= bgp_path_selection_cluster_length
;
1306 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1307 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1312 /* 15. Neighbor address comparision. */
1313 /* Do this only if neither path is "stale" as stale paths do not have
1314 * valid peer information (as the connection may or may not be up).
1316 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1317 *reason
= bgp_path_selection_stale
;
1320 "%s: %s wins over %s due to latter path being STALE",
1321 pfx_buf
, new_buf
, exist_buf
);
1325 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1326 *reason
= bgp_path_selection_stale
;
1329 "%s: %s loses to %s due to former path being STALE",
1330 pfx_buf
, new_buf
, exist_buf
);
1334 /* locally configured routes to advertise do not have su_remote */
1335 if (new->peer
->su_remote
== NULL
) {
1336 *reason
= bgp_path_selection_local_configured
;
1339 if (exist
->peer
->su_remote
== NULL
) {
1340 *reason
= bgp_path_selection_local_configured
;
1344 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1347 *reason
= bgp_path_selection_neighbor_ip
;
1350 "%s: %s loses to %s due to Neighor IP comparison",
1351 pfx_buf
, new_buf
, exist_buf
);
1356 *reason
= bgp_path_selection_neighbor_ip
;
1359 "%s: %s wins over %s due to Neighor IP comparison",
1360 pfx_buf
, new_buf
, exist_buf
);
1364 *reason
= bgp_path_selection_default
;
1366 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1367 pfx_buf
, new_buf
, exist_buf
);
1373 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1374 struct bgp_path_info
*exist
, int *paths_eq
)
1376 enum bgp_path_selection_reason reason
;
1377 char pfx_buf
[PREFIX2STR_BUFFER
];
1379 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1380 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1383 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1384 * is preferred, or 0 if they are the same (usually will only occur if
1385 * multipath is enabled
1386 * This version is compatible with */
1387 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1388 struct bgp_path_info
*exist
, char *pfx_buf
,
1389 afi_t afi
, safi_t safi
,
1390 enum bgp_path_selection_reason
*reason
)
1394 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1408 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1409 const struct prefix
*p
,
1410 struct attr
*attr
, afi_t afi
,
1413 struct bgp_filter
*filter
;
1414 enum filter_type ret
= FILTER_PERMIT
;
1416 filter
= &peer
->filter
[afi
][safi
];
1418 #define FILTER_EXIST_WARN(F, f, filter) \
1419 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1420 zlog_debug("%s: Could not find configured input %s-list %s!", \
1421 peer->host, #f, F##_IN_NAME(filter));
1423 if (DISTRIBUTE_IN_NAME(filter
)) {
1424 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1426 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1433 if (PREFIX_LIST_IN_NAME(filter
)) {
1434 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1436 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1443 if (FILTER_LIST_IN_NAME(filter
)) {
1444 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1446 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1447 == AS_FILTER_DENY
) {
1454 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1455 char pfxprint
[PREFIX2STR_BUFFER
];
1457 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1458 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1459 ret
== FILTER_PERMIT
? "permit" : "deny");
1463 #undef FILTER_EXIST_WARN
1466 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1467 const struct prefix
*p
,
1468 struct attr
*attr
, afi_t afi
,
1471 struct bgp_filter
*filter
;
1472 enum filter_type ret
= FILTER_PERMIT
;
1474 filter
= &peer
->filter
[afi
][safi
];
1476 #define FILTER_EXIST_WARN(F, f, filter) \
1477 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1478 zlog_debug("%s: Could not find configured output %s-list %s!", \
1479 peer->host, #f, F##_OUT_NAME(filter));
1481 if (DISTRIBUTE_OUT_NAME(filter
)) {
1482 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1484 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1491 if (PREFIX_LIST_OUT_NAME(filter
)) {
1492 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1494 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1501 if (FILTER_LIST_OUT_NAME(filter
)) {
1502 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1504 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1505 == AS_FILTER_DENY
) {
1511 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1512 char pfxprint
[PREFIX2STR_BUFFER
];
1514 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1515 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1516 ret
== FILTER_PERMIT
? "permit" : "deny");
1521 #undef FILTER_EXIST_WARN
1524 /* If community attribute includes no_export then return 1. */
1525 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1527 if (bgp_attr_get_community(attr
)) {
1528 /* NO_ADVERTISE check. */
1529 if (community_include(bgp_attr_get_community(attr
),
1530 COMMUNITY_NO_ADVERTISE
))
1533 /* NO_EXPORT check. */
1534 if (peer
->sort
== BGP_PEER_EBGP
&&
1535 community_include(bgp_attr_get_community(attr
),
1536 COMMUNITY_NO_EXPORT
))
1539 /* NO_EXPORT_SUBCONFED check. */
1540 if (peer
->sort
== BGP_PEER_EBGP
1541 || peer
->sort
== BGP_PEER_CONFED
)
1542 if (community_include(bgp_attr_get_community(attr
),
1543 COMMUNITY_NO_EXPORT_SUBCONFED
))
1549 /* Route reflection loop check. */
1550 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1552 struct in_addr cluster_id
;
1553 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1556 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1557 cluster_id
= peer
->bgp
->cluster_id
;
1559 cluster_id
= peer
->bgp
->router_id
;
1561 if (cluster_loop_check(cluster
, cluster_id
))
1567 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1568 struct attr
*attr
, afi_t afi
, safi_t safi
,
1569 const char *rmap_name
, mpls_label_t
*label
,
1570 uint32_t num_labels
, struct bgp_dest
*dest
)
1572 struct bgp_filter
*filter
;
1573 struct bgp_path_info rmap_path
= { 0 };
1574 struct bgp_path_info_extra extra
= { 0 };
1575 route_map_result_t ret
;
1576 struct route_map
*rmap
= NULL
;
1578 filter
= &peer
->filter
[afi
][safi
];
1580 /* Apply default weight value. */
1581 if (peer
->weight
[afi
][safi
])
1582 attr
->weight
= peer
->weight
[afi
][safi
];
1585 rmap
= route_map_lookup_by_name(rmap_name
);
1590 if (ROUTE_MAP_IN_NAME(filter
)) {
1591 rmap
= ROUTE_MAP_IN(filter
);
1598 /* Route map apply. */
1600 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1601 /* Duplicate current value to new strucutre for modification. */
1602 rmap_path
.peer
= peer
;
1603 rmap_path
.attr
= attr
;
1604 rmap_path
.extra
= &extra
;
1605 rmap_path
.net
= dest
;
1607 extra
.num_labels
= num_labels
;
1608 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1609 memcpy(extra
.label
, label
,
1610 num_labels
* sizeof(mpls_label_t
));
1612 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1614 /* Apply BGP route map to the attribute. */
1615 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1617 peer
->rmap_type
= 0;
1619 if (ret
== RMAP_DENYMATCH
)
1625 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1626 struct attr
*attr
, afi_t afi
, safi_t safi
,
1627 const char *rmap_name
)
1629 struct bgp_path_info rmap_path
;
1630 route_map_result_t ret
;
1631 struct route_map
*rmap
= NULL
;
1635 * So if we get to this point and have no rmap_name
1636 * we want to just show the output as it currently
1642 /* Apply default weight value. */
1643 if (peer
->weight
[afi
][safi
])
1644 attr
->weight
= peer
->weight
[afi
][safi
];
1646 rmap
= route_map_lookup_by_name(rmap_name
);
1649 * If we have a route map name and we do not find
1650 * the routemap that means we have an implicit
1656 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1657 /* Route map apply. */
1658 /* Duplicate current value to new strucutre for modification. */
1659 rmap_path
.peer
= peer
;
1660 rmap_path
.attr
= attr
;
1662 rmap_type
= peer
->rmap_type
;
1663 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1665 /* Apply BGP route map to the attribute. */
1666 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1668 peer
->rmap_type
= rmap_type
;
1670 if (ret
== RMAP_DENYMATCH
)
1672 * caller has multiple error paths with bgp_attr_flush()
1679 /* If this is an EBGP peer with remove-private-AS */
1680 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1681 struct peer
*peer
, struct attr
*attr
)
1683 if (peer
->sort
== BGP_PEER_EBGP
1684 && (peer_af_flag_check(peer
, afi
, safi
,
1685 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1686 || peer_af_flag_check(peer
, afi
, safi
,
1687 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1688 || peer_af_flag_check(peer
, afi
, safi
,
1689 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1690 || peer_af_flag_check(peer
, afi
, safi
,
1691 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1692 // Take action on the entire aspath
1693 if (peer_af_flag_check(peer
, afi
, safi
,
1694 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1695 || peer_af_flag_check(peer
, afi
, safi
,
1696 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1697 if (peer_af_flag_check(
1699 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1700 attr
->aspath
= aspath_replace_private_asns(
1701 attr
->aspath
, bgp
->as
, peer
->as
);
1704 * Even if the aspath consists of just private ASNs we
1705 * need to walk the AS-Path to maintain all instances
1706 * of the peer's ASN to break possible loops.
1709 attr
->aspath
= aspath_remove_private_asns(
1710 attr
->aspath
, peer
->as
);
1713 // 'all' was not specified so the entire aspath must be private
1715 // for us to do anything
1716 else if (aspath_private_as_check(attr
->aspath
)) {
1717 if (peer_af_flag_check(
1719 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1720 attr
->aspath
= aspath_replace_private_asns(
1721 attr
->aspath
, bgp
->as
, peer
->as
);
1724 * Walk the aspath to retain any instances of
1727 attr
->aspath
= aspath_remove_private_asns(
1728 attr
->aspath
, peer
->as
);
1733 /* If this is an EBGP peer with as-override */
1734 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1735 struct peer
*peer
, struct attr
*attr
)
1737 if (peer
->sort
== BGP_PEER_EBGP
1738 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1739 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1740 attr
->aspath
= aspath_replace_specific_asn(
1741 attr
->aspath
, peer
->as
, bgp
->as
);
1745 void bgp_attr_add_llgr_community(struct attr
*attr
)
1747 struct community
*old
;
1748 struct community
*new;
1749 struct community
*merge
;
1750 struct community
*llgr
;
1752 old
= bgp_attr_get_community(attr
);
1753 llgr
= community_str2com("llgr-stale");
1758 merge
= community_merge(community_dup(old
), llgr
);
1760 if (old
->refcnt
== 0)
1761 community_free(&old
);
1763 new = community_uniq_sort(merge
);
1764 community_free(&merge
);
1766 new = community_dup(llgr
);
1769 community_free(&llgr
);
1771 bgp_attr_set_community(attr
, new);
1772 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1775 void bgp_attr_add_gshut_community(struct attr
*attr
)
1777 struct community
*old
;
1778 struct community
*new;
1779 struct community
*merge
;
1780 struct community
*gshut
;
1782 old
= bgp_attr_get_community(attr
);
1783 gshut
= community_str2com("graceful-shutdown");
1788 merge
= community_merge(community_dup(old
), gshut
);
1790 if (old
->refcnt
== 0)
1791 community_free(&old
);
1793 new = community_uniq_sort(merge
);
1794 community_free(&merge
);
1796 new = community_dup(gshut
);
1799 community_free(&gshut
);
1800 bgp_attr_set_community(attr
, new);
1801 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1803 /* When we add the graceful-shutdown community we must also
1804 * lower the local-preference */
1805 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1806 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1810 /* Notify BGP Conditional advertisement scanner process. */
1811 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1813 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1814 afi_t afi
= SUBGRP_AFI(subgrp
);
1815 safi_t safi
= SUBGRP_SAFI(subgrp
);
1816 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1818 if (!ADVERTISE_MAP_NAME(filter
))
1821 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1824 peer
->advmap_table_change
= true;
1828 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1830 if (family
== AF_INET
) {
1831 attr
->nexthop
.s_addr
= INADDR_ANY
;
1832 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1834 if (family
== AF_INET6
)
1835 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1836 if (family
== AF_EVPN
)
1837 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1840 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1841 struct update_subgroup
*subgrp
,
1842 const struct prefix
*p
, struct attr
*attr
,
1843 struct attr
*post_attr
)
1845 struct bgp_filter
*filter
;
1848 struct peer
*onlypeer
;
1850 struct attr
*piattr
;
1851 route_map_result_t ret
;
1856 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1857 bool nh_reset
= false;
1860 if (DISABLE_BGP_ANNOUNCE
)
1863 afi
= SUBGRP_AFI(subgrp
);
1864 safi
= SUBGRP_SAFI(subgrp
);
1865 peer
= SUBGRP_PEER(subgrp
);
1867 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1868 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1871 filter
= &peer
->filter
[afi
][safi
];
1872 bgp
= SUBGRP_INST(subgrp
);
1873 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1876 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
1877 peer
->pmax_out
[afi
][safi
] != 0 &&
1878 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
1879 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
1880 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
1881 zlog_debug("%s reached maximum prefix to be send (%u)",
1882 peer
->host
, peer
->pmax_out
[afi
][safi
]);
1887 #ifdef ENABLE_BGP_VNC
1888 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1889 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1890 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1893 * direct and direct_ext type routes originate internally even
1894 * though they can have peer pointers that reference other
1897 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1903 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1904 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1905 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1906 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1908 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1913 /* With addpath we may be asked to TX all kinds of paths so make sure
1915 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1916 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1917 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1921 /* If this is not the bestpath then check to see if there is an enabled
1923 * feature that requires us to advertise it */
1924 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1925 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1930 /* Aggregate-address suppress check. */
1931 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
1935 * If we are doing VRF 2 VRF leaking via the import
1936 * statement, we want to prevent the route going
1937 * off box as that the RT and RD created are localy
1938 * significant and globaly useless.
1940 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1941 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1944 /* If it's labeled safi, make sure the route has a valid label. */
1945 if (safi
== SAFI_LABELED_UNICAST
) {
1946 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1947 if (!bgp_is_valid_label(&label
)) {
1948 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1949 zlog_debug("u%" PRIu64
":s%" PRIu64
1950 " %pFX is filtered - no label (%p)",
1951 subgrp
->update_group
->id
, subgrp
->id
,
1957 /* Do not send back route to sender. */
1958 if (onlypeer
&& from
== onlypeer
) {
1962 /* Do not send the default route in the BGP table if the neighbor is
1963 * configured for default-originate */
1964 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1965 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1966 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1968 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1972 /* Transparency check. */
1973 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1974 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1979 /* If community is not disabled check the no-export and local. */
1980 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1981 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1982 zlog_debug("%s: community filter check fail for %pFX",
1987 /* If the attribute has originator-id and it is same as remote
1989 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1990 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1991 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1993 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1998 /* ORF prefix-list filter check */
1999 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2000 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2001 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2002 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2003 if (peer
->orf_plist
[afi
][safi
]) {
2004 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2006 if (bgp_debug_update(NULL
, p
,
2007 subgrp
->update_group
, 0))
2009 "%s [Update:SEND] %pFX is filtered via ORF",
2015 /* Output filter check. */
2016 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2017 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2018 zlog_debug("%s [Update:SEND] %pFX is filtered",
2023 /* AS path loop check. */
2024 if (onlypeer
&& onlypeer
->as_path_loop_detection
2025 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
2026 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2028 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2029 onlypeer
->host
, onlypeer
->as
);
2033 /* If we're a CONFED we need to loop check the CONFED ID too */
2034 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2035 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
2036 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2038 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
2039 peer
->host
, bgp
->confed_id
);
2044 /* Route-Reflect check. */
2045 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2050 /* IBGP reflection check. */
2051 if (reflect
&& !samepeer_safe
) {
2052 /* A route from a Client peer. */
2053 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2054 PEER_FLAG_REFLECTOR_CLIENT
)) {
2055 /* Reflect to all the Non-Client peers and also to the
2056 Client peers other than the originator. Originator
2058 is already done. So there is noting to do. */
2059 /* no bgp client-to-client reflection check. */
2060 if (CHECK_FLAG(bgp
->flags
,
2061 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2062 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2063 PEER_FLAG_REFLECTOR_CLIENT
))
2066 /* A route from a Non-client peer. Reflect to all other
2068 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2069 PEER_FLAG_REFLECTOR_CLIENT
))
2074 /* For modify attribute, copy it to temporary structure.
2075 * post_attr comes from BGP conditional advertisements, where
2076 * attributes are already processed by advertise-map route-map,
2077 * and this needs to be saved instead of overwriting from the
2085 /* If local-preference is not set. */
2086 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2087 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2088 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2089 attr
->local_pref
= bgp
->default_local_pref
;
2092 /* If originator-id is not set and the route is to be reflected,
2093 set the originator id */
2095 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2096 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2097 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2100 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2102 if (peer
->sort
== BGP_PEER_EBGP
2103 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2104 if (from
!= bgp
->peer_self
&& !transparent
2105 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2106 PEER_FLAG_MED_UNCHANGED
))
2108 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2111 /* Since the nexthop attribute can vary per peer, it is not explicitly
2113 * in announce check, only certain flags and length (or number of
2115 * -- for IPv6/MP_REACH) are set here in order to guide the update
2117 * code in setting the nexthop(s) on a per peer basis in
2119 * Typically, the source nexthop in the attribute is preserved but in
2121 * scenarios where we know it will always be overwritten, we reset the
2122 * nexthop to "0" in an attempt to achieve better Update packing. An
2123 * example of this is when a prefix from each of 2 IBGP peers needs to
2125 * announced to an EBGP peer (and they have the same attributes barring
2129 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2131 #define NEXTHOP_IS_V6 \
2132 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2133 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2134 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2135 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2137 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2139 * the peer (group) is configured to receive link-local nexthop
2141 * and it is available in the prefix OR we're not reflecting the route,
2142 * link-local nexthop address is valid and
2143 * the peer (group) to whom we're going to announce is on a shared
2145 * and this is either a self-originated route or the peer is EBGP.
2146 * By checking if nexthop LL address is valid we are sure that
2147 * we do not announce LL address as `::`.
2149 if (NEXTHOP_IS_V6
) {
2150 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2151 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2152 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2153 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2154 || (!reflect
&& !transparent
2155 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2156 && peer
->shared_network
2157 && (from
== bgp
->peer_self
2158 || peer
->sort
== BGP_PEER_EBGP
))) {
2159 attr
->mp_nexthop_len
=
2160 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2163 /* Clear off link-local nexthop in source, whenever it is not
2165 * ensure more prefixes share the same attribute for
2168 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2169 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2170 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2173 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2174 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2176 /* Route map & unsuppress-map apply. */
2178 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2179 struct bgp_path_info rmap_path
= {0};
2180 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2181 struct attr dummy_attr
= {0};
2183 /* Fill temp path_info */
2184 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2187 /* don't confuse inbound and outbound setting */
2188 RESET_FLAG(attr
->rmap_change_flags
);
2191 * The route reflector is not allowed to modify the attributes
2192 * of the reflected IBGP routes unless explicitly allowed.
2194 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2195 && !CHECK_FLAG(bgp
->flags
,
2196 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2198 rmap_path
.attr
= &dummy_attr
;
2201 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2203 if (bgp_path_suppressed(pi
))
2204 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2207 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2210 peer
->rmap_type
= 0;
2212 if (ret
== RMAP_DENYMATCH
) {
2213 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2215 "%s [Update:SEND] %pFX is filtered by route-map '%s'",
2217 ROUTE_MAP_OUT_NAME(filter
));
2219 bgp_attr_flush(&dummy_attr
);
2224 /* RFC 8212 to prevent route leaks.
2225 * This specification intends to improve this situation by requiring the
2226 * explicit configuration of both BGP Import and Export Policies for any
2227 * External BGP (EBGP) session such as customers, peers, or
2228 * confederation boundaries for all enabled address families. Through
2229 * codification of the aforementioned requirement, operators will
2230 * benefit from consistent behavior across different BGP
2233 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2234 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2235 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2236 NULL
) > FIFTEENMINUTE2USEC
||
2237 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2239 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2240 monotime(&bgp
->ebgprequirespolicywarning
);
2245 /* draft-ietf-idr-deprecate-as-set-confed-set
2246 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2247 * Eventually, This document (if approved) updates RFC 4271
2248 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2249 * and obsoletes RFC 6472.
2251 if (peer
->bgp
->reject_as_sets
)
2252 if (aspath_check_as_sets(attr
->aspath
))
2255 /* Codification of AS 0 Processing */
2256 if (aspath_check_as_zero(attr
->aspath
))
2259 if (bgp_in_graceful_shutdown(bgp
)) {
2260 if (peer
->sort
== BGP_PEER_IBGP
2261 || peer
->sort
== BGP_PEER_CONFED
) {
2262 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2263 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2265 bgp_attr_add_gshut_community(attr
);
2269 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2270 * Capability" to a neighbor MUST perform the following upon receiving
2271 * a route from that neighbor with the "LLGR_STALE" community, or upon
2272 * attaching the "LLGR_STALE" community itself per Section 4.2:
2274 * The route SHOULD NOT be advertised to any neighbor from which the
2275 * Long-lived Graceful Restart Capability has not been received.
2277 if (bgp_attr_get_community(attr
) &&
2278 community_include(bgp_attr_get_community(attr
),
2279 COMMUNITY_LLGR_STALE
) &&
2280 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2281 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2284 /* After route-map has been applied, we check to see if the nexthop to
2285 * be carried in the attribute (that is used for the announcement) can
2286 * be cleared off or not. We do this in all cases where we would be
2287 * setting the nexthop to "ourselves". For IPv6, we only need to
2289 * the global nexthop here; the link-local nexthop would have been
2291 * already, and if not, it is required by the update formation code.
2292 * Also see earlier comments in this function.
2295 * If route-map has performed some operation on the nexthop or the peer
2296 * configuration says to pass it unchanged, we cannot reset the nexthop
2297 * here, so only attempt to do it if these aren't true. Note that the
2298 * route-map handler itself might have cleared the nexthop, if for
2300 * it is configured as 'peer-address'.
2302 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2303 piattr
->rmap_change_flags
)
2305 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2306 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2307 /* We can reset the nexthop, if setting (or forcing) it to
2309 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2310 PEER_FLAG_NEXTHOP_SELF
)
2311 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2312 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2314 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2315 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2316 subgroup_announce_reset_nhop(
2317 (peer_cap_enhe(peer
, afi
, safi
)
2323 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2324 /* Can also reset the nexthop if announcing to EBGP, but
2326 * no peer in the subgroup is on a shared subnet.
2327 * Note: 3rd party nexthop currently implemented for
2330 if ((p
->family
== AF_INET
) &&
2331 (!bgp_subgrp_multiaccess_check_v4(
2334 subgroup_announce_reset_nhop(
2335 (peer_cap_enhe(peer
, afi
, safi
)
2342 if ((p
->family
== AF_INET6
) &&
2343 (!bgp_subgrp_multiaccess_check_v6(
2344 piattr
->mp_nexthop_global
,
2346 subgroup_announce_reset_nhop(
2347 (peer_cap_enhe(peer
, afi
, safi
)
2356 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2358 * This flag is used for leaked vpn-vrf routes
2360 int family
= p
->family
;
2362 if (peer_cap_enhe(peer
, afi
, safi
))
2365 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2367 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2368 __func__
, family2str(family
));
2369 subgroup_announce_reset_nhop(family
, attr
);
2374 /* If IPv6/MP and nexthop does not have any override and happens
2376 * be a link-local address, reset it so that we don't pass along
2378 * source's link-local IPv6 address to recipients who may not be
2380 * the same interface.
2382 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2383 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2384 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2390 * When the next hop is set to ourselves, if all multipaths have
2391 * link-bandwidth announce the cumulative bandwidth as that makes
2392 * the most sense. However, don't modify if the link-bandwidth has
2393 * been explicitly set by user policy.
2396 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2397 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2398 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2399 bgp_attr_set_ecommunity(
2401 ecommunity_replace_linkbw(
2402 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2405 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2410 static void bgp_route_select_timer_expire(struct thread
*thread
)
2412 struct afi_safi_info
*info
;
2417 info
= THREAD_ARG(thread
);
2422 if (BGP_DEBUG(update
, UPDATE_OUT
))
2423 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2426 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2428 XFREE(MTYPE_TMP
, info
);
2430 /* Best path selection */
2431 bgp_best_path_select_defer(bgp
, afi
, safi
);
2434 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2435 struct bgp_maxpaths_cfg
*mpath_cfg
,
2436 struct bgp_path_info_pair
*result
, afi_t afi
,
2439 struct bgp_path_info
*new_select
;
2440 struct bgp_path_info
*old_select
;
2441 struct bgp_path_info
*pi
;
2442 struct bgp_path_info
*pi1
;
2443 struct bgp_path_info
*pi2
;
2444 struct bgp_path_info
*nextpi
= NULL
;
2445 int paths_eq
, do_mpath
, debug
;
2446 struct list mp_list
;
2447 char pfx_buf
[PREFIX2STR_BUFFER
];
2448 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2450 bgp_mp_list_init(&mp_list
);
2452 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2454 debug
= bgp_debug_bestpath(dest
);
2457 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2459 dest
->reason
= bgp_path_selection_none
;
2460 /* bgp deterministic-med */
2462 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2464 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2465 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2467 bgp_path_info_unset_flag(dest
, pi1
,
2468 BGP_PATH_DMED_SELECTED
);
2470 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2472 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2474 if (BGP_PATH_HOLDDOWN(pi1
))
2476 if (pi1
->peer
!= bgp
->peer_self
)
2477 if (!peer_established(pi1
->peer
))
2482 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2483 if (CHECK_FLAG(pi2
->flags
,
2484 BGP_PATH_DMED_CHECK
))
2486 if (BGP_PATH_HOLDDOWN(pi2
))
2488 if (pi2
->peer
!= bgp
->peer_self
2491 PEER_STATUS_NSF_WAIT
))
2492 if (pi2
->peer
->status
2496 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2498 && !aspath_cmp_left_confed(
2503 if (bgp_path_info_cmp(
2504 bgp
, pi2
, new_select
,
2505 &paths_eq
, mpath_cfg
, debug
,
2508 bgp_path_info_unset_flag(
2510 BGP_PATH_DMED_SELECTED
);
2514 bgp_path_info_set_flag(
2515 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2518 bgp_path_info_set_flag(dest
, new_select
,
2519 BGP_PATH_DMED_CHECK
);
2520 bgp_path_info_set_flag(dest
, new_select
,
2521 BGP_PATH_DMED_SELECTED
);
2524 bgp_path_info_path_with_addpath_rx_str(
2525 new_select
, path_buf
, sizeof(path_buf
));
2527 "%pBD(%s): %s is the bestpath from AS %u",
2528 dest
, bgp
->name_pretty
, path_buf
,
2529 aspath_get_first_as(
2530 new_select
->attr
->aspath
));
2535 /* Check old selected route and new selected route. */
2538 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2539 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2540 enum bgp_path_selection_reason reason
;
2542 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2545 if (BGP_PATH_HOLDDOWN(pi
)) {
2546 /* reap REMOVED routes, if needs be
2547 * selected route must stay for a while longer though
2549 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2550 && (pi
!= old_select
))
2551 bgp_path_info_reap(dest
, pi
);
2554 zlog_debug("%s: pi %p in holddown", __func__
,
2560 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2561 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2562 if (!peer_established(pi
->peer
)) {
2566 "%s: pi %p non self peer %s not estab state",
2567 __func__
, pi
, pi
->peer
->host
);
2572 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2573 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2574 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2576 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2580 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2582 reason
= dest
->reason
;
2583 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2584 debug
, pfx_buf
, afi
, safi
,
2586 if (new_select
== NULL
&&
2587 reason
!= bgp_path_selection_none
)
2588 dest
->reason
= reason
;
2593 /* Now that we know which path is the bestpath see if any of the other
2595 * qualify as multipaths
2599 bgp_path_info_path_with_addpath_rx_str(
2600 new_select
, path_buf
, sizeof(path_buf
));
2602 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2604 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2605 dest
, bgp
->name_pretty
, path_buf
,
2606 old_select
? old_select
->peer
->host
: "NONE");
2609 if (do_mpath
&& new_select
) {
2610 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2611 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2614 bgp_path_info_path_with_addpath_rx_str(
2615 pi
, path_buf
, sizeof(path_buf
));
2617 if (pi
== new_select
) {
2620 "%pBD(%s): %s is the bestpath, add to the multipath list",
2621 dest
, bgp
->name_pretty
,
2623 bgp_mp_list_add(&mp_list
, pi
);
2627 if (BGP_PATH_HOLDDOWN(pi
))
2630 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2631 && !CHECK_FLAG(pi
->peer
->sflags
,
2632 PEER_STATUS_NSF_WAIT
))
2633 if (!peer_established(pi
->peer
))
2636 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2639 "%pBD: %s has the same nexthop as the bestpath, skip it",
2644 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2645 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2651 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2653 bgp_mp_list_add(&mp_list
, pi
);
2658 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2660 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2661 bgp_mp_list_clear(&mp_list
);
2663 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2665 result
->old
= old_select
;
2666 result
->new = new_select
;
2672 * A new route/change in bestpath of an existing route. Evaluate the path
2673 * for advertisement to the subgroup.
2675 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2676 struct bgp_path_info
*selected
,
2677 struct bgp_dest
*dest
,
2678 uint32_t addpath_tx_id
)
2680 const struct prefix
*p
;
2681 struct peer
*onlypeer
;
2688 p
= bgp_dest_get_prefix(dest
);
2689 afi
= SUBGRP_AFI(subgrp
);
2690 safi
= SUBGRP_SAFI(subgrp
);
2691 bgp
= SUBGRP_INST(subgrp
);
2692 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2695 if (BGP_DEBUG(update
, UPDATE_OUT
))
2696 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2698 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2699 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2700 PEER_STATUS_ORF_WAIT_REFRESH
))
2703 memset(&attr
, 0, sizeof(struct attr
));
2704 /* It's initialized in bgp_announce_check() */
2706 /* Announcement to the subgroup. If the route is filtered withdraw it.
2707 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2708 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2711 advertise
= bgp_check_advertise(bgp
, dest
);
2714 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2716 /* Route is selected, if the route is already installed
2717 * in FIB, then it is advertised
2720 if (!bgp_check_withdrawal(bgp
, dest
))
2721 bgp_adj_out_set_subgroup(
2722 dest
, subgrp
, &attr
, selected
);
2724 bgp_adj_out_unset_subgroup(
2725 dest
, subgrp
, 1, addpath_tx_id
);
2728 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2732 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2734 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2739 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2740 * This is called at the end of route processing.
2742 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2744 struct bgp_path_info
*pi
;
2746 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2747 if (BGP_PATH_HOLDDOWN(pi
))
2749 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2750 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2755 * Has the route changed from the RIB's perspective? This is invoked only
2756 * if the route selection returns the same best route as earlier - to
2757 * determine if we need to update zebra or not.
2759 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2761 struct bgp_path_info
*mpinfo
;
2763 /* If this is multipath, check all selected paths for any nexthop
2764 * change or attribute change. Some attribute changes (e.g., community)
2765 * aren't of relevance to the RIB, but we'll update zebra to ensure
2766 * we handle the case of BGP nexthop change. This is the behavior
2767 * when the best path has an attribute change anyway.
2769 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2770 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2771 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2775 * If this is multipath, check all selected paths for any nexthop change
2777 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2778 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2779 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2780 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2784 /* Nothing has changed from the RIB's perspective. */
2788 struct bgp_process_queue
{
2790 STAILQ_HEAD(, bgp_dest
) pqueue
;
2791 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2793 unsigned int queued
;
2796 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2797 safi_t safi
, struct bgp_dest
*dest
,
2798 struct bgp_path_info
*new_select
,
2799 struct bgp_path_info
*old_select
)
2801 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2803 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2806 if (advertise_type5_routes(bgp
, afi
) && new_select
2807 && is_route_injectable_into_evpn(new_select
)) {
2809 /* apply the route-map */
2810 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2811 route_map_result_t ret
;
2812 struct bgp_path_info rmap_path
;
2813 struct bgp_path_info_extra rmap_path_extra
;
2814 struct attr dummy_attr
;
2816 dummy_attr
= *new_select
->attr
;
2818 /* Fill temp path_info */
2819 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2820 new_select
, new_select
->peer
,
2823 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2825 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2828 if (ret
== RMAP_DENYMATCH
) {
2829 bgp_attr_flush(&dummy_attr
);
2830 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2833 bgp_evpn_advertise_type5_route(
2834 bgp
, p
, &dummy_attr
, afi
, safi
);
2836 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2839 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2840 && is_route_injectable_into_evpn(old_select
))
2841 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2845 * Utility to determine whether a particular path_info should use
2846 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2847 * in a path where we basically _know_ this is a BGP-LU route.
2849 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
2851 /* Certain types get imp null; so do paths where the nexthop is
2854 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2855 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2856 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
2858 else if (new_select
->extra
== NULL
||
2859 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
2860 /* TODO -- should be configurable? */
2867 * old_select = The old best path
2868 * new_select = the new best path
2870 * if (!old_select && new_select)
2871 * We are sending new information on.
2873 * if (old_select && new_select) {
2874 * if (new_select != old_select)
2875 * We have a new best path send a change
2877 * We've received a update with new attributes that needs
2881 * if (old_select && !new_select)
2882 * We have no eligible route that we can announce or the rn
2885 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2886 afi_t afi
, safi_t safi
)
2888 struct bgp_path_info
*new_select
;
2889 struct bgp_path_info
*old_select
;
2890 struct bgp_path_info_pair old_and_new
;
2893 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2895 debug
= bgp_debug_bestpath(dest
);
2898 "%s: bgp delete in progress, ignoring event, p=%pBD",
2902 /* Is it end of initial update? (after startup) */
2904 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2905 sizeof(bgp
->update_delay_zebra_resume_time
));
2907 bgp
->main_zebra_update_hold
= 0;
2908 FOREACH_AFI_SAFI (afi
, safi
) {
2909 if (bgp_fibupd_safi(safi
))
2910 bgp_zebra_announce_table(bgp
, afi
, safi
);
2912 bgp
->main_peers_update_hold
= 0;
2914 bgp_start_routeadv(bgp
);
2918 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2920 debug
= bgp_debug_bestpath(dest
);
2922 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__
,
2923 dest
, bgp
->name_pretty
, afi2str(afi
),
2926 /* The best path calculation for the route is deferred if
2927 * BGP_NODE_SELECT_DEFER is set
2929 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2930 if (BGP_DEBUG(update
, UPDATE_OUT
))
2931 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
2935 /* Best path selection. */
2936 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2938 old_select
= old_and_new
.old
;
2939 new_select
= old_and_new
.new;
2941 /* Do we need to allocate or free labels?
2942 * Right now, since we only deal with per-prefix labels, it is not
2943 * necessary to do this upon changes to best path. Exceptions:
2944 * - label index has changed -> recalculate resulting label
2945 * - path_info sub_type changed -> switch to/from implicit-null
2946 * - no valid label (due to removed static label binding) -> get new one
2948 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2951 || bgp_label_index_differs(new_select
, old_select
)
2952 || new_select
->sub_type
!= old_select
->sub_type
2953 || !bgp_is_valid_label(&dest
->local_label
)) {
2954 /* Enforced penultimate hop popping:
2955 * implicit-null for local routes, aggregate
2956 * and redistributed routes
2958 if (bgp_lu_need_imp_null(new_select
)) {
2961 BGP_NODE_REGISTERED_FOR_LABEL
)
2964 BGP_NODE_LABEL_REQUESTED
))
2965 bgp_unregister_for_label(dest
);
2966 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2967 &dest
->local_label
);
2968 bgp_set_valid_label(&dest
->local_label
);
2970 bgp_register_for_label(dest
,
2973 } else if (CHECK_FLAG(dest
->flags
,
2974 BGP_NODE_REGISTERED_FOR_LABEL
)
2975 || CHECK_FLAG(dest
->flags
,
2976 BGP_NODE_LABEL_REQUESTED
)) {
2977 bgp_unregister_for_label(dest
);
2979 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
2980 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
2981 bgp_unregister_for_label(dest
);
2986 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
2987 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
2988 safi2str(safi
), old_select
, new_select
);
2990 /* If best route remains the same and this is not due to user-initiated
2991 * clear, see exactly what needs to be done.
2993 if (old_select
&& old_select
== new_select
2994 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2995 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2996 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2997 if (bgp_zebra_has_route_changed(old_select
)) {
2998 #ifdef ENABLE_BGP_VNC
2999 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3000 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3002 if (bgp_fibupd_safi(safi
)
3003 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3005 if (BGP_SUPPRESS_FIB_ENABLED(bgp
)
3006 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
3007 SET_FLAG(dest
->flags
,
3008 BGP_NODE_FIB_INSTALL_PENDING
);
3010 if (new_select
->type
== ZEBRA_ROUTE_BGP
3011 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3012 || new_select
->sub_type
3013 == BGP_ROUTE_IMPORTED
))
3015 bgp_zebra_announce(dest
, p
, old_select
,
3020 /* If there is a change of interest to peers, reannounce the
3022 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3023 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3024 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3025 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3027 /* unicast routes must also be annouced to
3028 * labeled-unicast update-groups */
3029 if (safi
== SAFI_UNICAST
)
3030 group_announce_route(bgp
, afi
,
3031 SAFI_LABELED_UNICAST
, dest
,
3034 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3035 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3038 /* advertise/withdraw type-5 routes */
3039 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3040 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3041 bgp_process_evpn_route_injection(
3042 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3044 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3045 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3046 bgp_zebra_clear_route_change_flags(dest
);
3047 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3051 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3053 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3055 /* bestpath has changed; bump version */
3056 if (old_select
|| new_select
) {
3057 bgp_bump_version(dest
);
3059 if (!bgp
->t_rmap_def_originate_eval
) {
3063 update_group_refresh_default_originate_route_map
,
3064 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3065 &bgp
->t_rmap_def_originate_eval
);
3070 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3073 zlog_debug("%s: setting SELECTED flag", __func__
);
3074 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3075 bgp_path_info_unset_flag(dest
, new_select
,
3076 BGP_PATH_ATTR_CHANGED
);
3077 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3078 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3081 #ifdef ENABLE_BGP_VNC
3082 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3083 if (old_select
!= new_select
) {
3085 vnc_import_bgp_exterior_del_route(bgp
, p
,
3087 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3090 vnc_import_bgp_exterior_add_route(bgp
, p
,
3092 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3098 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3100 /* unicast routes must also be annouced to labeled-unicast update-groups
3102 if (safi
== SAFI_UNICAST
)
3103 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3107 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3108 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3110 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3111 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3112 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3113 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3115 if (BGP_SUPPRESS_FIB_ENABLED(bgp
))
3116 SET_FLAG(dest
->flags
,
3117 BGP_NODE_FIB_INSTALL_PENDING
);
3119 /* if this is an evpn imported type-5 prefix,
3120 * we need to withdraw the route first to clear
3121 * the nh neigh and the RMAC entry.
3124 is_route_parent_evpn(old_select
))
3125 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3127 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3129 /* Withdraw the route from the kernel. */
3130 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3131 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3132 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3133 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3135 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3139 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3142 /* Clear any route change flags. */
3143 bgp_zebra_clear_route_change_flags(dest
);
3145 /* Reap old select bgp_path_info, if it has been removed */
3146 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3147 bgp_path_info_reap(dest
, old_select
);
3149 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3153 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3154 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3156 struct bgp_dest
*dest
;
3158 struct afi_safi_info
*thread_info
;
3160 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3161 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3163 thread_info
= THREAD_ARG(t
);
3164 XFREE(MTYPE_TMP
, thread_info
);
3165 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3168 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3169 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3170 get_afi_safi_str(afi
, safi
, false),
3171 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3174 /* Process the route list */
3175 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3176 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0;
3177 dest
= bgp_route_next(dest
)) {
3178 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3181 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3182 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3183 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3185 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
) {
3186 bgp_dest_unlock_node(dest
);
3191 /* Send EOR message when all routes are processed */
3192 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3193 bgp_send_delayed_eor(bgp
);
3194 /* Send route processing complete message to RIB */
3195 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3196 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3200 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3202 thread_info
->afi
= afi
;
3203 thread_info
->safi
= safi
;
3204 thread_info
->bgp
= bgp
;
3206 /* If there are more routes to be processed, start the
3209 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3210 BGP_ROUTE_SELECT_DELAY
,
3211 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3215 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3217 struct bgp_process_queue
*pqnode
= data
;
3218 struct bgp
*bgp
= pqnode
->bgp
;
3219 struct bgp_table
*table
;
3220 struct bgp_dest
*dest
;
3223 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3224 bgp_process_main_one(bgp
, NULL
, 0, 0);
3225 /* should always have dedicated wq call */
3226 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3230 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3231 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3232 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3233 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3234 table
= bgp_dest_table(dest
);
3235 /* note, new DESTs may be added as part of processing */
3236 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3238 bgp_dest_unlock_node(dest
);
3239 bgp_table_unlock(table
);
3245 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3247 struct bgp_process_queue
*pqnode
= data
;
3249 bgp_unlock(pqnode
->bgp
);
3251 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3254 void bgp_process_queue_init(struct bgp
*bgp
)
3256 if (!bgp
->process_queue
) {
3259 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3260 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3263 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3264 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3265 bgp
->process_queue
->spec
.max_retries
= 0;
3266 bgp
->process_queue
->spec
.hold
= 50;
3267 /* Use a higher yield value of 50ms for main queue processing */
3268 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3271 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3273 struct bgp_process_queue
*pqnode
;
3275 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3276 sizeof(struct bgp_process_queue
));
3278 /* unlocked in bgp_processq_del */
3279 pqnode
->bgp
= bgp_lock(bgp
);
3280 STAILQ_INIT(&pqnode
->pqueue
);
3285 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3287 #define ARBITRARY_PROCESS_QLEN 10000
3288 struct work_queue
*wq
= bgp
->process_queue
;
3289 struct bgp_process_queue
*pqnode
;
3290 int pqnode_reuse
= 0;
3292 /* already scheduled for processing? */
3293 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3296 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3299 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3300 if (BGP_DEBUG(update
, UPDATE_OUT
))
3301 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3306 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3307 if (BGP_DEBUG(update
, UPDATE_OUT
))
3309 "Soft reconfigure table in progress for route %p",
3317 /* Add route nodes to an existing work queue item until reaching the
3318 limit only if is from the same BGP view and it's not an EOIU marker
3320 if (work_queue_item_count(wq
)) {
3321 struct work_queue_item
*item
= work_queue_last_item(wq
);
3322 pqnode
= item
->data
;
3324 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3325 || pqnode
->bgp
!= bgp
3326 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3327 pqnode
= bgp_processq_alloc(bgp
);
3331 pqnode
= bgp_processq_alloc(bgp
);
3332 /* all unlocked in bgp_process_wq */
3333 bgp_table_lock(bgp_dest_table(dest
));
3335 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3336 bgp_dest_lock_node(dest
);
3338 /* can't be enqueued twice */
3339 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3340 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3344 work_queue_add(wq
, pqnode
);
3349 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3351 struct bgp_process_queue
*pqnode
;
3353 if (bgp
->process_queue
== NULL
)
3356 pqnode
= bgp_processq_alloc(bgp
);
3358 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3359 work_queue_add(bgp
->process_queue
, pqnode
);
3362 static void bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3366 peer
= THREAD_ARG(thread
);
3367 peer
->t_pmax_restart
= NULL
;
3369 if (bgp_debug_neighbor_events(peer
))
3371 "%s Maximum-prefix restart timer expired, restore peering",
3374 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3375 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3378 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3382 bool filtered
= false;
3383 struct bgp_dest
*dest
;
3384 struct bgp_adj_in
*ain
;
3385 struct attr attr
= {};
3386 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3388 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3389 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3390 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3394 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3398 if (bgp_input_modifier(
3399 peer
, rn_p
, &attr
, afi
, safi
,
3400 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3408 bgp_attr_flush(&attr
);
3415 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3419 iana_safi_t pkt_safi
;
3420 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3421 PEER_FLAG_MAX_PREFIX_FORCE
))
3422 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3423 + peer
->pcount
[afi
][safi
]
3424 : peer
->pcount
[afi
][safi
];
3426 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3429 if (pcount
> peer
->pmax
[afi
][safi
]) {
3430 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3431 PEER_STATUS_PREFIX_LIMIT
)
3436 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3437 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3438 peer
->pmax
[afi
][safi
]);
3439 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3441 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3442 PEER_FLAG_MAX_PREFIX_WARNING
))
3445 /* Convert AFI, SAFI to values for packet. */
3446 pkt_afi
= afi_int2iana(afi
);
3447 pkt_safi
= safi_int2iana(safi
);
3451 ndata
[0] = (pkt_afi
>> 8);
3453 ndata
[2] = pkt_safi
;
3454 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3455 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3456 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3457 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3459 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3460 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3461 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3465 /* Dynamic peers will just close their connection. */
3466 if (peer_dynamic_neighbor(peer
))
3469 /* restart timer start */
3470 if (peer
->pmax_restart
[afi
][safi
]) {
3471 peer
->v_pmax_restart
=
3472 peer
->pmax_restart
[afi
][safi
] * 60;
3474 if (bgp_debug_neighbor_events(peer
))
3476 "%s Maximum-prefix restart timer started for %d secs",
3477 peer
->host
, peer
->v_pmax_restart
);
3479 BGP_TIMER_ON(peer
->t_pmax_restart
,
3480 bgp_maximum_prefix_restart_timer
,
3481 peer
->v_pmax_restart
);
3486 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3487 PEER_STATUS_PREFIX_LIMIT
);
3490 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3491 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3492 PEER_STATUS_PREFIX_THRESHOLD
)
3497 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3498 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3499 peer
->pmax
[afi
][safi
]);
3500 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3501 PEER_STATUS_PREFIX_THRESHOLD
);
3503 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3504 PEER_STATUS_PREFIX_THRESHOLD
);
3508 /* Unconditionally remove the route from the RIB, without taking
3509 * damping into consideration (eg, because the session went down)
3511 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3512 struct peer
*peer
, afi_t afi
, safi_t safi
)
3515 struct bgp
*bgp
= NULL
;
3516 bool delete_route
= false;
3518 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3521 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3522 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3524 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3527 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3528 delete_route
= true;
3529 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3530 delete_route
= true;
3532 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3533 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3534 bgp
= pi
->peer
->bgp
;
3535 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3540 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3541 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3544 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3545 struct peer
*peer
, afi_t afi
, safi_t safi
,
3546 struct prefix_rd
*prd
)
3548 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3550 /* apply dampening, if result is suppressed, we'll be retaining
3551 * the bgp_path_info in the RIB for historical reference.
3553 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3554 && peer
->sort
== BGP_PEER_EBGP
)
3555 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3556 == BGP_DAMP_SUPPRESSED
) {
3557 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3562 #ifdef ENABLE_BGP_VNC
3563 if (safi
== SAFI_MPLS_VPN
) {
3564 struct bgp_dest
*pdest
= NULL
;
3565 struct bgp_table
*table
= NULL
;
3567 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3568 (struct prefix
*)prd
);
3569 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3570 table
= bgp_dest_get_bgp_table_info(pdest
);
3572 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3573 peer
->bgp
, prd
, table
, p
, pi
);
3575 bgp_dest_unlock_node(pdest
);
3577 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3578 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3580 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3581 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3586 /* If this is an EVPN route, process for un-import. */
3587 if (safi
== SAFI_EVPN
)
3588 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3590 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3593 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3594 struct peer
*peer
, struct attr
*attr
,
3595 struct bgp_dest
*dest
)
3597 struct bgp_path_info
*new;
3599 /* Make new BGP info. */
3600 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3602 new->instance
= instance
;
3603 new->sub_type
= sub_type
;
3606 new->uptime
= bgp_clock();
3611 /* Check if received nexthop is valid or not. */
3612 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3613 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3614 struct bgp_dest
*dest
)
3617 bool is_bgp_static_route
=
3618 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3622 * Only validated for unicast and multicast currently.
3623 * Also valid for EVPN where the nexthop is an IP address.
3624 * If we are a bgp static route being checked then there is
3625 * no need to check to see if the nexthop is martian as
3626 * that it should be ok.
3628 if (is_bgp_static_route
||
3629 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3632 /* If NEXT_HOP is present, validate it. */
3633 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3634 if (attr
->nexthop
.s_addr
== INADDR_ANY
3635 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3636 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3640 /* If MP_NEXTHOP is present, validate it. */
3641 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3642 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3643 * it is not an IPv6 link-local address.
3645 * If we receive an UPDATE with nexthop length set to 32 bytes
3646 * we shouldn't discard an UPDATE if it's set to (::).
3647 * The link-local (2st) is validated along the code path later.
3649 if (attr
->mp_nexthop_len
) {
3650 switch (attr
->mp_nexthop_len
) {
3651 case BGP_ATTR_NHLEN_IPV4
:
3652 case BGP_ATTR_NHLEN_VPNV4
:
3653 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3655 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3656 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3660 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3661 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3662 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3663 &attr
->mp_nexthop_global
)
3664 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3665 || IN6_IS_ADDR_MULTICAST(
3666 &attr
->mp_nexthop_global
)
3667 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3670 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3671 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3672 || IN6_IS_ADDR_MULTICAST(
3673 &attr
->mp_nexthop_global
)
3674 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3687 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3689 struct community
*old
;
3690 struct community
*new;
3691 struct community
*merge
;
3692 struct community
*no_export
;
3694 old
= bgp_attr_get_community(attr
);
3695 no_export
= community_str2com("no-export");
3700 merge
= community_merge(community_dup(old
), no_export
);
3703 community_free(&old
);
3705 new = community_uniq_sort(merge
);
3706 community_free(&merge
);
3708 new = community_dup(no_export
);
3711 community_free(&no_export
);
3713 bgp_attr_set_community(attr
, new);
3714 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
3717 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3718 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3719 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3720 uint32_t num_labels
, int soft_reconfig
,
3721 struct bgp_route_evpn
*evpn
)
3724 int aspath_loop_count
= 0;
3725 struct bgp_dest
*dest
;
3727 struct attr new_attr
;
3728 struct attr
*attr_new
;
3729 struct bgp_path_info
*pi
;
3730 struct bgp_path_info
*new;
3731 struct bgp_path_info_extra
*extra
;
3733 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3735 int do_loop_check
= 1;
3736 int has_valid_label
= 0;
3738 uint8_t pi_type
= 0;
3739 uint8_t pi_sub_type
= 0;
3740 bool force_evpn_import
= false;
3741 safi_t orig_safi
= safi
;
3743 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3744 char pfxprint
[PREFIX2STR_BUFFER
];
3746 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3747 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3751 #ifdef ENABLE_BGP_VNC
3752 int vnc_implicit_withdraw
= 0;
3756 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3757 if (orig_safi
== SAFI_LABELED_UNICAST
)
3758 safi
= SAFI_UNICAST
;
3760 memset(&new_attr
, 0, sizeof(struct attr
));
3761 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3762 new_attr
.label
= MPLS_INVALID_LABEL
;
3765 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3766 /* TODO: Check to see if we can get rid of "is_valid_label" */
3767 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3768 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3770 has_valid_label
= bgp_is_valid_label(label
);
3772 if (has_valid_label
)
3773 assert(label
!= NULL
);
3775 /* Update overlay index of the attribute */
3776 if (afi
== AFI_L2VPN
&& evpn
)
3777 memcpy(&attr
->evpn_overlay
, evpn
,
3778 sizeof(struct bgp_route_evpn
));
3780 /* When peer's soft reconfiguration enabled. Record input packet in
3783 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3784 && peer
!= bgp
->peer_self
)
3785 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3787 /* Check previously received route. */
3788 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3789 if (pi
->peer
== peer
&& pi
->type
== type
3790 && pi
->sub_type
== sub_type
3791 && pi
->addpath_rx_id
== addpath_id
)
3794 /* AS path local-as loop check. */
3795 if (peer
->change_local_as
) {
3796 if (peer
->allowas_in
[afi
][safi
])
3797 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3798 else if (!CHECK_FLAG(peer
->flags
,
3799 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3800 aspath_loop_count
= 1;
3802 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3803 > aspath_loop_count
) {
3804 peer
->stat_pfx_aspath_loop
++;
3805 reason
= "as-path contains our own AS;";
3810 /* If the peer is configured for "allowas-in origin" and the last ASN in
3812 * as-path is our ASN then we do not need to call aspath_loop_check
3814 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3815 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3818 /* AS path loop check. */
3819 if (do_loop_check
) {
3820 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3821 > peer
->allowas_in
[afi
][safi
]
3822 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3823 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3824 > peer
->allowas_in
[afi
][safi
])) {
3825 peer
->stat_pfx_aspath_loop
++;
3826 reason
= "as-path contains our own AS;";
3831 /* Route reflector originator ID check. */
3832 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3833 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3834 peer
->stat_pfx_originator_loop
++;
3835 reason
= "originator is us;";
3839 /* Route reflector cluster ID check. */
3840 if (bgp_cluster_filter(peer
, attr
)) {
3841 peer
->stat_pfx_cluster_loop
++;
3842 reason
= "reflected from the same cluster;";
3846 /* Apply incoming filter. */
3847 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
3848 peer
->stat_pfx_filter
++;
3853 /* RFC 8212 to prevent route leaks.
3854 * This specification intends to improve this situation by requiring the
3855 * explicit configuration of both BGP Import and Export Policies for any
3856 * External BGP (EBGP) session such as customers, peers, or
3857 * confederation boundaries for all enabled address families. Through
3858 * codification of the aforementioned requirement, operators will
3859 * benefit from consistent behavior across different BGP
3862 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3863 if (!bgp_inbound_policy_exists(peer
,
3864 &peer
->filter
[afi
][safi
])) {
3865 reason
= "inbound policy missing";
3866 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
3867 NULL
) > FIFTEENMINUTE2USEC
||
3868 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
3870 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3871 monotime(&bgp
->ebgprequirespolicywarning
);
3876 /* draft-ietf-idr-deprecate-as-set-confed-set
3877 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3878 * Eventually, This document (if approved) updates RFC 4271
3879 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3880 * and obsoletes RFC 6472.
3882 if (peer
->bgp
->reject_as_sets
)
3883 if (aspath_check_as_sets(attr
->aspath
)) {
3885 "as-path contains AS_SET or AS_CONFED_SET type;";
3891 /* Apply incoming route-map.
3892 * NB: new_attr may now contain newly allocated values from route-map
3894 * commands, so we need bgp_attr_flush in the error paths, until we
3896 * the attr (which takes over the memory references) */
3897 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
3900 peer
->stat_pfx_filter
++;
3901 reason
= "route-map;";
3902 bgp_attr_flush(&new_attr
);
3906 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3907 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3908 /* remove from RIB previous entry */
3909 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3912 if (peer
->sort
== BGP_PEER_EBGP
) {
3915 * A BGP speaker receiving an announcement tagged with the
3916 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3917 * NO_EXPORT community as defined in RFC1997, or a
3918 * similar community, to prevent propagation of the
3919 * prefix outside the local AS. The community to prevent
3920 * propagation SHOULD be chosen according to the operator's
3923 if (bgp_attr_get_community(&new_attr
) &&
3924 community_include(bgp_attr_get_community(&new_attr
),
3925 COMMUNITY_BLACKHOLE
))
3926 bgp_attr_add_no_export_community(&new_attr
);
3928 /* If we receive the graceful-shutdown community from an eBGP
3929 * peer we must lower local-preference */
3930 if (bgp_attr_get_community(&new_attr
) &&
3931 community_include(bgp_attr_get_community(&new_attr
),
3933 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3934 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3936 /* If graceful-shutdown is configured then add the GSHUT
3937 * community to all paths received from eBGP peers */
3938 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3939 bgp_attr_add_gshut_community(&new_attr
);
3944 pi_sub_type
= pi
->sub_type
;
3947 /* next hop check. */
3948 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3949 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3951 peer
->stat_pfx_nh_invalid
++;
3952 reason
= "martian or self next-hop;";
3953 bgp_attr_flush(&new_attr
);
3957 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3958 peer
->stat_pfx_nh_invalid
++;
3959 reason
= "self mac;";
3960 bgp_attr_flush(&new_attr
);
3964 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3966 * Suppress fib is enabled
3967 * BGP_OPT_NO_FIB is not enabled
3968 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3969 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3971 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
3972 && (sub_type
== BGP_ROUTE_NORMAL
)
3973 && (!bgp_option_check(BGP_OPT_NO_FIB
))
3974 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
3975 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
3977 /* If maximum prefix count is configured and current prefix
3980 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
3981 bgp_attr_flush(&new_attr
);
3985 attr_new
= bgp_attr_intern(&new_attr
);
3987 /* If the update is implicit withdraw. */
3989 pi
->uptime
= bgp_clock();
3990 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3992 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3994 /* Same attribute comes in. */
3995 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3997 && (!has_valid_label
3998 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3999 num_labels
* sizeof(mpls_label_t
))
4001 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4002 BGP_CONFIG_DAMPENING
)
4003 && peer
->sort
== BGP_PEER_EBGP
4004 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4005 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4006 bgp_debug_rdpfxpath2str(
4007 afi
, safi
, prd
, p
, label
,
4008 num_labels
, addpath_id
? 1 : 0,
4009 addpath_id
, evpn
, pfx_buf
,
4011 zlog_debug("%s rcvd %s", peer
->host
,
4015 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4016 != BGP_DAMP_SUPPRESSED
) {
4017 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4019 bgp_process(bgp
, dest
, afi
, safi
);
4021 } else /* Duplicate - odd */
4023 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4024 if (!peer
->rcvd_attr_printed
) {
4026 "%s rcvd UPDATE w/ attr: %s",
4028 peer
->rcvd_attr_str
);
4029 peer
->rcvd_attr_printed
= 1;
4032 bgp_debug_rdpfxpath2str(
4033 afi
, safi
, prd
, p
, label
,
4034 num_labels
, addpath_id
? 1 : 0,
4035 addpath_id
, evpn
, pfx_buf
,
4038 "%s rcvd %s...duplicate ignored",
4039 peer
->host
, pfx_buf
);
4042 /* graceful restart STALE flag unset. */
4043 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4044 bgp_path_info_unset_flag(
4045 dest
, pi
, BGP_PATH_STALE
);
4046 bgp_dest_set_defer_flag(dest
, false);
4047 bgp_process(bgp
, dest
, afi
, safi
);
4051 bgp_dest_unlock_node(dest
);
4052 bgp_attr_unintern(&attr_new
);
4057 /* Withdraw/Announce before we fully processed the withdraw */
4058 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4059 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4060 bgp_debug_rdpfxpath2str(
4061 afi
, safi
, prd
, p
, label
, num_labels
,
4062 addpath_id
? 1 : 0, addpath_id
, evpn
,
4063 pfx_buf
, sizeof(pfx_buf
));
4065 "%s rcvd %s, flapped quicker than processing",
4066 peer
->host
, pfx_buf
);
4069 bgp_path_info_restore(dest
, pi
);
4072 * If the BGP_PATH_REMOVED flag is set, then EVPN
4073 * routes would have been unimported already when a
4074 * prior BGP withdraw processing happened. Such routes
4075 * need to be imported again, so flag accordingly.
4077 force_evpn_import
= true;
4080 /* Received Logging. */
4081 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4082 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4083 num_labels
, addpath_id
? 1 : 0,
4084 addpath_id
, evpn
, pfx_buf
,
4086 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
4089 /* graceful restart STALE flag unset. */
4090 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4091 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4092 bgp_dest_set_defer_flag(dest
, false);
4095 /* The attribute is changed. */
4096 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4098 /* implicit withdraw, decrement aggregate and pcount here.
4099 * only if update is accepted, they'll increment below.
4101 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4103 /* Update bgp route dampening information. */
4104 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4105 && peer
->sort
== BGP_PEER_EBGP
) {
4106 /* This is implicit withdraw so we should update
4109 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4110 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4112 #ifdef ENABLE_BGP_VNC
4113 if (safi
== SAFI_MPLS_VPN
) {
4114 struct bgp_dest
*pdest
= NULL
;
4115 struct bgp_table
*table
= NULL
;
4117 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4118 (struct prefix
*)prd
);
4119 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4120 table
= bgp_dest_get_bgp_table_info(pdest
);
4122 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4123 bgp
, prd
, table
, p
, pi
);
4125 bgp_dest_unlock_node(pdest
);
4127 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4128 && (safi
== SAFI_UNICAST
)) {
4129 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4131 * Implicit withdraw case.
4133 ++vnc_implicit_withdraw
;
4134 vnc_import_bgp_del_route(bgp
, p
, pi
);
4135 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4140 /* Special handling for EVPN update of an existing route. If the
4141 * extended community attribute has changed, we need to
4143 * the route using its existing extended community. It will be
4144 * subsequently processed for import with the new extended
4147 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4150 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4152 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4155 cmp
= ecommunity_cmp(
4156 bgp_attr_get_ecommunity(pi
->attr
),
4157 bgp_attr_get_ecommunity(attr_new
));
4159 if (bgp_debug_update(peer
, p
, NULL
, 1))
4161 "Change in EXT-COMM, existing %s new %s",
4163 bgp_attr_get_ecommunity(
4166 bgp_attr_get_ecommunity(
4168 if (safi
== SAFI_EVPN
)
4169 bgp_evpn_unimport_route(
4170 bgp
, afi
, safi
, p
, pi
);
4171 else /* SAFI_MPLS_VPN */
4172 vpn_leak_to_vrf_withdraw(bgp
,
4178 /* Update to new attribute. */
4179 bgp_attr_unintern(&pi
->attr
);
4180 pi
->attr
= attr_new
;
4182 /* Update MPLS label */
4183 if (has_valid_label
) {
4184 extra
= bgp_path_info_extra_get(pi
);
4185 if (extra
->label
!= label
) {
4186 memcpy(&extra
->label
, label
,
4187 num_labels
* sizeof(mpls_label_t
));
4188 extra
->num_labels
= num_labels
;
4190 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4191 bgp_set_valid_label(&extra
->label
[0]);
4194 /* Update SRv6 SID */
4195 if (attr
->srv6_l3vpn
) {
4196 extra
= bgp_path_info_extra_get(pi
);
4197 if (sid_diff(&extra
->sid
[0].sid
,
4198 &attr
->srv6_l3vpn
->sid
)) {
4199 sid_copy(&extra
->sid
[0].sid
,
4200 &attr
->srv6_l3vpn
->sid
);
4201 extra
->num_sids
= 1;
4203 extra
->sid
[0].loc_block_len
= 0;
4204 extra
->sid
[0].loc_node_len
= 0;
4205 extra
->sid
[0].func_len
= 0;
4206 extra
->sid
[0].arg_len
= 0;
4207 extra
->sid
[0].transposition_len
= 0;
4208 extra
->sid
[0].transposition_offset
= 0;
4210 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4211 extra
->sid
[0].loc_block_len
=
4212 attr
->srv6_l3vpn
->loc_block_len
;
4213 extra
->sid
[0].loc_node_len
=
4214 attr
->srv6_l3vpn
->loc_node_len
;
4215 extra
->sid
[0].func_len
=
4216 attr
->srv6_l3vpn
->func_len
;
4217 extra
->sid
[0].arg_len
=
4218 attr
->srv6_l3vpn
->arg_len
;
4219 extra
->sid
[0].transposition_len
=
4221 ->transposition_len
;
4222 extra
->sid
[0].transposition_offset
=
4224 ->transposition_offset
;
4227 } else if (attr
->srv6_vpn
) {
4228 extra
= bgp_path_info_extra_get(pi
);
4229 if (sid_diff(&extra
->sid
[0].sid
,
4230 &attr
->srv6_vpn
->sid
)) {
4231 sid_copy(&extra
->sid
[0].sid
,
4232 &attr
->srv6_vpn
->sid
);
4233 extra
->num_sids
= 1;
4237 #ifdef ENABLE_BGP_VNC
4238 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4239 && (safi
== SAFI_UNICAST
)) {
4240 if (vnc_implicit_withdraw
) {
4242 * Add back the route with its new attributes
4244 * The route is still selected, until the route
4246 * queued by bgp_process actually runs. We have
4248 * update to the VNC side immediately to avoid
4250 * configuration changes (e.g., route-map
4252 * trigger re-importation of the entire RIB.
4254 vnc_import_bgp_add_route(bgp
, p
, pi
);
4255 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4260 /* Update bgp route dampening information. */
4261 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4262 && peer
->sort
== BGP_PEER_EBGP
) {
4263 /* Now we do normal update dampening. */
4264 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4265 if (ret
== BGP_DAMP_SUPPRESSED
) {
4266 bgp_dest_unlock_node(dest
);
4271 /* Nexthop reachability check - for unicast and
4272 * labeled-unicast.. */
4273 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4274 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4275 || (safi
== SAFI_EVPN
&&
4276 bgp_evpn_is_prefix_nht_supported(p
))) {
4277 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4278 && peer
->ttl
== BGP_DEFAULT_TTL
4279 && !CHECK_FLAG(peer
->flags
,
4280 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4281 && !CHECK_FLAG(bgp
->flags
,
4282 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4287 struct bgp
*bgp_nexthop
= bgp
;
4289 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4290 bgp_nexthop
= pi
->extra
->bgp_orig
;
4292 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4294 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4295 safi
, pi
, NULL
, connected
,
4297 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4298 bgp_path_info_set_flag(dest
, pi
,
4301 if (BGP_DEBUG(nht
, NHT
)) {
4302 zlog_debug("%s(%pI4): NH unresolved",
4304 (in_addr_t
*)&attr_new
->nexthop
);
4306 bgp_path_info_unset_flag(dest
, pi
,
4310 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4312 #ifdef ENABLE_BGP_VNC
4313 if (safi
== SAFI_MPLS_VPN
) {
4314 struct bgp_dest
*pdest
= NULL
;
4315 struct bgp_table
*table
= NULL
;
4317 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4318 (struct prefix
*)prd
);
4319 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4320 table
= bgp_dest_get_bgp_table_info(pdest
);
4322 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4323 bgp
, prd
, table
, p
, pi
);
4325 bgp_dest_unlock_node(pdest
);
4329 /* If this is an EVPN route and some attribute has changed,
4330 * or we are explicitly told to perform a route import, process
4331 * route for import. If the extended community has changed, we
4333 * have done the un-import earlier and the import would result
4335 * route getting injected into appropriate L2 VNIs. If it is
4337 * some other attribute change, the import will result in
4339 * the attributes for the route in the VNI(s).
4341 if (safi
== SAFI_EVPN
&&
4342 (!same_attr
|| force_evpn_import
) &&
4343 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4344 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4346 /* Process change. */
4347 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4349 bgp_process(bgp
, dest
, afi
, safi
);
4350 bgp_dest_unlock_node(dest
);
4352 if (SAFI_UNICAST
== safi
4353 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4354 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4356 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4358 if ((SAFI_MPLS_VPN
== safi
)
4359 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4361 vpn_leak_to_vrf_update(bgp
, pi
);
4364 #ifdef ENABLE_BGP_VNC
4365 if (SAFI_MPLS_VPN
== safi
) {
4366 mpls_label_t label_decoded
= decode_label(label
);
4368 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4369 type
, sub_type
, &label_decoded
);
4371 if (SAFI_ENCAP
== safi
) {
4372 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4373 type
, sub_type
, NULL
);
4378 } // End of implicit withdraw
4380 /* Received Logging. */
4381 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4382 if (!peer
->rcvd_attr_printed
) {
4383 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4384 peer
->rcvd_attr_str
);
4385 peer
->rcvd_attr_printed
= 1;
4388 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4389 addpath_id
? 1 : 0, addpath_id
, evpn
,
4390 pfx_buf
, sizeof(pfx_buf
));
4391 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
4394 /* Make new BGP info. */
4395 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4397 /* Update MPLS label */
4398 if (has_valid_label
) {
4399 extra
= bgp_path_info_extra_get(new);
4400 if (extra
->label
!= label
) {
4401 memcpy(&extra
->label
, label
,
4402 num_labels
* sizeof(mpls_label_t
));
4403 extra
->num_labels
= num_labels
;
4405 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4406 bgp_set_valid_label(&extra
->label
[0]);
4409 /* Update SRv6 SID */
4410 if (safi
== SAFI_MPLS_VPN
) {
4411 extra
= bgp_path_info_extra_get(new);
4412 if (attr
->srv6_l3vpn
) {
4413 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4414 extra
->num_sids
= 1;
4416 extra
->sid
[0].loc_block_len
=
4417 attr
->srv6_l3vpn
->loc_block_len
;
4418 extra
->sid
[0].loc_node_len
=
4419 attr
->srv6_l3vpn
->loc_node_len
;
4420 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4421 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4422 extra
->sid
[0].transposition_len
=
4423 attr
->srv6_l3vpn
->transposition_len
;
4424 extra
->sid
[0].transposition_offset
=
4425 attr
->srv6_l3vpn
->transposition_offset
;
4426 } else if (attr
->srv6_vpn
) {
4427 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4428 extra
->num_sids
= 1;
4432 /* Nexthop reachability check. */
4433 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4434 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4435 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4436 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4437 && peer
->ttl
== BGP_DEFAULT_TTL
4438 && !CHECK_FLAG(peer
->flags
,
4439 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4440 && !CHECK_FLAG(bgp
->flags
,
4441 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4446 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4448 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4450 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4451 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4453 if (BGP_DEBUG(nht
, NHT
)) {
4454 char buf1
[INET6_ADDRSTRLEN
];
4456 (const void *)&attr_new
->nexthop
,
4457 buf1
, INET6_ADDRSTRLEN
);
4458 zlog_debug("%s(%s): NH unresolved", __func__
,
4461 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4464 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4467 new->addpath_rx_id
= addpath_id
;
4469 /* Increment prefix */
4470 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4472 /* Register new BGP information. */
4473 bgp_path_info_add(dest
, new);
4475 /* route_node_get lock */
4476 bgp_dest_unlock_node(dest
);
4478 #ifdef ENABLE_BGP_VNC
4479 if (safi
== SAFI_MPLS_VPN
) {
4480 struct bgp_dest
*pdest
= NULL
;
4481 struct bgp_table
*table
= NULL
;
4483 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4484 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4485 table
= bgp_dest_get_bgp_table_info(pdest
);
4487 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4488 bgp
, prd
, table
, p
, new);
4490 bgp_dest_unlock_node(pdest
);
4494 /* If this is an EVPN route, process for import. */
4495 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4496 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4498 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4500 /* Process change. */
4501 bgp_process(bgp
, dest
, afi
, safi
);
4503 if (SAFI_UNICAST
== safi
4504 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4505 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4506 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4508 if ((SAFI_MPLS_VPN
== safi
)
4509 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4511 vpn_leak_to_vrf_update(bgp
, new);
4513 #ifdef ENABLE_BGP_VNC
4514 if (SAFI_MPLS_VPN
== safi
) {
4515 mpls_label_t label_decoded
= decode_label(label
);
4517 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4518 sub_type
, &label_decoded
);
4520 if (SAFI_ENCAP
== safi
) {
4521 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4528 /* This BGP update is filtered. Log the reason then update BGP
4531 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4533 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4534 if (!peer
->rcvd_attr_printed
) {
4535 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4536 peer
->rcvd_attr_str
);
4537 peer
->rcvd_attr_printed
= 1;
4540 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4541 addpath_id
? 1 : 0, addpath_id
, evpn
,
4542 pfx_buf
, sizeof(pfx_buf
));
4543 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4544 peer
->host
, pfx_buf
, reason
);
4548 /* If this is an EVPN route, un-import it as it is now filtered.
4550 if (safi
== SAFI_EVPN
)
4551 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4553 if (SAFI_UNICAST
== safi
4554 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4555 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4557 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4559 if ((SAFI_MPLS_VPN
== safi
)
4560 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4562 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4565 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4568 bgp_dest_unlock_node(dest
);
4570 #ifdef ENABLE_BGP_VNC
4572 * Filtered update is treated as an implicit withdrawal (see
4574 * a few lines above)
4576 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4577 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4585 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4586 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4587 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4588 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4591 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4592 struct bgp_dest
*dest
;
4593 struct bgp_path_info
*pi
;
4595 #ifdef ENABLE_BGP_VNC
4596 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4597 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4605 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4607 /* If peer is soft reconfiguration enabled. Record input packet for
4608 * further calculation.
4610 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4611 * routes that are filtered. This tanks out Quagga RS pretty badly due
4613 * the iteration over all RS clients.
4614 * Since we need to remove the entry from adj_in anyway, do that first
4616 * if there was no entry, we don't need to do anything more.
4618 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4619 && peer
!= bgp
->peer_self
)
4620 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4621 peer
->stat_pfx_dup_withdraw
++;
4623 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4624 bgp_debug_rdpfxpath2str(
4625 afi
, safi
, prd
, p
, label
, num_labels
,
4626 addpath_id
? 1 : 0, addpath_id
, NULL
,
4627 pfx_buf
, sizeof(pfx_buf
));
4629 "%s withdrawing route %s not in adj-in",
4630 peer
->host
, pfx_buf
);
4632 bgp_dest_unlock_node(dest
);
4636 /* Lookup withdrawn route. */
4637 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4638 if (pi
->peer
== peer
&& pi
->type
== type
4639 && pi
->sub_type
== sub_type
4640 && pi
->addpath_rx_id
== addpath_id
)
4644 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4645 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4646 addpath_id
? 1 : 0, addpath_id
, NULL
,
4647 pfx_buf
, sizeof(pfx_buf
));
4648 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4652 /* Withdraw specified route from routing table. */
4653 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4654 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4655 if (SAFI_UNICAST
== safi
4656 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4657 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4658 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4660 if ((SAFI_MPLS_VPN
== safi
)
4661 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4663 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4665 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4666 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4667 addpath_id
? 1 : 0, addpath_id
, NULL
,
4668 pfx_buf
, sizeof(pfx_buf
));
4669 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4672 /* Unlock bgp_node_get() lock. */
4673 bgp_dest_unlock_node(dest
);
4678 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4681 struct update_subgroup
*subgrp
;
4682 subgrp
= peer_subgroup(peer
, afi
, safi
);
4683 subgroup_default_originate(subgrp
, withdraw
);
4688 * bgp_stop_announce_route_timer
4690 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4692 if (!paf
->t_announce_route
)
4695 thread_cancel(&paf
->t_announce_route
);
4699 * bgp_announce_route_timer_expired
4701 * Callback that is invoked when the route announcement timer for a
4704 static void bgp_announce_route_timer_expired(struct thread
*t
)
4706 struct peer_af
*paf
;
4709 paf
= THREAD_ARG(t
);
4712 if (!peer_established(peer
))
4715 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4718 peer_af_announce_route(paf
, 1);
4720 /* Notify BGP conditional advertisement scanner percess */
4721 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
4725 * bgp_announce_route
4727 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4729 * if force is true we will force an update even if the update
4730 * limiting code is attempted to kick in.
4732 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
4734 struct peer_af
*paf
;
4735 struct update_subgroup
*subgrp
;
4737 paf
= peer_af_find(peer
, afi
, safi
);
4740 subgrp
= PAF_SUBGRP(paf
);
4743 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4744 * or a refresh has already been triggered.
4746 if (!subgrp
|| paf
->t_announce_route
)
4750 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
4753 * Start a timer to stagger/delay the announce. This serves
4754 * two purposes - announcement can potentially be combined for
4755 * multiple peers and the announcement doesn't happen in the
4758 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4759 (subgrp
->peer_count
== 1)
4760 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4761 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4762 &paf
->t_announce_route
);
4766 * Announce routes from all AF tables to a peer.
4768 * This should ONLY be called when there is a need to refresh the
4769 * routes to the peer based on a policy change for this peer alone
4770 * or a route refresh request received from the peer.
4771 * The operation will result in splitting the peer from its existing
4772 * subgroups and putting it in new subgroups.
4774 void bgp_announce_route_all(struct peer
*peer
)
4779 FOREACH_AFI_SAFI (afi
, safi
)
4780 bgp_announce_route(peer
, afi
, safi
, false);
4783 /* Flag or unflag bgp_dest to determine whether it should be treated by
4784 * bgp_soft_reconfig_table_task.
4785 * Flag if flag is true. Unflag if flag is false.
4787 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
4789 struct bgp_dest
*dest
;
4790 struct bgp_adj_in
*ain
;
4795 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4796 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4797 if (ain
->peer
!= NULL
)
4800 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
4801 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4803 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4807 static int bgp_soft_reconfig_table_update(struct peer
*peer
,
4808 struct bgp_dest
*dest
,
4809 struct bgp_adj_in
*ain
, afi_t afi
,
4810 safi_t safi
, struct prefix_rd
*prd
)
4812 struct bgp_path_info
*pi
;
4813 uint32_t num_labels
= 0;
4814 mpls_label_t
*label_pnt
= NULL
;
4815 struct bgp_route_evpn evpn
;
4817 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4818 if (pi
->peer
== peer
)
4821 if (pi
&& pi
->extra
)
4822 num_labels
= pi
->extra
->num_labels
;
4824 label_pnt
= &pi
->extra
->label
[0];
4826 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
4829 memset(&evpn
, 0, sizeof(evpn
));
4831 return bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
4832 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
4833 BGP_ROUTE_NORMAL
, prd
, label_pnt
, num_labels
, 1,
4837 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4838 struct bgp_table
*table
,
4839 struct prefix_rd
*prd
)
4842 struct bgp_dest
*dest
;
4843 struct bgp_adj_in
*ain
;
4846 table
= peer
->bgp
->rib
[afi
][safi
];
4848 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4849 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4850 if (ain
->peer
!= peer
)
4853 ret
= bgp_soft_reconfig_table_update(peer
, dest
, ain
,
4857 bgp_dest_unlock_node(dest
);
4863 /* Do soft reconfig table per bgp table.
4864 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4865 * when BGP_NODE_SOFT_RECONFIG is set,
4866 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4867 * Schedule a new thread to continue the job.
4868 * Without splitting the full job into several part,
4869 * vtysh waits for the job to finish before responding to a BGP command
4871 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
4873 uint32_t iter
, max_iter
;
4875 struct bgp_dest
*dest
;
4876 struct bgp_adj_in
*ain
;
4878 struct bgp_table
*table
;
4879 struct prefix_rd
*prd
;
4880 struct listnode
*node
, *nnode
;
4882 table
= THREAD_ARG(thread
);
4885 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
4886 if (table
->soft_reconfig_init
) {
4887 /* first call of the function with a new srta structure.
4888 * Don't do any treatment this time on nodes
4889 * in order vtysh to respond quickly
4894 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
4895 dest
= bgp_route_next(dest
)) {
4896 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
4899 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4901 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4902 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
4904 if (ain
->peer
!= peer
)
4907 ret
= bgp_soft_reconfig_table_update(
4908 peer
, dest
, ain
, table
->afi
,
4913 bgp_dest_unlock_node(dest
);
4915 table
->soft_reconfig_peers
,
4917 bgp_announce_route(peer
, table
->afi
,
4918 table
->safi
, false);
4920 table
->soft_reconfig_peers
)) {
4922 &table
->soft_reconfig_peers
);
4923 bgp_soft_reconfig_table_flag(
4932 /* we're either starting the initial iteration,
4933 * or we're going to continue an ongoing iteration
4935 if (dest
|| table
->soft_reconfig_init
) {
4936 table
->soft_reconfig_init
= false;
4937 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
4938 table
, 0, &table
->soft_reconfig_thread
);
4941 /* we're done, clean up the background iteration context info and
4942 schedule route annoucement
4944 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
4945 listnode_delete(table
->soft_reconfig_peers
, peer
);
4946 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
4949 list_delete(&table
->soft_reconfig_peers
);
4953 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4955 * - bgp cannot be NULL
4956 * - if table and peer are NULL, cancel all threads within the bgp instance
4957 * - if table is NULL and peer is not,
4958 * remove peer in all threads within the bgp instance
4959 * - if peer is NULL, cancel all threads matching table within the bgp instance
4961 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
4962 const struct bgp_table
*table
,
4963 const struct peer
*peer
)
4966 struct listnode
*node
, *nnode
;
4968 struct bgp_table
*ntable
;
4973 FOREACH_AFI_SAFI (afi
, safi
) {
4974 ntable
= bgp
->rib
[afi
][safi
];
4977 if (table
&& table
!= ntable
)
4980 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
4982 if (peer
&& peer
!= npeer
)
4984 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
4987 if (!ntable
->soft_reconfig_peers
4988 || !list_isempty(ntable
->soft_reconfig_peers
))
4991 list_delete(&ntable
->soft_reconfig_peers
);
4992 bgp_soft_reconfig_table_flag(ntable
, false);
4993 BGP_TIMER_OFF(ntable
->soft_reconfig_thread
);
4997 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4999 struct bgp_dest
*dest
;
5000 struct bgp_table
*table
;
5001 struct listnode
*node
, *nnode
;
5003 struct peer_af
*paf
;
5005 if (!peer_established(peer
))
5008 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5009 && (safi
!= SAFI_EVPN
)) {
5010 table
= peer
->bgp
->rib
[afi
][safi
];
5014 table
->soft_reconfig_init
= true;
5016 if (!table
->soft_reconfig_peers
)
5017 table
->soft_reconfig_peers
= list_new();
5019 /* add peer to the table soft_reconfig_peers if not already
5022 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5028 listnode_add(table
->soft_reconfig_peers
, peer
);
5030 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5031 * on table would start back at the beginning.
5033 bgp_soft_reconfig_table_flag(table
, true);
5035 if (!table
->soft_reconfig_thread
)
5036 thread_add_event(bm
->master
,
5037 bgp_soft_reconfig_table_task
, table
, 0,
5038 &table
->soft_reconfig_thread
);
5039 /* Cancel bgp_announce_route_timer_expired threads.
5040 * bgp_announce_route_timer_expired threads have been scheduled
5041 * to announce routes as soon as the soft_reconfigure process
5043 * In this case, soft_reconfigure is also scheduled by using
5044 * a thread but is planned after the
5045 * bgp_announce_route_timer_expired threads. It means that,
5046 * without cancelling the threads, the route announcement task
5047 * would run before the soft reconfiguration one. That would
5048 * useless and would block vtysh during several seconds. Route
5049 * announcements are rescheduled as soon as the soft_reconfigure
5052 paf
= peer_af_find(peer
, afi
, safi
);
5054 bgp_stop_announce_route_timer(paf
);
5056 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5057 dest
= bgp_route_next(dest
)) {
5058 table
= bgp_dest_get_bgp_table_info(dest
);
5063 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5064 struct prefix_rd prd
;
5066 prd
.family
= AF_UNSPEC
;
5068 memcpy(&prd
.val
, p
->u
.val
, 8);
5070 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5075 struct bgp_clear_node_queue
{
5076 struct bgp_dest
*dest
;
5079 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5081 struct bgp_clear_node_queue
*cnq
= data
;
5082 struct bgp_dest
*dest
= cnq
->dest
;
5083 struct peer
*peer
= wq
->spec
.data
;
5084 struct bgp_path_info
*pi
;
5086 afi_t afi
= bgp_dest_table(dest
)->afi
;
5087 safi_t safi
= bgp_dest_table(dest
)->safi
;
5089 assert(dest
&& peer
);
5092 /* It is possible that we have multiple paths for a prefix from a peer
5093 * if that peer is using AddPath.
5095 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5096 if (pi
->peer
!= peer
)
5099 /* graceful restart STALE flag set. */
5100 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5101 && peer
->nsf
[afi
][safi
])
5102 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5103 PEER_STATUS_ENHANCED_REFRESH
))
5104 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5105 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5106 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5108 /* If this is an EVPN route, process for
5110 if (safi
== SAFI_EVPN
)
5111 bgp_evpn_unimport_route(
5113 bgp_dest_get_prefix(dest
), pi
);
5114 /* Handle withdraw for VRF route-leaking and L3VPN */
5115 if (SAFI_UNICAST
== safi
5116 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5117 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5118 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5121 if (SAFI_MPLS_VPN
== safi
&&
5122 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5123 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5126 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5132 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5134 struct bgp_clear_node_queue
*cnq
= data
;
5135 struct bgp_dest
*dest
= cnq
->dest
;
5136 struct bgp_table
*table
= bgp_dest_table(dest
);
5138 bgp_dest_unlock_node(dest
);
5139 bgp_table_unlock(table
);
5140 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5143 static void bgp_clear_node_complete(struct work_queue
*wq
)
5145 struct peer
*peer
= wq
->spec
.data
;
5147 /* Tickle FSM to start moving again */
5148 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5150 peer_unlock(peer
); /* bgp_clear_route */
5153 static void bgp_clear_node_queue_init(struct peer
*peer
)
5155 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5157 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5158 #undef CLEAR_QUEUE_NAME_LEN
5160 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5161 peer
->clear_node_queue
->spec
.hold
= 10;
5162 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5163 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5164 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5165 peer
->clear_node_queue
->spec
.max_retries
= 0;
5167 /* we only 'lock' this peer reference when the queue is actually active
5169 peer
->clear_node_queue
->spec
.data
= peer
;
5172 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5173 struct bgp_table
*table
)
5175 struct bgp_dest
*dest
;
5176 int force
= peer
->bgp
->process_queue
? 0 : 1;
5179 table
= peer
->bgp
->rib
[afi
][safi
];
5181 /* If still no table => afi/safi isn't configured at all or smth. */
5185 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5186 struct bgp_path_info
*pi
, *next
;
5187 struct bgp_adj_in
*ain
;
5188 struct bgp_adj_in
*ain_next
;
5190 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5191 * queued for every clearing peer, regardless of whether it is
5192 * relevant to the peer at hand.
5194 * Overview: There are 3 different indices which need to be
5195 * scrubbed, potentially, when a peer is removed:
5197 * 1 peer's routes visible via the RIB (ie accepted routes)
5198 * 2 peer's routes visible by the (optional) peer's adj-in index
5199 * 3 other routes visible by the peer's adj-out index
5201 * 3 there is no hurry in scrubbing, once the struct peer is
5202 * removed from bgp->peer, we could just GC such deleted peer's
5203 * adj-outs at our leisure.
5205 * 1 and 2 must be 'scrubbed' in some way, at least made
5206 * invisible via RIB index before peer session is allowed to be
5207 * brought back up. So one needs to know when such a 'search' is
5212 * - there'd be a single global queue or a single RIB walker
5213 * - rather than tracking which route_nodes still need to be
5214 * examined on a peer basis, we'd track which peers still
5217 * Given that our per-peer prefix-counts now should be reliable,
5218 * this may actually be achievable. It doesn't seem to be a huge
5219 * problem at this time,
5221 * It is possible that we have multiple paths for a prefix from
5223 * if that peer is using AddPath.
5227 ain_next
= ain
->next
;
5229 if (ain
->peer
== peer
)
5230 bgp_adj_in_remove(dest
, ain
);
5235 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5237 if (pi
->peer
!= peer
)
5241 bgp_path_info_reap(dest
, pi
);
5243 struct bgp_clear_node_queue
*cnq
;
5245 /* both unlocked in bgp_clear_node_queue_del */
5246 bgp_table_lock(bgp_dest_table(dest
));
5247 bgp_dest_lock_node(dest
);
5249 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5250 sizeof(struct bgp_clear_node_queue
));
5252 work_queue_add(peer
->clear_node_queue
, cnq
);
5260 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5262 struct bgp_dest
*dest
;
5263 struct bgp_table
*table
;
5265 if (peer
->clear_node_queue
== NULL
)
5266 bgp_clear_node_queue_init(peer
);
5268 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5269 * Idle until it receives a Clearing_Completed event. This protects
5270 * against peers which flap faster than we can we clear, which could
5273 * a) race with routes from the new session being installed before
5274 * clear_route_node visits the node (to delete the route of that
5276 * b) resource exhaustion, clear_route_node likely leads to an entry
5277 * on the process_main queue. Fast-flapping could cause that queue
5281 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5282 * the unlock will happen upon work-queue completion; other wise, the
5283 * unlock happens at the end of this function.
5285 if (!peer
->clear_node_queue
->thread
)
5288 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5289 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5291 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5292 dest
= bgp_route_next(dest
)) {
5293 table
= bgp_dest_get_bgp_table_info(dest
);
5297 bgp_clear_route_table(peer
, afi
, safi
, table
);
5300 /* unlock if no nodes got added to the clear-node-queue. */
5301 if (!peer
->clear_node_queue
->thread
)
5305 void bgp_clear_route_all(struct peer
*peer
)
5310 FOREACH_AFI_SAFI (afi
, safi
)
5311 bgp_clear_route(peer
, afi
, safi
);
5313 #ifdef ENABLE_BGP_VNC
5314 rfapiProcessPeerDown(peer
);
5318 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5320 struct bgp_table
*table
;
5321 struct bgp_dest
*dest
;
5322 struct bgp_adj_in
*ain
;
5323 struct bgp_adj_in
*ain_next
;
5325 table
= peer
->bgp
->rib
[afi
][safi
];
5327 /* It is possible that we have multiple paths for a prefix from a peer
5328 * if that peer is using AddPath.
5330 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5334 ain_next
= ain
->next
;
5336 if (ain
->peer
== peer
)
5337 bgp_adj_in_remove(dest
, ain
);
5344 /* If any of the routes from the peer have been marked with the NO_LLGR
5345 * community, either as sent by the peer, or as the result of a configured
5346 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5347 * operation of [RFC4271].
5349 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5351 struct bgp_dest
*dest
;
5352 struct bgp_path_info
*pi
;
5353 struct bgp_table
*table
;
5355 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5356 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5357 dest
= bgp_route_next(dest
)) {
5358 struct bgp_dest
*rm
;
5360 /* look for neighbor in tables */
5361 table
= bgp_dest_get_bgp_table_info(dest
);
5365 for (rm
= bgp_table_top(table
); rm
;
5366 rm
= bgp_route_next(rm
))
5367 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5369 if (pi
->peer
!= peer
)
5372 peer
->af_sflags
[afi
][safi
],
5373 PEER_STATUS_LLGR_WAIT
) &&
5374 bgp_attr_get_community(pi
->attr
) &&
5376 bgp_attr_get_community(
5380 if (!CHECK_FLAG(pi
->flags
,
5385 * If this is VRF leaked route
5386 * process for withdraw.
5389 BGP_ROUTE_IMPORTED
&&
5390 peer
->bgp
->inst_type
==
5391 BGP_INSTANCE_TYPE_DEFAULT
)
5392 vpn_leak_to_vrf_withdraw(
5395 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5400 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5401 dest
= bgp_route_next(dest
))
5402 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5404 if (pi
->peer
!= peer
)
5406 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5407 PEER_STATUS_LLGR_WAIT
) &&
5408 bgp_attr_get_community(pi
->attr
) &&
5410 bgp_attr_get_community(pi
->attr
),
5413 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5415 if (safi
== SAFI_UNICAST
&&
5416 (peer
->bgp
->inst_type
==
5417 BGP_INSTANCE_TYPE_VRF
||
5418 peer
->bgp
->inst_type
==
5419 BGP_INSTANCE_TYPE_DEFAULT
))
5420 vpn_leak_from_vrf_withdraw(
5421 bgp_get_default(), peer
->bgp
,
5424 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5430 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5432 struct bgp_dest
*dest
, *ndest
;
5433 struct bgp_path_info
*pi
;
5434 struct bgp_table
*table
;
5436 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5437 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5438 dest
= bgp_route_next(dest
)) {
5439 table
= bgp_dest_get_bgp_table_info(dest
);
5443 for (ndest
= bgp_table_top(table
); ndest
;
5444 ndest
= bgp_route_next(ndest
)) {
5445 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5447 if (pi
->peer
!= peer
)
5451 peer
->af_sflags
[afi
][safi
],
5452 PEER_STATUS_ENHANCED_REFRESH
))
5453 && !CHECK_FLAG(pi
->flags
,
5457 BGP_PATH_UNUSEABLE
)) {
5458 if (bgp_debug_neighbor_events(
5461 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5465 bgp_dest_get_prefix(
5468 bgp_path_info_set_flag(
5476 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5477 dest
= bgp_route_next(dest
)) {
5478 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5480 if (pi
->peer
!= peer
)
5483 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5484 PEER_STATUS_ENHANCED_REFRESH
))
5485 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5486 && !CHECK_FLAG(pi
->flags
,
5487 BGP_PATH_UNUSEABLE
)) {
5488 if (bgp_debug_neighbor_events(peer
))
5490 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5494 bgp_dest_get_prefix(
5497 bgp_path_info_set_flag(dest
, pi
,
5505 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5507 if (peer
->sort
== BGP_PEER_IBGP
)
5510 if (peer
->sort
== BGP_PEER_EBGP
5511 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5512 || FILTER_LIST_OUT_NAME(filter
)
5513 || DISTRIBUTE_OUT_NAME(filter
)))
5518 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5520 if (peer
->sort
== BGP_PEER_IBGP
)
5523 if (peer
->sort
== BGP_PEER_EBGP
5524 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5525 || FILTER_LIST_IN_NAME(filter
)
5526 || DISTRIBUTE_IN_NAME(filter
)))
5531 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5534 struct bgp_dest
*dest
;
5535 struct bgp_path_info
*pi
;
5536 struct bgp_path_info
*next
;
5538 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5539 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5540 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5544 /* Unimport EVPN routes from VRFs */
5545 if (safi
== SAFI_EVPN
)
5546 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5549 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5550 && pi
->type
== ZEBRA_ROUTE_BGP
5551 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5552 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5553 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5555 if (bgp_fibupd_safi(safi
))
5556 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5559 bgp_path_info_reap(dest
, pi
);
5563 /* Delete all kernel routes. */
5564 void bgp_cleanup_routes(struct bgp
*bgp
)
5567 struct bgp_dest
*dest
;
5568 struct bgp_table
*table
;
5570 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5571 if (afi
== AFI_L2VPN
)
5573 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5576 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5578 if (afi
!= AFI_L2VPN
) {
5580 safi
= SAFI_MPLS_VPN
;
5581 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5582 dest
= bgp_route_next(dest
)) {
5583 table
= bgp_dest_get_bgp_table_info(dest
);
5584 if (table
!= NULL
) {
5585 bgp_cleanup_table(bgp
, table
, safi
);
5586 bgp_table_finish(&table
);
5587 bgp_dest_set_bgp_table_info(dest
, NULL
);
5588 bgp_dest_unlock_node(dest
);
5592 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5593 dest
= bgp_route_next(dest
)) {
5594 table
= bgp_dest_get_bgp_table_info(dest
);
5595 if (table
!= NULL
) {
5596 bgp_cleanup_table(bgp
, table
, safi
);
5597 bgp_table_finish(&table
);
5598 bgp_dest_set_bgp_table_info(dest
, NULL
);
5599 bgp_dest_unlock_node(dest
);
5604 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5605 dest
= bgp_route_next(dest
)) {
5606 table
= bgp_dest_get_bgp_table_info(dest
);
5607 if (table
!= NULL
) {
5608 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5609 bgp_table_finish(&table
);
5610 bgp_dest_set_bgp_table_info(dest
, NULL
);
5611 bgp_dest_unlock_node(dest
);
5616 void bgp_reset(void)
5619 bgp_zclient_reset();
5620 access_list_reset();
5621 prefix_list_reset();
5624 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5626 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5627 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5628 PEER_CAP_ADDPATH_AF_TX_RCV
));
5631 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5633 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5634 struct bgp_nlri
*packet
)
5643 bool addpath_capable
;
5644 uint32_t addpath_id
;
5647 lim
= pnt
+ packet
->length
;
5649 safi
= packet
->safi
;
5651 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5653 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5654 syntactic validity. If the field is syntactically incorrect,
5655 then the Error Subcode is set to Invalid Network Field. */
5656 for (; pnt
< lim
; pnt
+= psize
) {
5657 /* Clear prefix structure. */
5658 memset(&p
, 0, sizeof(struct prefix
));
5660 if (addpath_capable
) {
5662 /* When packet overflow occurs return immediately. */
5663 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5664 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5666 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5667 addpath_id
= ntohl(addpath_id
);
5668 pnt
+= BGP_ADDPATH_ID_LEN
;
5671 /* Fetch prefix length. */
5672 p
.prefixlen
= *pnt
++;
5673 /* afi/safi validity already verified by caller,
5674 * bgp_update_receive */
5675 p
.family
= afi2family(afi
);
5677 /* Prefix length check. */
5678 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5681 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5682 peer
->host
, p
.prefixlen
, packet
->afi
);
5683 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5686 /* Packet size overflow check. */
5687 psize
= PSIZE(p
.prefixlen
);
5689 /* When packet overflow occur return immediately. */
5690 if (pnt
+ psize
> lim
) {
5693 "%s [Error] Update packet error (prefix length %d overflows packet)",
5694 peer
->host
, p
.prefixlen
);
5695 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5698 /* Defensive coding, double-check the psize fits in a struct
5700 if (psize
> (ssize_t
)sizeof(p
.u
)) {
5703 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5704 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
5705 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5708 /* Fetch prefix from NLRI packet. */
5709 memcpy(p
.u
.val
, pnt
, psize
);
5711 /* Check address. */
5712 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5713 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5714 /* From RFC4271 Section 6.3:
5716 * If a prefix in the NLRI field is semantically
5718 * (e.g., an unexpected multicast IP address),
5720 * be logged locally, and the prefix SHOULD be
5725 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5726 peer
->host
, &p
.u
.prefix4
);
5731 /* Check address. */
5732 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5733 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5736 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5737 peer
->host
, &p
.u
.prefix6
);
5741 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5744 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5745 peer
->host
, &p
.u
.prefix6
);
5751 /* Normal process. */
5753 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5754 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5755 NULL
, NULL
, 0, 0, NULL
);
5757 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5758 safi
, ZEBRA_ROUTE_BGP
,
5759 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5762 /* Do not send BGP notification twice when maximum-prefix count
5764 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5765 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5767 /* Address family configuration mismatch. */
5769 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5772 /* Packet length consistency check. */
5776 "%s [Error] Update packet error (prefix length mismatch with total length)",
5778 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5781 return BGP_NLRI_PARSE_OK
;
5784 static struct bgp_static
*bgp_static_new(void)
5786 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5789 static void bgp_static_free(struct bgp_static
*bgp_static
)
5791 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5792 route_map_counter_decrement(bgp_static
->rmap
.map
);
5794 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5795 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5798 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5799 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5801 struct bgp_dest
*dest
;
5802 struct bgp_path_info
*pi
;
5803 struct bgp_path_info
*new;
5804 struct bgp_path_info rmap_path
;
5806 struct attr
*attr_new
;
5807 route_map_result_t ret
;
5808 #ifdef ENABLE_BGP_VNC
5809 int vnc_implicit_withdraw
= 0;
5814 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5816 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5818 attr
.nexthop
= bgp_static
->igpnexthop
;
5819 attr
.med
= bgp_static
->igpmetric
;
5820 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5822 if (bgp_static
->atomic
)
5823 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5825 /* Store label index, if required. */
5826 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5827 attr
.label_index
= bgp_static
->label_index
;
5828 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5831 /* Apply route-map. */
5832 if (bgp_static
->rmap
.name
) {
5833 struct attr attr_tmp
= attr
;
5835 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5836 rmap_path
.peer
= bgp
->peer_self
;
5837 rmap_path
.attr
= &attr_tmp
;
5839 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5841 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5843 bgp
->peer_self
->rmap_type
= 0;
5845 if (ret
== RMAP_DENYMATCH
) {
5846 /* Free uninterned attribute. */
5847 bgp_attr_flush(&attr_tmp
);
5849 /* Unintern original. */
5850 aspath_unintern(&attr
.aspath
);
5851 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5855 if (bgp_in_graceful_shutdown(bgp
))
5856 bgp_attr_add_gshut_community(&attr_tmp
);
5858 attr_new
= bgp_attr_intern(&attr_tmp
);
5861 if (bgp_in_graceful_shutdown(bgp
))
5862 bgp_attr_add_gshut_community(&attr
);
5864 attr_new
= bgp_attr_intern(&attr
);
5867 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5868 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5869 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5873 if (attrhash_cmp(pi
->attr
, attr_new
)
5874 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5875 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5876 bgp_dest_unlock_node(dest
);
5877 bgp_attr_unintern(&attr_new
);
5878 aspath_unintern(&attr
.aspath
);
5881 /* The attribute is changed. */
5882 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5884 /* Rewrite BGP route information. */
5885 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5886 bgp_path_info_restore(dest
, pi
);
5888 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5889 #ifdef ENABLE_BGP_VNC
5890 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5891 && (safi
== SAFI_UNICAST
)) {
5892 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5894 * Implicit withdraw case.
5895 * We have to do this before pi is
5898 ++vnc_implicit_withdraw
;
5899 vnc_import_bgp_del_route(bgp
, p
, pi
);
5900 vnc_import_bgp_exterior_del_route(
5905 bgp_attr_unintern(&pi
->attr
);
5906 pi
->attr
= attr_new
;
5907 pi
->uptime
= bgp_clock();
5908 #ifdef ENABLE_BGP_VNC
5909 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5910 && (safi
== SAFI_UNICAST
)) {
5911 if (vnc_implicit_withdraw
) {
5912 vnc_import_bgp_add_route(bgp
, p
, pi
);
5913 vnc_import_bgp_exterior_add_route(
5919 /* Nexthop reachability check. */
5920 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5921 && (safi
== SAFI_UNICAST
5922 || safi
== SAFI_LABELED_UNICAST
)) {
5924 struct bgp
*bgp_nexthop
= bgp
;
5926 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5927 bgp_nexthop
= pi
->extra
->bgp_orig
;
5929 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5930 afi
, safi
, pi
, NULL
,
5932 bgp_path_info_set_flag(dest
, pi
,
5935 if (BGP_DEBUG(nht
, NHT
)) {
5936 char buf1
[INET6_ADDRSTRLEN
];
5937 inet_ntop(p
->family
,
5941 "%s(%s): Route not in table, not advertising",
5944 bgp_path_info_unset_flag(
5945 dest
, pi
, BGP_PATH_VALID
);
5948 /* Delete the NHT structure if any, if we're
5950 * enabling/disabling import check. We
5951 * deregister the route
5952 * from NHT to avoid overloading NHT and the
5953 * process interaction
5955 bgp_unlink_nexthop(pi
);
5956 bgp_path_info_set_flag(dest
, pi
,
5959 /* Process change. */
5960 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5961 bgp_process(bgp
, dest
, afi
, safi
);
5963 if (SAFI_UNICAST
== safi
5964 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5966 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5967 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5971 bgp_dest_unlock_node(dest
);
5972 aspath_unintern(&attr
.aspath
);
5977 /* Make new BGP info. */
5978 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5980 /* Nexthop reachability check. */
5981 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5982 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5983 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
5985 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5987 if (BGP_DEBUG(nht
, NHT
)) {
5988 char buf1
[INET6_ADDRSTRLEN
];
5989 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5992 "%s(%s): Route not in table, not advertising",
5995 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5998 /* Delete the NHT structure if any, if we're toggling between
5999 * enabling/disabling import check. We deregister the route
6000 * from NHT to avoid overloading NHT and the process interaction
6002 bgp_unlink_nexthop(new);
6004 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6007 /* Aggregate address increment. */
6008 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6010 /* Register new BGP information. */
6011 bgp_path_info_add(dest
, new);
6013 /* route_node_get lock */
6014 bgp_dest_unlock_node(dest
);
6016 /* Process change. */
6017 bgp_process(bgp
, dest
, afi
, safi
);
6019 if (SAFI_UNICAST
== safi
6020 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6021 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6022 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6025 /* Unintern original. */
6026 aspath_unintern(&attr
.aspath
);
6029 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6032 struct bgp_dest
*dest
;
6033 struct bgp_path_info
*pi
;
6035 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6037 /* Check selected route and self inserted route. */
6038 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6039 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6040 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6043 /* Withdraw static BGP route from routing table. */
6045 if (SAFI_UNICAST
== safi
6046 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6047 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6048 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6050 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6051 bgp_unlink_nexthop(pi
);
6052 bgp_path_info_delete(dest
, pi
);
6053 bgp_process(bgp
, dest
, afi
, safi
);
6056 /* Unlock bgp_node_lookup. */
6057 bgp_dest_unlock_node(dest
);
6061 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6063 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6064 afi_t afi
, safi_t safi
,
6065 struct prefix_rd
*prd
)
6067 struct bgp_dest
*dest
;
6068 struct bgp_path_info
*pi
;
6070 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6072 /* Check selected route and self inserted route. */
6073 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6074 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6075 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6078 /* Withdraw static BGP route from routing table. */
6080 #ifdef ENABLE_BGP_VNC
6081 rfapiProcessWithdraw(
6082 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6083 1); /* Kill, since it is an administrative change */
6085 if (SAFI_MPLS_VPN
== safi
6086 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6087 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6089 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6090 bgp_path_info_delete(dest
, pi
);
6091 bgp_process(bgp
, dest
, afi
, safi
);
6094 /* Unlock bgp_node_lookup. */
6095 bgp_dest_unlock_node(dest
);
6098 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6099 struct bgp_static
*bgp_static
, afi_t afi
,
6102 struct bgp_dest
*dest
;
6103 struct bgp_path_info
*new;
6104 struct attr
*attr_new
;
6105 struct attr attr
= {0};
6106 struct bgp_path_info
*pi
;
6107 #ifdef ENABLE_BGP_VNC
6108 mpls_label_t label
= 0;
6110 uint32_t num_labels
= 0;
6114 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6116 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6119 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
6121 attr
.nexthop
= bgp_static
->igpnexthop
;
6122 attr
.med
= bgp_static
->igpmetric
;
6123 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6125 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6126 || (safi
== SAFI_ENCAP
)) {
6127 if (afi
== AFI_IP
) {
6128 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6129 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6132 if (afi
== AFI_L2VPN
) {
6133 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6134 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6135 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6136 &bgp_static
->gatewayIp
.u
.prefix4
,
6138 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6139 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6140 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6141 &bgp_static
->gatewayIp
.u
.prefix6
,
6144 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6145 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6146 struct bgp_encap_type_vxlan bet
;
6147 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
6148 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6149 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6151 if (bgp_static
->router_mac
) {
6152 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6155 /* Apply route-map. */
6156 if (bgp_static
->rmap
.name
) {
6157 struct attr attr_tmp
= attr
;
6158 struct bgp_path_info rmap_path
;
6159 route_map_result_t ret
;
6161 rmap_path
.peer
= bgp
->peer_self
;
6162 rmap_path
.attr
= &attr_tmp
;
6164 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6166 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6168 bgp
->peer_self
->rmap_type
= 0;
6170 if (ret
== RMAP_DENYMATCH
) {
6171 /* Free uninterned attribute. */
6172 bgp_attr_flush(&attr_tmp
);
6174 /* Unintern original. */
6175 aspath_unintern(&attr
.aspath
);
6176 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6181 attr_new
= bgp_attr_intern(&attr_tmp
);
6183 attr_new
= bgp_attr_intern(&attr
);
6186 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6187 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6188 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6192 if (attrhash_cmp(pi
->attr
, attr_new
)
6193 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6194 bgp_dest_unlock_node(dest
);
6195 bgp_attr_unintern(&attr_new
);
6196 aspath_unintern(&attr
.aspath
);
6199 /* The attribute is changed. */
6200 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6202 /* Rewrite BGP route information. */
6203 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6204 bgp_path_info_restore(dest
, pi
);
6206 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6207 bgp_attr_unintern(&pi
->attr
);
6208 pi
->attr
= attr_new
;
6209 pi
->uptime
= bgp_clock();
6210 #ifdef ENABLE_BGP_VNC
6212 label
= decode_label(&pi
->extra
->label
[0]);
6215 /* Process change. */
6216 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6217 bgp_process(bgp
, dest
, afi
, safi
);
6219 if (SAFI_MPLS_VPN
== safi
6220 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6221 vpn_leak_to_vrf_update(bgp
, pi
);
6223 #ifdef ENABLE_BGP_VNC
6224 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6225 pi
->attr
, afi
, safi
, pi
->type
,
6226 pi
->sub_type
, &label
);
6228 bgp_dest_unlock_node(dest
);
6229 aspath_unintern(&attr
.aspath
);
6235 /* Make new BGP info. */
6236 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6238 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6239 bgp_path_info_extra_get(new);
6241 new->extra
->label
[0] = bgp_static
->label
;
6242 new->extra
->num_labels
= num_labels
;
6244 #ifdef ENABLE_BGP_VNC
6245 label
= decode_label(&bgp_static
->label
);
6248 /* Aggregate address increment. */
6249 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6251 /* Register new BGP information. */
6252 bgp_path_info_add(dest
, new);
6253 /* route_node_get lock */
6254 bgp_dest_unlock_node(dest
);
6256 /* Process change. */
6257 bgp_process(bgp
, dest
, afi
, safi
);
6259 if (SAFI_MPLS_VPN
== safi
6260 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6261 vpn_leak_to_vrf_update(bgp
, new);
6263 #ifdef ENABLE_BGP_VNC
6264 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6265 safi
, new->type
, new->sub_type
, &label
);
6268 /* Unintern original. */
6269 aspath_unintern(&attr
.aspath
);
6272 /* Configure static BGP network. When user don't run zebra, static
6273 route should be installed as valid. */
6274 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6275 const char *ip_str
, afi_t afi
, safi_t safi
,
6276 const char *rmap
, int backdoor
, uint32_t label_index
)
6278 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6281 struct bgp_static
*bgp_static
;
6282 struct bgp_dest
*dest
;
6283 uint8_t need_update
= 0;
6285 /* Convert IP prefix string to struct prefix. */
6286 ret
= str2prefix(ip_str
, &p
);
6288 vty_out(vty
, "%% Malformed prefix\n");
6289 return CMD_WARNING_CONFIG_FAILED
;
6291 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6292 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6293 return CMD_WARNING_CONFIG_FAILED
;
6300 /* Set BGP static route configuration. */
6301 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6304 vty_out(vty
, "%% Can't find static route specified\n");
6305 return CMD_WARNING_CONFIG_FAILED
;
6308 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6310 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6311 && (label_index
!= bgp_static
->label_index
)) {
6313 "%% label-index doesn't match static route\n");
6314 bgp_dest_unlock_node(dest
);
6315 return CMD_WARNING_CONFIG_FAILED
;
6318 if ((rmap
&& bgp_static
->rmap
.name
)
6319 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6321 "%% route-map name doesn't match static route\n");
6322 bgp_dest_unlock_node(dest
);
6323 return CMD_WARNING_CONFIG_FAILED
;
6326 /* Update BGP RIB. */
6327 if (!bgp_static
->backdoor
)
6328 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6330 /* Clear configuration. */
6331 bgp_static_free(bgp_static
);
6332 bgp_dest_set_bgp_static_info(dest
, NULL
);
6333 bgp_dest_unlock_node(dest
);
6334 bgp_dest_unlock_node(dest
);
6337 /* Set BGP static route configuration. */
6338 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6339 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6341 /* Configuration change. */
6342 /* Label index cannot be changed. */
6343 if (bgp_static
->label_index
!= label_index
) {
6344 vty_out(vty
, "%% cannot change label-index\n");
6345 return CMD_WARNING_CONFIG_FAILED
;
6348 /* Check previous routes are installed into BGP. */
6349 if (bgp_static
->valid
6350 && bgp_static
->backdoor
!= backdoor
)
6353 bgp_static
->backdoor
= backdoor
;
6356 XFREE(MTYPE_ROUTE_MAP_NAME
,
6357 bgp_static
->rmap
.name
);
6358 route_map_counter_decrement(
6359 bgp_static
->rmap
.map
);
6360 bgp_static
->rmap
.name
=
6361 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6362 bgp_static
->rmap
.map
=
6363 route_map_lookup_by_name(rmap
);
6364 route_map_counter_increment(
6365 bgp_static
->rmap
.map
);
6367 XFREE(MTYPE_ROUTE_MAP_NAME
,
6368 bgp_static
->rmap
.name
);
6369 route_map_counter_decrement(
6370 bgp_static
->rmap
.map
);
6371 bgp_static
->rmap
.map
= NULL
;
6372 bgp_static
->valid
= 0;
6374 bgp_dest_unlock_node(dest
);
6376 /* New configuration. */
6377 bgp_static
= bgp_static_new();
6378 bgp_static
->backdoor
= backdoor
;
6379 bgp_static
->valid
= 0;
6380 bgp_static
->igpmetric
= 0;
6381 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6382 bgp_static
->label_index
= label_index
;
6385 XFREE(MTYPE_ROUTE_MAP_NAME
,
6386 bgp_static
->rmap
.name
);
6387 route_map_counter_decrement(
6388 bgp_static
->rmap
.map
);
6389 bgp_static
->rmap
.name
=
6390 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6391 bgp_static
->rmap
.map
=
6392 route_map_lookup_by_name(rmap
);
6393 route_map_counter_increment(
6394 bgp_static
->rmap
.map
);
6396 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6399 bgp_static
->valid
= 1;
6401 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6403 if (!bgp_static
->backdoor
)
6404 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6410 void bgp_static_add(struct bgp
*bgp
)
6414 struct bgp_dest
*dest
;
6415 struct bgp_dest
*rm
;
6416 struct bgp_table
*table
;
6417 struct bgp_static
*bgp_static
;
6419 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6420 FOREACH_AFI_SAFI (afi
, safi
)
6421 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6422 dest
= bgp_route_next(dest
)) {
6423 if (!bgp_dest_has_bgp_path_info_data(dest
))
6426 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6427 || (safi
== SAFI_EVPN
)) {
6428 table
= bgp_dest_get_bgp_table_info(dest
);
6430 for (rm
= bgp_table_top(table
); rm
;
6431 rm
= bgp_route_next(rm
)) {
6433 bgp_dest_get_bgp_static_info(
6435 bgp_static_update_safi(
6436 bgp
, bgp_dest_get_prefix(rm
),
6437 bgp_static
, afi
, safi
);
6441 bgp
, bgp_dest_get_prefix(dest
),
6442 bgp_dest_get_bgp_static_info(dest
), afi
,
6446 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6449 /* Called from bgp_delete(). Delete all static routes from the BGP
6451 void bgp_static_delete(struct bgp
*bgp
)
6455 struct bgp_dest
*dest
;
6456 struct bgp_dest
*rm
;
6457 struct bgp_table
*table
;
6458 struct bgp_static
*bgp_static
;
6460 FOREACH_AFI_SAFI (afi
, safi
)
6461 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6462 dest
= bgp_route_next(dest
)) {
6463 if (!bgp_dest_has_bgp_path_info_data(dest
))
6466 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6467 || (safi
== SAFI_EVPN
)) {
6468 table
= bgp_dest_get_bgp_table_info(dest
);
6470 for (rm
= bgp_table_top(table
); rm
;
6471 rm
= bgp_route_next(rm
)) {
6473 bgp_dest_get_bgp_static_info(
6478 bgp_static_withdraw_safi(
6479 bgp
, bgp_dest_get_prefix(rm
),
6481 (struct prefix_rd
*)
6482 bgp_dest_get_prefix(
6484 bgp_static_free(bgp_static
);
6485 bgp_dest_set_bgp_static_info(rm
,
6487 bgp_dest_unlock_node(rm
);
6490 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6491 bgp_static_withdraw(bgp
,
6492 bgp_dest_get_prefix(dest
),
6494 bgp_static_free(bgp_static
);
6495 bgp_dest_set_bgp_static_info(dest
, NULL
);
6496 bgp_dest_unlock_node(dest
);
6501 void bgp_static_redo_import_check(struct bgp
*bgp
)
6505 struct bgp_dest
*dest
;
6506 struct bgp_dest
*rm
;
6507 struct bgp_table
*table
;
6508 struct bgp_static
*bgp_static
;
6510 /* Use this flag to force reprocessing of the route */
6511 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6512 FOREACH_AFI_SAFI (afi
, safi
) {
6513 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6514 dest
= bgp_route_next(dest
)) {
6515 if (!bgp_dest_has_bgp_path_info_data(dest
))
6518 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6519 || (safi
== SAFI_EVPN
)) {
6520 table
= bgp_dest_get_bgp_table_info(dest
);
6522 for (rm
= bgp_table_top(table
); rm
;
6523 rm
= bgp_route_next(rm
)) {
6525 bgp_dest_get_bgp_static_info(
6527 bgp_static_update_safi(
6528 bgp
, bgp_dest_get_prefix(rm
),
6529 bgp_static
, afi
, safi
);
6532 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6533 bgp_static_update(bgp
,
6534 bgp_dest_get_prefix(dest
),
6535 bgp_static
, afi
, safi
);
6539 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6542 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6545 struct bgp_table
*table
;
6546 struct bgp_dest
*dest
;
6547 struct bgp_path_info
*pi
;
6549 /* Do not install the aggregate route if BGP is in the
6550 * process of termination.
6552 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6553 || (bgp
->peer_self
== NULL
))
6556 table
= bgp
->rib
[afi
][safi
];
6557 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6558 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6559 if (pi
->peer
== bgp
->peer_self
6560 && ((pi
->type
== ZEBRA_ROUTE_BGP
6561 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6562 || (pi
->type
!= ZEBRA_ROUTE_BGP
6564 == BGP_ROUTE_REDISTRIBUTE
))) {
6565 bgp_aggregate_decrement(
6566 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6568 bgp_unlink_nexthop(pi
);
6569 bgp_path_info_delete(dest
, pi
);
6570 bgp_process(bgp
, dest
, afi
, safi
);
6577 * Purge all networks and redistributed routes from routing table.
6578 * Invoked upon the instance going down.
6580 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6585 FOREACH_AFI_SAFI (afi
, safi
)
6586 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6591 * Currently this is used to set static routes for VPN and ENCAP.
6592 * I think it can probably be factored with bgp_static_set.
6594 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6595 const char *ip_str
, const char *rd_str
,
6596 const char *label_str
, const char *rmap_str
,
6597 int evpn_type
, const char *esi
, const char *gwip
,
6598 const char *ethtag
, const char *routermac
)
6600 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6603 struct prefix_rd prd
;
6604 struct bgp_dest
*pdest
;
6605 struct bgp_dest
*dest
;
6606 struct bgp_table
*table
;
6607 struct bgp_static
*bgp_static
;
6608 mpls_label_t label
= MPLS_INVALID_LABEL
;
6609 struct prefix gw_ip
;
6611 /* validate ip prefix */
6612 ret
= str2prefix(ip_str
, &p
);
6614 vty_out(vty
, "%% Malformed prefix\n");
6615 return CMD_WARNING_CONFIG_FAILED
;
6618 if ((afi
== AFI_L2VPN
)
6619 && (bgp_build_evpn_prefix(evpn_type
,
6620 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6621 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6622 return CMD_WARNING_CONFIG_FAILED
;
6625 ret
= str2prefix_rd(rd_str
, &prd
);
6627 vty_out(vty
, "%% Malformed rd\n");
6628 return CMD_WARNING_CONFIG_FAILED
;
6632 unsigned long label_val
;
6633 label_val
= strtoul(label_str
, NULL
, 10);
6634 encode_label(label_val
, &label
);
6637 if (safi
== SAFI_EVPN
) {
6638 if (esi
&& str2esi(esi
, NULL
) == 0) {
6639 vty_out(vty
, "%% Malformed ESI\n");
6640 return CMD_WARNING_CONFIG_FAILED
;
6642 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6643 vty_out(vty
, "%% Malformed Router MAC\n");
6644 return CMD_WARNING_CONFIG_FAILED
;
6647 memset(&gw_ip
, 0, sizeof(struct prefix
));
6648 ret
= str2prefix(gwip
, &gw_ip
);
6650 vty_out(vty
, "%% Malformed GatewayIp\n");
6651 return CMD_WARNING_CONFIG_FAILED
;
6653 if ((gw_ip
.family
== AF_INET
6654 && is_evpn_prefix_ipaddr_v6(
6655 (struct prefix_evpn
*)&p
))
6656 || (gw_ip
.family
== AF_INET6
6657 && is_evpn_prefix_ipaddr_v4(
6658 (struct prefix_evpn
*)&p
))) {
6660 "%% GatewayIp family differs with IP prefix\n");
6661 return CMD_WARNING_CONFIG_FAILED
;
6665 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6666 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6667 bgp_dest_set_bgp_table_info(pdest
,
6668 bgp_table_init(bgp
, afi
, safi
));
6669 table
= bgp_dest_get_bgp_table_info(pdest
);
6671 dest
= bgp_node_get(table
, &p
);
6673 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6674 vty_out(vty
, "%% Same network configuration exists\n");
6675 bgp_dest_unlock_node(dest
);
6677 /* New configuration. */
6678 bgp_static
= bgp_static_new();
6679 bgp_static
->backdoor
= 0;
6680 bgp_static
->valid
= 0;
6681 bgp_static
->igpmetric
= 0;
6682 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6683 bgp_static
->label
= label
;
6684 bgp_static
->prd
= prd
;
6687 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6688 route_map_counter_decrement(bgp_static
->rmap
.map
);
6689 bgp_static
->rmap
.name
=
6690 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6691 bgp_static
->rmap
.map
=
6692 route_map_lookup_by_name(rmap_str
);
6693 route_map_counter_increment(bgp_static
->rmap
.map
);
6696 if (safi
== SAFI_EVPN
) {
6698 bgp_static
->eth_s_id
=
6701 str2esi(esi
, bgp_static
->eth_s_id
);
6704 bgp_static
->router_mac
=
6705 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
6706 (void)prefix_str2mac(routermac
,
6707 bgp_static
->router_mac
);
6710 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
6712 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6714 bgp_static
->valid
= 1;
6715 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
6721 /* Configure static BGP network. */
6722 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6723 const char *ip_str
, const char *rd_str
,
6724 const char *label_str
, int evpn_type
, const char *esi
,
6725 const char *gwip
, const char *ethtag
)
6727 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6730 struct prefix_rd prd
;
6731 struct bgp_dest
*pdest
;
6732 struct bgp_dest
*dest
;
6733 struct bgp_table
*table
;
6734 struct bgp_static
*bgp_static
;
6735 mpls_label_t label
= MPLS_INVALID_LABEL
;
6737 /* Convert IP prefix string to struct prefix. */
6738 ret
= str2prefix(ip_str
, &p
);
6740 vty_out(vty
, "%% Malformed prefix\n");
6741 return CMD_WARNING_CONFIG_FAILED
;
6744 if ((afi
== AFI_L2VPN
)
6745 && (bgp_build_evpn_prefix(evpn_type
,
6746 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6747 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6748 return CMD_WARNING_CONFIG_FAILED
;
6750 ret
= str2prefix_rd(rd_str
, &prd
);
6752 vty_out(vty
, "%% Malformed rd\n");
6753 return CMD_WARNING_CONFIG_FAILED
;
6757 unsigned long label_val
;
6758 label_val
= strtoul(label_str
, NULL
, 10);
6759 encode_label(label_val
, &label
);
6762 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6763 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6764 bgp_dest_set_bgp_table_info(pdest
,
6765 bgp_table_init(bgp
, afi
, safi
));
6767 bgp_dest_unlock_node(pdest
);
6768 table
= bgp_dest_get_bgp_table_info(pdest
);
6770 dest
= bgp_node_lookup(table
, &p
);
6773 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6775 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6776 bgp_static_free(bgp_static
);
6777 bgp_dest_set_bgp_static_info(dest
, NULL
);
6778 bgp_dest_unlock_node(dest
);
6779 bgp_dest_unlock_node(dest
);
6781 vty_out(vty
, "%% Can't find the route\n");
6786 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6787 const char *rmap_name
)
6789 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6790 struct bgp_rmap
*rmap
;
6792 rmap
= &bgp
->table_map
[afi
][safi
];
6794 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6795 route_map_counter_decrement(rmap
->map
);
6796 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6797 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6798 route_map_counter_increment(rmap
->map
);
6800 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6801 route_map_counter_decrement(rmap
->map
);
6805 if (bgp_fibupd_safi(safi
))
6806 bgp_zebra_announce_table(bgp
, afi
, safi
);
6811 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6812 const char *rmap_name
)
6814 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6815 struct bgp_rmap
*rmap
;
6817 rmap
= &bgp
->table_map
[afi
][safi
];
6818 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6819 route_map_counter_decrement(rmap
->map
);
6822 if (bgp_fibupd_safi(safi
))
6823 bgp_zebra_announce_table(bgp
, afi
, safi
);
6828 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6831 if (bgp
->table_map
[afi
][safi
].name
) {
6832 vty_out(vty
, " table-map %s\n",
6833 bgp
->table_map
[afi
][safi
].name
);
6837 DEFUN (bgp_table_map
,
6840 "BGP table to RIB route download filter\n"
6841 "Name of the route map\n")
6844 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6845 argv
[idx_word
]->arg
);
6847 DEFUN (no_bgp_table_map
,
6848 no_bgp_table_map_cmd
,
6849 "no table-map WORD",
6851 "BGP table to RIB route download filter\n"
6852 "Name of the route map\n")
6855 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6856 argv
[idx_word
]->arg
);
6862 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6863 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6864 backdoor$backdoor}]",
6866 "Specify a network to announce via BGP\n"
6871 "Route-map to modify the attributes\n"
6872 "Name of the route map\n"
6873 "Label index to associate with the prefix\n"
6874 "Label index value\n"
6875 "Specify a BGP backdoor route\n")
6877 char addr_prefix_str
[BUFSIZ
];
6882 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6884 sizeof(addr_prefix_str
));
6886 vty_out(vty
, "%% Inconsistent address and mask\n");
6887 return CMD_WARNING_CONFIG_FAILED
;
6891 return bgp_static_set(
6892 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
6893 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
6894 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6897 DEFPY(ipv6_bgp_network
,
6898 ipv6_bgp_network_cmd
,
6899 "[no] network X:X::X:X/M$prefix \
6900 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6902 "Specify a network to announce via BGP\n"
6904 "Route-map to modify the attributes\n"
6905 "Name of the route map\n"
6906 "Label index to associate with the prefix\n"
6907 "Label index value\n")
6909 return bgp_static_set(
6910 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
6911 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6914 static struct bgp_aggregate
*bgp_aggregate_new(void)
6916 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6919 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6921 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
6922 route_map_counter_decrement(aggregate
->suppress_map
);
6923 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6924 route_map_counter_decrement(aggregate
->rmap
.map
);
6925 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6929 * Helper function to avoid repeated code: prepare variables for a
6930 * `route_map_apply` call.
6932 * \returns `true` on route map match, otherwise `false`.
6934 static bool aggr_suppress_map_test(struct bgp
*bgp
,
6935 struct bgp_aggregate
*aggregate
,
6936 struct bgp_path_info
*pi
)
6938 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
6939 route_map_result_t rmr
= RMAP_DENYMATCH
;
6940 struct bgp_path_info rmap_path
= {};
6941 struct attr attr
= {};
6943 /* No route map entries created, just don't match. */
6944 if (aggregate
->suppress_map
== NULL
)
6947 /* Call route map matching and return result. */
6948 attr
.aspath
= aspath_empty();
6949 rmap_path
.peer
= bgp
->peer_self
;
6950 rmap_path
.attr
= &attr
;
6952 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
6953 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
6954 bgp
->peer_self
->rmap_type
= 0;
6956 bgp_attr_flush(&attr
);
6957 aspath_unintern(&attr
.aspath
);
6959 return rmr
== RMAP_PERMITMATCH
;
6962 /** Test whether the aggregation has suppressed this path or not. */
6963 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
6964 struct bgp_path_info
*pi
)
6966 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
6969 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
6973 * Suppress this path and keep the reference.
6975 * \returns `true` if needs processing otherwise `false`.
6977 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
6978 struct bgp_path_info
*pi
)
6980 struct bgp_path_info_extra
*pie
;
6982 /* Path is already suppressed by this aggregation. */
6983 if (aggr_suppress_exists(aggregate
, pi
))
6986 pie
= bgp_path_info_extra_get(pi
);
6988 /* This is the first suppression, allocate memory and list it. */
6989 if (pie
->aggr_suppressors
== NULL
)
6990 pie
->aggr_suppressors
= list_new();
6992 listnode_add(pie
->aggr_suppressors
, aggregate
);
6994 /* Only mark for processing if suppressed. */
6995 if (listcount(pie
->aggr_suppressors
) == 1) {
6996 if (BGP_DEBUG(update
, UPDATE_OUT
))
6997 zlog_debug("aggregate-address suppressing: %pFX",
6998 bgp_dest_get_prefix(pi
->net
));
7000 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7008 * Unsuppress this path and remove the reference.
7010 * \returns `true` if needs processing otherwise `false`.
7012 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7013 struct bgp_path_info
*pi
)
7015 /* Path wasn't suppressed. */
7016 if (!aggr_suppress_exists(aggregate
, pi
))
7019 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7021 /* Unsuppress and free extra memory if last item. */
7022 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7023 if (BGP_DEBUG(update
, UPDATE_OUT
))
7024 zlog_debug("aggregate-address unsuppressing: %pFX",
7025 bgp_dest_get_prefix(pi
->net
));
7027 list_delete(&pi
->extra
->aggr_suppressors
);
7028 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7035 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7036 struct aspath
*aspath
,
7037 struct community
*comm
,
7038 struct ecommunity
*ecomm
,
7039 struct lcommunity
*lcomm
)
7041 static struct aspath
*ae
= NULL
;
7044 ae
= aspath_empty();
7049 if (origin
!= pi
->attr
->origin
)
7052 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7055 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7058 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7061 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7064 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7070 static void bgp_aggregate_install(
7071 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7072 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7073 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7074 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7076 struct bgp_dest
*dest
;
7077 struct bgp_table
*table
;
7078 struct bgp_path_info
*pi
, *orig
, *new;
7081 table
= bgp
->rib
[afi
][safi
];
7083 dest
= bgp_node_get(table
, p
);
7085 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7086 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7087 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7091 * If we have paths with different MEDs, then don't install
7092 * (or uninstall) the aggregate route.
7094 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7095 goto uninstall_aggregate_route
;
7097 if (aggregate
->count
> 0) {
7099 * If the aggregate information has not changed
7100 * no need to re-install it again.
7102 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7103 ecommunity
, lcommunity
)) {
7104 bgp_dest_unlock_node(dest
);
7107 aspath_free(aspath
);
7109 community_free(&community
);
7111 ecommunity_free(&ecommunity
);
7113 lcommunity_free(&lcommunity
);
7119 * Mark the old as unusable
7122 bgp_path_info_delete(dest
, pi
);
7124 attr
= bgp_attr_aggregate_intern(
7125 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7126 aggregate
, atomic_aggregate
, p
);
7129 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7130 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7131 zlog_debug("%s: %pFX null attribute", __func__
,
7136 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7137 bgp
->peer_self
, attr
, dest
);
7139 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7141 bgp_path_info_add(dest
, new);
7142 bgp_process(bgp
, dest
, afi
, safi
);
7144 uninstall_aggregate_route
:
7145 for (pi
= orig
; pi
; pi
= pi
->next
)
7146 if (pi
->peer
== bgp
->peer_self
7147 && pi
->type
== ZEBRA_ROUTE_BGP
7148 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7151 /* Withdraw static BGP route from routing table. */
7153 bgp_path_info_delete(dest
, pi
);
7154 bgp_process(bgp
, dest
, afi
, safi
);
7158 bgp_dest_unlock_node(dest
);
7162 * Check if the current path has different MED than other known paths.
7164 * \returns `true` if the MED matched the others else `false`.
7166 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7167 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7169 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7171 /* This is the first route being analyzed. */
7172 if (!aggregate
->med_initialized
) {
7173 aggregate
->med_initialized
= true;
7174 aggregate
->med_mismatched
= false;
7175 aggregate
->med_matched_value
= cur_med
;
7177 /* Check if routes with different MED showed up. */
7178 if (cur_med
!= aggregate
->med_matched_value
)
7179 aggregate
->med_mismatched
= true;
7182 return !aggregate
->med_mismatched
;
7186 * Initializes and tests all routes in the aggregate address path for MED
7189 * \returns `true` if all MEDs are the same otherwise `false`.
7191 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7192 struct bgp
*bgp
, const struct prefix
*p
,
7193 afi_t afi
, safi_t safi
)
7195 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7196 const struct prefix
*dest_p
;
7197 struct bgp_dest
*dest
, *top
;
7198 struct bgp_path_info
*pi
;
7199 bool med_matched
= true;
7201 aggregate
->med_initialized
= false;
7203 top
= bgp_node_get(table
, p
);
7204 for (dest
= bgp_node_get(table
, p
); dest
;
7205 dest
= bgp_route_next_until(dest
, top
)) {
7206 dest_p
= bgp_dest_get_prefix(dest
);
7207 if (dest_p
->prefixlen
<= p
->prefixlen
)
7210 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7211 if (BGP_PATH_HOLDDOWN(pi
))
7213 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7215 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7216 med_matched
= false;
7223 bgp_dest_unlock_node(top
);
7229 * Toggles the route suppression status for this aggregate address
7232 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7233 struct bgp
*bgp
, const struct prefix
*p
,
7234 afi_t afi
, safi_t safi
, bool suppress
)
7236 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7237 const struct prefix
*dest_p
;
7238 struct bgp_dest
*dest
, *top
;
7239 struct bgp_path_info
*pi
;
7240 bool toggle_suppression
;
7242 /* We've found a different MED we must revert any suppressed routes. */
7243 top
= bgp_node_get(table
, p
);
7244 for (dest
= bgp_node_get(table
, p
); dest
;
7245 dest
= bgp_route_next_until(dest
, top
)) {
7246 dest_p
= bgp_dest_get_prefix(dest
);
7247 if (dest_p
->prefixlen
<= p
->prefixlen
)
7250 toggle_suppression
= false;
7251 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7252 if (BGP_PATH_HOLDDOWN(pi
))
7254 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7257 /* We are toggling suppression back. */
7259 /* Suppress route if not suppressed already. */
7260 if (aggr_suppress_path(aggregate
, pi
))
7261 toggle_suppression
= true;
7265 /* Install route if there is no more suppression. */
7266 if (aggr_unsuppress_path(aggregate
, pi
))
7267 toggle_suppression
= true;
7270 if (toggle_suppression
)
7271 bgp_process(bgp
, dest
, afi
, safi
);
7273 bgp_dest_unlock_node(top
);
7277 * Aggregate address MED matching incremental test: this function is called
7278 * when the initial aggregation occurred and we are only testing a single
7281 * In addition to testing and setting the MED validity it also installs back
7282 * suppressed routes (if summary is configured).
7284 * Must not be called in `bgp_aggregate_route`.
7286 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7287 struct bgp
*bgp
, const struct prefix
*p
,
7288 afi_t afi
, safi_t safi
,
7289 struct bgp_path_info
*pi
, bool is_adding
)
7291 /* MED matching disabled. */
7292 if (!aggregate
->match_med
)
7295 /* Aggregation with different MED, nothing to do. */
7296 if (aggregate
->med_mismatched
)
7300 * Test the current entry:
7302 * is_adding == true: if the new entry doesn't match then we must
7303 * install all suppressed routes.
7305 * is_adding == false: if the entry being removed was the last
7306 * unmatching entry then we can suppress all routes.
7309 if (bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
)
7310 && aggregate
->summary_only
)
7311 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
,
7314 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7316 /* No mismatches, just quit. */
7317 if (!aggregate
->med_mismatched
)
7320 /* Route summarization is disabled. */
7321 if (!aggregate
->summary_only
)
7324 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7327 /* Update an aggregate as routes are added/removed from the BGP table */
7328 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7329 safi_t safi
, struct bgp_aggregate
*aggregate
)
7331 struct bgp_table
*table
;
7332 struct bgp_dest
*top
;
7333 struct bgp_dest
*dest
;
7335 struct aspath
*aspath
= NULL
;
7336 struct community
*community
= NULL
;
7337 struct ecommunity
*ecommunity
= NULL
;
7338 struct lcommunity
*lcommunity
= NULL
;
7339 struct bgp_path_info
*pi
;
7340 unsigned long match
= 0;
7341 uint8_t atomic_aggregate
= 0;
7343 /* If the bgp instance is being deleted or self peer is deleted
7344 * then do not create aggregate route
7346 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7347 || (bgp
->peer_self
== NULL
))
7350 /* Initialize and test routes for MED difference. */
7351 if (aggregate
->match_med
)
7352 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7355 * Reset aggregate count: we might've been called from route map
7356 * update so in that case we must retest all more specific routes.
7358 * \see `bgp_route_map_process_update`.
7360 aggregate
->count
= 0;
7361 aggregate
->incomplete_origin_count
= 0;
7362 aggregate
->incomplete_origin_count
= 0;
7363 aggregate
->egp_origin_count
= 0;
7365 /* ORIGIN attribute: If at least one route among routes that are
7366 aggregated has ORIGIN with the value INCOMPLETE, then the
7367 aggregated route must have the ORIGIN attribute with the value
7368 INCOMPLETE. Otherwise, if at least one route among routes that
7369 are aggregated has ORIGIN with the value EGP, then the aggregated
7370 route must have the origin attribute with the value EGP. In all
7371 other case the value of the ORIGIN attribute of the aggregated
7372 route is INTERNAL. */
7373 origin
= BGP_ORIGIN_IGP
;
7375 table
= bgp
->rib
[afi
][safi
];
7377 top
= bgp_node_get(table
, p
);
7378 for (dest
= bgp_node_get(table
, p
); dest
;
7379 dest
= bgp_route_next_until(dest
, top
)) {
7380 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7382 if (dest_p
->prefixlen
<= p
->prefixlen
)
7385 /* If suppress fib is enabled and route not installed
7386 * in FIB, skip the route
7388 if (!bgp_check_advertise(bgp
, dest
))
7393 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7394 if (BGP_PATH_HOLDDOWN(pi
))
7398 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7399 atomic_aggregate
= 1;
7401 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7405 * summary-only aggregate route suppress
7406 * aggregated route announcements.
7409 * Don't create summaries if MED didn't match
7410 * otherwise neither the specific routes and the
7411 * aggregation will be announced.
7413 if (aggregate
->summary_only
7414 && AGGREGATE_MED_VALID(aggregate
)) {
7415 if (aggr_suppress_path(aggregate
, pi
))
7420 * Suppress more specific routes that match the route
7424 * Don't suppress routes if MED matching is enabled and
7425 * it mismatched otherwise we might end up with no
7426 * routes for this path.
7428 if (aggregate
->suppress_map_name
7429 && AGGREGATE_MED_VALID(aggregate
)
7430 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7431 if (aggr_suppress_path(aggregate
, pi
))
7438 * If at least one route among routes that are
7439 * aggregated has ORIGIN with the value INCOMPLETE,
7440 * then the aggregated route MUST have the ORIGIN
7441 * attribute with the value INCOMPLETE. Otherwise, if
7442 * at least one route among routes that are aggregated
7443 * has ORIGIN with the value EGP, then the aggregated
7444 * route MUST have the ORIGIN attribute with the value
7447 switch (pi
->attr
->origin
) {
7448 case BGP_ORIGIN_INCOMPLETE
:
7449 aggregate
->incomplete_origin_count
++;
7451 case BGP_ORIGIN_EGP
:
7452 aggregate
->egp_origin_count
++;
7460 if (!aggregate
->as_set
)
7464 * as-set aggregate route generate origin, as path,
7465 * and community aggregation.
7467 /* Compute aggregate route's as-path.
7469 bgp_compute_aggregate_aspath_hash(aggregate
,
7472 /* Compute aggregate route's community.
7474 if (bgp_attr_get_community(pi
->attr
))
7475 bgp_compute_aggregate_community_hash(
7477 bgp_attr_get_community(pi
->attr
));
7479 /* Compute aggregate route's extended community.
7481 if (bgp_attr_get_ecommunity(pi
->attr
))
7482 bgp_compute_aggregate_ecommunity_hash(
7484 bgp_attr_get_ecommunity(pi
->attr
));
7486 /* Compute aggregate route's large community.
7488 if (bgp_attr_get_lcommunity(pi
->attr
))
7489 bgp_compute_aggregate_lcommunity_hash(
7491 bgp_attr_get_lcommunity(pi
->attr
));
7494 bgp_process(bgp
, dest
, afi
, safi
);
7496 if (aggregate
->as_set
) {
7497 bgp_compute_aggregate_aspath_val(aggregate
);
7498 bgp_compute_aggregate_community_val(aggregate
);
7499 bgp_compute_aggregate_ecommunity_val(aggregate
);
7500 bgp_compute_aggregate_lcommunity_val(aggregate
);
7504 bgp_dest_unlock_node(top
);
7507 if (aggregate
->incomplete_origin_count
> 0)
7508 origin
= BGP_ORIGIN_INCOMPLETE
;
7509 else if (aggregate
->egp_origin_count
> 0)
7510 origin
= BGP_ORIGIN_EGP
;
7512 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7513 origin
= aggregate
->origin
;
7515 if (aggregate
->as_set
) {
7516 if (aggregate
->aspath
)
7517 /* Retrieve aggregate route's as-path.
7519 aspath
= aspath_dup(aggregate
->aspath
);
7521 if (aggregate
->community
)
7522 /* Retrieve aggregate route's community.
7524 community
= community_dup(aggregate
->community
);
7526 if (aggregate
->ecommunity
)
7527 /* Retrieve aggregate route's ecommunity.
7529 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7531 if (aggregate
->lcommunity
)
7532 /* Retrieve aggregate route's lcommunity.
7534 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7537 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7538 ecommunity
, lcommunity
, atomic_aggregate
,
7542 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7543 safi_t safi
, struct bgp_aggregate
*aggregate
)
7545 struct bgp_table
*table
;
7546 struct bgp_dest
*top
;
7547 struct bgp_dest
*dest
;
7548 struct bgp_path_info
*pi
;
7549 unsigned long match
;
7551 table
= bgp
->rib
[afi
][safi
];
7553 /* If routes exists below this node, generate aggregate routes. */
7554 top
= bgp_node_get(table
, p
);
7555 for (dest
= bgp_node_get(table
, p
); dest
;
7556 dest
= bgp_route_next_until(dest
, top
)) {
7557 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7559 if (dest_p
->prefixlen
<= p
->prefixlen
)
7563 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7564 if (BGP_PATH_HOLDDOWN(pi
))
7567 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7571 * This route is suppressed: attempt to unsuppress it.
7573 * `aggr_unsuppress_path` will fail if this particular
7574 * aggregate route was not the suppressor.
7576 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7577 listcount(pi
->extra
->aggr_suppressors
)) {
7578 if (aggr_unsuppress_path(aggregate
, pi
))
7584 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7585 aggregate
->incomplete_origin_count
--;
7586 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7587 aggregate
->egp_origin_count
--;
7589 if (aggregate
->as_set
) {
7590 /* Remove as-path from aggregate.
7592 bgp_remove_aspath_from_aggregate_hash(
7596 if (bgp_attr_get_community(pi
->attr
))
7597 /* Remove community from aggregate.
7599 bgp_remove_comm_from_aggregate_hash(
7601 bgp_attr_get_community(
7604 if (bgp_attr_get_ecommunity(pi
->attr
))
7605 /* Remove ecommunity from aggregate.
7607 bgp_remove_ecomm_from_aggregate_hash(
7609 bgp_attr_get_ecommunity(
7612 if (bgp_attr_get_lcommunity(pi
->attr
))
7613 /* Remove lcommunity from aggregate.
7615 bgp_remove_lcomm_from_aggregate_hash(
7617 bgp_attr_get_lcommunity(
7622 /* If this node was suppressed, process the change. */
7624 bgp_process(bgp
, dest
, afi
, safi
);
7626 if (aggregate
->as_set
) {
7627 aspath_free(aggregate
->aspath
);
7628 aggregate
->aspath
= NULL
;
7629 if (aggregate
->community
)
7630 community_free(&aggregate
->community
);
7631 if (aggregate
->ecommunity
)
7632 ecommunity_free(&aggregate
->ecommunity
);
7633 if (aggregate
->lcommunity
)
7634 lcommunity_free(&aggregate
->lcommunity
);
7637 bgp_dest_unlock_node(top
);
7640 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7641 const struct prefix
*aggr_p
,
7642 struct bgp_path_info
*pinew
, afi_t afi
,
7644 struct bgp_aggregate
*aggregate
)
7647 struct aspath
*aspath
= NULL
;
7648 uint8_t atomic_aggregate
= 0;
7649 struct community
*community
= NULL
;
7650 struct ecommunity
*ecommunity
= NULL
;
7651 struct lcommunity
*lcommunity
= NULL
;
7653 /* If the bgp instance is being deleted or self peer is deleted
7654 * then do not create aggregate route
7656 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7657 || (bgp
->peer_self
== NULL
))
7660 /* ORIGIN attribute: If at least one route among routes that are
7661 * aggregated has ORIGIN with the value INCOMPLETE, then the
7662 * aggregated route must have the ORIGIN attribute with the value
7663 * INCOMPLETE. Otherwise, if at least one route among routes that
7664 * are aggregated has ORIGIN with the value EGP, then the aggregated
7665 * route must have the origin attribute with the value EGP. In all
7666 * other case the value of the ORIGIN attribute of the aggregated
7667 * route is INTERNAL.
7669 origin
= BGP_ORIGIN_IGP
;
7674 * This must be called before `summary` check to avoid
7675 * "suppressing" twice.
7677 if (aggregate
->match_med
)
7678 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7681 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7682 aggr_suppress_path(aggregate
, pinew
);
7684 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7685 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7686 aggr_suppress_path(aggregate
, pinew
);
7688 switch (pinew
->attr
->origin
) {
7689 case BGP_ORIGIN_INCOMPLETE
:
7690 aggregate
->incomplete_origin_count
++;
7692 case BGP_ORIGIN_EGP
:
7693 aggregate
->egp_origin_count
++;
7701 if (aggregate
->incomplete_origin_count
> 0)
7702 origin
= BGP_ORIGIN_INCOMPLETE
;
7703 else if (aggregate
->egp_origin_count
> 0)
7704 origin
= BGP_ORIGIN_EGP
;
7706 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7707 origin
= aggregate
->origin
;
7709 if (aggregate
->as_set
) {
7710 /* Compute aggregate route's as-path.
7712 bgp_compute_aggregate_aspath(aggregate
,
7713 pinew
->attr
->aspath
);
7715 /* Compute aggregate route's community.
7717 if (bgp_attr_get_community(pinew
->attr
))
7718 bgp_compute_aggregate_community(
7719 aggregate
, bgp_attr_get_community(pinew
->attr
));
7721 /* Compute aggregate route's extended community.
7723 if (bgp_attr_get_ecommunity(pinew
->attr
))
7724 bgp_compute_aggregate_ecommunity(
7726 bgp_attr_get_ecommunity(pinew
->attr
));
7728 /* Compute aggregate route's large community.
7730 if (bgp_attr_get_lcommunity(pinew
->attr
))
7731 bgp_compute_aggregate_lcommunity(
7733 bgp_attr_get_lcommunity(pinew
->attr
));
7735 /* Retrieve aggregate route's as-path.
7737 if (aggregate
->aspath
)
7738 aspath
= aspath_dup(aggregate
->aspath
);
7740 /* Retrieve aggregate route's community.
7742 if (aggregate
->community
)
7743 community
= community_dup(aggregate
->community
);
7745 /* Retrieve aggregate route's ecommunity.
7747 if (aggregate
->ecommunity
)
7748 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7750 /* Retrieve aggregate route's lcommunity.
7752 if (aggregate
->lcommunity
)
7753 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7756 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7757 aspath
, community
, ecommunity
,
7758 lcommunity
, atomic_aggregate
, aggregate
);
7761 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7763 struct bgp_path_info
*pi
,
7764 struct bgp_aggregate
*aggregate
,
7765 const struct prefix
*aggr_p
)
7768 struct aspath
*aspath
= NULL
;
7769 uint8_t atomic_aggregate
= 0;
7770 struct community
*community
= NULL
;
7771 struct ecommunity
*ecommunity
= NULL
;
7772 struct lcommunity
*lcommunity
= NULL
;
7773 unsigned long match
= 0;
7775 /* If the bgp instance is being deleted or self peer is deleted
7776 * then do not create aggregate route
7778 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7779 || (bgp
->peer_self
== NULL
))
7782 if (BGP_PATH_HOLDDOWN(pi
))
7785 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7788 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7789 if (aggr_unsuppress_path(aggregate
, pi
))
7792 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7793 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7794 if (aggr_unsuppress_path(aggregate
, pi
))
7798 * This must be called after `summary`, `suppress-map` check to avoid
7799 * "unsuppressing" twice.
7801 if (aggregate
->match_med
)
7802 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
,
7805 if (aggregate
->count
> 0)
7808 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7809 aggregate
->incomplete_origin_count
--;
7810 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7811 aggregate
->egp_origin_count
--;
7813 if (aggregate
->as_set
) {
7814 /* Remove as-path from aggregate.
7816 bgp_remove_aspath_from_aggregate(aggregate
,
7819 if (bgp_attr_get_community(pi
->attr
))
7820 /* Remove community from aggregate.
7822 bgp_remove_community_from_aggregate(
7823 aggregate
, bgp_attr_get_community(pi
->attr
));
7825 if (bgp_attr_get_ecommunity(pi
->attr
))
7826 /* Remove ecommunity from aggregate.
7828 bgp_remove_ecommunity_from_aggregate(
7829 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
7831 if (bgp_attr_get_lcommunity(pi
->attr
))
7832 /* Remove lcommunity from aggregate.
7834 bgp_remove_lcommunity_from_aggregate(
7835 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
7838 /* If this node was suppressed, process the change. */
7840 bgp_process(bgp
, pi
->net
, afi
, safi
);
7842 origin
= BGP_ORIGIN_IGP
;
7843 if (aggregate
->incomplete_origin_count
> 0)
7844 origin
= BGP_ORIGIN_INCOMPLETE
;
7845 else if (aggregate
->egp_origin_count
> 0)
7846 origin
= BGP_ORIGIN_EGP
;
7848 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7849 origin
= aggregate
->origin
;
7851 if (aggregate
->as_set
) {
7852 /* Retrieve aggregate route's as-path.
7854 if (aggregate
->aspath
)
7855 aspath
= aspath_dup(aggregate
->aspath
);
7857 /* Retrieve aggregate route's community.
7859 if (aggregate
->community
)
7860 community
= community_dup(aggregate
->community
);
7862 /* Retrieve aggregate route's ecommunity.
7864 if (aggregate
->ecommunity
)
7865 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7867 /* Retrieve aggregate route's lcommunity.
7869 if (aggregate
->lcommunity
)
7870 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7873 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7874 aspath
, community
, ecommunity
,
7875 lcommunity
, atomic_aggregate
, aggregate
);
7878 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
7879 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
7881 struct bgp_dest
*child
;
7882 struct bgp_dest
*dest
;
7883 struct bgp_aggregate
*aggregate
;
7884 struct bgp_table
*table
;
7886 table
= bgp
->aggregate
[afi
][safi
];
7888 /* No aggregates configured. */
7889 if (bgp_table_top_nolock(table
) == NULL
)
7892 if (p
->prefixlen
== 0)
7895 if (BGP_PATH_HOLDDOWN(pi
))
7898 /* If suppress fib is enabled and route not installed
7899 * in FIB, do not update the aggregate route
7901 if (!bgp_check_advertise(bgp
, pi
->net
))
7904 child
= bgp_node_get(table
, p
);
7906 /* Aggregate address configuration check. */
7907 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7908 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7910 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7911 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7912 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
7916 bgp_dest_unlock_node(child
);
7919 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
7920 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
7922 struct bgp_dest
*child
;
7923 struct bgp_dest
*dest
;
7924 struct bgp_aggregate
*aggregate
;
7925 struct bgp_table
*table
;
7927 table
= bgp
->aggregate
[afi
][safi
];
7929 /* No aggregates configured. */
7930 if (bgp_table_top_nolock(table
) == NULL
)
7933 if (p
->prefixlen
== 0)
7936 child
= bgp_node_get(table
, p
);
7938 /* Aggregate address configuration check. */
7939 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7940 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7942 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7943 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7944 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
7948 bgp_dest_unlock_node(child
);
7951 /* Aggregate route attribute. */
7952 #define AGGREGATE_SUMMARY_ONLY 1
7953 #define AGGREGATE_AS_SET 1
7954 #define AGGREGATE_AS_UNSET 0
7956 static const char *bgp_origin2str(uint8_t origin
)
7959 case BGP_ORIGIN_IGP
:
7961 case BGP_ORIGIN_EGP
:
7963 case BGP_ORIGIN_INCOMPLETE
:
7964 return "incomplete";
7969 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
7972 case RPKI_NOT_BEING_USED
:
7982 assert(!"We should never get here this is a dev escape");
7986 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
7987 afi_t afi
, safi_t safi
)
7989 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7992 struct bgp_dest
*dest
;
7993 struct bgp_aggregate
*aggregate
;
7995 /* Convert string to prefix structure. */
7996 ret
= str2prefix(prefix_str
, &p
);
7998 vty_out(vty
, "Malformed prefix\n");
7999 return CMD_WARNING_CONFIG_FAILED
;
8003 /* Old configuration check. */
8004 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8007 "%% There is no aggregate-address configuration.\n");
8008 return CMD_WARNING_CONFIG_FAILED
;
8011 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8012 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8013 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8014 NULL
, NULL
, 0, aggregate
);
8016 /* Unlock aggregate address configuration. */
8017 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8019 if (aggregate
->community
)
8020 community_free(&aggregate
->community
);
8022 if (aggregate
->community_hash
) {
8023 /* Delete all communities in the hash.
8025 hash_clean(aggregate
->community_hash
,
8026 bgp_aggr_community_remove
);
8027 /* Free up the community_hash.
8029 hash_free(aggregate
->community_hash
);
8032 if (aggregate
->ecommunity
)
8033 ecommunity_free(&aggregate
->ecommunity
);
8035 if (aggregate
->ecommunity_hash
) {
8036 /* Delete all ecommunities in the hash.
8038 hash_clean(aggregate
->ecommunity_hash
,
8039 bgp_aggr_ecommunity_remove
);
8040 /* Free up the ecommunity_hash.
8042 hash_free(aggregate
->ecommunity_hash
);
8045 if (aggregate
->lcommunity
)
8046 lcommunity_free(&aggregate
->lcommunity
);
8048 if (aggregate
->lcommunity_hash
) {
8049 /* Delete all lcommunities in the hash.
8051 hash_clean(aggregate
->lcommunity_hash
,
8052 bgp_aggr_lcommunity_remove
);
8053 /* Free up the lcommunity_hash.
8055 hash_free(aggregate
->lcommunity_hash
);
8058 if (aggregate
->aspath
)
8059 aspath_free(aggregate
->aspath
);
8061 if (aggregate
->aspath_hash
) {
8062 /* Delete all as-paths in the hash.
8064 hash_clean(aggregate
->aspath_hash
,
8065 bgp_aggr_aspath_remove
);
8066 /* Free up the aspath_hash.
8068 hash_free(aggregate
->aspath_hash
);
8071 bgp_aggregate_free(aggregate
);
8072 bgp_dest_unlock_node(dest
);
8073 bgp_dest_unlock_node(dest
);
8078 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8079 safi_t safi
, const char *rmap
,
8080 uint8_t summary_only
, uint8_t as_set
,
8081 uint8_t origin
, bool match_med
,
8082 const char *suppress_map
)
8084 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8087 struct bgp_dest
*dest
;
8088 struct bgp_aggregate
*aggregate
;
8089 uint8_t as_set_new
= as_set
;
8091 if (suppress_map
&& summary_only
) {
8093 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8094 return CMD_WARNING_CONFIG_FAILED
;
8097 /* Convert string to prefix structure. */
8098 ret
= str2prefix(prefix_str
, &p
);
8100 vty_out(vty
, "Malformed prefix\n");
8101 return CMD_WARNING_CONFIG_FAILED
;
8105 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8106 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8107 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8109 return CMD_WARNING_CONFIG_FAILED
;
8112 /* Old configuration check. */
8113 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8114 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8117 vty_out(vty
, "There is already same aggregate network.\n");
8118 /* try to remove the old entry */
8119 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8121 vty_out(vty
, "Error deleting aggregate.\n");
8122 bgp_dest_unlock_node(dest
);
8123 return CMD_WARNING_CONFIG_FAILED
;
8127 /* Make aggregate address structure. */
8128 aggregate
= bgp_aggregate_new();
8129 aggregate
->summary_only
= summary_only
;
8130 aggregate
->match_med
= match_med
;
8132 /* Network operators MUST NOT locally generate any new
8133 * announcements containing AS_SET or AS_CONFED_SET. If they have
8134 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8135 * SHOULD withdraw those routes and re-announce routes for the
8136 * aggregate or component prefixes (i.e., the more-specific routes
8137 * subsumed by the previously aggregated route) without AS_SET
8138 * or AS_CONFED_SET in the updates.
8140 if (bgp
->reject_as_sets
) {
8141 if (as_set
== AGGREGATE_AS_SET
) {
8142 as_set_new
= AGGREGATE_AS_UNSET
;
8144 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8147 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8151 aggregate
->as_set
= as_set_new
;
8152 aggregate
->safi
= safi
;
8153 /* Override ORIGIN attribute if defined.
8154 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8155 * to IGP which is not what rfc4271 says.
8156 * This enables the same behavior, optionally.
8158 aggregate
->origin
= origin
;
8161 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8162 route_map_counter_decrement(aggregate
->rmap
.map
);
8163 aggregate
->rmap
.name
=
8164 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8165 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8166 route_map_counter_increment(aggregate
->rmap
.map
);
8170 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8171 route_map_counter_decrement(aggregate
->suppress_map
);
8173 aggregate
->suppress_map_name
=
8174 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8175 aggregate
->suppress_map
=
8176 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8177 route_map_counter_increment(aggregate
->suppress_map
);
8180 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8182 /* Aggregate address insert into BGP routing table. */
8183 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8188 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8189 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8191 "|summary-only$summary_only"
8192 "|route-map WORD$rmap_name"
8193 "|origin <egp|igp|incomplete>$origin_s"
8194 "|matching-MED-only$match_med"
8195 "|suppress-map WORD$suppress_map"
8198 "Configure BGP aggregate entries\n"
8199 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
8200 "Generate AS set path information\n"
8201 "Filter more specific routes from updates\n"
8202 "Apply route map to aggregate network\n"
8207 "Unknown heritage\n"
8208 "Only aggregate routes with matching MED\n"
8209 "Suppress the selected more specific routes\n"
8210 "Route map with the route selectors\n")
8212 const char *prefix_s
= NULL
;
8213 safi_t safi
= bgp_node_safi(vty
);
8214 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8215 int as_set
= AGGREGATE_AS_UNSET
;
8216 char prefix_buf
[PREFIX2STR_BUFFER
];
8219 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8222 vty_out(vty
, "%% Inconsistent address and mask\n");
8223 return CMD_WARNING_CONFIG_FAILED
;
8225 prefix_s
= prefix_buf
;
8227 prefix_s
= prefix_str
;
8230 if (strcmp(origin_s
, "egp") == 0)
8231 origin
= BGP_ORIGIN_EGP
;
8232 else if (strcmp(origin_s
, "igp") == 0)
8233 origin
= BGP_ORIGIN_IGP
;
8234 else if (strcmp(origin_s
, "incomplete") == 0)
8235 origin
= BGP_ORIGIN_INCOMPLETE
;
8239 as_set
= AGGREGATE_AS_SET
;
8241 /* Handle configuration removal, otherwise installation. */
8243 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8245 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8246 summary_only
!= NULL
, as_set
, origin
,
8247 match_med
!= NULL
, suppress_map
);
8250 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8251 "[no] aggregate-address X:X::X:X/M$prefix [{"
8253 "|summary-only$summary_only"
8254 "|route-map WORD$rmap_name"
8255 "|origin <egp|igp|incomplete>$origin_s"
8256 "|matching-MED-only$match_med"
8257 "|suppress-map WORD$suppress_map"
8260 "Configure BGP aggregate entries\n"
8261 "Aggregate prefix\n"
8262 "Generate AS set path information\n"
8263 "Filter more specific routes from updates\n"
8264 "Apply route map to aggregate network\n"
8269 "Unknown heritage\n"
8270 "Only aggregate routes with matching MED\n"
8271 "Suppress the selected more specific routes\n"
8272 "Route map with the route selectors\n")
8274 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8275 int as_set
= AGGREGATE_AS_UNSET
;
8278 if (strcmp(origin_s
, "egp") == 0)
8279 origin
= BGP_ORIGIN_EGP
;
8280 else if (strcmp(origin_s
, "igp") == 0)
8281 origin
= BGP_ORIGIN_IGP
;
8282 else if (strcmp(origin_s
, "incomplete") == 0)
8283 origin
= BGP_ORIGIN_INCOMPLETE
;
8287 as_set
= AGGREGATE_AS_SET
;
8289 /* Handle configuration removal, otherwise installation. */
8291 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8294 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8295 rmap_name
, summary_only
!= NULL
, as_set
,
8296 origin
, match_med
!= NULL
, suppress_map
);
8299 /* Redistribute route treatment. */
8300 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8301 const union g_addr
*nexthop
, ifindex_t ifindex
,
8302 enum nexthop_types_t nhtype
, uint8_t distance
,
8303 enum blackhole_type bhtype
, uint32_t metric
,
8304 uint8_t type
, unsigned short instance
,
8307 struct bgp_path_info
*new;
8308 struct bgp_path_info
*bpi
;
8309 struct bgp_path_info rmap_path
;
8310 struct bgp_dest
*bn
;
8312 struct attr
*new_attr
;
8314 route_map_result_t ret
;
8315 struct bgp_redist
*red
;
8317 /* Make default attribute. */
8318 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
8320 * This must not be NULL to satisfy Coverity SA
8322 assert(attr
.aspath
);
8325 case NEXTHOP_TYPE_IFINDEX
:
8327 case NEXTHOP_TYPE_IPV4
:
8328 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8329 attr
.nexthop
= nexthop
->ipv4
;
8331 case NEXTHOP_TYPE_IPV6
:
8332 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8333 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8334 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8336 case NEXTHOP_TYPE_BLACKHOLE
:
8337 switch (p
->family
) {
8339 attr
.nexthop
.s_addr
= INADDR_ANY
;
8342 memset(&attr
.mp_nexthop_global
, 0,
8343 sizeof(attr
.mp_nexthop_global
));
8344 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8347 attr
.bh_type
= bhtype
;
8350 attr
.nh_type
= nhtype
;
8351 attr
.nh_ifindex
= ifindex
;
8354 attr
.distance
= distance
;
8355 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8358 afi
= family2afi(p
->family
);
8360 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8362 struct attr attr_new
;
8364 /* Copy attribute for modification. */
8367 if (red
->redist_metric_flag
)
8368 attr_new
.med
= red
->redist_metric
;
8370 /* Apply route-map. */
8371 if (red
->rmap
.name
) {
8372 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
8373 rmap_path
.peer
= bgp
->peer_self
;
8374 rmap_path
.attr
= &attr_new
;
8376 SET_FLAG(bgp
->peer_self
->rmap_type
,
8377 PEER_RMAP_TYPE_REDISTRIBUTE
);
8379 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8381 bgp
->peer_self
->rmap_type
= 0;
8383 if (ret
== RMAP_DENYMATCH
) {
8384 /* Free uninterned attribute. */
8385 bgp_attr_flush(&attr_new
);
8387 /* Unintern original. */
8388 aspath_unintern(&attr
.aspath
);
8389 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8394 if (bgp_in_graceful_shutdown(bgp
))
8395 bgp_attr_add_gshut_community(&attr_new
);
8397 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8398 SAFI_UNICAST
, p
, NULL
);
8400 new_attr
= bgp_attr_intern(&attr_new
);
8402 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8403 if (bpi
->peer
== bgp
->peer_self
8404 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8408 /* Ensure the (source route) type is updated. */
8410 if (attrhash_cmp(bpi
->attr
, new_attr
)
8411 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8412 bgp_attr_unintern(&new_attr
);
8413 aspath_unintern(&attr
.aspath
);
8414 bgp_dest_unlock_node(bn
);
8417 /* The attribute is changed. */
8418 bgp_path_info_set_flag(bn
, bpi
,
8419 BGP_PATH_ATTR_CHANGED
);
8421 /* Rewrite BGP route information. */
8422 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8423 bgp_path_info_restore(bn
, bpi
);
8425 bgp_aggregate_decrement(
8426 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8427 bgp_attr_unintern(&bpi
->attr
);
8428 bpi
->attr
= new_attr
;
8429 bpi
->uptime
= bgp_clock();
8431 /* Process change. */
8432 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8434 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8435 bgp_dest_unlock_node(bn
);
8436 aspath_unintern(&attr
.aspath
);
8438 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8440 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8442 vpn_leak_from_vrf_update(
8443 bgp_get_default(), bgp
, bpi
);
8449 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8450 bgp
->peer_self
, new_attr
, bn
);
8451 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8453 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8454 bgp_path_info_add(bn
, new);
8455 bgp_dest_unlock_node(bn
);
8456 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8457 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8459 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8460 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8462 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8466 /* Unintern original. */
8467 aspath_unintern(&attr
.aspath
);
8470 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8471 unsigned short instance
)
8474 struct bgp_dest
*dest
;
8475 struct bgp_path_info
*pi
;
8476 struct bgp_redist
*red
;
8478 afi
= family2afi(p
->family
);
8480 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8482 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8483 SAFI_UNICAST
, p
, NULL
);
8485 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8486 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8490 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8491 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8493 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8496 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8497 bgp_path_info_delete(dest
, pi
);
8498 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8500 bgp_dest_unlock_node(dest
);
8504 /* Withdraw specified route type's route. */
8505 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8506 unsigned short instance
)
8508 struct bgp_dest
*dest
;
8509 struct bgp_path_info
*pi
;
8510 struct bgp_table
*table
;
8512 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8514 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8515 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8516 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8517 && pi
->instance
== instance
)
8521 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8522 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8524 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8527 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8528 pi
, afi
, SAFI_UNICAST
);
8529 bgp_path_info_delete(dest
, pi
);
8530 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8535 /* Static function to display route. */
8536 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8537 struct vty
*vty
, json_object
*json
, bool wide
)
8542 if (p
->family
== AF_INET
) {
8544 len
= vty_out(vty
, "%pFX", p
);
8546 json_object_string_add(json
, "prefix",
8547 inet_ntop(p
->family
,
8550 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8551 json_object_string_addf(json
, "network", "%pFX", p
);
8552 json_object_int_add(json
, "version", dest
->version
);
8554 } else if (p
->family
== AF_ETHERNET
) {
8555 len
= vty_out(vty
, "%pFX", p
);
8556 } else if (p
->family
== AF_EVPN
) {
8558 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8560 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8561 } else if (p
->family
== AF_FLOWSPEC
) {
8562 route_vty_out_flowspec(vty
, p
, NULL
,
8564 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8565 NLRI_STRING_FORMAT_MIN
, json
);
8568 len
= vty_out(vty
, "%pFX", p
);
8570 json_object_string_add(json
, "prefix",
8571 inet_ntop(p
->family
,
8574 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8575 json_object_string_addf(json
, "network", "%pFX", p
);
8576 json_object_int_add(json
, "version", dest
->version
);
8581 len
= wide
? (45 - len
) : (17 - len
);
8583 vty_out(vty
, "\n%*s", 20, " ");
8585 vty_out(vty
, "%*s", len
, " ");
8589 enum bgp_display_type
{
8593 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8596 case bgp_path_selection_none
:
8597 return "Nothing to Select";
8598 case bgp_path_selection_first
:
8599 return "First path received";
8600 case bgp_path_selection_evpn_sticky_mac
:
8601 return "EVPN Sticky Mac";
8602 case bgp_path_selection_evpn_seq
:
8603 return "EVPN sequence number";
8604 case bgp_path_selection_evpn_lower_ip
:
8605 return "EVPN lower IP";
8606 case bgp_path_selection_evpn_local_path
:
8607 return "EVPN local ES path";
8608 case bgp_path_selection_evpn_non_proxy
:
8609 return "EVPN non proxy";
8610 case bgp_path_selection_weight
:
8612 case bgp_path_selection_local_pref
:
8613 return "Local Pref";
8614 case bgp_path_selection_local_route
:
8615 return "Local Route";
8616 case bgp_path_selection_confed_as_path
:
8617 return "Confederation based AS Path";
8618 case bgp_path_selection_as_path
:
8620 case bgp_path_selection_origin
:
8622 case bgp_path_selection_med
:
8624 case bgp_path_selection_peer
:
8626 case bgp_path_selection_confed
:
8627 return "Confed Peer Type";
8628 case bgp_path_selection_igp_metric
:
8629 return "IGP Metric";
8630 case bgp_path_selection_older
:
8631 return "Older Path";
8632 case bgp_path_selection_router_id
:
8634 case bgp_path_selection_cluster_length
:
8635 return "Cluster length";
8636 case bgp_path_selection_stale
:
8637 return "Path Staleness";
8638 case bgp_path_selection_local_configured
:
8639 return "Locally configured route";
8640 case bgp_path_selection_neighbor_ip
:
8641 return "Neighbor IP";
8642 case bgp_path_selection_default
:
8643 return "Nothing left to compare";
8645 return "Invalid (internal error)";
8648 /* Print the short form route status for a bgp_path_info */
8649 static void route_vty_short_status_out(struct vty
*vty
,
8650 struct bgp_path_info
*path
,
8651 const struct prefix
*p
,
8652 json_object
*json_path
)
8654 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8658 /* Route status display. */
8659 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8660 json_object_boolean_true_add(json_path
, "removed");
8662 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8663 json_object_boolean_true_add(json_path
, "stale");
8665 if (path
->extra
&& bgp_path_suppressed(path
))
8666 json_object_boolean_true_add(json_path
, "suppressed");
8668 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8669 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8670 json_object_boolean_true_add(json_path
, "valid");
8673 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8674 json_object_boolean_true_add(json_path
, "history");
8676 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8677 json_object_boolean_true_add(json_path
, "damped");
8679 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8680 json_object_boolean_true_add(json_path
, "bestpath");
8681 json_object_string_add(json_path
, "selectionReason",
8682 bgp_path_selection_reason2str(
8683 path
->net
->reason
));
8686 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8687 json_object_boolean_true_add(json_path
, "multipath");
8689 /* Internal route. */
8690 if ((path
->peer
->as
)
8691 && (path
->peer
->as
== path
->peer
->local_as
))
8692 json_object_string_add(json_path
, "pathFrom",
8695 json_object_string_add(json_path
, "pathFrom",
8701 /* RPKI validation state */
8703 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
8705 if (rpki_state
== RPKI_VALID
)
8707 else if (rpki_state
== RPKI_INVALID
)
8709 else if (rpki_state
== RPKI_NOTFOUND
)
8712 /* Route status display. */
8713 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8715 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8717 else if (bgp_path_suppressed(path
))
8719 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8720 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8726 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8728 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8730 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8732 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8737 /* Internal route. */
8738 if (path
->peer
&& (path
->peer
->as
)
8739 && (path
->peer
->as
== path
->peer
->local_as
))
8745 static char *bgp_nexthop_hostname(struct peer
*peer
,
8746 struct bgp_nexthop_cache
*bnc
)
8749 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8750 return peer
->hostname
;
8754 /* called from terminal list command */
8755 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8756 struct bgp_path_info
*path
, int display
, safi_t safi
,
8757 json_object
*json_paths
, bool wide
)
8760 struct attr
*attr
= path
->attr
;
8761 json_object
*json_path
= NULL
;
8762 json_object
*json_nexthops
= NULL
;
8763 json_object
*json_nexthop_global
= NULL
;
8764 json_object
*json_nexthop_ll
= NULL
;
8765 json_object
*json_ext_community
= NULL
;
8766 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8768 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8769 bool nexthop_othervrf
= false;
8770 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8771 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8772 char *nexthop_hostname
=
8773 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8774 char esi_buf
[ESI_STR_LEN
];
8777 json_path
= json_object_new_object();
8779 /* short status lead text */
8780 route_vty_short_status_out(vty
, path
, p
, json_path
);
8783 /* print prefix and mask */
8785 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8787 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8789 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8793 * If vrf id of nexthop is different from that of prefix,
8794 * set up printable string to append
8796 if (path
->extra
&& path
->extra
->bgp_orig
) {
8797 const char *self
= "";
8802 nexthop_othervrf
= true;
8803 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8805 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8806 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8807 "@%s%s", VRFID_NONE_STR
, self
);
8809 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8810 path
->extra
->bgp_orig
->vrf_id
, self
);
8812 if (path
->extra
->bgp_orig
->inst_type
8813 != BGP_INSTANCE_TYPE_DEFAULT
)
8815 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8817 const char *self
= "";
8822 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8826 * For ENCAP and EVPN routes, nexthop address family is not
8827 * neccessarily the same as the prefix address family.
8828 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8829 * EVPN routes are also exchanged with a MP nexthop. Currently,
8831 * is only IPv4, the value will be present in either
8833 * attr->mp_nexthop_global_in
8835 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
8838 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8842 snprintf(nexthop
, sizeof(nexthop
), "%s",
8843 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
8847 snprintf(nexthop
, sizeof(nexthop
), "%s",
8848 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
8852 snprintf(nexthop
, sizeof(nexthop
), "?");
8857 json_nexthop_global
= json_object_new_object();
8859 json_object_string_add(json_nexthop_global
, "ip",
8862 if (path
->peer
->hostname
)
8863 json_object_string_add(json_nexthop_global
,
8865 path
->peer
->hostname
);
8867 json_object_string_add(json_nexthop_global
, "afi",
8868 (af
== AF_INET
) ? "ipv4"
8870 json_object_boolean_true_add(json_nexthop_global
,
8873 if (nexthop_hostname
)
8874 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
8875 nexthop_hostname
, vrf_id_str
);
8877 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
8879 len
= wide
? (41 - len
) : (16 - len
);
8881 vty_out(vty
, "\n%*s", 36, " ");
8883 vty_out(vty
, "%*s", len
, " ");
8885 } else if (safi
== SAFI_EVPN
) {
8887 json_nexthop_global
= json_object_new_object();
8889 json_object_string_addf(json_nexthop_global
, "ip",
8890 "%pI4", &attr
->nexthop
);
8892 if (path
->peer
->hostname
)
8893 json_object_string_add(json_nexthop_global
,
8895 path
->peer
->hostname
);
8897 json_object_string_add(json_nexthop_global
, "afi",
8899 json_object_boolean_true_add(json_nexthop_global
,
8902 if (nexthop_hostname
)
8903 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8904 nexthop_hostname
, vrf_id_str
);
8906 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8909 len
= wide
? (41 - len
) : (16 - len
);
8911 vty_out(vty
, "\n%*s", 36, " ");
8913 vty_out(vty
, "%*s", len
, " ");
8915 } else if (safi
== SAFI_FLOWSPEC
) {
8916 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
8918 json_nexthop_global
= json_object_new_object();
8920 json_object_string_add(json_nexthop_global
,
8922 json_object_string_addf(json_nexthop_global
,
8926 if (path
->peer
->hostname
)
8927 json_object_string_add(
8928 json_nexthop_global
, "hostname",
8929 path
->peer
->hostname
);
8931 json_object_boolean_true_add(
8932 json_nexthop_global
,
8935 if (nexthop_hostname
)
8936 len
= vty_out(vty
, "%pI4(%s)%s",
8941 len
= vty_out(vty
, "%pI4%s",
8945 len
= wide
? (41 - len
) : (16 - len
);
8947 vty_out(vty
, "\n%*s", 36, " ");
8949 vty_out(vty
, "%*s", len
, " ");
8952 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8954 json_nexthop_global
= json_object_new_object();
8956 json_object_string_addf(json_nexthop_global
, "ip",
8957 "%pI4", &attr
->nexthop
);
8959 if (path
->peer
->hostname
)
8960 json_object_string_add(json_nexthop_global
,
8962 path
->peer
->hostname
);
8964 json_object_string_add(json_nexthop_global
, "afi",
8966 json_object_boolean_true_add(json_nexthop_global
,
8969 if (nexthop_hostname
)
8970 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8971 nexthop_hostname
, vrf_id_str
);
8973 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8976 len
= wide
? (41 - len
) : (16 - len
);
8978 vty_out(vty
, "\n%*s", 36, " ");
8980 vty_out(vty
, "%*s", len
, " ");
8985 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8987 json_nexthop_global
= json_object_new_object();
8988 json_object_string_addf(json_nexthop_global
, "ip",
8990 &attr
->mp_nexthop_global
);
8992 if (path
->peer
->hostname
)
8993 json_object_string_add(json_nexthop_global
,
8995 path
->peer
->hostname
);
8997 json_object_string_add(json_nexthop_global
, "afi",
8999 json_object_string_add(json_nexthop_global
, "scope",
9002 /* We display both LL & GL if both have been
9004 if ((attr
->mp_nexthop_len
9005 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9006 || (path
->peer
->conf_if
)) {
9007 json_nexthop_ll
= json_object_new_object();
9008 json_object_string_addf(
9009 json_nexthop_ll
, "ip", "%pI6",
9010 &attr
->mp_nexthop_local
);
9012 if (path
->peer
->hostname
)
9013 json_object_string_add(
9014 json_nexthop_ll
, "hostname",
9015 path
->peer
->hostname
);
9017 json_object_string_add(json_nexthop_ll
, "afi",
9019 json_object_string_add(json_nexthop_ll
, "scope",
9022 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9023 &attr
->mp_nexthop_local
)
9025 && !attr
->mp_nexthop_prefer_global
)
9026 json_object_boolean_true_add(
9027 json_nexthop_ll
, "used");
9029 json_object_boolean_true_add(
9030 json_nexthop_global
, "used");
9032 json_object_boolean_true_add(
9033 json_nexthop_global
, "used");
9035 /* Display LL if LL/Global both in table unless
9036 * prefer-global is set */
9037 if (((attr
->mp_nexthop_len
9038 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9039 && !attr
->mp_nexthop_prefer_global
)
9040 || (path
->peer
->conf_if
)) {
9041 if (path
->peer
->conf_if
) {
9042 len
= vty_out(vty
, "%s",
9043 path
->peer
->conf_if
);
9044 /* len of IPv6 addr + max len of def
9046 len
= wide
? (41 - len
) : (16 - len
);
9049 vty_out(vty
, "\n%*s", 36, " ");
9051 vty_out(vty
, "%*s", len
, " ");
9053 if (nexthop_hostname
)
9056 &attr
->mp_nexthop_local
,
9062 &attr
->mp_nexthop_local
,
9065 len
= wide
? (41 - len
) : (16 - len
);
9068 vty_out(vty
, "\n%*s", 36, " ");
9070 vty_out(vty
, "%*s", len
, " ");
9073 if (nexthop_hostname
)
9074 len
= vty_out(vty
, "%pI6(%s)%s",
9075 &attr
->mp_nexthop_global
,
9079 len
= vty_out(vty
, "%pI6%s",
9080 &attr
->mp_nexthop_global
,
9083 len
= wide
? (41 - len
) : (16 - len
);
9086 vty_out(vty
, "\n%*s", 36, " ");
9088 vty_out(vty
, "%*s", len
, " ");
9094 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9096 json_object_int_add(json_path
, "metric", attr
->med
);
9098 vty_out(vty
, "%7u", attr
->med
);
9100 vty_out(vty
, "%10u", attr
->med
);
9101 else if (!json_paths
) {
9103 vty_out(vty
, "%*s", 7, " ");
9105 vty_out(vty
, "%*s", 10, " ");
9109 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9111 json_object_int_add(json_path
, "locPrf",
9114 vty_out(vty
, "%7u", attr
->local_pref
);
9115 else if (!json_paths
)
9119 json_object_int_add(json_path
, "weight", attr
->weight
);
9121 vty_out(vty
, "%7u ", attr
->weight
);
9125 json_object_string_add(
9126 json_path
, "peerId",
9127 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
9133 json_object_string_add(json_path
, "path",
9136 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9141 json_object_string_add(json_path
, "origin",
9142 bgp_origin_long_str
[attr
->origin
]);
9144 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9147 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9148 json_object_string_add(json_path
, "esi",
9149 esi_to_str(&attr
->esi
,
9150 esi_buf
, sizeof(esi_buf
)));
9152 if (safi
== SAFI_EVPN
&&
9153 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9154 json_ext_community
= json_object_new_object();
9155 json_object_string_add(
9156 json_ext_community
, "string",
9157 bgp_attr_get_ecommunity(attr
)->str
);
9158 json_object_object_add(json_path
,
9159 "extendedCommunity",
9160 json_ext_community
);
9164 json_object_boolean_true_add(json_path
,
9165 "announceNexthopSelf");
9166 if (nexthop_othervrf
) {
9167 json_object_string_add(json_path
, "nhVrfName",
9170 json_object_int_add(json_path
, "nhVrfId",
9171 ((nexthop_vrfid
== VRF_UNKNOWN
)
9173 : (int)nexthop_vrfid
));
9178 if (json_nexthop_global
|| json_nexthop_ll
) {
9179 json_nexthops
= json_object_new_array();
9181 if (json_nexthop_global
)
9182 json_object_array_add(json_nexthops
,
9183 json_nexthop_global
);
9185 if (json_nexthop_ll
)
9186 json_object_array_add(json_nexthops
,
9189 json_object_object_add(json_path
, "nexthops",
9193 json_object_array_add(json_paths
, json_path
);
9197 if (safi
== SAFI_EVPN
) {
9198 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9199 /* XXX - add these params to the json out */
9200 vty_out(vty
, "%*s", 20, " ");
9201 vty_out(vty
, "ESI:%s",
9202 esi_to_str(&attr
->esi
, esi_buf
,
9208 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9209 vty_out(vty
, "%*s", 20, " ");
9210 vty_out(vty
, "%s\n",
9211 bgp_attr_get_ecommunity(attr
)->str
);
9215 #ifdef ENABLE_BGP_VNC
9216 /* prints an additional line, indented, with VNC info, if
9218 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9219 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9224 /* called from terminal list command */
9225 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9226 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9227 bool use_json
, json_object
*json_ar
, bool wide
)
9229 json_object
*json_status
= NULL
;
9230 json_object
*json_net
= NULL
;
9234 /* Route status display. */
9236 json_status
= json_object_new_object();
9237 json_net
= json_object_new_object();
9244 /* print prefix and mask */
9246 if (safi
== SAFI_EVPN
)
9247 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9248 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9249 json_object_string_add(
9250 json_net
, "addrPrefix",
9251 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9253 json_object_int_add(json_net
, "prefixLen",
9255 json_object_string_addf(json_net
, "network", "%pFX", p
);
9258 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9260 /* Print attribute */
9263 if (p
->family
== AF_INET
9264 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9265 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9266 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9267 json_object_string_addf(
9268 json_net
, "nextHop", "%pI4",
9269 &attr
->mp_nexthop_global_in
);
9271 json_object_string_addf(
9272 json_net
, "nextHop", "%pI4",
9274 } else if (p
->family
== AF_INET6
9275 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9276 json_object_string_addf(
9277 json_net
, "nextHopGlobal", "%pI6",
9278 &attr
->mp_nexthop_global
);
9279 } else if (p
->family
== AF_EVPN
9280 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9281 json_object_string_addf(
9282 json_net
, "nextHop", "%pI4",
9283 &attr
->mp_nexthop_global_in
);
9287 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9288 json_object_int_add(json_net
, "metric",
9291 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9292 json_object_int_add(json_net
, "locPrf",
9295 json_object_int_add(json_net
, "weight", attr
->weight
);
9299 json_object_string_add(json_net
, "path",
9303 json_object_string_add(json_net
, "bgpOriginCode",
9304 bgp_origin_str
[attr
->origin
]);
9306 if (p
->family
== AF_INET
9307 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9308 || safi
== SAFI_EVPN
9309 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9310 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9311 || safi
== SAFI_EVPN
)
9312 vty_out(vty
, "%-16pI4",
9313 &attr
->mp_nexthop_global_in
);
9315 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9317 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9318 } else if (p
->family
== AF_INET6
9319 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9325 &attr
->mp_nexthop_global
, buf
,
9327 len
= wide
? (41 - len
) : (16 - len
);
9329 vty_out(vty
, "\n%*s", 36, " ");
9331 vty_out(vty
, "%*s", len
, " ");
9334 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9336 vty_out(vty
, "%7u", attr
->med
);
9338 vty_out(vty
, "%10u", attr
->med
);
9344 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9345 vty_out(vty
, "%7u", attr
->local_pref
);
9349 vty_out(vty
, "%7u ", attr
->weight
);
9353 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9356 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9360 json_object_boolean_true_add(json_status
, "*");
9361 json_object_boolean_true_add(json_status
, ">");
9362 json_object_object_add(json_net
, "appliedStatusSymbols",
9365 prefix2str(p
, buff
, PREFIX_STRLEN
);
9366 json_object_object_add(json_ar
, buff
, json_net
);
9371 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9372 struct bgp_path_info
*path
, int display
, safi_t safi
,
9375 json_object
*json_out
= NULL
;
9377 mpls_label_t label
= MPLS_INVALID_LABEL
;
9383 json_out
= json_object_new_object();
9385 /* short status lead text */
9386 route_vty_short_status_out(vty
, path
, p
, json_out
);
9388 /* print prefix and mask */
9391 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9393 vty_out(vty
, "%*s", 17, " ");
9396 /* Print attribute */
9398 if (((p
->family
== AF_INET
)
9399 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9400 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9401 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9402 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9403 || safi
== SAFI_EVPN
) {
9405 json_object_string_addf(
9406 json_out
, "mpNexthopGlobalIn", "%pI4",
9407 &attr
->mp_nexthop_global_in
);
9409 vty_out(vty
, "%-16pI4",
9410 &attr
->mp_nexthop_global_in
);
9413 json_object_string_addf(json_out
, "nexthop",
9414 "%pI4", &attr
->nexthop
);
9416 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9418 } else if (((p
->family
== AF_INET6
)
9419 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9420 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9421 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9424 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9426 json_object_string_addf(
9427 json_out
, "mpNexthopGlobalIn", "%pI6",
9428 &attr
->mp_nexthop_global
);
9432 &attr
->mp_nexthop_global
,
9433 buf_a
, sizeof(buf_a
)));
9434 } else if (attr
->mp_nexthop_len
9435 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9436 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9437 &attr
->mp_nexthop_global
,
9438 &attr
->mp_nexthop_local
);
9440 json_object_string_add(json_out
,
9441 "mpNexthopGlobalLocal",
9444 vty_out(vty
, "%s", buf_a
);
9448 label
= decode_label(&path
->extra
->label
[0]);
9450 if (bgp_is_valid_label(&label
)) {
9452 json_object_int_add(json_out
, "notag", label
);
9453 json_object_array_add(json
, json_out
);
9455 vty_out(vty
, "notag/%d", label
);
9462 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9463 struct bgp_path_info
*path
, int display
,
9464 json_object
*json_paths
)
9467 char buf
[BUFSIZ
] = {0};
9468 json_object
*json_path
= NULL
;
9469 json_object
*json_nexthop
= NULL
;
9470 json_object
*json_overlay
= NULL
;
9476 json_path
= json_object_new_object();
9477 json_overlay
= json_object_new_object();
9478 json_nexthop
= json_object_new_object();
9481 /* short status lead text */
9482 route_vty_short_status_out(vty
, path
, p
, json_path
);
9484 /* print prefix and mask */
9486 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9488 vty_out(vty
, "%*s", 17, " ");
9490 /* Print attribute */
9493 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9497 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
9499 vty_out(vty
, "%-16s", buf
);
9501 json_object_string_add(json_nexthop
, "ip", buf
);
9503 json_object_string_add(json_nexthop
, "afi", "ipv4");
9505 json_object_object_add(json_path
, "nexthop",
9510 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
9511 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
9513 vty_out(vty
, "%s(%s)", buf
, buf1
);
9515 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
9517 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
9520 json_object_string_add(json_nexthop
, "afi", "ipv6");
9522 json_object_object_add(json_path
, "nexthop",
9530 json_object_string_add(json_nexthop
, "Error",
9531 "Unsupported address-family");
9532 json_object_string_add(json_nexthop
, "error",
9533 "Unsupported address-family");
9537 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9539 ipaddr2str(&eo
->gw_ip
, buf
, BUFSIZ
);
9542 vty_out(vty
, "/%s", buf
);
9544 json_object_string_add(json_overlay
, "gw", buf
);
9546 if (bgp_attr_get_ecommunity(attr
)) {
9548 struct ecommunity_val
*routermac
= ecommunity_lookup(
9549 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9550 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9553 mac
= ecom_mac2str((char *)routermac
->val
);
9556 vty_out(vty
, "/%s", mac
);
9558 json_object_string_add(json_overlay
, "rmac",
9561 XFREE(MTYPE_TMP
, mac
);
9568 json_object_object_add(json_path
, "overlay", json_overlay
);
9570 json_object_array_add(json_paths
, json_path
);
9574 /* dampening route */
9575 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9576 struct bgp_path_info
*path
, int display
,
9577 afi_t afi
, safi_t safi
, bool use_json
,
9578 json_object
*json_paths
)
9580 struct attr
*attr
= path
->attr
;
9582 char timebuf
[BGP_UPTIME_LEN
];
9583 json_object
*json_path
= NULL
;
9586 json_path
= json_object_new_object();
9588 /* short status lead text */
9589 route_vty_short_status_out(vty
, path
, p
, json_path
);
9591 /* print prefix and mask */
9594 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9596 vty_out(vty
, "%*s", 17, " ");
9598 len
= vty_out(vty
, "%s", path
->peer
->host
);
9602 vty_out(vty
, "\n%*s", 34, " ");
9604 vty_out(vty
, "%*s", len
, " ");
9607 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9608 BGP_UPTIME_LEN
, afi
, safi
,
9612 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9614 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9618 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9619 safi
, use_json
, json_path
);
9622 json_object_string_add(json_path
, "asPath",
9625 json_object_string_add(json_path
, "origin",
9626 bgp_origin_str
[attr
->origin
]);
9627 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9629 json_object_array_add(json_paths
, json_path
);
9634 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9635 struct bgp_path_info
*path
, int display
,
9636 afi_t afi
, safi_t safi
, bool use_json
,
9637 json_object
*json_paths
)
9639 struct attr
*attr
= path
->attr
;
9640 struct bgp_damp_info
*bdi
;
9641 char timebuf
[BGP_UPTIME_LEN
];
9643 json_object
*json_path
= NULL
;
9649 json_path
= json_object_new_object();
9651 bdi
= path
->extra
->damp_info
;
9653 /* short status lead text */
9654 route_vty_short_status_out(vty
, path
, p
, json_path
);
9658 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9660 vty_out(vty
, "%*s", 17, " ");
9662 len
= vty_out(vty
, "%s", path
->peer
->host
);
9665 vty_out(vty
, "\n%*s", 33, " ");
9667 vty_out(vty
, "%*s", len
, " ");
9669 len
= vty_out(vty
, "%d", bdi
->flap
);
9674 vty_out(vty
, "%*s", len
, " ");
9676 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9677 BGP_UPTIME_LEN
, 0, NULL
));
9679 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9680 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9682 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9683 BGP_UPTIME_LEN
, afi
,
9684 safi
, use_json
, NULL
));
9686 vty_out(vty
, "%*s ", 8, " ");
9689 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9691 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9695 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9696 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
9698 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9701 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9702 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9703 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9704 BGP_UPTIME_LEN
, afi
, safi
,
9705 use_json
, json_path
);
9708 json_object_string_add(json_path
, "asPath",
9711 json_object_string_add(json_path
, "origin",
9712 bgp_origin_str
[attr
->origin
]);
9714 json_object_array_add(json_paths
, json_path
);
9718 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9719 int *first
, const char *header
,
9720 json_object
*json_adv_to
)
9722 char buf1
[INET6_ADDRSTRLEN
];
9723 json_object
*json_peer
= NULL
;
9726 /* 'advertised-to' is a dictionary of peers we have advertised
9728 * prefix too. The key is the peer's IP or swpX, the value is
9730 * hostname if we know it and "" if not.
9732 json_peer
= json_object_new_object();
9735 json_object_string_add(json_peer
, "hostname",
9739 json_object_object_add(json_adv_to
, peer
->conf_if
,
9742 json_object_object_add(
9744 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
9748 vty_out(vty
, "%s", header
);
9753 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9755 vty_out(vty
, " %s(%s)", peer
->hostname
,
9758 vty_out(vty
, " %s(%s)", peer
->hostname
,
9759 sockunion2str(&peer
->su
, buf1
,
9763 vty_out(vty
, " %s", peer
->conf_if
);
9766 sockunion2str(&peer
->su
, buf1
,
9772 static void route_vty_out_tx_ids(struct vty
*vty
,
9773 struct bgp_addpath_info_data
*d
)
9777 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9778 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9779 d
->addpath_tx_id
[i
],
9780 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9784 static void route_vty_out_detail_es_info(struct vty
*vty
,
9785 struct bgp_path_info
*pi
,
9787 json_object
*json_path
)
9789 char esi_buf
[ESI_STR_LEN
];
9790 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9791 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9792 ATTR_ES_PEER_ROUTER
);
9793 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9794 ATTR_ES_PEER_ACTIVE
);
9795 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9796 ATTR_ES_PEER_PROXY
);
9797 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9799 json_object
*json_es_info
= NULL
;
9801 json_object_string_add(
9804 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9805 json_es_info
= json_object_new_object();
9807 json_object_boolean_true_add(
9808 json_es_info
, "localEs");
9810 json_object_boolean_true_add(
9811 json_es_info
, "peerActive");
9813 json_object_boolean_true_add(
9814 json_es_info
, "peerProxy");
9816 json_object_boolean_true_add(
9817 json_es_info
, "peerRouter");
9818 if (attr
->mm_sync_seqnum
)
9819 json_object_int_add(
9820 json_es_info
, "peerSeq",
9821 attr
->mm_sync_seqnum
);
9822 json_object_object_add(
9823 json_path
, "es_info",
9827 if (bgp_evpn_attr_is_sync(attr
))
9829 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9831 es_local
? "local-es":"",
9832 peer_proxy
? "proxy " : "",
9833 peer_active
? "active ":"",
9834 peer_router
? "router ":"",
9835 attr
->mm_sync_seqnum
);
9837 vty_out(vty
, " ESI %s %s\n",
9839 es_local
? "local-es":"");
9843 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
9844 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
9845 enum rpki_states rpki_curr_state
,
9846 json_object
*json_paths
)
9848 char buf
[INET6_ADDRSTRLEN
];
9850 struct attr
*attr
= path
->attr
;
9851 int sockunion_vty_out(struct vty
*, union sockunion
*);
9853 json_object
*json_bestpath
= NULL
;
9854 json_object
*json_cluster_list
= NULL
;
9855 json_object
*json_cluster_list_list
= NULL
;
9856 json_object
*json_ext_community
= NULL
;
9857 json_object
*json_last_update
= NULL
;
9858 json_object
*json_pmsi
= NULL
;
9859 json_object
*json_nexthop_global
= NULL
;
9860 json_object
*json_nexthop_ll
= NULL
;
9861 json_object
*json_nexthops
= NULL
;
9862 json_object
*json_path
= NULL
;
9863 json_object
*json_peer
= NULL
;
9864 json_object
*json_string
= NULL
;
9865 json_object
*json_adv_to
= NULL
;
9867 struct listnode
*node
, *nnode
;
9869 bool addpath_capable
;
9871 unsigned int first_as
;
9873 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9875 char *nexthop_hostname
=
9876 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9879 json_path
= json_object_new_object();
9880 json_peer
= json_object_new_object();
9881 json_nexthop_global
= json_object_new_object();
9884 if (safi
== SAFI_EVPN
) {
9886 vty_out(vty
, " Route %pRN", bn
);
9893 if (path
->extra
&& path
->extra
->num_labels
) {
9894 bgp_evpn_label2str(path
->extra
->label
,
9895 path
->extra
->num_labels
, tag_buf
,
9898 if (safi
== SAFI_EVPN
) {
9900 if (tag_buf
[0] != '\0')
9901 vty_out(vty
, " VNI %s", tag_buf
);
9904 json_object_string_add(json_path
, "VNI",
9906 json_object_string_add(json_path
, "vni",
9912 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9913 struct bgp_path_info
*parent_ri
;
9914 struct bgp_dest
*dest
, *pdest
;
9916 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9917 dest
= parent_ri
->net
;
9918 if (dest
&& dest
->pdest
) {
9919 pdest
= dest
->pdest
;
9921 (struct prefix_rd
*)bgp_dest_get_prefix(
9923 buf1
, sizeof(buf1
));
9924 if (is_pi_family_evpn(parent_ri
)) {
9926 " Imported from %s:%pFX, VNI %s",
9928 (struct prefix_evpn
*)
9929 bgp_dest_get_prefix(
9932 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
9933 vty_out(vty
, ", L3NHG %s",
9935 & ATTR_ES_L3_NHG_ACTIVE
)
9942 " Imported from %s:%pFX\n",
9944 (struct prefix_evpn
*)
9945 bgp_dest_get_prefix(
9951 if (safi
== SAFI_EVPN
9952 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
9953 char gwip_buf
[INET6_ADDRSTRLEN
];
9955 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
9959 json_object_string_add(json_path
, "gatewayIP",
9962 vty_out(vty
, " Gateway IP %s", gwip_buf
);
9965 if (safi
== SAFI_EVPN
)
9968 /* Line1 display AS-path, Aggregator */
9971 if (!attr
->aspath
->json
)
9972 aspath_str_update(attr
->aspath
, true);
9973 json_object_lock(attr
->aspath
->json
);
9974 json_object_object_add(json_path
, "aspath",
9975 attr
->aspath
->json
);
9977 if (attr
->aspath
->segments
)
9978 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9980 vty_out(vty
, " Local");
9984 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9986 json_object_boolean_true_add(json_path
, "removed");
9988 vty_out(vty
, ", (removed)");
9991 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9993 json_object_boolean_true_add(json_path
, "stale");
9995 vty_out(vty
, ", (stale)");
9998 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10000 json_object_int_add(json_path
, "aggregatorAs",
10001 attr
->aggregator_as
);
10002 json_object_string_addf(json_path
, "aggregatorId",
10003 "%pI4", &attr
->aggregator_addr
);
10005 vty_out(vty
, ", (aggregated by %u %pI4)",
10006 attr
->aggregator_as
, &attr
->aggregator_addr
);
10010 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10011 PEER_FLAG_REFLECTOR_CLIENT
)) {
10013 json_object_boolean_true_add(json_path
,
10014 "rxedFromRrClient");
10016 vty_out(vty
, ", (Received from a RR-client)");
10019 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10020 PEER_FLAG_RSERVER_CLIENT
)) {
10022 json_object_boolean_true_add(json_path
,
10023 "rxedFromRsClient");
10025 vty_out(vty
, ", (Received from a RS-client)");
10028 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10030 json_object_boolean_true_add(json_path
,
10031 "dampeningHistoryEntry");
10033 vty_out(vty
, ", (history entry)");
10034 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10036 json_object_boolean_true_add(json_path
,
10037 "dampeningSuppressed");
10039 vty_out(vty
, ", (suppressed due to dampening)");
10043 vty_out(vty
, "\n");
10045 /* Line2 display Next-hop, Neighbor, Router-id */
10046 /* Display the nexthop */
10047 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
10049 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
10050 || bn_p
->family
== AF_EVPN
)
10051 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
10052 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
10053 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10054 || safi
== SAFI_EVPN
) {
10056 json_object_string_addf(
10057 json_nexthop_global
, "ip", "%pI4",
10058 &attr
->mp_nexthop_global_in
);
10060 if (path
->peer
->hostname
)
10061 json_object_string_add(
10062 json_nexthop_global
, "hostname",
10063 path
->peer
->hostname
);
10065 if (nexthop_hostname
)
10066 vty_out(vty
, " %pI4(%s)",
10067 &attr
->mp_nexthop_global_in
,
10070 vty_out(vty
, " %pI4",
10071 &attr
->mp_nexthop_global_in
);
10075 json_object_string_addf(json_nexthop_global
,
10079 if (path
->peer
->hostname
)
10080 json_object_string_add(
10081 json_nexthop_global
, "hostname",
10082 path
->peer
->hostname
);
10084 if (nexthop_hostname
)
10085 vty_out(vty
, " %pI4(%s)",
10089 vty_out(vty
, " %pI4",
10095 json_object_string_add(json_nexthop_global
, "afi",
10099 json_object_string_addf(json_nexthop_global
, "ip",
10101 &attr
->mp_nexthop_global
);
10103 if (path
->peer
->hostname
)
10104 json_object_string_add(json_nexthop_global
,
10106 path
->peer
->hostname
);
10108 json_object_string_add(json_nexthop_global
, "afi",
10110 json_object_string_add(json_nexthop_global
, "scope",
10113 if (nexthop_hostname
)
10114 vty_out(vty
, " %pI6(%s)",
10115 &attr
->mp_nexthop_global
,
10118 vty_out(vty
, " %pI6",
10119 &attr
->mp_nexthop_global
);
10123 /* Display the IGP cost or 'inaccessible' */
10124 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10126 json_object_boolean_false_add(json_nexthop_global
,
10129 vty_out(vty
, " (inaccessible)");
10131 if (path
->extra
&& path
->extra
->igpmetric
) {
10133 json_object_int_add(json_nexthop_global
,
10135 path
->extra
->igpmetric
);
10137 vty_out(vty
, " (metric %u)",
10138 path
->extra
->igpmetric
);
10141 /* IGP cost is 0, display this only for json */
10144 json_object_int_add(json_nexthop_global
,
10149 json_object_boolean_true_add(json_nexthop_global
,
10153 /* Display peer "from" output */
10154 /* This path was originated locally */
10155 if (path
->peer
== bgp
->peer_self
) {
10157 if (safi
== SAFI_EVPN
10158 || (bn_p
->family
== AF_INET
10159 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
10161 json_object_string_add(json_peer
, "peerId",
10164 vty_out(vty
, " from 0.0.0.0 ");
10167 json_object_string_add(json_peer
, "peerId",
10170 vty_out(vty
, " from :: ");
10174 json_object_string_addf(json_peer
, "routerId", "%pI4",
10177 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10180 /* We RXed this path from one of our peers */
10184 json_object_string_add(json_peer
, "peerId",
10185 sockunion2str(&path
->peer
->su
,
10188 json_object_string_addf(json_peer
, "routerId", "%pI4",
10189 &path
->peer
->remote_id
);
10191 if (path
->peer
->hostname
)
10192 json_object_string_add(json_peer
, "hostname",
10193 path
->peer
->hostname
);
10195 if (path
->peer
->domainname
)
10196 json_object_string_add(json_peer
, "domainname",
10197 path
->peer
->domainname
);
10199 if (path
->peer
->conf_if
)
10200 json_object_string_add(json_peer
, "interface",
10201 path
->peer
->conf_if
);
10203 if (path
->peer
->conf_if
) {
10204 if (path
->peer
->hostname
10205 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10206 BGP_FLAG_SHOW_HOSTNAME
))
10207 vty_out(vty
, " from %s(%s)",
10208 path
->peer
->hostname
,
10209 path
->peer
->conf_if
);
10211 vty_out(vty
, " from %s",
10212 path
->peer
->conf_if
);
10214 if (path
->peer
->hostname
10215 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10216 BGP_FLAG_SHOW_HOSTNAME
))
10217 vty_out(vty
, " from %s(%s)",
10218 path
->peer
->hostname
,
10221 vty_out(vty
, " from %s",
10222 sockunion2str(&path
->peer
->su
,
10227 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10228 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10230 vty_out(vty
, " (%s)",
10232 &path
->peer
->remote_id
, buf1
,
10238 * Note when vrfid of nexthop is different from that of prefix
10240 if (path
->extra
&& path
->extra
->bgp_orig
) {
10241 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10246 if (path
->extra
->bgp_orig
->inst_type
10247 == BGP_INSTANCE_TYPE_DEFAULT
)
10248 vn
= VRF_DEFAULT_NAME
;
10250 vn
= path
->extra
->bgp_orig
->name
;
10252 json_object_string_add(json_path
, "nhVrfName", vn
);
10254 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10255 json_object_int_add(json_path
, "nhVrfId", -1);
10257 json_object_int_add(json_path
, "nhVrfId",
10258 (int)nexthop_vrfid
);
10261 if (nexthop_vrfid
== VRF_UNKNOWN
)
10262 vty_out(vty
, " vrf ?");
10266 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10267 vty_out(vty
, " vrf %s(%u)",
10268 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10273 if (nexthop_self
) {
10275 json_object_boolean_true_add(json_path
,
10276 "announceNexthopSelf");
10278 vty_out(vty
, " announce-nh-self");
10283 vty_out(vty
, "\n");
10285 /* display the link-local nexthop */
10286 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10288 json_nexthop_ll
= json_object_new_object();
10289 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10290 &attr
->mp_nexthop_local
);
10292 if (path
->peer
->hostname
)
10293 json_object_string_add(json_nexthop_ll
,
10295 path
->peer
->hostname
);
10297 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10298 json_object_string_add(json_nexthop_ll
, "scope",
10301 json_object_boolean_true_add(json_nexthop_ll
,
10304 if (!attr
->mp_nexthop_prefer_global
)
10305 json_object_boolean_true_add(json_nexthop_ll
,
10308 json_object_boolean_true_add(
10309 json_nexthop_global
, "used");
10311 vty_out(vty
, " (%s) %s\n",
10312 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10313 buf
, INET6_ADDRSTRLEN
),
10314 attr
->mp_nexthop_prefer_global
10315 ? "(prefer-global)"
10319 /* If we do not have a link-local nexthop then we must flag the
10320 global as "used" */
10323 json_object_boolean_true_add(json_nexthop_global
,
10327 if (safi
== SAFI_EVPN
&&
10328 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10329 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10332 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10333 * Int/Ext/Local, Atomic, best */
10335 json_object_string_add(json_path
, "origin",
10336 bgp_origin_long_str
[attr
->origin
]);
10338 vty_out(vty
, " Origin %s",
10339 bgp_origin_long_str
[attr
->origin
]);
10341 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10343 json_object_int_add(json_path
, "metric", attr
->med
);
10345 vty_out(vty
, ", metric %u", attr
->med
);
10348 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10350 json_object_int_add(json_path
, "locPrf",
10353 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10356 if (attr
->weight
!= 0) {
10358 json_object_int_add(json_path
, "weight", attr
->weight
);
10360 vty_out(vty
, ", weight %u", attr
->weight
);
10363 if (attr
->tag
!= 0) {
10365 json_object_int_add(json_path
, "tag", attr
->tag
);
10367 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10370 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10372 json_object_boolean_false_add(json_path
, "valid");
10374 vty_out(vty
, ", invalid");
10375 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10377 json_object_boolean_true_add(json_path
, "valid");
10379 vty_out(vty
, ", valid");
10383 json_object_int_add(json_path
, "version", bn
->version
);
10385 if (path
->peer
!= bgp
->peer_self
) {
10386 if (path
->peer
->as
== path
->peer
->local_as
) {
10387 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10389 json_object_string_add(
10391 "confed-internal");
10393 vty_out(vty
, ", confed-internal");
10396 json_object_string_add(
10397 json_peer
, "type", "internal");
10399 vty_out(vty
, ", internal");
10402 if (bgp_confederation_peers_check(bgp
,
10405 json_object_string_add(
10407 "confed-external");
10409 vty_out(vty
, ", confed-external");
10412 json_object_string_add(
10413 json_peer
, "type", "external");
10415 vty_out(vty
, ", external");
10418 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10420 json_object_boolean_true_add(json_path
, "aggregated");
10421 json_object_boolean_true_add(json_path
, "local");
10423 vty_out(vty
, ", aggregated, local");
10425 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10427 json_object_boolean_true_add(json_path
, "sourced");
10429 vty_out(vty
, ", sourced");
10432 json_object_boolean_true_add(json_path
, "sourced");
10433 json_object_boolean_true_add(json_path
, "local");
10435 vty_out(vty
, ", sourced, local");
10439 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10441 json_object_boolean_true_add(json_path
,
10442 "atomicAggregate");
10444 vty_out(vty
, ", atomic-aggregate");
10447 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10448 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10449 && bgp_path_info_mpath_count(path
))) {
10451 json_object_boolean_true_add(json_path
, "multipath");
10453 vty_out(vty
, ", multipath");
10456 // Mark the bestpath(s)
10457 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10458 first_as
= aspath_get_first_as(attr
->aspath
);
10461 if (!json_bestpath
)
10462 json_bestpath
= json_object_new_object();
10463 json_object_int_add(json_bestpath
, "bestpathFromAs",
10467 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10469 vty_out(vty
, ", bestpath-from-AS Local");
10473 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10475 if (!json_bestpath
)
10476 json_bestpath
= json_object_new_object();
10477 json_object_boolean_true_add(json_bestpath
, "overall");
10478 json_object_string_add(
10479 json_bestpath
, "selectionReason",
10480 bgp_path_selection_reason2str(bn
->reason
));
10482 vty_out(vty
, ", best");
10483 vty_out(vty
, " (%s)",
10484 bgp_path_selection_reason2str(bn
->reason
));
10488 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10490 json_object_string_add(
10491 json_path
, "rpkiValidationState",
10492 bgp_rpki_validation2str(rpki_curr_state
));
10494 vty_out(vty
, ", rpki validation-state: %s",
10495 bgp_rpki_validation2str(rpki_curr_state
));
10499 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10502 vty_out(vty
, "\n");
10504 /* Line 4 display Community */
10505 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10507 if (!bgp_attr_get_community(attr
)->json
)
10508 community_str(bgp_attr_get_community(attr
),
10510 json_object_lock(bgp_attr_get_community(attr
)->json
);
10511 json_object_object_add(
10512 json_path
, "community",
10513 bgp_attr_get_community(attr
)->json
);
10515 vty_out(vty
, " Community: %s\n",
10516 bgp_attr_get_community(attr
)->str
);
10520 /* Line 5 display Extended-community */
10521 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10523 json_ext_community
= json_object_new_object();
10524 json_object_string_add(
10525 json_ext_community
, "string",
10526 bgp_attr_get_ecommunity(attr
)->str
);
10527 json_object_object_add(json_path
, "extendedCommunity",
10528 json_ext_community
);
10530 vty_out(vty
, " Extended Community: %s\n",
10531 bgp_attr_get_ecommunity(attr
)->str
);
10535 /* Line 6 display Large community */
10536 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10538 if (!bgp_attr_get_lcommunity(attr
)->json
)
10539 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10541 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10542 json_object_object_add(
10543 json_path
, "largeCommunity",
10544 bgp_attr_get_lcommunity(attr
)->json
);
10546 vty_out(vty
, " Large Community: %s\n",
10547 bgp_attr_get_lcommunity(attr
)->str
);
10551 /* Line 7 display Originator, Cluster-id */
10552 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10553 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10554 char buf
[BUFSIZ
] = {0};
10556 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10558 json_object_string_addf(json_path
,
10559 "originatorId", "%pI4",
10560 &attr
->originator_id
);
10562 vty_out(vty
, " Originator: %pI4",
10563 &attr
->originator_id
);
10566 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10567 struct cluster_list
*cluster
=
10568 bgp_attr_get_cluster(attr
);
10572 json_cluster_list
= json_object_new_object();
10573 json_cluster_list_list
=
10574 json_object_new_array();
10576 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10577 json_string
= json_object_new_string(
10580 buf
, sizeof(buf
)));
10581 json_object_array_add(
10582 json_cluster_list_list
,
10587 * struct cluster_list does not have
10588 * "str" variable like aspath and community
10589 * do. Add this someday if someone asks
10591 * json_object_string_add(json_cluster_list,
10592 * "string", cluster->str);
10594 json_object_object_add(json_cluster_list
,
10596 json_cluster_list_list
);
10597 json_object_object_add(json_path
, "clusterList",
10598 json_cluster_list
);
10600 vty_out(vty
, ", Cluster list: ");
10602 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10603 vty_out(vty
, "%pI4 ",
10604 &cluster
->list
[i
]);
10610 vty_out(vty
, "\n");
10613 if (path
->extra
&& path
->extra
->damp_info
)
10614 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10617 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10618 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10619 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
10622 json_object_int_add(json_path
, "remoteLabel", label
);
10624 vty_out(vty
, " Remote label: %d\n", label
);
10628 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10629 inet_ntop(AF_INET6
, &path
->extra
->sid
[0].sid
, buf
, sizeof(buf
));
10631 json_object_string_add(json_path
, "remoteSid", buf
);
10633 vty_out(vty
, " Remote SID: %s\n", buf
);
10637 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10639 json_object_int_add(json_path
, "labelIndex",
10640 attr
->label_index
);
10642 vty_out(vty
, " Label Index: %d\n",
10643 attr
->label_index
);
10646 /* Line 8 display Addpath IDs */
10647 if (path
->addpath_rx_id
10648 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10650 json_object_int_add(json_path
, "addpathRxId",
10651 path
->addpath_rx_id
);
10653 /* Keep backwards compatibility with the old API
10654 * by putting TX All's ID in the old field
10656 json_object_int_add(
10657 json_path
, "addpathTxId",
10659 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10661 /* ... but create a specific field for each
10664 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10665 json_object_int_add(
10667 bgp_addpath_names(i
)->id_json_name
,
10668 path
->tx_addpath
.addpath_tx_id
[i
]);
10671 vty_out(vty
, " AddPath ID: RX %u, ",
10672 path
->addpath_rx_id
);
10674 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10678 /* If we used addpath to TX a non-bestpath we need to display
10679 * "Advertised to" on a path-by-path basis
10681 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10684 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10686 bgp_addpath_encode_tx(peer
, afi
, safi
);
10687 has_adj
= bgp_adj_out_lookup(
10689 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10690 &path
->tx_addpath
));
10692 if ((addpath_capable
&& has_adj
)
10693 || (!addpath_capable
&& has_adj
10694 && CHECK_FLAG(path
->flags
,
10695 BGP_PATH_SELECTED
))) {
10696 if (json_path
&& !json_adv_to
)
10697 json_adv_to
= json_object_new_object();
10699 route_vty_out_advertised_to(
10701 " Advertised to:", json_adv_to
);
10707 json_object_object_add(
10708 json_path
, "advertisedTo", json_adv_to
);
10712 vty_out(vty
, "\n");
10717 /* Line 9 display Uptime */
10718 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
10720 json_last_update
= json_object_new_object();
10721 json_object_int_add(json_last_update
, "epoch", tbuf
);
10722 json_object_string_add(json_last_update
, "string",
10724 json_object_object_add(json_path
, "lastUpdate",
10727 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10729 /* Line 10 display PMSI tunnel attribute, if present */
10730 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10731 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10732 bgp_attr_get_pmsi_tnl_type(attr
),
10733 PMSI_TNLTYPE_STR_DEFAULT
);
10736 json_pmsi
= json_object_new_object();
10737 json_object_string_add(json_pmsi
, "tunnelType", str
);
10738 json_object_int_add(json_pmsi
, "label",
10739 label2vni(&attr
->label
));
10740 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10742 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10743 str
, label2vni(&attr
->label
));
10746 if (path
->peer
->t_gr_restart
&&
10747 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10748 unsigned long gr_remaining
=
10749 thread_timer_remain_second(path
->peer
->t_gr_restart
);
10752 json_object_int_add(json_path
,
10753 "gracefulRestartSecondsRemaining",
10757 " Time until Graceful Restart stale route deleted: %lu\n",
10761 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
10762 bgp_attr_get_community(attr
) &&
10763 community_include(bgp_attr_get_community(attr
),
10764 COMMUNITY_LLGR_STALE
)) {
10765 unsigned long llgr_remaining
= thread_timer_remain_second(
10766 path
->peer
->t_llgr_stale
[afi
][safi
]);
10769 json_object_int_add(json_path
, "llgrSecondsRemaining",
10773 " Time until Long-lived stale route deleted: %lu\n",
10777 /* Output some debug about internal state of the dest flags */
10779 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10780 json_object_boolean_true_add(json_path
, "processScheduled");
10781 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10782 json_object_boolean_true_add(json_path
, "userCleared");
10783 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10784 json_object_boolean_true_add(json_path
, "labelChanged");
10785 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10786 json_object_boolean_true_add(json_path
, "registeredForLabel");
10787 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10788 json_object_boolean_true_add(json_path
, "selectDefered");
10789 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10790 json_object_boolean_true_add(json_path
, "fibInstalled");
10791 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10792 json_object_boolean_true_add(json_path
, "fibPending");
10794 if (json_nexthop_global
|| json_nexthop_ll
) {
10795 json_nexthops
= json_object_new_array();
10797 if (json_nexthop_global
)
10798 json_object_array_add(json_nexthops
,
10799 json_nexthop_global
);
10801 if (json_nexthop_ll
)
10802 json_object_array_add(json_nexthops
,
10805 json_object_object_add(json_path
, "nexthops",
10809 json_object_object_add(json_path
, "peer", json_peer
);
10810 json_object_array_add(json_paths
, json_path
);
10814 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10815 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10816 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10818 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10819 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10821 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10822 const char *comstr
, int exact
, afi_t afi
,
10823 safi_t safi
, uint16_t show_flags
);
10825 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10826 struct bgp_table
*table
, enum bgp_show_type type
,
10827 void *output_arg
, const char *rd
, int is_last
,
10828 unsigned long *output_cum
, unsigned long *total_cum
,
10829 unsigned long *json_header_depth
, uint16_t show_flags
,
10830 enum rpki_states rpki_target_state
)
10832 struct bgp_path_info
*pi
;
10833 struct bgp_dest
*dest
;
10834 bool header
= true;
10835 bool json_detail_header
= false;
10837 unsigned long output_count
= 0;
10838 unsigned long total_count
= 0;
10840 json_object
*json_paths
= NULL
;
10842 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10843 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
10844 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10846 if (output_cum
&& *output_cum
!= 0)
10849 if (use_json
&& !*json_header_depth
) {
10851 *json_header_depth
= 1;
10853 vty_out(vty
, "{\n");
10854 *json_header_depth
= 2;
10858 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10859 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10860 " \"localAS\": %u,\n \"routes\": { ",
10861 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
10862 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
10865 table
->version
, &bgp
->router_id
,
10866 bgp
->default_local_pref
, bgp
->as
);
10868 vty_out(vty
, " \"routeDistinguishers\" : {");
10869 ++*json_header_depth
;
10873 if (use_json
&& rd
) {
10874 vty_out(vty
, " \"%s\" : { ", rd
);
10877 /* Check for 'json detail', where we need header output once per dest */
10878 if (use_json
&& CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
) &&
10879 type
!= bgp_show_type_dampend_paths
&&
10880 type
!= bgp_show_type_damp_neighbor
&&
10881 type
!= bgp_show_type_flap_statistics
&&
10882 type
!= bgp_show_type_flap_neighbor
)
10883 json_detail_header
= true;
10885 /* Start processing of routes. */
10886 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
10887 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10888 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
10889 bool json_detail
= json_detail_header
;
10891 pi
= bgp_dest_get_bgp_path_info(dest
);
10897 json_paths
= json_object_new_array();
10901 for (; pi
; pi
= pi
->next
) {
10902 struct community
*picomm
= NULL
;
10904 picomm
= bgp_attr_get_community(pi
->attr
);
10908 if (type
== bgp_show_type_prefix_version
) {
10910 strtoul(output_arg
, NULL
, 10);
10911 if (dest
->version
< version
)
10915 if (type
== bgp_show_type_community_alias
) {
10916 char *alias
= output_arg
;
10917 char **communities
;
10919 bool found
= false;
10922 frrstr_split(picomm
->str
, " ",
10923 &communities
, &num
);
10924 for (int i
= 0; i
< num
; i
++) {
10925 const char *com2alias
=
10926 bgp_community2alias(
10929 && strcmp(alias
, com2alias
)
10935 XFREE(MTYPE_TMP
, communities
);
10939 bgp_attr_get_lcommunity(pi
->attr
)) {
10940 frrstr_split(bgp_attr_get_lcommunity(
10943 " ", &communities
, &num
);
10944 for (int i
= 0; i
< num
; i
++) {
10945 const char *com2alias
=
10946 bgp_community2alias(
10949 && strcmp(alias
, com2alias
)
10955 XFREE(MTYPE_TMP
, communities
);
10962 if (type
== bgp_show_type_rpki
) {
10963 if (dest_p
->family
== AF_INET
10964 || dest_p
->family
== AF_INET6
)
10965 rpki_curr_state
= hook_call(
10966 bgp_rpki_prefix_status
,
10967 pi
->peer
, pi
->attr
, dest_p
);
10968 if (rpki_target_state
!= RPKI_NOT_BEING_USED
10969 && rpki_curr_state
!= rpki_target_state
)
10973 if (type
== bgp_show_type_flap_statistics
10974 || type
== bgp_show_type_flap_neighbor
10975 || type
== bgp_show_type_dampend_paths
10976 || type
== bgp_show_type_damp_neighbor
) {
10977 if (!(pi
->extra
&& pi
->extra
->damp_info
))
10980 if (type
== bgp_show_type_regexp
) {
10981 regex_t
*regex
= output_arg
;
10983 if (bgp_regexec(regex
, pi
->attr
->aspath
)
10987 if (type
== bgp_show_type_prefix_list
) {
10988 struct prefix_list
*plist
= output_arg
;
10990 if (prefix_list_apply(plist
, dest_p
)
10994 if (type
== bgp_show_type_filter_list
) {
10995 struct as_list
*as_list
= output_arg
;
10997 if (as_list_apply(as_list
, pi
->attr
->aspath
)
10998 != AS_FILTER_PERMIT
)
11001 if (type
== bgp_show_type_route_map
) {
11002 struct route_map
*rmap
= output_arg
;
11003 struct bgp_path_info path
;
11004 struct attr dummy_attr
;
11005 route_map_result_t ret
;
11007 dummy_attr
= *pi
->attr
;
11009 path
.peer
= pi
->peer
;
11010 path
.attr
= &dummy_attr
;
11012 ret
= route_map_apply(rmap
, dest_p
, &path
);
11013 bgp_attr_flush(&dummy_attr
);
11014 if (ret
== RMAP_DENYMATCH
)
11017 if (type
== bgp_show_type_neighbor
11018 || type
== bgp_show_type_flap_neighbor
11019 || type
== bgp_show_type_damp_neighbor
) {
11020 union sockunion
*su
= output_arg
;
11022 if (pi
->peer
== NULL
11023 || pi
->peer
->su_remote
== NULL
11024 || !sockunion_same(pi
->peer
->su_remote
, su
))
11027 if (type
== bgp_show_type_cidr_only
) {
11028 uint32_t destination
;
11030 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11031 if (IN_CLASSC(destination
)
11032 && dest_p
->prefixlen
== 24)
11034 if (IN_CLASSB(destination
)
11035 && dest_p
->prefixlen
== 16)
11037 if (IN_CLASSA(destination
)
11038 && dest_p
->prefixlen
== 8)
11041 if (type
== bgp_show_type_prefix_longer
) {
11043 if (!prefix_match(p
, dest_p
))
11046 if (type
== bgp_show_type_community_all
) {
11050 if (type
== bgp_show_type_community
) {
11051 struct community
*com
= output_arg
;
11053 if (!picomm
|| !community_match(picomm
, com
))
11056 if (type
== bgp_show_type_community_exact
) {
11057 struct community
*com
= output_arg
;
11059 if (!picomm
|| !community_cmp(picomm
, com
))
11062 if (type
== bgp_show_type_community_list
) {
11063 struct community_list
*list
= output_arg
;
11065 if (!community_list_match(picomm
, list
))
11068 if (type
== bgp_show_type_community_list_exact
) {
11069 struct community_list
*list
= output_arg
;
11071 if (!community_list_exact_match(picomm
, list
))
11074 if (type
== bgp_show_type_lcommunity
) {
11075 struct lcommunity
*lcom
= output_arg
;
11077 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11079 bgp_attr_get_lcommunity(pi
->attr
),
11084 if (type
== bgp_show_type_lcommunity_exact
) {
11085 struct lcommunity
*lcom
= output_arg
;
11087 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11089 bgp_attr_get_lcommunity(pi
->attr
),
11093 if (type
== bgp_show_type_lcommunity_list
) {
11094 struct community_list
*list
= output_arg
;
11096 if (!lcommunity_list_match(
11097 bgp_attr_get_lcommunity(pi
->attr
),
11102 == bgp_show_type_lcommunity_list_exact
) {
11103 struct community_list
*list
= output_arg
;
11105 if (!lcommunity_list_exact_match(
11106 bgp_attr_get_lcommunity(pi
->attr
),
11110 if (type
== bgp_show_type_lcommunity_all
) {
11111 if (!bgp_attr_get_lcommunity(pi
->attr
))
11114 if (type
== bgp_show_type_dampend_paths
11115 || type
== bgp_show_type_damp_neighbor
) {
11116 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11117 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11121 if (!use_json
&& header
) {
11123 "BGP table version is %" PRIu64
11124 ", local router ID is %pI4, vrf id ",
11125 table
->version
, &bgp
->router_id
);
11126 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11127 vty_out(vty
, "%s", VRFID_NONE_STR
);
11129 vty_out(vty
, "%u", bgp
->vrf_id
);
11130 vty_out(vty
, "\n");
11131 vty_out(vty
, "Default local pref %u, ",
11132 bgp
->default_local_pref
);
11133 vty_out(vty
, "local AS %u\n", bgp
->as
);
11134 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11135 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11136 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11137 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11138 if (type
== bgp_show_type_dampend_paths
11139 || type
== bgp_show_type_damp_neighbor
)
11140 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11141 else if (type
== bgp_show_type_flap_statistics
11142 || type
== bgp_show_type_flap_neighbor
)
11143 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11145 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11146 : BGP_SHOW_HEADER
));
11149 } else if (json_detail
&& json_paths
!= NULL
) {
11150 const struct prefix_rd
*prd
;
11151 json_object
*jtemp
;
11153 /* Use common detail header, for most types;
11154 * need a json 'object'.
11157 jtemp
= json_object_new_object();
11158 prd
= bgp_rd_from_dest(dest
, safi
);
11160 route_vty_out_detail_header(
11161 vty
, bgp
, dest
, prd
, table
->afi
,
11164 json_object_array_add(json_paths
, jtemp
);
11166 json_detail
= false;
11169 if (rd
!= NULL
&& !display
&& !output_count
) {
11172 "Route Distinguisher: %s\n",
11175 if (type
== bgp_show_type_dampend_paths
11176 || type
== bgp_show_type_damp_neighbor
)
11177 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11178 AFI_IP
, safi
, use_json
,
11180 else if (type
== bgp_show_type_flap_statistics
11181 || type
== bgp_show_type_flap_neighbor
)
11182 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11183 AFI_IP
, safi
, use_json
,
11186 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
11187 route_vty_out_detail(
11188 vty
, bgp
, dest
, pi
,
11189 family2afi(dest_p
->family
),
11190 safi
, RPKI_NOT_BEING_USED
,
11193 route_vty_out(vty
, dest_p
, pi
, display
,
11194 safi
, json_paths
, wide
);
11204 /* encode prefix */
11205 if (dest_p
->family
== AF_FLOWSPEC
) {
11206 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11209 bgp_fs_nlri_get_string(
11211 dest_p
->u
.prefix_flowspec
.ptr
,
11212 dest_p
->u
.prefix_flowspec
.prefixlen
,
11213 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11214 family2afi(dest_p
->u
11215 .prefix_flowspec
.family
));
11217 vty_out(vty
, "\"%s/%d\": ", retstr
,
11218 dest_p
->u
.prefix_flowspec
11221 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11222 dest_p
->u
.prefix_flowspec
11226 vty_out(vty
, "\"%pFX\": ", dest_p
);
11228 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11230 vty_json(vty
, json_paths
);
11234 json_object_free(json_paths
);
11238 output_count
+= *output_cum
;
11239 *output_cum
= output_count
;
11242 total_count
+= *total_cum
;
11243 *total_cum
= total_count
;
11247 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11251 for (i
= 0; i
< *json_header_depth
; ++i
)
11252 vty_out(vty
, " } ");
11254 vty_out(vty
, "\n");
11258 /* No route is displayed */
11259 if (output_count
== 0) {
11260 if (type
== bgp_show_type_normal
)
11262 "No BGP prefixes displayed, %ld exist\n",
11266 "\nDisplayed %ld routes and %ld total paths\n",
11267 output_count
, total_count
);
11271 return CMD_SUCCESS
;
11274 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11275 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11276 enum bgp_show_type type
, void *output_arg
, bool use_json
)
11278 struct bgp_dest
*dest
, *next
;
11279 unsigned long output_cum
= 0;
11280 unsigned long total_cum
= 0;
11281 unsigned long json_header_depth
= 0;
11282 struct bgp_table
*itable
;
11284 uint16_t show_flags
= 0;
11286 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11289 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11291 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11292 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11294 next
= bgp_route_next(dest
);
11295 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11298 itable
= bgp_dest_get_bgp_table_info(dest
);
11299 if (itable
!= NULL
) {
11300 struct prefix_rd prd
;
11301 char rd
[RD_ADDRSTRLEN
];
11303 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11304 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11305 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11306 rd
, next
== NULL
, &output_cum
,
11307 &total_cum
, &json_header_depth
,
11308 show_flags
, RPKI_NOT_BEING_USED
);
11314 if (output_cum
== 0)
11315 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11319 "\nDisplayed %ld routes and %ld total paths\n",
11320 output_cum
, total_cum
);
11322 return CMD_SUCCESS
;
11325 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11326 enum bgp_show_type type
, void *output_arg
,
11327 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11329 struct bgp_table
*table
;
11330 unsigned long json_header_depth
= 0;
11331 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11334 bgp
= bgp_get_default();
11339 vty_out(vty
, "No BGP process is configured\n");
11341 vty_out(vty
, "{}\n");
11342 return CMD_WARNING
;
11345 /* Labeled-unicast routes live in the unicast table. */
11346 if (safi
== SAFI_LABELED_UNICAST
)
11347 safi
= SAFI_UNICAST
;
11349 table
= bgp
->rib
[afi
][safi
];
11350 /* use MPLS and ENCAP specific shows until they are merged */
11351 if (safi
== SAFI_MPLS_VPN
) {
11352 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11353 output_arg
, use_json
);
11356 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11357 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11358 output_arg
, use_json
,
11362 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11363 NULL
, NULL
, &json_header_depth
, show_flags
,
11364 rpki_target_state
);
11367 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11368 safi_t safi
, uint16_t show_flags
)
11370 struct listnode
*node
, *nnode
;
11373 bool route_output
= false;
11374 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11377 vty_out(vty
, "{\n");
11379 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11380 route_output
= true;
11383 vty_out(vty
, ",\n");
11387 vty_out(vty
, "\"%s\":",
11388 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11392 vty_out(vty
, "\nInstance %s:\n",
11393 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11397 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11398 show_flags
, RPKI_NOT_BEING_USED
);
11402 vty_out(vty
, "}\n");
11403 else if (!route_output
)
11404 vty_out(vty
, "%% BGP instance not found\n");
11407 /* Header of detailed BGP route information */
11408 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11409 struct bgp_dest
*dest
,
11410 const struct prefix_rd
*prd
,
11411 afi_t afi
, safi_t safi
, json_object
*json
)
11413 struct bgp_path_info
*pi
;
11414 const struct prefix
*p
;
11416 struct listnode
*node
, *nnode
;
11417 char buf1
[RD_ADDRSTRLEN
];
11421 int accept_own
= 0;
11422 int route_filter_translated_v4
= 0;
11423 int route_filter_v4
= 0;
11424 int route_filter_translated_v6
= 0;
11425 int route_filter_v6
= 0;
11426 int llgr_stale
= 0;
11428 int accept_own_nexthop
= 0;
11431 int no_advertise
= 0;
11435 int has_valid_label
= 0;
11436 mpls_label_t label
= 0;
11437 json_object
*json_adv_to
= NULL
;
11439 p
= bgp_dest_get_prefix(dest
);
11440 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
11442 if (has_valid_label
)
11443 label
= label_pton(&dest
->local_label
);
11445 if (safi
== SAFI_EVPN
) {
11448 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11449 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11451 prd
? ":" : "", (struct prefix_evpn
*)p
);
11453 json_object_string_add(json
, "rd",
11454 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11456 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11461 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11463 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11464 ? prefix_rd2str(prd
, buf1
,
11467 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11471 json_object_string_addf(json
, "prefix", "%pFX", p
);
11472 json_object_int_add(json
, "version", dest
->version
);
11477 if (has_valid_label
) {
11479 json_object_int_add(json
, "localLabel", label
);
11481 vty_out(vty
, "Local label: %d\n", label
);
11485 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11486 vty_out(vty
, "not allocated\n");
11488 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11489 struct community
*picomm
= NULL
;
11491 picomm
= bgp_attr_get_community(pi
->attr
);
11494 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11496 if (bgp_path_suppressed(pi
))
11502 no_advertise
+= community_include(
11503 picomm
, COMMUNITY_NO_ADVERTISE
);
11505 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11507 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11509 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11510 route_filter_translated_v4
+= community_include(
11511 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11512 route_filter_translated_v6
+= community_include(
11513 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11514 route_filter_v4
+= community_include(
11515 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11516 route_filter_v6
+= community_include(
11517 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11519 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11520 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11521 accept_own_nexthop
+= community_include(
11522 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11524 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11525 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11530 vty_out(vty
, "Paths: (%d available", count
);
11532 vty_out(vty
, ", best #%d", best
);
11533 if (safi
== SAFI_UNICAST
) {
11534 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11535 vty_out(vty
, ", table %s",
11538 vty_out(vty
, ", vrf %s",
11542 vty_out(vty
, ", no best path");
11546 ", accept own local route exported and imported in different VRF");
11547 else if (route_filter_translated_v4
)
11549 ", mark translated RTs for VPNv4 route filtering");
11550 else if (route_filter_v4
)
11552 ", attach RT as-is for VPNv4 route filtering");
11553 else if (route_filter_translated_v6
)
11555 ", mark translated RTs for VPNv6 route filtering");
11556 else if (route_filter_v6
)
11558 ", attach RT as-is for VPNv6 route filtering");
11559 else if (llgr_stale
)
11561 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11564 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11565 else if (accept_own_nexthop
)
11567 ", accept local nexthop");
11568 else if (blackhole
)
11569 vty_out(vty
, ", inform peer to blackhole prefix");
11570 else if (no_export
)
11571 vty_out(vty
, ", not advertised to EBGP peer");
11572 else if (no_advertise
)
11573 vty_out(vty
, ", not advertised to any peer");
11575 vty_out(vty
, ", not advertised outside local AS");
11578 ", inform EBGP peer not to advertise to their EBGP peers");
11582 ", Advertisements suppressed by an aggregate.");
11583 vty_out(vty
, ")\n");
11586 /* If we are not using addpath then we can display Advertised to and
11588 * show what peers we advertised the bestpath to. If we are using
11590 * though then we must display Advertised to on a path-by-path basis. */
11591 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11592 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11593 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11594 if (json
&& !json_adv_to
)
11595 json_adv_to
= json_object_new_object();
11597 route_vty_out_advertised_to(
11599 " Advertised to non peer-group peers:\n ",
11606 json_object_object_add(json
, "advertisedTo",
11611 vty_out(vty
, " Not advertised to any peer");
11612 vty_out(vty
, "\n");
11617 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
11618 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11619 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11620 json_object
*json
, enum bgp_path_type pathtype
,
11621 int *display
, enum rpki_states rpki_target_state
)
11623 struct bgp_path_info
*pi
;
11625 char rdbuf
[RD_ADDRSTRLEN
];
11626 json_object
*json_header
= NULL
;
11627 json_object
*json_paths
= NULL
;
11628 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
11630 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11631 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11633 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
11634 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
11635 pi
->peer
, pi
->attr
, p
);
11637 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11638 && rpki_curr_state
!= rpki_target_state
)
11641 if (json
&& !json_paths
) {
11642 /* Instantiate json_paths only if path is valid */
11643 json_paths
= json_object_new_array();
11645 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11646 json_header
= json_object_new_object();
11648 json_header
= json
;
11652 route_vty_out_detail_header(
11653 vty
, bgp
, bgp_node
, pfx_rd
,
11654 AFI_IP
, safi
, json_header
);
11659 if (pathtype
== BGP_PATH_SHOW_ALL
11660 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11661 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11662 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11663 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11664 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11665 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
11666 safi
, rpki_curr_state
, json_paths
);
11669 if (json
&& json_paths
) {
11670 json_object_object_add(json_header
, "paths", json_paths
);
11673 json_object_object_add(json
, rdbuf
, json_header
);
11678 * Return rd based on safi
11680 static const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
11684 case SAFI_MPLS_VPN
:
11687 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
11694 /* Display specified route of BGP table. */
11695 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11696 struct bgp_table
*rib
, const char *ip_str
,
11697 afi_t afi
, safi_t safi
,
11698 enum rpki_states rpki_target_state
,
11699 struct prefix_rd
*prd
, int prefix_check
,
11700 enum bgp_path_type pathtype
, bool use_json
)
11704 struct prefix match
;
11705 struct bgp_dest
*dest
;
11706 struct bgp_dest
*rm
;
11707 struct bgp_table
*table
;
11708 json_object
*json
= NULL
;
11709 json_object
*json_paths
= NULL
;
11711 /* Check IP address argument. */
11712 ret
= str2prefix(ip_str
, &match
);
11714 vty_out(vty
, "address is malformed\n");
11715 return CMD_WARNING
;
11718 match
.family
= afi2family(afi
);
11721 json
= json_object_new_object();
11723 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11724 for (dest
= bgp_table_top(rib
); dest
;
11725 dest
= bgp_route_next(dest
)) {
11726 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11728 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11730 table
= bgp_dest_get_bgp_table_info(dest
);
11734 rm
= bgp_node_match(table
, &match
);
11738 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11740 && rm_p
->prefixlen
!= match
.prefixlen
) {
11741 bgp_dest_unlock_node(rm
);
11745 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11746 bgp
, afi
, safi
, json
, pathtype
,
11747 &display
, rpki_target_state
);
11749 bgp_dest_unlock_node(rm
);
11751 } else if (safi
== SAFI_EVPN
) {
11752 struct bgp_dest
*longest_pfx
;
11753 bool is_exact_pfxlen_match
= false;
11755 for (dest
= bgp_table_top(rib
); dest
;
11756 dest
= bgp_route_next(dest
)) {
11757 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11759 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11761 table
= bgp_dest_get_bgp_table_info(dest
);
11765 longest_pfx
= NULL
;
11766 is_exact_pfxlen_match
= false;
11768 * Search through all the prefixes for a match. The
11769 * pfx's are enumerated in ascending order of pfxlens.
11770 * So, the last pfx match is the longest match. Set
11771 * is_exact_pfxlen_match when we get exact pfxlen match
11773 for (rm
= bgp_table_top(table
); rm
;
11774 rm
= bgp_route_next(rm
)) {
11775 const struct prefix
*rm_p
=
11776 bgp_dest_get_prefix(rm
);
11778 * Get prefixlen of the ip-prefix within type5
11781 if (evpn_type5_prefix_match(rm_p
, &match
)
11785 bgp_evpn_get_type5_prefixlen(
11787 if (type5_pfxlen
== match
.prefixlen
) {
11788 is_exact_pfxlen_match
= true;
11789 bgp_dest_unlock_node(rm
);
11798 if (prefix_check
&& !is_exact_pfxlen_match
)
11802 bgp_dest_lock_node(rm
);
11804 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11805 bgp
, afi
, safi
, json
, pathtype
,
11806 &display
, rpki_target_state
);
11808 bgp_dest_unlock_node(rm
);
11810 } else if (safi
== SAFI_FLOWSPEC
) {
11812 json_paths
= json_object_new_array();
11814 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11815 &match
, prefix_check
,
11821 json_object_object_add(json
, "paths",
11824 json_object_free(json_paths
);
11827 dest
= bgp_node_match(rib
, &match
);
11828 if (dest
!= NULL
) {
11829 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11831 || dest_p
->prefixlen
== match
.prefixlen
) {
11832 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
11833 safi
, json
, pathtype
,
11834 &display
, rpki_target_state
);
11837 bgp_dest_unlock_node(dest
);
11842 vty_json(vty
, json
);
11845 vty_out(vty
, "%% Network not in table\n");
11846 return CMD_WARNING
;
11850 return CMD_SUCCESS
;
11853 /* Display specified route of Main RIB */
11854 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
11855 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
11856 int prefix_check
, enum bgp_path_type pathtype
,
11857 enum rpki_states rpki_target_state
, bool use_json
)
11860 bgp
= bgp_get_default();
11863 vty_out(vty
, "No BGP process is configured\n");
11865 vty_out(vty
, "{}\n");
11866 return CMD_WARNING
;
11870 /* labeled-unicast routes live in the unicast table */
11871 if (safi
== SAFI_LABELED_UNICAST
)
11872 safi
= SAFI_UNICAST
;
11874 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
11875 afi
, safi
, rpki_target_state
, prd
,
11876 prefix_check
, pathtype
, use_json
);
11879 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
11880 struct cmd_token
**argv
, bool exact
, afi_t afi
,
11881 safi_t safi
, bool uj
)
11883 struct lcommunity
*lcom
;
11888 uint16_t show_flags
= 0;
11892 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11894 b
= buffer_new(1024);
11895 for (i
= 0; i
< argc
; i
++) {
11897 buffer_putc(b
, ' ');
11899 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
11901 buffer_putstr(b
, argv
[i
]->arg
);
11905 buffer_putc(b
, '\0');
11907 str
= buffer_getstr(b
);
11910 lcom
= lcommunity_str2com(str
);
11911 XFREE(MTYPE_TMP
, str
);
11913 vty_out(vty
, "%% Large-community malformed\n");
11914 return CMD_WARNING
;
11917 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11918 (exact
? bgp_show_type_lcommunity_exact
11919 : bgp_show_type_lcommunity
),
11920 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
11922 lcommunity_free(&lcom
);
11926 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
11927 const char *lcom
, bool exact
, afi_t afi
,
11928 safi_t safi
, bool uj
)
11930 struct community_list
*list
;
11931 uint16_t show_flags
= 0;
11934 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11937 list
= community_list_lookup(bgp_clist
, lcom
, 0,
11938 LARGE_COMMUNITY_LIST_MASTER
);
11939 if (list
== NULL
) {
11940 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
11942 return CMD_WARNING
;
11945 return bgp_show(vty
, bgp
, afi
, safi
,
11946 (exact
? bgp_show_type_lcommunity_list_exact
11947 : bgp_show_type_lcommunity_list
),
11948 list
, show_flags
, RPKI_NOT_BEING_USED
);
11951 DEFUN (show_ip_bgp_large_community_list
,
11952 show_ip_bgp_large_community_list_cmd
,
11953 "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]",
11957 BGP_INSTANCE_HELP_STR
11959 BGP_SAFI_WITH_LABEL_HELP_STR
11960 "Display routes matching the large-community-list\n"
11961 "large-community-list number\n"
11962 "large-community-list name\n"
11963 "Exact match of the large-communities\n"
11966 afi_t afi
= AFI_IP6
;
11967 safi_t safi
= SAFI_UNICAST
;
11969 bool exact_match
= 0;
11970 struct bgp
*bgp
= NULL
;
11971 bool uj
= use_json(argc
, argv
);
11976 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11979 return CMD_WARNING
;
11981 argv_find(argv
, argc
, "large-community-list", &idx
);
11983 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11985 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11988 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
11989 exact_match
, afi
, safi
, uj
);
11991 DEFUN (show_ip_bgp_large_community
,
11992 show_ip_bgp_large_community_cmd
,
11993 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11997 BGP_INSTANCE_HELP_STR
11999 BGP_SAFI_WITH_LABEL_HELP_STR
12000 "Display routes matching the large-communities\n"
12001 "List of large-community numbers\n"
12002 "Exact match of the large-communities\n"
12005 afi_t afi
= AFI_IP6
;
12006 safi_t safi
= SAFI_UNICAST
;
12008 bool exact_match
= 0;
12009 struct bgp
*bgp
= NULL
;
12010 bool uj
= use_json(argc
, argv
);
12011 uint16_t show_flags
= 0;
12015 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12018 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12021 return CMD_WARNING
;
12023 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12024 if (argv_find(argv
, argc
, "exact-match", &idx
))
12026 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12027 exact_match
, afi
, safi
, uj
);
12029 return bgp_show(vty
, bgp
, afi
, safi
,
12030 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12031 RPKI_NOT_BEING_USED
);
12034 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12035 safi_t safi
, struct json_object
*json_array
);
12036 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12037 safi_t safi
, struct json_object
*json
);
12040 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12041 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12042 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12043 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12045 bool uj
= use_json(argc
, argv
);
12046 struct bgp
*bgp
= NULL
;
12047 safi_t safi
= SAFI_UNICAST
;
12048 afi_t afi
= AFI_IP6
;
12050 struct json_object
*json_all
= NULL
;
12051 struct json_object
*json_afi_safi
= NULL
;
12053 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12056 return CMD_WARNING
;
12059 json_all
= json_object_new_object();
12061 FOREACH_AFI_SAFI (afi
, safi
) {
12063 * So limit output to those afi/safi pairs that
12064 * actually have something interesting in them
12066 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12071 json_afi_safi
= json_object_new_array();
12072 json_object_object_add(
12074 get_afi_safi_str(afi
, safi
, true),
12077 json_afi_safi
= NULL
;
12080 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12084 vty_json(vty
, json_all
);
12086 return CMD_SUCCESS
;
12089 /* BGP route print out function without JSON */
12090 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12091 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12092 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12096 BGP_INSTANCE_HELP_STR
12099 "BGP RIB advertisement statistics\n"
12102 afi_t afi
= AFI_IP6
;
12103 safi_t safi
= SAFI_UNICAST
;
12104 struct bgp
*bgp
= NULL
;
12106 bool uj
= use_json(argc
, argv
);
12107 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12109 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12112 return CMD_WARNING
;
12115 json_afi_safi
= json_object_new_array();
12117 json_afi_safi
= NULL
;
12119 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12122 json
= json_object_new_object();
12123 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12125 vty_json(vty
, json
);
12130 /* BGP route print out function without JSON */
12131 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12132 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12133 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12135 statistics [json]",
12136 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12137 BGP_SAFI_WITH_LABEL_HELP_STR
12138 "BGP RIB advertisement statistics\n" JSON_STR
)
12140 afi_t afi
= AFI_IP6
;
12141 safi_t safi
= SAFI_UNICAST
;
12142 struct bgp
*bgp
= NULL
;
12144 bool uj
= use_json(argc
, argv
);
12145 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12147 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12150 return CMD_WARNING
;
12153 json_afi_safi
= json_object_new_array();
12155 json_afi_safi
= NULL
;
12157 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12160 json
= json_object_new_object();
12161 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12163 vty_json(vty
, json
);
12168 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12169 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12170 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12171 "]] [all$all] dampening parameters [json]",
12172 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12173 BGP_SAFI_WITH_LABEL_HELP_STR
12174 "Display the entries for all address families\n"
12175 "Display detailed information about dampening\n"
12176 "Display detail of configured dampening parameters\n"
12179 afi_t afi
= AFI_IP6
;
12180 safi_t safi
= SAFI_UNICAST
;
12181 struct bgp
*bgp
= NULL
;
12183 uint16_t show_flags
= 0;
12184 bool uj
= use_json(argc
, argv
);
12188 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12191 /* [<ipv4|ipv6> [all]] */
12193 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12194 if (argv_find(argv
, argc
, "ipv4", &idx
))
12195 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12197 if (argv_find(argv
, argc
, "ipv6", &idx
))
12198 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12201 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12204 return CMD_WARNING
;
12206 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12209 /* BGP route print out function */
12210 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12211 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12212 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12216 |dampening <flap-statistics|dampened-paths>\
12217 |community [AA:NN|local-AS|no-advertise|no-export\
12218 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12219 |accept-own|accept-own-nexthop|route-filter-v6\
12220 |route-filter-v4|route-filter-translated-v6\
12221 |route-filter-translated-v4] [exact-match]\
12222 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12223 |filter-list AS_PATH_FILTER_NAME\
12226 |rpki <invalid|valid|notfound>\
12227 |version (1-4294967295)\
12229 |A.B.C.D/M longer-prefixes\
12230 |X:X::X:X/M longer-prefixes\
12231 ] [json$uj [detail$detail] | wide$wide]",
12232 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12233 BGP_SAFI_WITH_LABEL_HELP_STR
12234 "Display the entries for all address families\n"
12235 "Display only routes with non-natural netmasks\n"
12236 "Display detailed information about dampening\n"
12237 "Display flap statistics of routes\n"
12238 "Display paths suppressed due to dampening\n"
12239 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12240 "Do not send outside local AS (well-known community)\n"
12241 "Do not advertise to any peer (well-known community)\n"
12242 "Do not export to next AS (well-known community)\n"
12243 "Graceful shutdown (well-known community)\n"
12244 "Do not export to any peer (well-known community)\n"
12245 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12246 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12247 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12248 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12249 "Should accept VPN route with local nexthop (well-known community)\n"
12250 "RT VPNv6 route filtering (well-known community)\n"
12251 "RT VPNv4 route filtering (well-known community)\n"
12252 "RT translated VPNv6 route filtering (well-known community)\n"
12253 "RT translated VPNv4 route filtering (well-known community)\n"
12254 "Exact match of the communities\n"
12255 "Community-list number\n"
12256 "Community-list name\n"
12257 "Display routes matching the community-list\n"
12258 "Exact match of the communities\n"
12259 "Display routes conforming to the filter-list\n"
12260 "Regular expression access list name\n"
12261 "Display routes conforming to the prefix-list\n"
12262 "Prefix-list name\n"
12263 "Display routes matching the route-map\n"
12264 "A route-map to match on\n"
12265 "RPKI route types\n"
12266 "A valid path as determined by rpki\n"
12267 "A invalid path as determined by rpki\n"
12268 "A path that has no rpki data\n"
12269 "Display prefixes with matching version numbers\n"
12270 "Version number and above\n"
12271 "Display prefixes with matching BGP community alias\n"
12272 "BGP community alias\n"
12274 "Display route and more specific routes\n"
12276 "Display route and more specific routes\n"
12278 "Display detailed version of JSON output\n"
12279 "Increase table width for longer prefixes\n")
12281 afi_t afi
= AFI_IP6
;
12282 safi_t safi
= SAFI_UNICAST
;
12283 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12284 void *output_arg
= NULL
;
12285 struct bgp
*bgp
= NULL
;
12287 int exact_match
= 0;
12288 char *community
= NULL
;
12290 uint16_t show_flags
= 0;
12291 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12296 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12300 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12302 /* [<ipv4|ipv6> [all]] */
12304 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12306 if (argv_find(argv
, argc
, "ipv4", &idx
))
12307 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12309 if (argv_find(argv
, argc
, "ipv6", &idx
))
12310 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12314 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12316 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12319 return CMD_WARNING
;
12321 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12322 sh_type
= bgp_show_type_cidr_only
;
12324 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12325 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12326 sh_type
= bgp_show_type_dampend_paths
;
12327 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12328 sh_type
= bgp_show_type_flap_statistics
;
12331 if (argv_find(argv
, argc
, "community", &idx
)) {
12332 char *maybecomm
= NULL
;
12334 if (idx
+ 1 < argc
) {
12335 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12336 maybecomm
= argv
[idx
+ 1]->arg
;
12338 maybecomm
= argv
[idx
+ 1]->text
;
12341 if (maybecomm
&& !strmatch(maybecomm
, "json")
12342 && !strmatch(maybecomm
, "exact-match"))
12343 community
= maybecomm
;
12345 if (argv_find(argv
, argc
, "exact-match", &idx
))
12349 sh_type
= bgp_show_type_community_all
;
12352 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12353 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12354 struct community_list
*list
;
12356 if (argv_find(argv
, argc
, "exact-match", &idx
))
12359 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12360 COMMUNITY_LIST_MASTER
);
12361 if (list
== NULL
) {
12363 "%% %s is not a valid community-list name\n",
12364 clist_number_or_name
);
12365 return CMD_WARNING
;
12369 sh_type
= bgp_show_type_community_list_exact
;
12371 sh_type
= bgp_show_type_community_list
;
12375 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12376 const char *filter
= argv
[++idx
]->arg
;
12377 struct as_list
*as_list
;
12379 as_list
= as_list_lookup(filter
);
12380 if (as_list
== NULL
) {
12382 "%% %s is not a valid AS-path access-list name\n",
12384 return CMD_WARNING
;
12387 sh_type
= bgp_show_type_filter_list
;
12388 output_arg
= as_list
;
12391 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12392 const char *prefix_list_str
= argv
[++idx
]->arg
;
12393 struct prefix_list
*plist
;
12395 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12396 if (plist
== NULL
) {
12397 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
12399 return CMD_WARNING
;
12402 sh_type
= bgp_show_type_prefix_list
;
12403 output_arg
= plist
;
12406 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12407 const char *rmap_str
= argv
[++idx
]->arg
;
12408 struct route_map
*rmap
;
12410 rmap
= route_map_lookup_by_name(rmap_str
);
12412 vty_out(vty
, "%% %s is not a valid route-map name\n",
12414 return CMD_WARNING
;
12417 sh_type
= bgp_show_type_route_map
;
12421 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12422 sh_type
= bgp_show_type_rpki
;
12423 if (argv_find(argv
, argc
, "valid", &idx
))
12424 rpki_target_state
= RPKI_VALID
;
12425 else if (argv_find(argv
, argc
, "invalid", &idx
))
12426 rpki_target_state
= RPKI_INVALID
;
12429 /* Display prefixes with matching version numbers */
12430 if (argv_find(argv
, argc
, "version", &idx
)) {
12431 sh_type
= bgp_show_type_prefix_version
;
12432 output_arg
= argv
[idx
+ 1]->arg
;
12435 /* Display prefixes with matching BGP community alias */
12436 if (argv_find(argv
, argc
, "alias", &idx
)) {
12437 sh_type
= bgp_show_type_community_alias
;
12438 output_arg
= argv
[idx
+ 1]->arg
;
12441 /* prefix-longer */
12442 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12443 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12444 const char *prefix_str
= argv
[idx
]->arg
;
12446 if (!str2prefix(prefix_str
, &p
)) {
12447 vty_out(vty
, "%% Malformed Prefix\n");
12448 return CMD_WARNING
;
12451 sh_type
= bgp_show_type_prefix_longer
;
12456 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12458 return bgp_show_community(vty
, bgp
, community
,
12459 exact_match
, afi
, safi
,
12462 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12463 output_arg
, show_flags
,
12464 rpki_target_state
);
12466 struct listnode
*node
;
12468 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12472 vty_out(vty
, "{\n");
12474 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12475 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12476 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12479 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12480 FOREACH_SAFI (safi
) {
12481 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12489 vty_out(vty
, ",\n");
12490 vty_out(vty
, "\"%s\":{\n",
12491 get_afi_safi_str(afi
,
12496 "\nFor address family: %s\n",
12502 bgp_show_community(
12503 vty
, abgp
, community
,
12504 exact_match
, afi
, safi
,
12507 bgp_show(vty
, abgp
, afi
, safi
,
12508 sh_type
, output_arg
,
12510 rpki_target_state
);
12512 vty_out(vty
, "}\n");
12516 /* show <ip> bgp all: for each AFI and SAFI*/
12517 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12518 FOREACH_AFI_SAFI (afi
, safi
) {
12519 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12527 vty_out(vty
, ",\n");
12529 vty_out(vty
, "\"%s\":{\n",
12530 get_afi_safi_str(afi
,
12535 "\nFor address family: %s\n",
12541 bgp_show_community(
12542 vty
, abgp
, community
,
12543 exact_match
, afi
, safi
,
12546 bgp_show(vty
, abgp
, afi
, safi
,
12547 sh_type
, output_arg
,
12549 rpki_target_state
);
12551 vty_out(vty
, "}\n");
12556 vty_out(vty
, "}\n");
12558 return CMD_SUCCESS
;
12561 DEFUN (show_ip_bgp_route
,
12562 show_ip_bgp_route_cmd
,
12563 "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]",
12567 BGP_INSTANCE_HELP_STR
12569 BGP_SAFI_WITH_LABEL_HELP_STR
12570 "Network in the BGP routing table to display\n"
12572 "Network in the BGP routing table to display\n"
12574 "Display only the bestpath\n"
12575 "Display only multipaths\n"
12576 "Display only paths that match the specified rpki state\n"
12577 "A valid path as determined by rpki\n"
12578 "A invalid path as determined by rpki\n"
12579 "A path that has no rpki data\n"
12582 int prefix_check
= 0;
12584 afi_t afi
= AFI_IP6
;
12585 safi_t safi
= SAFI_UNICAST
;
12586 char *prefix
= NULL
;
12587 struct bgp
*bgp
= NULL
;
12588 enum bgp_path_type path_type
;
12589 bool uj
= use_json(argc
, argv
);
12593 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12596 return CMD_WARNING
;
12600 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12601 return CMD_WARNING
;
12604 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12605 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12606 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12608 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12609 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12612 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12613 && afi
!= AFI_IP6
) {
12615 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12616 return CMD_WARNING
;
12618 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12619 && afi
!= AFI_IP
) {
12621 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12622 return CMD_WARNING
;
12625 prefix
= argv
[idx
]->arg
;
12627 /* [<bestpath|multipath>] */
12628 if (argv_find(argv
, argc
, "bestpath", &idx
))
12629 path_type
= BGP_PATH_SHOW_BESTPATH
;
12630 else if (argv_find(argv
, argc
, "multipath", &idx
))
12631 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12633 path_type
= BGP_PATH_SHOW_ALL
;
12635 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12636 path_type
, RPKI_NOT_BEING_USED
, uj
);
12639 DEFUN (show_ip_bgp_regexp
,
12640 show_ip_bgp_regexp_cmd
,
12641 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12645 BGP_INSTANCE_HELP_STR
12647 BGP_SAFI_WITH_LABEL_HELP_STR
12648 "Display routes matching the AS path regular expression\n"
12649 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12652 afi_t afi
= AFI_IP6
;
12653 safi_t safi
= SAFI_UNICAST
;
12654 struct bgp
*bgp
= NULL
;
12655 bool uj
= use_json(argc
, argv
);
12656 char *regstr
= NULL
;
12659 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12662 return CMD_WARNING
;
12664 // get index of regex
12665 if (argv_find(argv
, argc
, "REGEX", &idx
))
12666 regstr
= argv
[idx
]->arg
;
12669 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12670 bgp_show_type_regexp
, uj
);
12673 DEFPY (show_ip_bgp_instance_all
,
12674 show_ip_bgp_instance_all_cmd
,
12675 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12679 BGP_INSTANCE_ALL_HELP_STR
12681 BGP_SAFI_WITH_LABEL_HELP_STR
12683 "Increase table width for longer prefixes\n")
12685 afi_t afi
= AFI_IP6
;
12686 safi_t safi
= SAFI_UNICAST
;
12687 struct bgp
*bgp
= NULL
;
12689 uint16_t show_flags
= 0;
12693 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12697 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12699 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12702 return CMD_WARNING
;
12704 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12705 return CMD_SUCCESS
;
12708 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12709 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12714 uint16_t show_flags
= 0;
12717 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12719 if (!config_bgp_aspath_validate(regstr
)) {
12720 vty_out(vty
, "Invalid character in REGEX %s\n",
12722 return CMD_WARNING_CONFIG_FAILED
;
12725 regex
= bgp_regcomp(regstr
);
12727 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12728 return CMD_WARNING
;
12731 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
12732 RPKI_NOT_BEING_USED
);
12733 bgp_regex_free(regex
);
12737 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12738 const char *comstr
, int exact
, afi_t afi
,
12739 safi_t safi
, uint16_t show_flags
)
12741 struct community
*com
;
12744 com
= community_str2com(comstr
);
12746 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12747 return CMD_WARNING
;
12750 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12751 (exact
? bgp_show_type_community_exact
12752 : bgp_show_type_community
),
12753 com
, show_flags
, RPKI_NOT_BEING_USED
);
12754 community_free(&com
);
12760 BGP_STATS_MAXBITLEN
= 0,
12762 BGP_STATS_PREFIXES
,
12764 BGP_STATS_UNAGGREGATEABLE
,
12765 BGP_STATS_MAX_AGGREGATEABLE
,
12766 BGP_STATS_AGGREGATES
,
12768 BGP_STATS_ASPATH_COUNT
,
12769 BGP_STATS_ASPATH_MAXHOPS
,
12770 BGP_STATS_ASPATH_TOTHOPS
,
12771 BGP_STATS_ASPATH_MAXSIZE
,
12772 BGP_STATS_ASPATH_TOTSIZE
,
12773 BGP_STATS_ASN_HIGHEST
,
12777 #define TABLE_STATS_IDX_VTY 0
12778 #define TABLE_STATS_IDX_JSON 1
12780 static const char *table_stats_strs
[][2] = {
12781 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12782 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12783 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12784 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12785 "unaggregateablePrefixes"},
12786 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12787 "maximumAggregateablePrefixes"},
12788 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12789 "bgpAggregateAdvertisements"},
12790 [BGP_STATS_SPACE
] = {"Address space advertised",
12791 "addressSpaceAdvertised"},
12792 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12793 "advertisementsWithPaths"},
12794 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12796 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12798 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12799 "averageAsPathLengthHops"},
12800 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12801 "averageAsPathSizeBytes"},
12802 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12803 [BGP_STATS_MAX
] = {NULL
, NULL
}
12806 struct bgp_table_stats
{
12807 struct bgp_table
*table
;
12808 unsigned long long counts
[BGP_STATS_MAX
];
12809 double total_space
;
12812 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
12813 struct bgp_table_stats
*ts
, unsigned int space
)
12815 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
12816 struct bgp_path_info
*pi
;
12817 const struct prefix
*rn_p
;
12819 if (!bgp_dest_has_bgp_path_info_data(dest
))
12822 rn_p
= bgp_dest_get_prefix(dest
);
12823 ts
->counts
[BGP_STATS_PREFIXES
]++;
12824 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
12826 /* check if the prefix is included by any other announcements */
12827 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
12828 pdest
= bgp_dest_parent_nolock(pdest
);
12830 if (pdest
== NULL
|| pdest
== top
) {
12831 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
12832 /* announced address space */
12834 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
12835 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
12836 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
12839 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
12840 ts
->counts
[BGP_STATS_RIB
]++;
12842 if (CHECK_FLAG(pi
->attr
->flag
,
12843 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
12844 ts
->counts
[BGP_STATS_AGGREGATES
]++;
12846 /* as-path stats */
12847 if (pi
->attr
->aspath
) {
12848 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
12849 unsigned int size
= aspath_size(pi
->attr
->aspath
);
12850 as_t highest
= aspath_highest(pi
->attr
->aspath
);
12852 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
12854 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
12855 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
12857 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
12858 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
12860 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
12861 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
12862 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
12863 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
12868 static void bgp_table_stats_walker(struct thread
*t
)
12870 struct bgp_dest
*dest
, *ndest
;
12871 struct bgp_dest
*top
;
12872 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
12873 unsigned int space
= 0;
12875 if (!(top
= bgp_table_top(ts
->table
)))
12878 switch (ts
->table
->afi
) {
12880 space
= IPV4_MAX_BITLEN
;
12883 space
= IPV6_MAX_BITLEN
;
12886 space
= EVPN_ROUTE_PREFIXLEN
;
12892 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
12894 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
12895 if (ts
->table
->safi
== SAFI_MPLS_VPN
12896 || ts
->table
->safi
== SAFI_ENCAP
12897 || ts
->table
->safi
== SAFI_EVPN
) {
12898 struct bgp_table
*table
;
12900 table
= bgp_dest_get_bgp_table_info(dest
);
12904 top
= bgp_table_top(table
);
12905 for (ndest
= bgp_table_top(table
); ndest
;
12906 ndest
= bgp_route_next(ndest
))
12907 bgp_table_stats_rn(ndest
, top
, ts
, space
);
12909 bgp_table_stats_rn(dest
, top
, ts
, space
);
12914 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
12915 struct json_object
*json_array
)
12917 struct listnode
*node
, *nnode
;
12920 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
12921 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12924 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12925 safi_t safi
, struct json_object
*json_array
)
12927 struct bgp_table_stats ts
;
12929 int ret
= CMD_SUCCESS
;
12931 struct json_object
*json
= NULL
;
12934 json
= json_object_new_object();
12936 if (!bgp
->rib
[afi
][safi
]) {
12937 char warning_msg
[50];
12939 snprintf(warning_msg
, sizeof(warning_msg
),
12940 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
12944 vty_out(vty
, "%s\n", warning_msg
);
12946 json_object_string_add(json
, "warning", warning_msg
);
12949 goto end_table_stats
;
12953 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
12954 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
12956 json_object_string_add(json
, "instance", bgp
->name_pretty
);
12958 /* labeled-unicast routes live in the unicast table */
12959 if (safi
== SAFI_LABELED_UNICAST
)
12960 safi
= SAFI_UNICAST
;
12962 memset(&ts
, 0, sizeof(ts
));
12963 ts
.table
= bgp
->rib
[afi
][safi
];
12964 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
12966 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
12967 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
12968 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
12972 case BGP_STATS_ASPATH_TOTHOPS
:
12973 case BGP_STATS_ASPATH_TOTSIZE
:
12976 temp_buf
, sizeof(temp_buf
), "%12.2f",
12978 ? (float)ts
.counts
[i
]
12980 [BGP_STATS_ASPATH_COUNT
]
12982 vty_out(vty
, "%-30s: %s",
12983 table_stats_strs
[i
]
12984 [TABLE_STATS_IDX_VTY
],
12987 json_object_double_add(
12989 table_stats_strs
[i
]
12990 [TABLE_STATS_IDX_JSON
],
12992 ? (double)ts
.counts
[i
]
12993 / (double)ts
.counts
12994 [BGP_STATS_ASPATH_COUNT
]
12998 case BGP_STATS_TOTPLEN
:
13001 temp_buf
, sizeof(temp_buf
), "%12.2f",
13003 ? (float)ts
.counts
[i
]
13005 [BGP_STATS_PREFIXES
]
13007 vty_out(vty
, "%-30s: %s",
13008 table_stats_strs
[i
]
13009 [TABLE_STATS_IDX_VTY
],
13012 json_object_double_add(
13014 table_stats_strs
[i
]
13015 [TABLE_STATS_IDX_JSON
],
13017 ? (double)ts
.counts
[i
]
13018 / (double)ts
.counts
13019 [BGP_STATS_PREFIXES
]
13023 case BGP_STATS_SPACE
:
13025 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13027 vty_out(vty
, "%-30s: %s\n",
13028 table_stats_strs
[i
]
13029 [TABLE_STATS_IDX_VTY
],
13032 json_object_double_add(
13034 table_stats_strs
[i
]
13035 [TABLE_STATS_IDX_JSON
],
13036 (double)ts
.total_space
);
13038 if (afi
== AFI_IP6
) {
13040 snprintf(temp_buf
, sizeof(temp_buf
),
13043 * pow(2.0, -128 + 32));
13044 vty_out(vty
, "%30s: %s\n",
13045 "/32 equivalent %s\n",
13048 json_object_double_add(
13049 json
, "/32equivalent",
13050 (double)(ts
.total_space
13055 snprintf(temp_buf
, sizeof(temp_buf
),
13058 * pow(2.0, -128 + 48));
13059 vty_out(vty
, "%30s: %s\n",
13060 "/48 equivalent %s\n",
13063 json_object_double_add(
13064 json
, "/48equivalent",
13065 (double)(ts
.total_space
13071 snprintf(temp_buf
, sizeof(temp_buf
),
13073 ts
.total_space
* 100.
13075 vty_out(vty
, "%30s: %s\n",
13076 "% announced ", temp_buf
);
13078 json_object_double_add(
13079 json
, "%announced",
13080 (double)(ts
.total_space
* 100.
13084 snprintf(temp_buf
, sizeof(temp_buf
),
13087 * pow(2.0, -32 + 8));
13088 vty_out(vty
, "%30s: %s\n",
13089 "/8 equivalent ", temp_buf
);
13091 json_object_double_add(
13092 json
, "/8equivalent",
13093 (double)(ts
.total_space
13094 * pow(2.0, -32 + 8)));
13097 snprintf(temp_buf
, sizeof(temp_buf
),
13100 * pow(2.0, -32 + 24));
13101 vty_out(vty
, "%30s: %s\n",
13102 "/24 equivalent ", temp_buf
);
13104 json_object_double_add(
13105 json
, "/24equivalent",
13106 (double)(ts
.total_space
13107 * pow(2.0, -32 + 24)));
13113 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13115 vty_out(vty
, "%-30s: %s",
13116 table_stats_strs
[i
]
13117 [TABLE_STATS_IDX_VTY
],
13120 json_object_int_add(
13122 table_stats_strs
[i
]
13123 [TABLE_STATS_IDX_JSON
],
13128 vty_out(vty
, "\n");
13132 json_object_array_add(json_array
, json
);
13136 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13137 safi_t safi
, struct json_object
*json_array
)
13140 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13141 return CMD_SUCCESS
;
13144 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13156 PCOUNT_BPATH_SELECTED
,
13157 PCOUNT_PFCNT
, /* the figure we display to users */
13161 static const char *const pcount_strs
[] = {
13162 [PCOUNT_ADJ_IN
] = "Adj-in",
13163 [PCOUNT_DAMPED
] = "Damped",
13164 [PCOUNT_REMOVED
] = "Removed",
13165 [PCOUNT_HISTORY
] = "History",
13166 [PCOUNT_STALE
] = "Stale",
13167 [PCOUNT_VALID
] = "Valid",
13168 [PCOUNT_ALL
] = "All RIB",
13169 [PCOUNT_COUNTED
] = "PfxCt counted",
13170 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13171 [PCOUNT_PFCNT
] = "Useable",
13172 [PCOUNT_MAX
] = NULL
,
13175 struct peer_pcounts
{
13176 unsigned int count
[PCOUNT_MAX
];
13177 const struct peer
*peer
;
13178 const struct bgp_table
*table
;
13182 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13184 const struct bgp_adj_in
*ain
;
13185 const struct bgp_path_info
*pi
;
13186 const struct peer
*peer
= pc
->peer
;
13188 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13189 if (ain
->peer
== peer
)
13190 pc
->count
[PCOUNT_ADJ_IN
]++;
13192 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13194 if (pi
->peer
!= peer
)
13197 pc
->count
[PCOUNT_ALL
]++;
13199 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13200 pc
->count
[PCOUNT_DAMPED
]++;
13201 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13202 pc
->count
[PCOUNT_HISTORY
]++;
13203 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13204 pc
->count
[PCOUNT_REMOVED
]++;
13205 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13206 pc
->count
[PCOUNT_STALE
]++;
13207 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13208 pc
->count
[PCOUNT_VALID
]++;
13209 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13210 pc
->count
[PCOUNT_PFCNT
]++;
13211 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13212 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13214 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13215 pc
->count
[PCOUNT_COUNTED
]++;
13216 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13218 EC_LIB_DEVELOPMENT
,
13219 "Attempting to count but flags say it is unusable");
13221 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13223 EC_LIB_DEVELOPMENT
,
13224 "Not counted but flags say we should");
13229 static void bgp_peer_count_walker(struct thread
*t
)
13231 struct bgp_dest
*rn
, *rm
;
13232 const struct bgp_table
*table
;
13233 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13235 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13236 || pc
->safi
== SAFI_EVPN
) {
13237 /* Special handling for 2-level routing tables. */
13238 for (rn
= bgp_table_top(pc
->table
); rn
;
13239 rn
= bgp_route_next(rn
)) {
13240 table
= bgp_dest_get_bgp_table_info(rn
);
13242 for (rm
= bgp_table_top(table
); rm
;
13243 rm
= bgp_route_next(rm
))
13244 bgp_peer_count_proc(rm
, pc
);
13247 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13248 bgp_peer_count_proc(rn
, pc
);
13251 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13252 safi_t safi
, bool use_json
)
13254 struct peer_pcounts pcounts
= {.peer
= peer
};
13256 json_object
*json
= NULL
;
13257 json_object
*json_loop
= NULL
;
13260 json
= json_object_new_object();
13261 json_loop
= json_object_new_object();
13264 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13265 || !peer
->bgp
->rib
[afi
][safi
]) {
13267 json_object_string_add(
13269 "No such neighbor or address family");
13270 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13271 json_object_free(json
);
13272 json_object_free(json_loop
);
13274 vty_out(vty
, "%% No such neighbor or address family\n");
13276 return CMD_WARNING
;
13279 memset(&pcounts
, 0, sizeof(pcounts
));
13280 pcounts
.peer
= peer
;
13281 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13282 pcounts
.safi
= safi
;
13284 /* in-place call via thread subsystem so as to record execution time
13285 * stats for the thread-walk (i.e. ensure this can't be blamed on
13286 * on just vty_read()).
13288 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13291 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13292 json_object_string_add(json
, "multiProtocol",
13293 get_afi_safi_str(afi
, safi
, true));
13294 json_object_int_add(json
, "pfxCounter",
13295 peer
->pcount
[afi
][safi
]);
13297 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13298 json_object_int_add(json_loop
, pcount_strs
[i
],
13301 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13303 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13304 json_object_string_add(json
, "pfxctDriftFor",
13306 json_object_string_add(
13307 json
, "recommended",
13308 "Please report this bug, with the above command output");
13310 vty_json(vty
, json
);
13314 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13315 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13316 peer
->hostname
, peer
->host
,
13317 get_afi_safi_str(afi
, safi
, false));
13319 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13320 get_afi_safi_str(afi
, safi
, false));
13323 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13324 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13326 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13327 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13330 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13331 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13333 "Please report this bug, with the above command output\n");
13337 return CMD_SUCCESS
;
13340 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13341 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13342 "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]",
13346 BGP_INSTANCE_HELP_STR
13349 "Detailed information on TCP and BGP neighbor connections\n"
13350 "Neighbor to display information about\n"
13351 "Neighbor to display information about\n"
13352 "Neighbor on BGP configured interface\n"
13353 "Display detailed prefix count information\n"
13356 afi_t afi
= AFI_IP6
;
13357 safi_t safi
= SAFI_UNICAST
;
13360 struct bgp
*bgp
= NULL
;
13361 bool uj
= use_json(argc
, argv
);
13366 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13369 return CMD_WARNING
;
13371 argv_find(argv
, argc
, "neighbors", &idx
);
13372 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13374 return CMD_WARNING
;
13376 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13379 #ifdef KEEP_OLD_VPN_COMMANDS
13380 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13381 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13382 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13387 "Display information about all VPNv4 NLRIs\n"
13388 "Detailed information on TCP and BGP neighbor connections\n"
13389 "Neighbor to display information about\n"
13390 "Neighbor to display information about\n"
13391 "Neighbor on BGP configured interface\n"
13392 "Display detailed prefix count information\n"
13397 bool uj
= use_json(argc
, argv
);
13399 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13401 return CMD_WARNING
;
13403 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13406 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13407 show_ip_bgp_vpn_all_route_prefix_cmd
,
13408 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13413 "Display information about all VPNv4 NLRIs\n"
13414 "Network in the BGP routing table to display\n"
13415 "Network in the BGP routing table to display\n"
13419 char *network
= NULL
;
13420 struct bgp
*bgp
= bgp_get_default();
13422 vty_out(vty
, "Can't find default instance\n");
13423 return CMD_WARNING
;
13426 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13427 network
= argv
[idx
]->arg
;
13428 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13429 network
= argv
[idx
]->arg
;
13431 vty_out(vty
, "Unable to figure out Network\n");
13432 return CMD_WARNING
;
13435 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13436 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13437 use_json(argc
, argv
));
13439 #endif /* KEEP_OLD_VPN_COMMANDS */
13441 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13442 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13443 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13448 "Network in the BGP routing table to display\n"
13449 "Network in the BGP routing table to display\n"
13450 "Network in the BGP routing table to display\n"
13451 "Network in the BGP routing table to display\n"
13455 char *network
= NULL
;
13456 int prefix_check
= 0;
13458 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13459 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13460 network
= argv
[idx
]->arg
;
13461 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13462 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13463 network
= argv
[idx
]->arg
;
13466 vty_out(vty
, "Unable to figure out Network\n");
13467 return CMD_WARNING
;
13469 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13470 prefix_check
, BGP_PATH_SHOW_ALL
,
13471 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13474 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
13475 struct bgp_table
*table
, int *header1
,
13476 int *header2
, json_object
*json
,
13477 json_object
*json_scode
,
13478 json_object
*json_ocode
, bool wide
)
13480 uint64_t version
= table
? table
->version
: 0;
13484 json_object_int_add(json
, "bgpTableVersion", version
);
13485 json_object_string_addf(json
, "bgpLocalRouterId",
13486 "%pI4", &bgp
->router_id
);
13487 json_object_int_add(json
, "defaultLocPrf",
13488 bgp
->default_local_pref
);
13489 json_object_int_add(json
, "localAS", bgp
->as
);
13490 json_object_object_add(json
, "bgpStatusCodes",
13492 json_object_object_add(json
, "bgpOriginCodes",
13496 "BGP table version is %" PRIu64
13497 ", local router ID is %pI4, vrf id ",
13498 version
, &bgp
->router_id
);
13499 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13500 vty_out(vty
, "%s", VRFID_NONE_STR
);
13502 vty_out(vty
, "%u", bgp
->vrf_id
);
13503 vty_out(vty
, "\n");
13504 vty_out(vty
, "Default local pref %u, ",
13505 bgp
->default_local_pref
);
13506 vty_out(vty
, "local AS %u\n", bgp
->as
);
13507 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13508 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13509 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13510 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13516 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13517 : BGP_SHOW_HEADER
));
13523 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13524 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13525 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13526 json_object
*json_scode
, json_object
*json_ocode
,
13527 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13528 unsigned long *output_count
, unsigned long *filtered_count
)
13530 struct bgp_adj_in
*ain
;
13531 struct bgp_adj_out
*adj
;
13532 struct bgp_dest
*dest
;
13536 struct update_subgroup
*subgrp
;
13537 struct peer_af
*paf
;
13538 bool route_filtered
;
13539 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13540 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13541 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13542 || (safi
== SAFI_EVPN
))
13548 subgrp
= peer_subgroup(peer
, afi
, safi
);
13550 if (type
== bgp_show_adj_route_advertised
&& subgrp
13551 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13553 json_object_int_add(json
, "bgpTableVersion",
13555 json_object_string_addf(json
, "bgpLocalRouterId",
13556 "%pI4", &bgp
->router_id
);
13557 json_object_int_add(json
, "defaultLocPrf",
13558 bgp
->default_local_pref
);
13559 json_object_int_add(json
, "localAS", bgp
->as
);
13560 json_object_object_add(json
, "bgpStatusCodes",
13562 json_object_object_add(json
, "bgpOriginCodes",
13564 json_object_string_add(
13565 json
, "bgpOriginatingDefaultNetwork",
13566 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13569 "BGP table version is %" PRIu64
13570 ", local router ID is %pI4, vrf id ",
13571 table
->version
, &bgp
->router_id
);
13572 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13573 vty_out(vty
, "%s", VRFID_NONE_STR
);
13575 vty_out(vty
, "%u", bgp
->vrf_id
);
13576 vty_out(vty
, "\n");
13577 vty_out(vty
, "Default local pref %u, ",
13578 bgp
->default_local_pref
);
13579 vty_out(vty
, "local AS %u\n", bgp
->as
);
13580 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13581 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13582 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13583 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13585 vty_out(vty
, "Originating default network %s\n\n",
13586 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13591 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13592 if (type
== bgp_show_adj_route_received
13593 || type
== bgp_show_adj_route_filtered
) {
13594 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13595 if (ain
->peer
!= peer
)
13598 show_adj_route_header(vty
, bgp
, table
, header1
,
13599 header2
, json
, json_scode
,
13602 if ((safi
== SAFI_MPLS_VPN
)
13603 || (safi
== SAFI_ENCAP
)
13604 || (safi
== SAFI_EVPN
)) {
13606 json_object_string_add(
13607 json_ar
, "rd", rd_str
);
13608 else if (show_rd
&& rd_str
) {
13610 "Route Distinguisher: %s\n",
13617 route_filtered
= false;
13619 /* Filter prefix using distribute list,
13620 * filter list or prefix list
13622 const struct prefix
*rn_p
=
13623 bgp_dest_get_prefix(dest
);
13624 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13627 route_filtered
= true;
13629 /* Filter prefix using route-map */
13630 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13631 safi
, rmap_name
, NULL
,
13634 if (type
== bgp_show_adj_route_filtered
&&
13635 !route_filtered
&& ret
!= RMAP_DENY
) {
13636 bgp_attr_flush(&attr
);
13640 if (type
== bgp_show_adj_route_received
13641 && (route_filtered
|| ret
== RMAP_DENY
))
13642 (*filtered_count
)++;
13644 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
13645 use_json
, json_ar
, wide
);
13646 bgp_attr_flush(&attr
);
13649 } else if (type
== bgp_show_adj_route_advertised
) {
13650 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13651 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13652 if (paf
->peer
!= peer
|| !adj
->attr
)
13655 show_adj_route_header(vty
, bgp
, table
,
13660 const struct prefix
*rn_p
=
13661 bgp_dest_get_prefix(dest
);
13664 ret
= bgp_output_modifier(
13665 peer
, rn_p
, &attr
, afi
, safi
,
13668 if (ret
!= RMAP_DENY
) {
13669 if ((safi
== SAFI_MPLS_VPN
)
13670 || (safi
== SAFI_ENCAP
)
13671 || (safi
== SAFI_EVPN
)) {
13673 json_object_string_add(
13680 "Route Distinguisher: %s\n",
13686 vty
, dest
, rn_p
, &attr
,
13687 safi
, use_json
, json_ar
,
13691 (*filtered_count
)++;
13694 bgp_attr_flush(&attr
);
13696 } else if (type
== bgp_show_adj_route_bestpath
) {
13697 struct bgp_path_info
*pi
;
13699 show_adj_route_header(vty
, bgp
, table
, header1
, header2
,
13700 json
, json_scode
, json_ocode
,
13703 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13705 if (pi
->peer
!= peer
)
13708 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13711 route_vty_out_tmp(vty
, dest
,
13712 bgp_dest_get_prefix(dest
),
13713 pi
->attr
, safi
, use_json
,
13721 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13722 safi_t safi
, enum bgp_show_adj_route_type type
,
13723 const char *rmap_name
, uint16_t show_flags
)
13726 struct bgp_table
*table
;
13727 json_object
*json
= NULL
;
13728 json_object
*json_scode
= NULL
;
13729 json_object
*json_ocode
= NULL
;
13730 json_object
*json_ar
= NULL
;
13731 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13733 /* Init BGP headers here so they're only displayed once
13734 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13740 * Initialize variables for each RD
13741 * All prefixes under an RD is aggregated within "json_routes"
13743 char rd_str
[BUFSIZ
] = {0};
13744 json_object
*json_routes
= NULL
;
13747 /* For 2-tier tables, prefix counts need to be
13748 * maintained across multiple runs of show_adj_route()
13750 unsigned long output_count_per_rd
;
13751 unsigned long filtered_count_per_rd
;
13752 unsigned long output_count
= 0;
13753 unsigned long filtered_count
= 0;
13756 json
= json_object_new_object();
13757 json_ar
= json_object_new_object();
13758 json_scode
= json_object_new_object();
13759 json_ocode
= json_object_new_object();
13761 json_object_string_add(json_scode
, "suppressed", "s");
13762 json_object_string_add(json_scode
, "damped", "d");
13763 json_object_string_add(json_scode
, "history", "h");
13764 json_object_string_add(json_scode
, "valid", "*");
13765 json_object_string_add(json_scode
, "best", ">");
13766 json_object_string_add(json_scode
, "multipath", "=");
13767 json_object_string_add(json_scode
, "internal", "i");
13768 json_object_string_add(json_scode
, "ribFailure", "r");
13769 json_object_string_add(json_scode
, "stale", "S");
13770 json_object_string_add(json_scode
, "removed", "R");
13772 json_object_string_add(json_ocode
, "igp", "i");
13773 json_object_string_add(json_ocode
, "egp", "e");
13774 json_object_string_add(json_ocode
, "incomplete", "?");
13777 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13779 json_object_string_add(
13781 "No such neighbor or address family");
13782 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13783 json_object_free(json
);
13784 json_object_free(json_ar
);
13785 json_object_free(json_scode
);
13786 json_object_free(json_ocode
);
13788 vty_out(vty
, "%% No such neighbor or address family\n");
13790 return CMD_WARNING
;
13793 if ((type
== bgp_show_adj_route_received
13794 || type
== bgp_show_adj_route_filtered
)
13795 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
13796 PEER_FLAG_SOFT_RECONFIG
)) {
13798 json_object_string_add(
13800 "Inbound soft reconfiguration not enabled");
13801 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13802 json_object_free(json
);
13803 json_object_free(json_ar
);
13804 json_object_free(json_scode
);
13805 json_object_free(json_ocode
);
13808 "%% Inbound soft reconfiguration not enabled\n");
13810 return CMD_WARNING
;
13815 /* labeled-unicast routes live in the unicast table */
13816 if (safi
== SAFI_LABELED_UNICAST
)
13817 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
13819 table
= bgp
->rib
[afi
][safi
];
13821 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13822 || (safi
== SAFI_EVPN
)) {
13824 struct bgp_dest
*dest
;
13826 for (dest
= bgp_table_top(table
); dest
;
13827 dest
= bgp_route_next(dest
)) {
13828 table
= bgp_dest_get_bgp_table_info(dest
);
13832 output_count_per_rd
= 0;
13833 filtered_count_per_rd
= 0;
13836 json_routes
= json_object_new_object();
13838 const struct prefix_rd
*prd
;
13839 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13842 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
13844 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
13845 rmap_name
, json
, json_routes
, json_scode
,
13846 json_ocode
, show_flags
, &header1
,
13847 &header2
, rd_str
, &output_count_per_rd
,
13848 &filtered_count_per_rd
);
13850 /* Don't include an empty RD in the output! */
13851 if (json_routes
&& (output_count_per_rd
> 0))
13852 json_object_object_add(json_ar
, rd_str
,
13855 output_count
+= output_count_per_rd
;
13856 filtered_count
+= filtered_count_per_rd
;
13859 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
13860 json
, json_ar
, json_scode
, json_ocode
,
13861 show_flags
, &header1
, &header2
, rd_str
,
13862 &output_count
, &filtered_count
);
13865 if (type
== bgp_show_adj_route_advertised
)
13866 json_object_object_add(json
, "advertisedRoutes",
13869 json_object_object_add(json
, "receivedRoutes", json_ar
);
13870 json_object_int_add(json
, "totalPrefixCounter", output_count
);
13871 json_object_int_add(json
, "filteredPrefixCounter",
13875 * These fields only give up ownership to `json` when `header1`
13876 * is used (set to zero). See code in `show_adj_route` and
13877 * `show_adj_route_header`.
13879 if (header1
== 1) {
13880 json_object_free(json_scode
);
13881 json_object_free(json_ocode
);
13884 vty_json(vty
, json
);
13885 } else if (output_count
> 0) {
13886 if (filtered_count
> 0)
13888 "\nTotal number of prefixes %ld (%ld filtered)\n",
13889 output_count
, filtered_count
);
13891 vty_out(vty
, "\nTotal number of prefixes %ld\n",
13895 return CMD_SUCCESS
;
13898 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
13899 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
13900 "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]",
13904 BGP_INSTANCE_HELP_STR
13906 BGP_SAFI_WITH_LABEL_HELP_STR
13907 "Detailed information on TCP and BGP neighbor connections\n"
13908 "Neighbor to display information about\n"
13909 "Neighbor to display information about\n"
13910 "Neighbor on BGP configured interface\n"
13911 "Display the routes selected by best path\n"
13913 "Increase table width for longer prefixes\n")
13915 afi_t afi
= AFI_IP6
;
13916 safi_t safi
= SAFI_UNICAST
;
13917 char *rmap_name
= NULL
;
13918 char *peerstr
= NULL
;
13919 struct bgp
*bgp
= NULL
;
13921 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
13923 uint16_t show_flags
= 0;
13926 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13929 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13931 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13935 return CMD_WARNING
;
13937 argv_find(argv
, argc
, "neighbors", &idx
);
13938 peerstr
= argv
[++idx
]->arg
;
13940 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13942 return CMD_WARNING
;
13944 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13948 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
13949 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
13950 "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 WORD] [json$uj | wide$wide]",
13954 BGP_INSTANCE_HELP_STR
13956 BGP_SAFI_WITH_LABEL_HELP_STR
13957 "Display the entries for all address families\n"
13958 "Detailed information on TCP and BGP neighbor connections\n"
13959 "Neighbor to display information about\n"
13960 "Neighbor to display information about\n"
13961 "Neighbor on BGP configured interface\n"
13962 "Display the routes advertised to a BGP neighbor\n"
13963 "Display the received routes from neighbor\n"
13964 "Display the filtered routes received from neighbor\n"
13965 "Route-map to modify the attributes\n"
13966 "Name of the route map\n"
13968 "Increase table width for longer prefixes\n")
13970 afi_t afi
= AFI_IP6
;
13971 safi_t safi
= SAFI_UNICAST
;
13972 char *rmap_name
= NULL
;
13973 char *peerstr
= NULL
;
13974 struct bgp
*bgp
= NULL
;
13976 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
13979 uint16_t show_flags
= 0;
13983 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13987 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
13988 if (argv_find(argv
, argc
, "ipv4", &idx
))
13989 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
13991 if (argv_find(argv
, argc
, "ipv6", &idx
))
13992 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
13996 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13998 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14001 return CMD_WARNING
;
14003 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14004 argv_find(argv
, argc
, "neighbors", &idx
);
14005 peerstr
= argv
[++idx
]->arg
;
14007 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14009 return CMD_WARNING
;
14011 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14012 type
= bgp_show_adj_route_advertised
;
14013 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14014 type
= bgp_show_adj_route_received
;
14015 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14016 type
= bgp_show_adj_route_filtered
;
14018 if (argv_find(argv
, argc
, "route-map", &idx
))
14019 rmap_name
= argv
[++idx
]->arg
;
14022 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14025 vty_out(vty
, "{\n");
14027 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14028 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14029 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14031 FOREACH_SAFI (safi
) {
14032 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
14039 vty_out(vty
, ",\n");
14040 vty_out(vty
, "\"%s\":",
14041 get_afi_safi_str(afi
, safi
, true));
14043 vty_out(vty
, "\nFor address family: %s\n",
14044 get_afi_safi_str(afi
, safi
, false));
14046 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14050 FOREACH_AFI_SAFI (afi
, safi
) {
14051 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
14058 vty_out(vty
, ",\n");
14059 vty_out(vty
, "\"%s\":",
14060 get_afi_safi_str(afi
, safi
, true));
14062 vty_out(vty
, "\nFor address family: %s\n",
14063 get_afi_safi_str(afi
, safi
, false));
14065 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14070 vty_out(vty
, "}\n");
14072 return CMD_SUCCESS
;
14075 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14076 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14077 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14081 BGP_INSTANCE_HELP_STR
14084 "Address Family modifier\n"
14085 "Detailed information on TCP and BGP neighbor connections\n"
14086 "Neighbor to display information about\n"
14087 "Neighbor to display information about\n"
14088 "Neighbor on BGP configured interface\n"
14089 "Display information received from a BGP neighbor\n"
14090 "Display the prefixlist filter\n"
14093 afi_t afi
= AFI_IP6
;
14094 safi_t safi
= SAFI_UNICAST
;
14095 char *peerstr
= NULL
;
14100 struct bgp
*bgp
= NULL
;
14101 bool uj
= use_json(argc
, argv
);
14106 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14109 return CMD_WARNING
;
14111 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14112 argv_find(argv
, argc
, "neighbors", &idx
);
14113 peerstr
= argv
[++idx
]->arg
;
14115 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14117 return CMD_WARNING
;
14119 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14120 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14123 vty_out(vty
, "Address Family: %s\n",
14124 get_afi_safi_str(afi
, safi
, false));
14125 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14128 vty_out(vty
, "{}\n");
14130 vty_out(vty
, "No functional output\n");
14133 return CMD_SUCCESS
;
14136 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14137 afi_t afi
, safi_t safi
,
14138 enum bgp_show_type type
, bool use_json
)
14140 uint16_t show_flags
= 0;
14143 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14145 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14147 json_object
*json_no
= NULL
;
14148 json_no
= json_object_new_object();
14149 json_object_string_add(
14150 json_no
, "warning",
14151 "No such neighbor or address family");
14152 vty_out(vty
, "%s\n",
14153 json_object_to_json_string(json_no
));
14154 json_object_free(json_no
);
14156 vty_out(vty
, "%% No such neighbor or address family\n");
14157 return CMD_WARNING
;
14160 /* labeled-unicast routes live in the unicast table */
14161 if (safi
== SAFI_LABELED_UNICAST
)
14162 safi
= SAFI_UNICAST
;
14164 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14165 RPKI_NOT_BEING_USED
);
14168 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14169 show_ip_bgp_flowspec_routes_detailed_cmd
,
14170 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14174 BGP_INSTANCE_HELP_STR
14177 "Detailed information on flowspec entries\n"
14180 afi_t afi
= AFI_IP6
;
14181 safi_t safi
= SAFI_UNICAST
;
14182 struct bgp
*bgp
= NULL
;
14184 bool uj
= use_json(argc
, argv
);
14185 uint16_t show_flags
= BGP_SHOW_OPT_DETAIL
;
14189 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14192 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14195 return CMD_WARNING
;
14197 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14198 show_flags
, RPKI_NOT_BEING_USED
);
14201 DEFUN (show_ip_bgp_neighbor_routes
,
14202 show_ip_bgp_neighbor_routes_cmd
,
14203 "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]",
14207 BGP_INSTANCE_HELP_STR
14209 BGP_SAFI_WITH_LABEL_HELP_STR
14210 "Detailed information on TCP and BGP neighbor connections\n"
14211 "Neighbor to display information about\n"
14212 "Neighbor to display information about\n"
14213 "Neighbor on BGP configured interface\n"
14214 "Display flap statistics of the routes learned from neighbor\n"
14215 "Display the dampened routes received from neighbor\n"
14216 "Display routes learned from neighbor\n"
14219 char *peerstr
= NULL
;
14220 struct bgp
*bgp
= NULL
;
14221 afi_t afi
= AFI_IP6
;
14222 safi_t safi
= SAFI_UNICAST
;
14224 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14226 bool uj
= use_json(argc
, argv
);
14231 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14234 return CMD_WARNING
;
14236 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14237 argv_find(argv
, argc
, "neighbors", &idx
);
14238 peerstr
= argv
[++idx
]->arg
;
14240 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14242 return CMD_WARNING
;
14244 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14245 sh_type
= bgp_show_type_flap_neighbor
;
14246 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14247 sh_type
= bgp_show_type_damp_neighbor
;
14248 else if (argv_find(argv
, argc
, "routes", &idx
))
14249 sh_type
= bgp_show_type_neighbor
;
14251 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14254 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14256 struct bgp_distance
{
14257 /* Distance value for the IP source prefix. */
14260 /* Name of the access-list to be matched. */
14264 DEFUN (show_bgp_afi_vpn_rd_route
,
14265 show_bgp_afi_vpn_rd_route_cmd
,
14266 "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]",
14270 "Address Family modifier\n"
14271 "Display information for a route distinguisher\n"
14272 "Route Distinguisher\n"
14273 "All Route Distinguishers\n"
14274 "Network in the BGP routing table to display\n"
14275 "Network in the BGP routing table to display\n"
14279 struct prefix_rd prd
;
14280 afi_t afi
= AFI_MAX
;
14283 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14284 vty_out(vty
, "%% Malformed Address Family\n");
14285 return CMD_WARNING
;
14288 if (!strcmp(argv
[5]->arg
, "all"))
14289 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14290 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14291 RPKI_NOT_BEING_USED
,
14292 use_json(argc
, argv
));
14294 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14296 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14297 return CMD_WARNING
;
14300 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14301 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14302 use_json(argc
, argv
));
14305 static struct bgp_distance
*bgp_distance_new(void)
14307 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14310 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14312 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14315 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14316 const char *ip_str
, const char *access_list_str
)
14323 struct bgp_dest
*dest
;
14324 struct bgp_distance
*bdistance
;
14326 afi
= bgp_node_afi(vty
);
14327 safi
= bgp_node_safi(vty
);
14329 ret
= str2prefix(ip_str
, &p
);
14331 vty_out(vty
, "Malformed prefix\n");
14332 return CMD_WARNING_CONFIG_FAILED
;
14335 distance
= atoi(distance_str
);
14337 /* Get BGP distance node. */
14338 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14339 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14341 bgp_dest_unlock_node(dest
);
14343 bdistance
= bgp_distance_new();
14344 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14347 /* Set distance value. */
14348 bdistance
->distance
= distance
;
14350 /* Reset access-list configuration. */
14351 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14352 if (access_list_str
)
14353 bdistance
->access_list
=
14354 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14356 return CMD_SUCCESS
;
14359 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14360 const char *ip_str
, const char *access_list_str
)
14367 struct bgp_dest
*dest
;
14368 struct bgp_distance
*bdistance
;
14370 afi
= bgp_node_afi(vty
);
14371 safi
= bgp_node_safi(vty
);
14373 ret
= str2prefix(ip_str
, &p
);
14375 vty_out(vty
, "Malformed prefix\n");
14376 return CMD_WARNING_CONFIG_FAILED
;
14379 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14381 vty_out(vty
, "Can't find specified prefix\n");
14382 return CMD_WARNING_CONFIG_FAILED
;
14385 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14386 distance
= atoi(distance_str
);
14388 if (bdistance
->distance
!= distance
) {
14389 vty_out(vty
, "Distance does not match configured\n");
14390 bgp_dest_unlock_node(dest
);
14391 return CMD_WARNING_CONFIG_FAILED
;
14394 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14395 bgp_distance_free(bdistance
);
14397 bgp_dest_set_bgp_path_info(dest
, NULL
);
14398 bgp_dest_unlock_node(dest
);
14399 bgp_dest_unlock_node(dest
);
14401 return CMD_SUCCESS
;
14404 /* Apply BGP information to distance method. */
14405 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14406 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14408 struct bgp_dest
*dest
;
14409 struct prefix q
= {0};
14411 struct bgp_distance
*bdistance
;
14412 struct access_list
*alist
;
14413 struct bgp_static
*bgp_static
;
14418 peer
= pinfo
->peer
;
14420 if (pinfo
->attr
->distance
)
14421 return pinfo
->attr
->distance
;
14423 /* Check source address.
14424 * Note: for aggregate route, peer can have unspec af type.
14426 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14427 && !sockunion2hostprefix(&peer
->su
, &q
))
14430 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14432 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14433 bgp_dest_unlock_node(dest
);
14435 if (bdistance
->access_list
) {
14436 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14438 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14439 return bdistance
->distance
;
14441 return bdistance
->distance
;
14444 /* Backdoor check. */
14445 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14447 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14448 bgp_dest_unlock_node(dest
);
14450 if (bgp_static
->backdoor
) {
14451 if (bgp
->distance_local
[afi
][safi
])
14452 return bgp
->distance_local
[afi
][safi
];
14454 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14458 if (peer
->sort
== BGP_PEER_EBGP
) {
14459 if (bgp
->distance_ebgp
[afi
][safi
])
14460 return bgp
->distance_ebgp
[afi
][safi
];
14461 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14462 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14463 if (bgp
->distance_ibgp
[afi
][safi
])
14464 return bgp
->distance_ibgp
[afi
][safi
];
14465 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14467 if (bgp
->distance_local
[afi
][safi
])
14468 return bgp
->distance_local
[afi
][safi
];
14469 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14473 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14474 * we should tell ZEBRA update the routes for a specific
14475 * AFI/SAFI to reflect changes in RIB.
14477 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
14479 safi_t update_safi
)
14484 FOREACH_AFI_SAFI (afi
, safi
) {
14485 if (!bgp_fibupd_safi(safi
))
14488 if (afi
!= update_afi
&& safi
!= update_safi
)
14491 if (BGP_DEBUG(zebra
, ZEBRA
))
14493 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14494 __func__
, afi
, safi
);
14495 bgp_zebra_announce_table(bgp
, afi
, safi
);
14499 DEFUN (bgp_distance
,
14501 "distance bgp (1-255) (1-255) (1-255)",
14502 "Define an administrative distance\n"
14504 "Distance for routes external to the AS\n"
14505 "Distance for routes internal to the AS\n"
14506 "Distance for local routes\n")
14508 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14509 int idx_number
= 2;
14510 int idx_number_2
= 3;
14511 int idx_number_3
= 4;
14512 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
14513 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
14514 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
14518 afi
= bgp_node_afi(vty
);
14519 safi
= bgp_node_safi(vty
);
14521 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
14522 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
14523 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
14524 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
14525 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
14526 bgp
->distance_local
[afi
][safi
] = distance_local
;
14527 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14529 return CMD_SUCCESS
;
14532 DEFUN (no_bgp_distance
,
14533 no_bgp_distance_cmd
,
14534 "no distance bgp [(1-255) (1-255) (1-255)]",
14536 "Define an administrative distance\n"
14538 "Distance for routes external to the AS\n"
14539 "Distance for routes internal to the AS\n"
14540 "Distance for local routes\n")
14542 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14546 afi
= bgp_node_afi(vty
);
14547 safi
= bgp_node_safi(vty
);
14549 if (bgp
->distance_ebgp
[afi
][safi
] != 0
14550 || bgp
->distance_ibgp
[afi
][safi
] != 0
14551 || bgp
->distance_local
[afi
][safi
] != 0) {
14552 bgp
->distance_ebgp
[afi
][safi
] = 0;
14553 bgp
->distance_ibgp
[afi
][safi
] = 0;
14554 bgp
->distance_local
[afi
][safi
] = 0;
14555 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14557 return CMD_SUCCESS
;
14561 DEFUN (bgp_distance_source
,
14562 bgp_distance_source_cmd
,
14563 "distance (1-255) A.B.C.D/M",
14564 "Define an administrative distance\n"
14565 "Administrative distance\n"
14566 "IP source prefix\n")
14568 int idx_number
= 1;
14569 int idx_ipv4_prefixlen
= 2;
14570 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14571 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14572 return CMD_SUCCESS
;
14575 DEFUN (no_bgp_distance_source
,
14576 no_bgp_distance_source_cmd
,
14577 "no distance (1-255) A.B.C.D/M",
14579 "Define an administrative distance\n"
14580 "Administrative distance\n"
14581 "IP source prefix\n")
14583 int idx_number
= 2;
14584 int idx_ipv4_prefixlen
= 3;
14585 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14586 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14587 return CMD_SUCCESS
;
14590 DEFUN (bgp_distance_source_access_list
,
14591 bgp_distance_source_access_list_cmd
,
14592 "distance (1-255) A.B.C.D/M WORD",
14593 "Define an administrative distance\n"
14594 "Administrative distance\n"
14595 "IP source prefix\n"
14596 "Access list name\n")
14598 int idx_number
= 1;
14599 int idx_ipv4_prefixlen
= 2;
14601 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14602 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14603 return CMD_SUCCESS
;
14606 DEFUN (no_bgp_distance_source_access_list
,
14607 no_bgp_distance_source_access_list_cmd
,
14608 "no distance (1-255) A.B.C.D/M WORD",
14610 "Define an administrative distance\n"
14611 "Administrative distance\n"
14612 "IP source prefix\n"
14613 "Access list name\n")
14615 int idx_number
= 2;
14616 int idx_ipv4_prefixlen
= 3;
14618 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14619 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14620 return CMD_SUCCESS
;
14623 DEFUN (ipv6_bgp_distance_source
,
14624 ipv6_bgp_distance_source_cmd
,
14625 "distance (1-255) X:X::X:X/M",
14626 "Define an administrative distance\n"
14627 "Administrative distance\n"
14628 "IP source prefix\n")
14630 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
14631 return CMD_SUCCESS
;
14634 DEFUN (no_ipv6_bgp_distance_source
,
14635 no_ipv6_bgp_distance_source_cmd
,
14636 "no distance (1-255) X:X::X:X/M",
14638 "Define an administrative distance\n"
14639 "Administrative distance\n"
14640 "IP source prefix\n")
14642 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
14643 return CMD_SUCCESS
;
14646 DEFUN (ipv6_bgp_distance_source_access_list
,
14647 ipv6_bgp_distance_source_access_list_cmd
,
14648 "distance (1-255) X:X::X:X/M WORD",
14649 "Define an administrative distance\n"
14650 "Administrative distance\n"
14651 "IP source prefix\n"
14652 "Access list name\n")
14654 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
14655 return CMD_SUCCESS
;
14658 DEFUN (no_ipv6_bgp_distance_source_access_list
,
14659 no_ipv6_bgp_distance_source_access_list_cmd
,
14660 "no distance (1-255) X:X::X:X/M WORD",
14662 "Define an administrative distance\n"
14663 "Administrative distance\n"
14664 "IP source prefix\n"
14665 "Access list name\n")
14667 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
14668 return CMD_SUCCESS
;
14671 DEFUN (bgp_damp_set
,
14673 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
14674 "BGP Specific commands\n"
14675 "Enable route-flap dampening\n"
14676 "Half-life time for the penalty\n"
14677 "Value to start reusing a route\n"
14678 "Value to start suppressing a route\n"
14679 "Maximum duration to suppress a stable route\n")
14681 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14682 int idx_half_life
= 2;
14684 int idx_suppress
= 4;
14685 int idx_max_suppress
= 5;
14686 int half
= DEFAULT_HALF_LIFE
* 60;
14687 int reuse
= DEFAULT_REUSE
;
14688 int suppress
= DEFAULT_SUPPRESS
;
14689 int max
= 4 * half
;
14692 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14693 reuse
= atoi(argv
[idx_reuse
]->arg
);
14694 suppress
= atoi(argv
[idx_suppress
]->arg
);
14695 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
14696 } else if (argc
== 3) {
14697 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14702 * These can't be 0 but our SA doesn't understand the
14703 * way our cli is constructed
14707 if (suppress
< reuse
) {
14709 "Suppress value cannot be less than reuse value \n");
14713 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
14714 reuse
, suppress
, max
);
14717 DEFUN (bgp_damp_unset
,
14718 bgp_damp_unset_cmd
,
14719 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
14721 "BGP Specific commands\n"
14722 "Enable route-flap dampening\n"
14723 "Half-life time for the penalty\n"
14724 "Value to start reusing a route\n"
14725 "Value to start suppressing a route\n"
14726 "Maximum duration to suppress a stable route\n")
14728 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14729 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
14732 /* Display specified route of BGP table. */
14733 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14734 const char *ip_str
, afi_t afi
, safi_t safi
,
14735 struct prefix_rd
*prd
, int prefix_check
)
14738 struct prefix match
;
14739 struct bgp_dest
*dest
;
14740 struct bgp_dest
*rm
;
14741 struct bgp_path_info
*pi
;
14742 struct bgp_path_info
*pi_temp
;
14744 struct bgp_table
*table
;
14746 /* BGP structure lookup. */
14748 bgp
= bgp_lookup_by_name(view_name
);
14750 vty_out(vty
, "%% Can't find BGP instance %s\n",
14752 return CMD_WARNING
;
14755 bgp
= bgp_get_default();
14757 vty_out(vty
, "%% No BGP process is configured\n");
14758 return CMD_WARNING
;
14762 /* Check IP address argument. */
14763 ret
= str2prefix(ip_str
, &match
);
14765 vty_out(vty
, "%% address is malformed\n");
14766 return CMD_WARNING
;
14769 match
.family
= afi2family(afi
);
14771 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14772 || (safi
== SAFI_EVPN
)) {
14773 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
14774 dest
= bgp_route_next(dest
)) {
14775 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14777 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
14779 table
= bgp_dest_get_bgp_table_info(dest
);
14782 rm
= bgp_node_match(table
, &match
);
14786 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
14789 || rm_p
->prefixlen
== match
.prefixlen
) {
14790 pi
= bgp_dest_get_bgp_path_info(rm
);
14792 if (pi
->extra
&& pi
->extra
->damp_info
) {
14793 pi_temp
= pi
->next
;
14794 bgp_damp_info_free(
14795 pi
->extra
->damp_info
,
14803 bgp_dest_unlock_node(rm
);
14806 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
14807 if (dest
!= NULL
) {
14808 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14811 || dest_p
->prefixlen
== match
.prefixlen
) {
14812 pi
= bgp_dest_get_bgp_path_info(dest
);
14814 if (pi
->extra
&& pi
->extra
->damp_info
) {
14815 pi_temp
= pi
->next
;
14816 bgp_damp_info_free(
14817 pi
->extra
->damp_info
,
14825 bgp_dest_unlock_node(dest
);
14829 return CMD_SUCCESS
;
14832 DEFUN (clear_ip_bgp_dampening
,
14833 clear_ip_bgp_dampening_cmd
,
14834 "clear ip bgp dampening",
14838 "Clear route flap dampening information\n")
14840 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
14841 return CMD_SUCCESS
;
14844 DEFUN (clear_ip_bgp_dampening_prefix
,
14845 clear_ip_bgp_dampening_prefix_cmd
,
14846 "clear ip bgp dampening A.B.C.D/M",
14850 "Clear route flap dampening information\n"
14853 int idx_ipv4_prefixlen
= 4;
14854 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
14855 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
14858 DEFUN (clear_ip_bgp_dampening_address
,
14859 clear_ip_bgp_dampening_address_cmd
,
14860 "clear ip bgp dampening A.B.C.D",
14864 "Clear route flap dampening information\n"
14865 "Network to clear damping information\n")
14868 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
14869 SAFI_UNICAST
, NULL
, 0);
14872 DEFUN (clear_ip_bgp_dampening_address_mask
,
14873 clear_ip_bgp_dampening_address_mask_cmd
,
14874 "clear ip bgp dampening A.B.C.D A.B.C.D",
14878 "Clear route flap dampening information\n"
14879 "Network to clear damping information\n"
14883 int idx_ipv4_2
= 5;
14885 char prefix_str
[BUFSIZ
];
14887 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
14888 prefix_str
, sizeof(prefix_str
));
14890 vty_out(vty
, "%% Inconsistent address and mask\n");
14891 return CMD_WARNING
;
14894 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
14898 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
14900 struct vty
*vty
= arg
;
14901 struct peer
*peer
= bucket
->data
;
14902 char buf
[SU_ADDRSTRLEN
];
14904 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
14905 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
14908 DEFUN (show_bgp_listeners
,
14909 show_bgp_listeners_cmd
,
14910 "show bgp listeners",
14913 "Display Listen Sockets and who created them\n")
14915 bgp_dump_listener_info(vty
);
14917 return CMD_SUCCESS
;
14920 DEFUN (show_bgp_peerhash
,
14921 show_bgp_peerhash_cmd
,
14922 "show bgp peerhash",
14925 "Display information about the BGP peerhash\n")
14927 struct list
*instances
= bm
->bgp
;
14928 struct listnode
*node
;
14931 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
14932 vty_out(vty
, "BGP: %s\n", bgp
->name
);
14933 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
14937 return CMD_SUCCESS
;
14940 /* also used for encap safi */
14941 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
14942 afi_t afi
, safi_t safi
)
14944 struct bgp_dest
*pdest
;
14945 struct bgp_dest
*dest
;
14946 struct bgp_table
*table
;
14947 const struct prefix
*p
;
14948 const struct prefix_rd
*prd
;
14949 struct bgp_static
*bgp_static
;
14950 mpls_label_t label
;
14951 char rdbuf
[RD_ADDRSTRLEN
];
14953 /* Network configuration. */
14954 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14955 pdest
= bgp_route_next(pdest
)) {
14956 table
= bgp_dest_get_bgp_table_info(pdest
);
14960 for (dest
= bgp_table_top(table
); dest
;
14961 dest
= bgp_route_next(dest
)) {
14962 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14963 if (bgp_static
== NULL
)
14966 p
= bgp_dest_get_prefix(dest
);
14967 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14970 /* "network" configuration display. */
14971 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14972 label
= decode_label(&bgp_static
->label
);
14974 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
14975 if (safi
== SAFI_MPLS_VPN
)
14976 vty_out(vty
, " label %u", label
);
14978 if (bgp_static
->rmap
.name
)
14979 vty_out(vty
, " route-map %s",
14980 bgp_static
->rmap
.name
);
14982 if (bgp_static
->backdoor
)
14983 vty_out(vty
, " backdoor");
14985 vty_out(vty
, "\n");
14990 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
14991 afi_t afi
, safi_t safi
)
14993 struct bgp_dest
*pdest
;
14994 struct bgp_dest
*dest
;
14995 struct bgp_table
*table
;
14996 const struct prefix
*p
;
14997 const struct prefix_rd
*prd
;
14998 struct bgp_static
*bgp_static
;
14999 char buf
[PREFIX_STRLEN
* 2];
15000 char buf2
[SU_ADDRSTRLEN
];
15001 char rdbuf
[RD_ADDRSTRLEN
];
15002 char esi_buf
[ESI_BYTES
];
15004 /* Network configuration. */
15005 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15006 pdest
= bgp_route_next(pdest
)) {
15007 table
= bgp_dest_get_bgp_table_info(pdest
);
15011 for (dest
= bgp_table_top(table
); dest
;
15012 dest
= bgp_route_next(dest
)) {
15013 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15014 if (bgp_static
== NULL
)
15017 char *macrouter
= NULL
;
15019 if (bgp_static
->router_mac
)
15020 macrouter
= prefix_mac2str(
15021 bgp_static
->router_mac
, NULL
, 0);
15022 if (bgp_static
->eth_s_id
)
15023 esi_to_str(bgp_static
->eth_s_id
,
15024 esi_buf
, sizeof(esi_buf
));
15025 p
= bgp_dest_get_prefix(dest
);
15026 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15028 /* "network" configuration display. */
15029 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
15030 if (p
->u
.prefix_evpn
.route_type
== 5) {
15031 char local_buf
[PREFIX_STRLEN
];
15032 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15033 struct prefix_evpn
*)p
)
15037 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
15038 local_buf
, PREFIX_STRLEN
);
15039 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15040 p
->u
.prefix_evpn
.prefix_addr
15041 .ip_prefix_length
);
15043 prefix2str(p
, buf
, sizeof(buf
));
15046 if (bgp_static
->gatewayIp
.family
== AF_INET
15047 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15048 inet_ntop(bgp_static
->gatewayIp
.family
,
15049 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15052 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15054 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15055 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15058 XFREE(MTYPE_TMP
, macrouter
);
15063 /* Configuration of static route announcement and aggregate
15065 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15068 struct bgp_dest
*dest
;
15069 const struct prefix
*p
;
15070 struct bgp_static
*bgp_static
;
15071 struct bgp_aggregate
*bgp_aggregate
;
15073 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15074 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15078 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15079 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15083 /* Network configuration. */
15084 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15085 dest
= bgp_route_next(dest
)) {
15086 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15087 if (bgp_static
== NULL
)
15090 p
= bgp_dest_get_prefix(dest
);
15092 vty_out(vty
, " network %pFX", p
);
15094 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15095 vty_out(vty
, " label-index %u",
15096 bgp_static
->label_index
);
15098 if (bgp_static
->rmap
.name
)
15099 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15101 if (bgp_static
->backdoor
)
15102 vty_out(vty
, " backdoor");
15104 vty_out(vty
, "\n");
15107 /* Aggregate-address configuration. */
15108 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15109 dest
= bgp_route_next(dest
)) {
15110 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15111 if (bgp_aggregate
== NULL
)
15114 p
= bgp_dest_get_prefix(dest
);
15116 vty_out(vty
, " aggregate-address %pFX", p
);
15118 if (bgp_aggregate
->as_set
)
15119 vty_out(vty
, " as-set");
15121 if (bgp_aggregate
->summary_only
)
15122 vty_out(vty
, " summary-only");
15124 if (bgp_aggregate
->rmap
.name
)
15125 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15127 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15128 vty_out(vty
, " origin %s",
15129 bgp_origin2str(bgp_aggregate
->origin
));
15131 if (bgp_aggregate
->match_med
)
15132 vty_out(vty
, " matching-MED-only");
15134 if (bgp_aggregate
->suppress_map_name
)
15135 vty_out(vty
, " suppress-map %s",
15136 bgp_aggregate
->suppress_map_name
);
15138 vty_out(vty
, "\n");
15142 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15145 struct bgp_dest
*dest
;
15146 struct bgp_distance
*bdistance
;
15148 /* Distance configuration. */
15149 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15150 && bgp
->distance_local
[afi
][safi
]
15151 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15152 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15153 || bgp
->distance_local
[afi
][safi
]
15154 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15155 vty_out(vty
, " distance bgp %d %d %d\n",
15156 bgp
->distance_ebgp
[afi
][safi
],
15157 bgp
->distance_ibgp
[afi
][safi
],
15158 bgp
->distance_local
[afi
][safi
]);
15161 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15162 dest
= bgp_route_next(dest
)) {
15163 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15164 if (bdistance
!= NULL
)
15165 vty_out(vty
, " distance %d %pBD %s\n",
15166 bdistance
->distance
, dest
,
15167 bdistance
->access_list
? bdistance
->access_list
15172 /* Allocate routing table structure and install commands. */
15173 void bgp_route_init(void)
15178 /* Init BGP distance table. */
15179 FOREACH_AFI_SAFI (afi
, safi
)
15180 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15182 /* IPv4 BGP commands. */
15183 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15184 install_element(BGP_NODE
, &bgp_network_cmd
);
15185 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15187 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15189 /* IPv4 unicast configuration. */
15190 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15191 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15192 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15194 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15196 /* IPv4 multicast configuration. */
15197 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15198 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15199 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15200 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15202 /* IPv4 labeled-unicast configuration. */
15203 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15204 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15206 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15207 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15208 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15209 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15210 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15211 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15212 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15213 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15215 install_element(VIEW_NODE
,
15216 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15217 install_element(VIEW_NODE
,
15218 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15219 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15220 install_element(VIEW_NODE
,
15221 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15222 #ifdef KEEP_OLD_VPN_COMMANDS
15223 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15224 #endif /* KEEP_OLD_VPN_COMMANDS */
15225 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15226 install_element(VIEW_NODE
,
15227 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15229 /* BGP dampening clear commands */
15230 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15231 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15233 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15234 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15237 install_element(ENABLE_NODE
,
15238 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15239 #ifdef KEEP_OLD_VPN_COMMANDS
15240 install_element(ENABLE_NODE
,
15241 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15242 #endif /* KEEP_OLD_VPN_COMMANDS */
15244 /* New config IPv6 BGP commands. */
15245 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15246 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15247 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15249 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15251 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15253 /* IPv6 labeled unicast address family. */
15254 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15255 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15257 install_element(BGP_NODE
, &bgp_distance_cmd
);
15258 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15259 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15260 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15261 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15262 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15263 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15264 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15265 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15266 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15267 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15268 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15269 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15270 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15271 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15272 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15273 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15274 install_element(BGP_IPV4M_NODE
,
15275 &no_bgp_distance_source_access_list_cmd
);
15276 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15277 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15278 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15279 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15280 install_element(BGP_IPV6_NODE
,
15281 &ipv6_bgp_distance_source_access_list_cmd
);
15282 install_element(BGP_IPV6_NODE
,
15283 &no_ipv6_bgp_distance_source_access_list_cmd
);
15284 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15285 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15286 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15287 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15288 install_element(BGP_IPV6M_NODE
,
15289 &ipv6_bgp_distance_source_access_list_cmd
);
15290 install_element(BGP_IPV6M_NODE
,
15291 &no_ipv6_bgp_distance_source_access_list_cmd
);
15293 /* BGP dampening */
15294 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15295 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15296 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15297 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15298 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15299 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15300 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15301 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15302 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15303 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15304 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15305 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15306 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15307 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15309 /* Large Communities */
15310 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15311 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15313 /* show bgp ipv4 flowspec detailed */
15314 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15316 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15317 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15320 void bgp_route_finish(void)
15325 FOREACH_AFI_SAFI (afi
, safi
) {
15326 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15327 bgp_distance_table
[afi
][safi
] = NULL
;