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");
9535 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9537 ipaddr2str(&eo
->gw_ip
, buf
, BUFSIZ
);
9540 vty_out(vty
, "/%s", buf
);
9542 json_object_string_add(json_overlay
, "gw", buf
);
9544 if (bgp_attr_get_ecommunity(attr
)) {
9546 struct ecommunity_val
*routermac
= ecommunity_lookup(
9547 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9548 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9551 mac
= ecom_mac2str((char *)routermac
->val
);
9554 vty_out(vty
, "/%s", mac
);
9556 json_object_string_add(json_overlay
, "rmac",
9559 XFREE(MTYPE_TMP
, mac
);
9566 json_object_object_add(json_path
, "overlay", json_overlay
);
9568 json_object_array_add(json_paths
, json_path
);
9572 /* dampening route */
9573 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9574 struct bgp_path_info
*path
, int display
,
9575 afi_t afi
, safi_t safi
, bool use_json
,
9576 json_object
*json_paths
)
9578 struct attr
*attr
= path
->attr
;
9580 char timebuf
[BGP_UPTIME_LEN
];
9581 json_object
*json_path
= NULL
;
9584 json_path
= json_object_new_object();
9586 /* short status lead text */
9587 route_vty_short_status_out(vty
, path
, p
, json_path
);
9589 /* print prefix and mask */
9592 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9594 vty_out(vty
, "%*s", 17, " ");
9596 len
= vty_out(vty
, "%s", path
->peer
->host
);
9600 vty_out(vty
, "\n%*s", 34, " ");
9602 vty_out(vty
, "%*s", len
, " ");
9605 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9606 BGP_UPTIME_LEN
, afi
, safi
,
9610 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9612 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9616 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9617 safi
, use_json
, json_path
);
9620 json_object_string_add(json_path
, "asPath",
9623 json_object_string_add(json_path
, "origin",
9624 bgp_origin_str
[attr
->origin
]);
9625 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9627 json_object_array_add(json_paths
, json_path
);
9632 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9633 struct bgp_path_info
*path
, int display
,
9634 afi_t afi
, safi_t safi
, bool use_json
,
9635 json_object
*json_paths
)
9637 struct attr
*attr
= path
->attr
;
9638 struct bgp_damp_info
*bdi
;
9639 char timebuf
[BGP_UPTIME_LEN
];
9641 json_object
*json_path
= NULL
;
9647 json_path
= json_object_new_object();
9649 bdi
= path
->extra
->damp_info
;
9651 /* short status lead text */
9652 route_vty_short_status_out(vty
, path
, p
, json_path
);
9656 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9658 vty_out(vty
, "%*s", 17, " ");
9660 len
= vty_out(vty
, "%s", path
->peer
->host
);
9663 vty_out(vty
, "\n%*s", 33, " ");
9665 vty_out(vty
, "%*s", len
, " ");
9667 len
= vty_out(vty
, "%d", bdi
->flap
);
9672 vty_out(vty
, "%*s", len
, " ");
9674 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9675 BGP_UPTIME_LEN
, 0, NULL
));
9677 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9678 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9680 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9681 BGP_UPTIME_LEN
, afi
,
9682 safi
, use_json
, NULL
));
9684 vty_out(vty
, "%*s ", 8, " ");
9687 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9689 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9693 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9694 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
9696 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9699 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9700 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9701 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9702 BGP_UPTIME_LEN
, afi
, safi
,
9703 use_json
, json_path
);
9706 json_object_string_add(json_path
, "asPath",
9709 json_object_string_add(json_path
, "origin",
9710 bgp_origin_str
[attr
->origin
]);
9712 json_object_array_add(json_paths
, json_path
);
9716 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9717 int *first
, const char *header
,
9718 json_object
*json_adv_to
)
9720 char buf1
[INET6_ADDRSTRLEN
];
9721 json_object
*json_peer
= NULL
;
9724 /* 'advertised-to' is a dictionary of peers we have advertised
9726 * prefix too. The key is the peer's IP or swpX, the value is
9728 * hostname if we know it and "" if not.
9730 json_peer
= json_object_new_object();
9733 json_object_string_add(json_peer
, "hostname",
9737 json_object_object_add(json_adv_to
, peer
->conf_if
,
9740 json_object_object_add(
9742 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
9746 vty_out(vty
, "%s", header
);
9751 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9753 vty_out(vty
, " %s(%s)", peer
->hostname
,
9756 vty_out(vty
, " %s(%s)", peer
->hostname
,
9757 sockunion2str(&peer
->su
, buf1
,
9761 vty_out(vty
, " %s", peer
->conf_if
);
9764 sockunion2str(&peer
->su
, buf1
,
9770 static void route_vty_out_tx_ids(struct vty
*vty
,
9771 struct bgp_addpath_info_data
*d
)
9775 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9776 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9777 d
->addpath_tx_id
[i
],
9778 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9782 static void route_vty_out_detail_es_info(struct vty
*vty
,
9783 struct bgp_path_info
*pi
,
9785 json_object
*json_path
)
9787 char esi_buf
[ESI_STR_LEN
];
9788 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9789 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9790 ATTR_ES_PEER_ROUTER
);
9791 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9792 ATTR_ES_PEER_ACTIVE
);
9793 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9794 ATTR_ES_PEER_PROXY
);
9795 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9797 json_object
*json_es_info
= NULL
;
9799 json_object_string_add(
9802 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9803 json_es_info
= json_object_new_object();
9805 json_object_boolean_true_add(
9806 json_es_info
, "localEs");
9808 json_object_boolean_true_add(
9809 json_es_info
, "peerActive");
9811 json_object_boolean_true_add(
9812 json_es_info
, "peerProxy");
9814 json_object_boolean_true_add(
9815 json_es_info
, "peerRouter");
9816 if (attr
->mm_sync_seqnum
)
9817 json_object_int_add(
9818 json_es_info
, "peerSeq",
9819 attr
->mm_sync_seqnum
);
9820 json_object_object_add(
9821 json_path
, "es_info",
9825 if (bgp_evpn_attr_is_sync(attr
))
9827 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9829 es_local
? "local-es":"",
9830 peer_proxy
? "proxy " : "",
9831 peer_active
? "active ":"",
9832 peer_router
? "router ":"",
9833 attr
->mm_sync_seqnum
);
9835 vty_out(vty
, " ESI %s %s\n",
9837 es_local
? "local-es":"");
9841 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
9842 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
9843 enum rpki_states rpki_curr_state
,
9844 json_object
*json_paths
)
9846 char buf
[INET6_ADDRSTRLEN
];
9848 struct attr
*attr
= path
->attr
;
9849 int sockunion_vty_out(struct vty
*, union sockunion
*);
9851 json_object
*json_bestpath
= NULL
;
9852 json_object
*json_cluster_list
= NULL
;
9853 json_object
*json_cluster_list_list
= NULL
;
9854 json_object
*json_ext_community
= NULL
;
9855 json_object
*json_last_update
= NULL
;
9856 json_object
*json_pmsi
= NULL
;
9857 json_object
*json_nexthop_global
= NULL
;
9858 json_object
*json_nexthop_ll
= NULL
;
9859 json_object
*json_nexthops
= NULL
;
9860 json_object
*json_path
= NULL
;
9861 json_object
*json_peer
= NULL
;
9862 json_object
*json_string
= NULL
;
9863 json_object
*json_adv_to
= NULL
;
9865 struct listnode
*node
, *nnode
;
9867 bool addpath_capable
;
9869 unsigned int first_as
;
9871 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9873 char *nexthop_hostname
=
9874 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9877 json_path
= json_object_new_object();
9878 json_peer
= json_object_new_object();
9879 json_nexthop_global
= json_object_new_object();
9882 if (safi
== SAFI_EVPN
) {
9884 vty_out(vty
, " Route %pRN", bn
);
9891 if (path
->extra
&& path
->extra
->num_labels
) {
9892 bgp_evpn_label2str(path
->extra
->label
,
9893 path
->extra
->num_labels
, tag_buf
,
9896 if (safi
== SAFI_EVPN
) {
9898 if (tag_buf
[0] != '\0')
9899 vty_out(vty
, " VNI %s", tag_buf
);
9902 json_object_string_add(json_path
, "VNI",
9907 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9908 struct bgp_path_info
*parent_ri
;
9909 struct bgp_dest
*dest
, *pdest
;
9911 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9912 dest
= parent_ri
->net
;
9913 if (dest
&& dest
->pdest
) {
9914 pdest
= dest
->pdest
;
9916 (struct prefix_rd
*)bgp_dest_get_prefix(
9918 buf1
, sizeof(buf1
));
9919 if (is_pi_family_evpn(parent_ri
)) {
9921 " Imported from %s:%pFX, VNI %s",
9923 (struct prefix_evpn
*)
9924 bgp_dest_get_prefix(
9927 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
9928 vty_out(vty
, ", L3NHG %s",
9930 & ATTR_ES_L3_NHG_ACTIVE
)
9937 " Imported from %s:%pFX\n",
9939 (struct prefix_evpn
*)
9940 bgp_dest_get_prefix(
9946 if (safi
== SAFI_EVPN
9947 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
9948 char gwip_buf
[INET6_ADDRSTRLEN
];
9950 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
9954 json_object_string_add(json_path
, "gatewayIP",
9957 vty_out(vty
, " Gateway IP %s", gwip_buf
);
9960 if (safi
== SAFI_EVPN
)
9963 /* Line1 display AS-path, Aggregator */
9966 if (!attr
->aspath
->json
)
9967 aspath_str_update(attr
->aspath
, true);
9968 json_object_lock(attr
->aspath
->json
);
9969 json_object_object_add(json_path
, "aspath",
9970 attr
->aspath
->json
);
9972 if (attr
->aspath
->segments
)
9973 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9975 vty_out(vty
, " Local");
9979 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9981 json_object_boolean_true_add(json_path
, "removed");
9983 vty_out(vty
, ", (removed)");
9986 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9988 json_object_boolean_true_add(json_path
, "stale");
9990 vty_out(vty
, ", (stale)");
9993 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
9995 json_object_int_add(json_path
, "aggregatorAs",
9996 attr
->aggregator_as
);
9997 json_object_string_addf(json_path
, "aggregatorId",
9998 "%pI4", &attr
->aggregator_addr
);
10000 vty_out(vty
, ", (aggregated by %u %pI4)",
10001 attr
->aggregator_as
, &attr
->aggregator_addr
);
10005 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10006 PEER_FLAG_REFLECTOR_CLIENT
)) {
10008 json_object_boolean_true_add(json_path
,
10009 "rxedFromRrClient");
10011 vty_out(vty
, ", (Received from a RR-client)");
10014 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10015 PEER_FLAG_RSERVER_CLIENT
)) {
10017 json_object_boolean_true_add(json_path
,
10018 "rxedFromRsClient");
10020 vty_out(vty
, ", (Received from a RS-client)");
10023 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10025 json_object_boolean_true_add(json_path
,
10026 "dampeningHistoryEntry");
10028 vty_out(vty
, ", (history entry)");
10029 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10031 json_object_boolean_true_add(json_path
,
10032 "dampeningSuppressed");
10034 vty_out(vty
, ", (suppressed due to dampening)");
10038 vty_out(vty
, "\n");
10040 /* Line2 display Next-hop, Neighbor, Router-id */
10041 /* Display the nexthop */
10042 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
10044 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
10045 || bn_p
->family
== AF_EVPN
)
10046 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
10047 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
10048 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10049 || safi
== SAFI_EVPN
) {
10051 json_object_string_addf(
10052 json_nexthop_global
, "ip", "%pI4",
10053 &attr
->mp_nexthop_global_in
);
10055 if (path
->peer
->hostname
)
10056 json_object_string_add(
10057 json_nexthop_global
, "hostname",
10058 path
->peer
->hostname
);
10060 if (nexthop_hostname
)
10061 vty_out(vty
, " %pI4(%s)",
10062 &attr
->mp_nexthop_global_in
,
10065 vty_out(vty
, " %pI4",
10066 &attr
->mp_nexthop_global_in
);
10070 json_object_string_addf(json_nexthop_global
,
10074 if (path
->peer
->hostname
)
10075 json_object_string_add(
10076 json_nexthop_global
, "hostname",
10077 path
->peer
->hostname
);
10079 if (nexthop_hostname
)
10080 vty_out(vty
, " %pI4(%s)",
10084 vty_out(vty
, " %pI4",
10090 json_object_string_add(json_nexthop_global
, "afi",
10094 json_object_string_addf(json_nexthop_global
, "ip",
10096 &attr
->mp_nexthop_global
);
10098 if (path
->peer
->hostname
)
10099 json_object_string_add(json_nexthop_global
,
10101 path
->peer
->hostname
);
10103 json_object_string_add(json_nexthop_global
, "afi",
10105 json_object_string_add(json_nexthop_global
, "scope",
10108 if (nexthop_hostname
)
10109 vty_out(vty
, " %pI6(%s)",
10110 &attr
->mp_nexthop_global
,
10113 vty_out(vty
, " %pI6",
10114 &attr
->mp_nexthop_global
);
10118 /* Display the IGP cost or 'inaccessible' */
10119 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10121 json_object_boolean_false_add(json_nexthop_global
,
10124 vty_out(vty
, " (inaccessible)");
10126 if (path
->extra
&& path
->extra
->igpmetric
) {
10128 json_object_int_add(json_nexthop_global
,
10130 path
->extra
->igpmetric
);
10132 vty_out(vty
, " (metric %u)",
10133 path
->extra
->igpmetric
);
10136 /* IGP cost is 0, display this only for json */
10139 json_object_int_add(json_nexthop_global
,
10144 json_object_boolean_true_add(json_nexthop_global
,
10148 /* Display peer "from" output */
10149 /* This path was originated locally */
10150 if (path
->peer
== bgp
->peer_self
) {
10152 if (safi
== SAFI_EVPN
10153 || (bn_p
->family
== AF_INET
10154 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
10156 json_object_string_add(json_peer
, "peerId",
10159 vty_out(vty
, " from 0.0.0.0 ");
10162 json_object_string_add(json_peer
, "peerId",
10165 vty_out(vty
, " from :: ");
10169 json_object_string_addf(json_peer
, "routerId", "%pI4",
10172 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10175 /* We RXed this path from one of our peers */
10179 json_object_string_add(json_peer
, "peerId",
10180 sockunion2str(&path
->peer
->su
,
10183 json_object_string_addf(json_peer
, "routerId", "%pI4",
10184 &path
->peer
->remote_id
);
10186 if (path
->peer
->hostname
)
10187 json_object_string_add(json_peer
, "hostname",
10188 path
->peer
->hostname
);
10190 if (path
->peer
->domainname
)
10191 json_object_string_add(json_peer
, "domainname",
10192 path
->peer
->domainname
);
10194 if (path
->peer
->conf_if
)
10195 json_object_string_add(json_peer
, "interface",
10196 path
->peer
->conf_if
);
10198 if (path
->peer
->conf_if
) {
10199 if (path
->peer
->hostname
10200 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10201 BGP_FLAG_SHOW_HOSTNAME
))
10202 vty_out(vty
, " from %s(%s)",
10203 path
->peer
->hostname
,
10204 path
->peer
->conf_if
);
10206 vty_out(vty
, " from %s",
10207 path
->peer
->conf_if
);
10209 if (path
->peer
->hostname
10210 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10211 BGP_FLAG_SHOW_HOSTNAME
))
10212 vty_out(vty
, " from %s(%s)",
10213 path
->peer
->hostname
,
10216 vty_out(vty
, " from %s",
10217 sockunion2str(&path
->peer
->su
,
10222 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10223 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10225 vty_out(vty
, " (%s)",
10227 &path
->peer
->remote_id
, buf1
,
10233 * Note when vrfid of nexthop is different from that of prefix
10235 if (path
->extra
&& path
->extra
->bgp_orig
) {
10236 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10241 if (path
->extra
->bgp_orig
->inst_type
10242 == BGP_INSTANCE_TYPE_DEFAULT
)
10243 vn
= VRF_DEFAULT_NAME
;
10245 vn
= path
->extra
->bgp_orig
->name
;
10247 json_object_string_add(json_path
, "nhVrfName", vn
);
10249 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10250 json_object_int_add(json_path
, "nhVrfId", -1);
10252 json_object_int_add(json_path
, "nhVrfId",
10253 (int)nexthop_vrfid
);
10256 if (nexthop_vrfid
== VRF_UNKNOWN
)
10257 vty_out(vty
, " vrf ?");
10261 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10262 vty_out(vty
, " vrf %s(%u)",
10263 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10268 if (nexthop_self
) {
10270 json_object_boolean_true_add(json_path
,
10271 "announceNexthopSelf");
10273 vty_out(vty
, " announce-nh-self");
10278 vty_out(vty
, "\n");
10280 /* display the link-local nexthop */
10281 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10283 json_nexthop_ll
= json_object_new_object();
10284 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10285 &attr
->mp_nexthop_local
);
10287 if (path
->peer
->hostname
)
10288 json_object_string_add(json_nexthop_ll
,
10290 path
->peer
->hostname
);
10292 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10293 json_object_string_add(json_nexthop_ll
, "scope",
10296 json_object_boolean_true_add(json_nexthop_ll
,
10299 if (!attr
->mp_nexthop_prefer_global
)
10300 json_object_boolean_true_add(json_nexthop_ll
,
10303 json_object_boolean_true_add(
10304 json_nexthop_global
, "used");
10306 vty_out(vty
, " (%s) %s\n",
10307 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10308 buf
, INET6_ADDRSTRLEN
),
10309 attr
->mp_nexthop_prefer_global
10310 ? "(prefer-global)"
10314 /* If we do not have a link-local nexthop then we must flag the
10315 global as "used" */
10318 json_object_boolean_true_add(json_nexthop_global
,
10322 if (safi
== SAFI_EVPN
&&
10323 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10324 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10327 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10328 * Int/Ext/Local, Atomic, best */
10330 json_object_string_add(json_path
, "origin",
10331 bgp_origin_long_str
[attr
->origin
]);
10333 vty_out(vty
, " Origin %s",
10334 bgp_origin_long_str
[attr
->origin
]);
10336 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10338 json_object_int_add(json_path
, "metric", attr
->med
);
10340 vty_out(vty
, ", metric %u", attr
->med
);
10343 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10345 json_object_int_add(json_path
, "locPrf",
10348 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10351 if (attr
->weight
!= 0) {
10353 json_object_int_add(json_path
, "weight", attr
->weight
);
10355 vty_out(vty
, ", weight %u", attr
->weight
);
10358 if (attr
->tag
!= 0) {
10360 json_object_int_add(json_path
, "tag", attr
->tag
);
10362 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10365 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10367 json_object_boolean_false_add(json_path
, "valid");
10369 vty_out(vty
, ", invalid");
10370 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10372 json_object_boolean_true_add(json_path
, "valid");
10374 vty_out(vty
, ", valid");
10378 json_object_int_add(json_path
, "version", bn
->version
);
10380 if (path
->peer
!= bgp
->peer_self
) {
10381 if (path
->peer
->as
== path
->peer
->local_as
) {
10382 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10384 json_object_string_add(
10386 "confed-internal");
10388 vty_out(vty
, ", confed-internal");
10391 json_object_string_add(
10392 json_peer
, "type", "internal");
10394 vty_out(vty
, ", internal");
10397 if (bgp_confederation_peers_check(bgp
,
10400 json_object_string_add(
10402 "confed-external");
10404 vty_out(vty
, ", confed-external");
10407 json_object_string_add(
10408 json_peer
, "type", "external");
10410 vty_out(vty
, ", external");
10413 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10415 json_object_boolean_true_add(json_path
, "aggregated");
10416 json_object_boolean_true_add(json_path
, "local");
10418 vty_out(vty
, ", aggregated, local");
10420 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10422 json_object_boolean_true_add(json_path
, "sourced");
10424 vty_out(vty
, ", sourced");
10427 json_object_boolean_true_add(json_path
, "sourced");
10428 json_object_boolean_true_add(json_path
, "local");
10430 vty_out(vty
, ", sourced, local");
10434 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10436 json_object_boolean_true_add(json_path
,
10437 "atomicAggregate");
10439 vty_out(vty
, ", atomic-aggregate");
10442 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10443 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10444 && bgp_path_info_mpath_count(path
))) {
10446 json_object_boolean_true_add(json_path
, "multipath");
10448 vty_out(vty
, ", multipath");
10451 // Mark the bestpath(s)
10452 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10453 first_as
= aspath_get_first_as(attr
->aspath
);
10456 if (!json_bestpath
)
10457 json_bestpath
= json_object_new_object();
10458 json_object_int_add(json_bestpath
, "bestpathFromAs",
10462 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10464 vty_out(vty
, ", bestpath-from-AS Local");
10468 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10470 if (!json_bestpath
)
10471 json_bestpath
= json_object_new_object();
10472 json_object_boolean_true_add(json_bestpath
, "overall");
10473 json_object_string_add(
10474 json_bestpath
, "selectionReason",
10475 bgp_path_selection_reason2str(bn
->reason
));
10477 vty_out(vty
, ", best");
10478 vty_out(vty
, " (%s)",
10479 bgp_path_selection_reason2str(bn
->reason
));
10483 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10485 json_object_string_add(
10486 json_path
, "rpkiValidationState",
10487 bgp_rpki_validation2str(rpki_curr_state
));
10489 vty_out(vty
, ", rpki validation-state: %s",
10490 bgp_rpki_validation2str(rpki_curr_state
));
10494 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10497 vty_out(vty
, "\n");
10499 /* Line 4 display Community */
10500 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10502 if (!bgp_attr_get_community(attr
)->json
)
10503 community_str(bgp_attr_get_community(attr
),
10505 json_object_lock(bgp_attr_get_community(attr
)->json
);
10506 json_object_object_add(
10507 json_path
, "community",
10508 bgp_attr_get_community(attr
)->json
);
10510 vty_out(vty
, " Community: %s\n",
10511 bgp_attr_get_community(attr
)->str
);
10515 /* Line 5 display Extended-community */
10516 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10518 json_ext_community
= json_object_new_object();
10519 json_object_string_add(
10520 json_ext_community
, "string",
10521 bgp_attr_get_ecommunity(attr
)->str
);
10522 json_object_object_add(json_path
, "extendedCommunity",
10523 json_ext_community
);
10525 vty_out(vty
, " Extended Community: %s\n",
10526 bgp_attr_get_ecommunity(attr
)->str
);
10530 /* Line 6 display Large community */
10531 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10533 if (!bgp_attr_get_lcommunity(attr
)->json
)
10534 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10536 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10537 json_object_object_add(
10538 json_path
, "largeCommunity",
10539 bgp_attr_get_lcommunity(attr
)->json
);
10541 vty_out(vty
, " Large Community: %s\n",
10542 bgp_attr_get_lcommunity(attr
)->str
);
10546 /* Line 7 display Originator, Cluster-id */
10547 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10548 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10549 char buf
[BUFSIZ
] = {0};
10551 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10553 json_object_string_addf(json_path
,
10554 "originatorId", "%pI4",
10555 &attr
->originator_id
);
10557 vty_out(vty
, " Originator: %pI4",
10558 &attr
->originator_id
);
10561 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10562 struct cluster_list
*cluster
=
10563 bgp_attr_get_cluster(attr
);
10567 json_cluster_list
= json_object_new_object();
10568 json_cluster_list_list
=
10569 json_object_new_array();
10571 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10572 json_string
= json_object_new_string(
10575 buf
, sizeof(buf
)));
10576 json_object_array_add(
10577 json_cluster_list_list
,
10582 * struct cluster_list does not have
10583 * "str" variable like aspath and community
10584 * do. Add this someday if someone asks
10586 * json_object_string_add(json_cluster_list,
10587 * "string", cluster->str);
10589 json_object_object_add(json_cluster_list
,
10591 json_cluster_list_list
);
10592 json_object_object_add(json_path
, "clusterList",
10593 json_cluster_list
);
10595 vty_out(vty
, ", Cluster list: ");
10597 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10598 vty_out(vty
, "%pI4 ",
10599 &cluster
->list
[i
]);
10605 vty_out(vty
, "\n");
10608 if (path
->extra
&& path
->extra
->damp_info
)
10609 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10612 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10613 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10614 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
10617 json_object_int_add(json_path
, "remoteLabel", label
);
10619 vty_out(vty
, " Remote label: %d\n", label
);
10623 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10624 inet_ntop(AF_INET6
, &path
->extra
->sid
[0].sid
, buf
, sizeof(buf
));
10626 json_object_string_add(json_path
, "remoteSid", buf
);
10628 vty_out(vty
, " Remote SID: %s\n", buf
);
10632 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10634 json_object_int_add(json_path
, "labelIndex",
10635 attr
->label_index
);
10637 vty_out(vty
, " Label Index: %d\n",
10638 attr
->label_index
);
10641 /* Line 8 display Addpath IDs */
10642 if (path
->addpath_rx_id
10643 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10645 json_object_int_add(json_path
, "addpathRxId",
10646 path
->addpath_rx_id
);
10648 /* Keep backwards compatibility with the old API
10649 * by putting TX All's ID in the old field
10651 json_object_int_add(
10652 json_path
, "addpathTxId",
10654 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10656 /* ... but create a specific field for each
10659 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10660 json_object_int_add(
10662 bgp_addpath_names(i
)->id_json_name
,
10663 path
->tx_addpath
.addpath_tx_id
[i
]);
10666 vty_out(vty
, " AddPath ID: RX %u, ",
10667 path
->addpath_rx_id
);
10669 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10673 /* If we used addpath to TX a non-bestpath we need to display
10674 * "Advertised to" on a path-by-path basis
10676 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10679 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10681 bgp_addpath_encode_tx(peer
, afi
, safi
);
10682 has_adj
= bgp_adj_out_lookup(
10684 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10685 &path
->tx_addpath
));
10687 if ((addpath_capable
&& has_adj
)
10688 || (!addpath_capable
&& has_adj
10689 && CHECK_FLAG(path
->flags
,
10690 BGP_PATH_SELECTED
))) {
10691 if (json_path
&& !json_adv_to
)
10692 json_adv_to
= json_object_new_object();
10694 route_vty_out_advertised_to(
10696 " Advertised to:", json_adv_to
);
10702 json_object_object_add(
10703 json_path
, "advertisedTo", json_adv_to
);
10707 vty_out(vty
, "\n");
10712 /* Line 9 display Uptime */
10713 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
10715 json_last_update
= json_object_new_object();
10716 json_object_int_add(json_last_update
, "epoch", tbuf
);
10717 json_object_string_add(json_last_update
, "string",
10719 json_object_object_add(json_path
, "lastUpdate",
10722 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10724 /* Line 10 display PMSI tunnel attribute, if present */
10725 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10726 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10727 bgp_attr_get_pmsi_tnl_type(attr
),
10728 PMSI_TNLTYPE_STR_DEFAULT
);
10731 json_pmsi
= json_object_new_object();
10732 json_object_string_add(json_pmsi
, "tunnelType", str
);
10733 json_object_int_add(json_pmsi
, "label",
10734 label2vni(&attr
->label
));
10735 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10737 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10738 str
, label2vni(&attr
->label
));
10741 if (path
->peer
->t_gr_restart
&&
10742 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10743 unsigned long gr_remaining
=
10744 thread_timer_remain_second(path
->peer
->t_gr_restart
);
10747 json_object_int_add(json_path
,
10748 "gracefulRestartSecondsRemaining",
10752 " Time until Graceful Restart stale route deleted: %lu\n",
10756 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
10757 bgp_attr_get_community(attr
) &&
10758 community_include(bgp_attr_get_community(attr
),
10759 COMMUNITY_LLGR_STALE
)) {
10760 unsigned long llgr_remaining
= thread_timer_remain_second(
10761 path
->peer
->t_llgr_stale
[afi
][safi
]);
10764 json_object_int_add(json_path
, "llgrSecondsRemaining",
10768 " Time until Long-lived stale route deleted: %lu\n",
10772 /* Output some debug about internal state of the dest flags */
10774 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10775 json_object_boolean_true_add(json_path
, "processScheduled");
10776 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10777 json_object_boolean_true_add(json_path
, "userCleared");
10778 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10779 json_object_boolean_true_add(json_path
, "labelChanged");
10780 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10781 json_object_boolean_true_add(json_path
, "registeredForLabel");
10782 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10783 json_object_boolean_true_add(json_path
, "selectDefered");
10784 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10785 json_object_boolean_true_add(json_path
, "fibInstalled");
10786 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10787 json_object_boolean_true_add(json_path
, "fibPending");
10789 if (json_nexthop_global
|| json_nexthop_ll
) {
10790 json_nexthops
= json_object_new_array();
10792 if (json_nexthop_global
)
10793 json_object_array_add(json_nexthops
,
10794 json_nexthop_global
);
10796 if (json_nexthop_ll
)
10797 json_object_array_add(json_nexthops
,
10800 json_object_object_add(json_path
, "nexthops",
10804 json_object_object_add(json_path
, "peer", json_peer
);
10805 json_object_array_add(json_paths
, json_path
);
10809 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10810 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10811 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10813 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10814 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10816 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10817 const char *comstr
, int exact
, afi_t afi
,
10818 safi_t safi
, uint16_t show_flags
);
10820 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10821 struct bgp_table
*table
, enum bgp_show_type type
,
10822 void *output_arg
, const char *rd
, int is_last
,
10823 unsigned long *output_cum
, unsigned long *total_cum
,
10824 unsigned long *json_header_depth
, uint16_t show_flags
,
10825 enum rpki_states rpki_target_state
)
10827 struct bgp_path_info
*pi
;
10828 struct bgp_dest
*dest
;
10829 bool header
= true;
10830 bool json_detail_header
= false;
10832 unsigned long output_count
= 0;
10833 unsigned long total_count
= 0;
10835 json_object
*json_paths
= NULL
;
10837 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10838 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
10839 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10841 if (output_cum
&& *output_cum
!= 0)
10844 if (use_json
&& !*json_header_depth
) {
10846 *json_header_depth
= 1;
10848 vty_out(vty
, "{\n");
10849 *json_header_depth
= 2;
10853 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10854 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10855 " \"localAS\": %u,\n \"routes\": { ",
10856 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
10857 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
10860 table
->version
, &bgp
->router_id
,
10861 bgp
->default_local_pref
, bgp
->as
);
10863 vty_out(vty
, " \"routeDistinguishers\" : {");
10864 ++*json_header_depth
;
10868 if (use_json
&& rd
) {
10869 vty_out(vty
, " \"%s\" : { ", rd
);
10872 /* Check for 'json detail', where we need header output once per dest */
10873 if (use_json
&& CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
) &&
10874 type
!= bgp_show_type_dampend_paths
&&
10875 type
!= bgp_show_type_damp_neighbor
&&
10876 type
!= bgp_show_type_flap_statistics
&&
10877 type
!= bgp_show_type_flap_neighbor
)
10878 json_detail_header
= true;
10880 /* Start processing of routes. */
10881 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
10882 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10883 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
10884 bool json_detail
= json_detail_header
;
10886 pi
= bgp_dest_get_bgp_path_info(dest
);
10892 json_paths
= json_object_new_array();
10896 for (; pi
; pi
= pi
->next
) {
10897 struct community
*picomm
= NULL
;
10899 picomm
= bgp_attr_get_community(pi
->attr
);
10903 if (type
== bgp_show_type_prefix_version
) {
10905 strtoul(output_arg
, NULL
, 10);
10906 if (dest
->version
< version
)
10910 if (type
== bgp_show_type_community_alias
) {
10911 char *alias
= output_arg
;
10912 char **communities
;
10914 bool found
= false;
10917 frrstr_split(picomm
->str
, " ",
10918 &communities
, &num
);
10919 for (int i
= 0; i
< num
; i
++) {
10920 const char *com2alias
=
10921 bgp_community2alias(
10924 && strcmp(alias
, com2alias
)
10930 XFREE(MTYPE_TMP
, communities
);
10934 bgp_attr_get_lcommunity(pi
->attr
)) {
10935 frrstr_split(bgp_attr_get_lcommunity(
10938 " ", &communities
, &num
);
10939 for (int i
= 0; i
< num
; i
++) {
10940 const char *com2alias
=
10941 bgp_community2alias(
10944 && strcmp(alias
, com2alias
)
10950 XFREE(MTYPE_TMP
, communities
);
10957 if (type
== bgp_show_type_rpki
) {
10958 if (dest_p
->family
== AF_INET
10959 || dest_p
->family
== AF_INET6
)
10960 rpki_curr_state
= hook_call(
10961 bgp_rpki_prefix_status
,
10962 pi
->peer
, pi
->attr
, dest_p
);
10963 if (rpki_target_state
!= RPKI_NOT_BEING_USED
10964 && rpki_curr_state
!= rpki_target_state
)
10968 if (type
== bgp_show_type_flap_statistics
10969 || type
== bgp_show_type_flap_neighbor
10970 || type
== bgp_show_type_dampend_paths
10971 || type
== bgp_show_type_damp_neighbor
) {
10972 if (!(pi
->extra
&& pi
->extra
->damp_info
))
10975 if (type
== bgp_show_type_regexp
) {
10976 regex_t
*regex
= output_arg
;
10978 if (bgp_regexec(regex
, pi
->attr
->aspath
)
10982 if (type
== bgp_show_type_prefix_list
) {
10983 struct prefix_list
*plist
= output_arg
;
10985 if (prefix_list_apply(plist
, dest_p
)
10989 if (type
== bgp_show_type_filter_list
) {
10990 struct as_list
*as_list
= output_arg
;
10992 if (as_list_apply(as_list
, pi
->attr
->aspath
)
10993 != AS_FILTER_PERMIT
)
10996 if (type
== bgp_show_type_route_map
) {
10997 struct route_map
*rmap
= output_arg
;
10998 struct bgp_path_info path
;
10999 struct attr dummy_attr
;
11000 route_map_result_t ret
;
11002 dummy_attr
= *pi
->attr
;
11004 path
.peer
= pi
->peer
;
11005 path
.attr
= &dummy_attr
;
11007 ret
= route_map_apply(rmap
, dest_p
, &path
);
11008 bgp_attr_flush(&dummy_attr
);
11009 if (ret
== RMAP_DENYMATCH
)
11012 if (type
== bgp_show_type_neighbor
11013 || type
== bgp_show_type_flap_neighbor
11014 || type
== bgp_show_type_damp_neighbor
) {
11015 union sockunion
*su
= output_arg
;
11017 if (pi
->peer
== NULL
11018 || pi
->peer
->su_remote
== NULL
11019 || !sockunion_same(pi
->peer
->su_remote
, su
))
11022 if (type
== bgp_show_type_cidr_only
) {
11023 uint32_t destination
;
11025 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11026 if (IN_CLASSC(destination
)
11027 && dest_p
->prefixlen
== 24)
11029 if (IN_CLASSB(destination
)
11030 && dest_p
->prefixlen
== 16)
11032 if (IN_CLASSA(destination
)
11033 && dest_p
->prefixlen
== 8)
11036 if (type
== bgp_show_type_prefix_longer
) {
11038 if (!prefix_match(p
, dest_p
))
11041 if (type
== bgp_show_type_community_all
) {
11045 if (type
== bgp_show_type_community
) {
11046 struct community
*com
= output_arg
;
11048 if (!picomm
|| !community_match(picomm
, com
))
11051 if (type
== bgp_show_type_community_exact
) {
11052 struct community
*com
= output_arg
;
11054 if (!picomm
|| !community_cmp(picomm
, com
))
11057 if (type
== bgp_show_type_community_list
) {
11058 struct community_list
*list
= output_arg
;
11060 if (!community_list_match(picomm
, list
))
11063 if (type
== bgp_show_type_community_list_exact
) {
11064 struct community_list
*list
= output_arg
;
11066 if (!community_list_exact_match(picomm
, list
))
11069 if (type
== bgp_show_type_lcommunity
) {
11070 struct lcommunity
*lcom
= output_arg
;
11072 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11074 bgp_attr_get_lcommunity(pi
->attr
),
11079 if (type
== bgp_show_type_lcommunity_exact
) {
11080 struct lcommunity
*lcom
= output_arg
;
11082 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11084 bgp_attr_get_lcommunity(pi
->attr
),
11088 if (type
== bgp_show_type_lcommunity_list
) {
11089 struct community_list
*list
= output_arg
;
11091 if (!lcommunity_list_match(
11092 bgp_attr_get_lcommunity(pi
->attr
),
11097 == bgp_show_type_lcommunity_list_exact
) {
11098 struct community_list
*list
= output_arg
;
11100 if (!lcommunity_list_exact_match(
11101 bgp_attr_get_lcommunity(pi
->attr
),
11105 if (type
== bgp_show_type_lcommunity_all
) {
11106 if (!bgp_attr_get_lcommunity(pi
->attr
))
11109 if (type
== bgp_show_type_dampend_paths
11110 || type
== bgp_show_type_damp_neighbor
) {
11111 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11112 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11116 if (!use_json
&& header
) {
11118 "BGP table version is %" PRIu64
11119 ", local router ID is %pI4, vrf id ",
11120 table
->version
, &bgp
->router_id
);
11121 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11122 vty_out(vty
, "%s", VRFID_NONE_STR
);
11124 vty_out(vty
, "%u", bgp
->vrf_id
);
11125 vty_out(vty
, "\n");
11126 vty_out(vty
, "Default local pref %u, ",
11127 bgp
->default_local_pref
);
11128 vty_out(vty
, "local AS %u\n", bgp
->as
);
11129 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11130 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11131 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11132 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11133 if (type
== bgp_show_type_dampend_paths
11134 || type
== bgp_show_type_damp_neighbor
)
11135 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11136 else if (type
== bgp_show_type_flap_statistics
11137 || type
== bgp_show_type_flap_neighbor
)
11138 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11140 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11141 : BGP_SHOW_HEADER
));
11144 } else if (json_detail
&& json_paths
!= NULL
) {
11145 const struct prefix_rd
*prd
;
11146 json_object
*jtemp
;
11148 /* Use common detail header, for most types;
11149 * need a json 'object'.
11152 jtemp
= json_object_new_object();
11153 prd
= bgp_rd_from_dest(dest
, safi
);
11155 route_vty_out_detail_header(
11156 vty
, bgp
, dest
, prd
, table
->afi
,
11159 json_object_array_add(json_paths
, jtemp
);
11161 json_detail
= false;
11164 if (rd
!= NULL
&& !display
&& !output_count
) {
11167 "Route Distinguisher: %s\n",
11170 if (type
== bgp_show_type_dampend_paths
11171 || type
== bgp_show_type_damp_neighbor
)
11172 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11173 AFI_IP
, safi
, use_json
,
11175 else if (type
== bgp_show_type_flap_statistics
11176 || type
== bgp_show_type_flap_neighbor
)
11177 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11178 AFI_IP
, safi
, use_json
,
11181 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
11182 route_vty_out_detail(
11183 vty
, bgp
, dest
, pi
,
11184 family2afi(dest_p
->family
),
11185 safi
, RPKI_NOT_BEING_USED
,
11188 route_vty_out(vty
, dest_p
, pi
, display
,
11189 safi
, json_paths
, wide
);
11199 /* encode prefix */
11200 if (dest_p
->family
== AF_FLOWSPEC
) {
11201 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11204 bgp_fs_nlri_get_string(
11206 dest_p
->u
.prefix_flowspec
.ptr
,
11207 dest_p
->u
.prefix_flowspec
.prefixlen
,
11208 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11209 family2afi(dest_p
->u
11210 .prefix_flowspec
.family
));
11212 vty_out(vty
, "\"%s/%d\": ", retstr
,
11213 dest_p
->u
.prefix_flowspec
11216 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11217 dest_p
->u
.prefix_flowspec
11221 vty_out(vty
, "\"%pFX\": ", dest_p
);
11223 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11225 vty_json(vty
, json_paths
);
11229 json_object_free(json_paths
);
11233 output_count
+= *output_cum
;
11234 *output_cum
= output_count
;
11237 total_count
+= *total_cum
;
11238 *total_cum
= total_count
;
11242 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11246 for (i
= 0; i
< *json_header_depth
; ++i
)
11247 vty_out(vty
, " } ");
11249 vty_out(vty
, "\n");
11253 /* No route is displayed */
11254 if (output_count
== 0) {
11255 if (type
== bgp_show_type_normal
)
11257 "No BGP prefixes displayed, %ld exist\n",
11261 "\nDisplayed %ld routes and %ld total paths\n",
11262 output_count
, total_count
);
11266 return CMD_SUCCESS
;
11269 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11270 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11271 enum bgp_show_type type
, void *output_arg
, bool use_json
)
11273 struct bgp_dest
*dest
, *next
;
11274 unsigned long output_cum
= 0;
11275 unsigned long total_cum
= 0;
11276 unsigned long json_header_depth
= 0;
11277 struct bgp_table
*itable
;
11279 uint16_t show_flags
= 0;
11281 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11284 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11286 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11287 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11289 next
= bgp_route_next(dest
);
11290 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11293 itable
= bgp_dest_get_bgp_table_info(dest
);
11294 if (itable
!= NULL
) {
11295 struct prefix_rd prd
;
11296 char rd
[RD_ADDRSTRLEN
];
11298 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11299 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11300 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11301 rd
, next
== NULL
, &output_cum
,
11302 &total_cum
, &json_header_depth
,
11303 show_flags
, RPKI_NOT_BEING_USED
);
11309 if (output_cum
== 0)
11310 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11314 "\nDisplayed %ld routes and %ld total paths\n",
11315 output_cum
, total_cum
);
11317 return CMD_SUCCESS
;
11320 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11321 enum bgp_show_type type
, void *output_arg
,
11322 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11324 struct bgp_table
*table
;
11325 unsigned long json_header_depth
= 0;
11326 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11329 bgp
= bgp_get_default();
11334 vty_out(vty
, "No BGP process is configured\n");
11336 vty_out(vty
, "{}\n");
11337 return CMD_WARNING
;
11340 /* Labeled-unicast routes live in the unicast table. */
11341 if (safi
== SAFI_LABELED_UNICAST
)
11342 safi
= SAFI_UNICAST
;
11344 table
= bgp
->rib
[afi
][safi
];
11345 /* use MPLS and ENCAP specific shows until they are merged */
11346 if (safi
== SAFI_MPLS_VPN
) {
11347 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11348 output_arg
, use_json
);
11351 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11352 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11353 output_arg
, use_json
,
11357 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11358 NULL
, NULL
, &json_header_depth
, show_flags
,
11359 rpki_target_state
);
11362 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11363 safi_t safi
, uint16_t show_flags
)
11365 struct listnode
*node
, *nnode
;
11368 bool route_output
= false;
11369 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11372 vty_out(vty
, "{\n");
11374 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11375 route_output
= true;
11378 vty_out(vty
, ",\n");
11382 vty_out(vty
, "\"%s\":",
11383 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11387 vty_out(vty
, "\nInstance %s:\n",
11388 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11392 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11393 show_flags
, RPKI_NOT_BEING_USED
);
11397 vty_out(vty
, "}\n");
11398 else if (!route_output
)
11399 vty_out(vty
, "%% BGP instance not found\n");
11402 /* Header of detailed BGP route information */
11403 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11404 struct bgp_dest
*dest
,
11405 const struct prefix_rd
*prd
,
11406 afi_t afi
, safi_t safi
, json_object
*json
)
11408 struct bgp_path_info
*pi
;
11409 const struct prefix
*p
;
11411 struct listnode
*node
, *nnode
;
11412 char buf1
[RD_ADDRSTRLEN
];
11416 int accept_own
= 0;
11417 int route_filter_translated_v4
= 0;
11418 int route_filter_v4
= 0;
11419 int route_filter_translated_v6
= 0;
11420 int route_filter_v6
= 0;
11421 int llgr_stale
= 0;
11423 int accept_own_nexthop
= 0;
11426 int no_advertise
= 0;
11430 int has_valid_label
= 0;
11431 mpls_label_t label
= 0;
11432 json_object
*json_adv_to
= NULL
;
11434 p
= bgp_dest_get_prefix(dest
);
11435 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
11437 if (has_valid_label
)
11438 label
= label_pton(&dest
->local_label
);
11440 if (safi
== SAFI_EVPN
) {
11443 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11444 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11446 prd
? ":" : "", (struct prefix_evpn
*)p
);
11448 json_object_string_add(json
, "rd",
11449 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11451 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11456 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11458 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11459 ? prefix_rd2str(prd
, buf1
,
11462 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11466 json_object_string_addf(json
, "prefix", "%pFX", p
);
11467 json_object_int_add(json
, "version", dest
->version
);
11472 if (has_valid_label
) {
11474 json_object_int_add(json
, "localLabel", label
);
11476 vty_out(vty
, "Local label: %d\n", label
);
11480 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11481 vty_out(vty
, "not allocated\n");
11483 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11484 struct community
*picomm
= NULL
;
11486 picomm
= bgp_attr_get_community(pi
->attr
);
11489 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11491 if (bgp_path_suppressed(pi
))
11497 no_advertise
+= community_include(
11498 picomm
, COMMUNITY_NO_ADVERTISE
);
11500 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11502 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11504 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11505 route_filter_translated_v4
+= community_include(
11506 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11507 route_filter_translated_v6
+= community_include(
11508 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11509 route_filter_v4
+= community_include(
11510 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11511 route_filter_v6
+= community_include(
11512 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11514 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11515 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11516 accept_own_nexthop
+= community_include(
11517 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11519 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11520 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11525 vty_out(vty
, "Paths: (%d available", count
);
11527 vty_out(vty
, ", best #%d", best
);
11528 if (safi
== SAFI_UNICAST
) {
11529 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11530 vty_out(vty
, ", table %s",
11533 vty_out(vty
, ", vrf %s",
11537 vty_out(vty
, ", no best path");
11541 ", accept own local route exported and imported in different VRF");
11542 else if (route_filter_translated_v4
)
11544 ", mark translated RTs for VPNv4 route filtering");
11545 else if (route_filter_v4
)
11547 ", attach RT as-is for VPNv4 route filtering");
11548 else if (route_filter_translated_v6
)
11550 ", mark translated RTs for VPNv6 route filtering");
11551 else if (route_filter_v6
)
11553 ", attach RT as-is for VPNv6 route filtering");
11554 else if (llgr_stale
)
11556 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11559 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11560 else if (accept_own_nexthop
)
11562 ", accept local nexthop");
11563 else if (blackhole
)
11564 vty_out(vty
, ", inform peer to blackhole prefix");
11565 else if (no_export
)
11566 vty_out(vty
, ", not advertised to EBGP peer");
11567 else if (no_advertise
)
11568 vty_out(vty
, ", not advertised to any peer");
11570 vty_out(vty
, ", not advertised outside local AS");
11573 ", inform EBGP peer not to advertise to their EBGP peers");
11577 ", Advertisements suppressed by an aggregate.");
11578 vty_out(vty
, ")\n");
11581 /* If we are not using addpath then we can display Advertised to and
11583 * show what peers we advertised the bestpath to. If we are using
11585 * though then we must display Advertised to on a path-by-path basis. */
11586 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11587 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11588 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11589 if (json
&& !json_adv_to
)
11590 json_adv_to
= json_object_new_object();
11592 route_vty_out_advertised_to(
11594 " Advertised to non peer-group peers:\n ",
11601 json_object_object_add(json
, "advertisedTo",
11606 vty_out(vty
, " Not advertised to any peer");
11607 vty_out(vty
, "\n");
11612 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
11613 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11614 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11615 json_object
*json
, enum bgp_path_type pathtype
,
11616 int *display
, enum rpki_states rpki_target_state
)
11618 struct bgp_path_info
*pi
;
11620 char rdbuf
[RD_ADDRSTRLEN
];
11621 json_object
*json_header
= NULL
;
11622 json_object
*json_paths
= NULL
;
11623 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
11625 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11626 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11628 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
11629 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
11630 pi
->peer
, pi
->attr
, p
);
11632 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11633 && rpki_curr_state
!= rpki_target_state
)
11636 if (json
&& !json_paths
) {
11637 /* Instantiate json_paths only if path is valid */
11638 json_paths
= json_object_new_array();
11640 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11641 json_header
= json_object_new_object();
11643 json_header
= json
;
11647 route_vty_out_detail_header(
11648 vty
, bgp
, bgp_node
, pfx_rd
,
11649 AFI_IP
, safi
, json_header
);
11654 if (pathtype
== BGP_PATH_SHOW_ALL
11655 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11656 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11657 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11658 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11659 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11660 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
11661 safi
, rpki_curr_state
, json_paths
);
11664 if (json
&& json_paths
) {
11665 json_object_object_add(json_header
, "paths", json_paths
);
11668 json_object_object_add(json
, rdbuf
, json_header
);
11673 * Return rd based on safi
11675 static const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
11679 case SAFI_MPLS_VPN
:
11682 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
11689 /* Display specified route of BGP table. */
11690 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11691 struct bgp_table
*rib
, const char *ip_str
,
11692 afi_t afi
, safi_t safi
,
11693 enum rpki_states rpki_target_state
,
11694 struct prefix_rd
*prd
, int prefix_check
,
11695 enum bgp_path_type pathtype
, bool use_json
)
11699 struct prefix match
;
11700 struct bgp_dest
*dest
;
11701 struct bgp_dest
*rm
;
11702 struct bgp_table
*table
;
11703 json_object
*json
= NULL
;
11704 json_object
*json_paths
= NULL
;
11706 /* Check IP address argument. */
11707 ret
= str2prefix(ip_str
, &match
);
11709 vty_out(vty
, "address is malformed\n");
11710 return CMD_WARNING
;
11713 match
.family
= afi2family(afi
);
11716 json
= json_object_new_object();
11718 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11719 for (dest
= bgp_table_top(rib
); dest
;
11720 dest
= bgp_route_next(dest
)) {
11721 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11723 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11725 table
= bgp_dest_get_bgp_table_info(dest
);
11729 rm
= bgp_node_match(table
, &match
);
11733 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11735 && rm_p
->prefixlen
!= match
.prefixlen
) {
11736 bgp_dest_unlock_node(rm
);
11740 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11741 bgp
, afi
, safi
, json
, pathtype
,
11742 &display
, rpki_target_state
);
11744 bgp_dest_unlock_node(rm
);
11746 } else if (safi
== SAFI_EVPN
) {
11747 struct bgp_dest
*longest_pfx
;
11748 bool is_exact_pfxlen_match
= false;
11750 for (dest
= bgp_table_top(rib
); dest
;
11751 dest
= bgp_route_next(dest
)) {
11752 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11754 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11756 table
= bgp_dest_get_bgp_table_info(dest
);
11760 longest_pfx
= NULL
;
11761 is_exact_pfxlen_match
= false;
11763 * Search through all the prefixes for a match. The
11764 * pfx's are enumerated in ascending order of pfxlens.
11765 * So, the last pfx match is the longest match. Set
11766 * is_exact_pfxlen_match when we get exact pfxlen match
11768 for (rm
= bgp_table_top(table
); rm
;
11769 rm
= bgp_route_next(rm
)) {
11770 const struct prefix
*rm_p
=
11771 bgp_dest_get_prefix(rm
);
11773 * Get prefixlen of the ip-prefix within type5
11776 if (evpn_type5_prefix_match(rm_p
, &match
)
11780 bgp_evpn_get_type5_prefixlen(
11782 if (type5_pfxlen
== match
.prefixlen
) {
11783 is_exact_pfxlen_match
= true;
11784 bgp_dest_unlock_node(rm
);
11793 if (prefix_check
&& !is_exact_pfxlen_match
)
11797 bgp_dest_lock_node(rm
);
11799 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11800 bgp
, afi
, safi
, json
, pathtype
,
11801 &display
, rpki_target_state
);
11803 bgp_dest_unlock_node(rm
);
11805 } else if (safi
== SAFI_FLOWSPEC
) {
11807 json_paths
= json_object_new_array();
11809 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11810 &match
, prefix_check
,
11816 json_object_object_add(json
, "paths",
11819 json_object_free(json_paths
);
11822 dest
= bgp_node_match(rib
, &match
);
11823 if (dest
!= NULL
) {
11824 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11826 || dest_p
->prefixlen
== match
.prefixlen
) {
11827 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
11828 safi
, json
, pathtype
,
11829 &display
, rpki_target_state
);
11832 bgp_dest_unlock_node(dest
);
11837 vty_json(vty
, json
);
11840 vty_out(vty
, "%% Network not in table\n");
11841 return CMD_WARNING
;
11845 return CMD_SUCCESS
;
11848 /* Display specified route of Main RIB */
11849 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
11850 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
11851 int prefix_check
, enum bgp_path_type pathtype
,
11852 enum rpki_states rpki_target_state
, bool use_json
)
11855 bgp
= bgp_get_default();
11858 vty_out(vty
, "No BGP process is configured\n");
11860 vty_out(vty
, "{}\n");
11861 return CMD_WARNING
;
11865 /* labeled-unicast routes live in the unicast table */
11866 if (safi
== SAFI_LABELED_UNICAST
)
11867 safi
= SAFI_UNICAST
;
11869 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
11870 afi
, safi
, rpki_target_state
, prd
,
11871 prefix_check
, pathtype
, use_json
);
11874 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
11875 struct cmd_token
**argv
, bool exact
, afi_t afi
,
11876 safi_t safi
, bool uj
)
11878 struct lcommunity
*lcom
;
11883 uint16_t show_flags
= 0;
11887 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11889 b
= buffer_new(1024);
11890 for (i
= 0; i
< argc
; i
++) {
11892 buffer_putc(b
, ' ');
11894 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
11896 buffer_putstr(b
, argv
[i
]->arg
);
11900 buffer_putc(b
, '\0');
11902 str
= buffer_getstr(b
);
11905 lcom
= lcommunity_str2com(str
);
11906 XFREE(MTYPE_TMP
, str
);
11908 vty_out(vty
, "%% Large-community malformed\n");
11909 return CMD_WARNING
;
11912 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11913 (exact
? bgp_show_type_lcommunity_exact
11914 : bgp_show_type_lcommunity
),
11915 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
11917 lcommunity_free(&lcom
);
11921 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
11922 const char *lcom
, bool exact
, afi_t afi
,
11923 safi_t safi
, bool uj
)
11925 struct community_list
*list
;
11926 uint16_t show_flags
= 0;
11929 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11932 list
= community_list_lookup(bgp_clist
, lcom
, 0,
11933 LARGE_COMMUNITY_LIST_MASTER
);
11934 if (list
== NULL
) {
11935 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
11937 return CMD_WARNING
;
11940 return bgp_show(vty
, bgp
, afi
, safi
,
11941 (exact
? bgp_show_type_lcommunity_list_exact
11942 : bgp_show_type_lcommunity_list
),
11943 list
, show_flags
, RPKI_NOT_BEING_USED
);
11946 DEFUN (show_ip_bgp_large_community_list
,
11947 show_ip_bgp_large_community_list_cmd
,
11948 "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]",
11952 BGP_INSTANCE_HELP_STR
11954 BGP_SAFI_WITH_LABEL_HELP_STR
11955 "Display routes matching the large-community-list\n"
11956 "large-community-list number\n"
11957 "large-community-list name\n"
11958 "Exact match of the large-communities\n"
11961 afi_t afi
= AFI_IP6
;
11962 safi_t safi
= SAFI_UNICAST
;
11964 bool exact_match
= 0;
11965 struct bgp
*bgp
= NULL
;
11966 bool uj
= use_json(argc
, argv
);
11971 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11974 return CMD_WARNING
;
11976 argv_find(argv
, argc
, "large-community-list", &idx
);
11978 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11980 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11983 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
11984 exact_match
, afi
, safi
, uj
);
11986 DEFUN (show_ip_bgp_large_community
,
11987 show_ip_bgp_large_community_cmd
,
11988 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11992 BGP_INSTANCE_HELP_STR
11994 BGP_SAFI_WITH_LABEL_HELP_STR
11995 "Display routes matching the large-communities\n"
11996 "List of large-community numbers\n"
11997 "Exact match of the large-communities\n"
12000 afi_t afi
= AFI_IP6
;
12001 safi_t safi
= SAFI_UNICAST
;
12003 bool exact_match
= 0;
12004 struct bgp
*bgp
= NULL
;
12005 bool uj
= use_json(argc
, argv
);
12006 uint16_t show_flags
= 0;
12010 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12013 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12016 return CMD_WARNING
;
12018 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12019 if (argv_find(argv
, argc
, "exact-match", &idx
))
12021 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12022 exact_match
, afi
, safi
, uj
);
12024 return bgp_show(vty
, bgp
, afi
, safi
,
12025 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12026 RPKI_NOT_BEING_USED
);
12029 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12030 safi_t safi
, struct json_object
*json_array
);
12031 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12032 safi_t safi
, struct json_object
*json
);
12035 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12036 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12037 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12038 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12040 bool uj
= use_json(argc
, argv
);
12041 struct bgp
*bgp
= NULL
;
12042 safi_t safi
= SAFI_UNICAST
;
12043 afi_t afi
= AFI_IP6
;
12045 struct json_object
*json_all
= NULL
;
12046 struct json_object
*json_afi_safi
= NULL
;
12048 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12051 return CMD_WARNING
;
12054 json_all
= json_object_new_object();
12056 FOREACH_AFI_SAFI (afi
, safi
) {
12058 * So limit output to those afi/safi pairs that
12059 * actually have something interesting in them
12061 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12066 json_afi_safi
= json_object_new_array();
12067 json_object_object_add(
12069 get_afi_safi_str(afi
, safi
, true),
12072 json_afi_safi
= NULL
;
12075 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12079 vty_json(vty
, json_all
);
12081 return CMD_SUCCESS
;
12084 /* BGP route print out function without JSON */
12085 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12086 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12087 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12091 BGP_INSTANCE_HELP_STR
12094 "BGP RIB advertisement statistics\n"
12097 afi_t afi
= AFI_IP6
;
12098 safi_t safi
= SAFI_UNICAST
;
12099 struct bgp
*bgp
= NULL
;
12101 bool uj
= use_json(argc
, argv
);
12102 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12104 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12107 return CMD_WARNING
;
12110 json_afi_safi
= json_object_new_array();
12112 json_afi_safi
= NULL
;
12114 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12117 json
= json_object_new_object();
12118 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12120 vty_json(vty
, json
);
12125 /* BGP route print out function without JSON */
12126 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12127 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12128 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12130 statistics [json]",
12131 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12132 BGP_SAFI_WITH_LABEL_HELP_STR
12133 "BGP RIB advertisement statistics\n" JSON_STR
)
12135 afi_t afi
= AFI_IP6
;
12136 safi_t safi
= SAFI_UNICAST
;
12137 struct bgp
*bgp
= NULL
;
12139 bool uj
= use_json(argc
, argv
);
12140 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12142 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12145 return CMD_WARNING
;
12148 json_afi_safi
= json_object_new_array();
12150 json_afi_safi
= NULL
;
12152 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12155 json
= json_object_new_object();
12156 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12158 vty_json(vty
, json
);
12163 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12164 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12165 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12166 "]] [all$all] dampening parameters [json]",
12167 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12168 BGP_SAFI_WITH_LABEL_HELP_STR
12169 "Display the entries for all address families\n"
12170 "Display detailed information about dampening\n"
12171 "Display detail of configured dampening parameters\n"
12174 afi_t afi
= AFI_IP6
;
12175 safi_t safi
= SAFI_UNICAST
;
12176 struct bgp
*bgp
= NULL
;
12178 uint16_t show_flags
= 0;
12179 bool uj
= use_json(argc
, argv
);
12183 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12186 /* [<ipv4|ipv6> [all]] */
12188 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12189 if (argv_find(argv
, argc
, "ipv4", &idx
))
12190 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12192 if (argv_find(argv
, argc
, "ipv6", &idx
))
12193 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12196 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12199 return CMD_WARNING
;
12201 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12204 /* BGP route print out function */
12205 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12206 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12207 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12211 |dampening <flap-statistics|dampened-paths>\
12212 |community [AA:NN|local-AS|no-advertise|no-export\
12213 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12214 |accept-own|accept-own-nexthop|route-filter-v6\
12215 |route-filter-v4|route-filter-translated-v6\
12216 |route-filter-translated-v4] [exact-match]\
12217 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12218 |filter-list AS_PATH_FILTER_NAME\
12221 |rpki <invalid|valid|notfound>\
12222 |version (1-4294967295)\
12224 |A.B.C.D/M longer-prefixes\
12225 |X:X::X:X/M longer-prefixes\
12226 ] [json$uj [detail$detail] | wide$wide]",
12227 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12228 BGP_SAFI_WITH_LABEL_HELP_STR
12229 "Display the entries for all address families\n"
12230 "Display only routes with non-natural netmasks\n"
12231 "Display detailed information about dampening\n"
12232 "Display flap statistics of routes\n"
12233 "Display paths suppressed due to dampening\n"
12234 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12235 "Do not send outside local AS (well-known community)\n"
12236 "Do not advertise to any peer (well-known community)\n"
12237 "Do not export to next AS (well-known community)\n"
12238 "Graceful shutdown (well-known community)\n"
12239 "Do not export to any peer (well-known community)\n"
12240 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12241 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12242 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12243 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12244 "Should accept VPN route with local nexthop (well-known community)\n"
12245 "RT VPNv6 route filtering (well-known community)\n"
12246 "RT VPNv4 route filtering (well-known community)\n"
12247 "RT translated VPNv6 route filtering (well-known community)\n"
12248 "RT translated VPNv4 route filtering (well-known community)\n"
12249 "Exact match of the communities\n"
12250 "Community-list number\n"
12251 "Community-list name\n"
12252 "Display routes matching the community-list\n"
12253 "Exact match of the communities\n"
12254 "Display routes conforming to the filter-list\n"
12255 "Regular expression access list name\n"
12256 "Display routes conforming to the prefix-list\n"
12257 "Prefix-list name\n"
12258 "Display routes matching the route-map\n"
12259 "A route-map to match on\n"
12260 "RPKI route types\n"
12261 "A valid path as determined by rpki\n"
12262 "A invalid path as determined by rpki\n"
12263 "A path that has no rpki data\n"
12264 "Display prefixes with matching version numbers\n"
12265 "Version number and above\n"
12266 "Display prefixes with matching BGP community alias\n"
12267 "BGP community alias\n"
12269 "Display route and more specific routes\n"
12271 "Display route and more specific routes\n"
12273 "Display detailed version of JSON output\n"
12274 "Increase table width for longer prefixes\n")
12276 afi_t afi
= AFI_IP6
;
12277 safi_t safi
= SAFI_UNICAST
;
12278 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12279 void *output_arg
= NULL
;
12280 struct bgp
*bgp
= NULL
;
12282 int exact_match
= 0;
12283 char *community
= NULL
;
12285 uint16_t show_flags
= 0;
12286 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12291 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12295 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12297 /* [<ipv4|ipv6> [all]] */
12299 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12301 if (argv_find(argv
, argc
, "ipv4", &idx
))
12302 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12304 if (argv_find(argv
, argc
, "ipv6", &idx
))
12305 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12309 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12311 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12314 return CMD_WARNING
;
12316 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12317 sh_type
= bgp_show_type_cidr_only
;
12319 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12320 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12321 sh_type
= bgp_show_type_dampend_paths
;
12322 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12323 sh_type
= bgp_show_type_flap_statistics
;
12326 if (argv_find(argv
, argc
, "community", &idx
)) {
12327 char *maybecomm
= NULL
;
12329 if (idx
+ 1 < argc
) {
12330 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12331 maybecomm
= argv
[idx
+ 1]->arg
;
12333 maybecomm
= argv
[idx
+ 1]->text
;
12336 if (maybecomm
&& !strmatch(maybecomm
, "json")
12337 && !strmatch(maybecomm
, "exact-match"))
12338 community
= maybecomm
;
12340 if (argv_find(argv
, argc
, "exact-match", &idx
))
12344 sh_type
= bgp_show_type_community_all
;
12347 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12348 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12349 struct community_list
*list
;
12351 if (argv_find(argv
, argc
, "exact-match", &idx
))
12354 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12355 COMMUNITY_LIST_MASTER
);
12356 if (list
== NULL
) {
12358 "%% %s is not a valid community-list name\n",
12359 clist_number_or_name
);
12360 return CMD_WARNING
;
12364 sh_type
= bgp_show_type_community_list_exact
;
12366 sh_type
= bgp_show_type_community_list
;
12370 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12371 const char *filter
= argv
[++idx
]->arg
;
12372 struct as_list
*as_list
;
12374 as_list
= as_list_lookup(filter
);
12375 if (as_list
== NULL
) {
12377 "%% %s is not a valid AS-path access-list name\n",
12379 return CMD_WARNING
;
12382 sh_type
= bgp_show_type_filter_list
;
12383 output_arg
= as_list
;
12386 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12387 const char *prefix_list_str
= argv
[++idx
]->arg
;
12388 struct prefix_list
*plist
;
12390 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12391 if (plist
== NULL
) {
12392 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
12394 return CMD_WARNING
;
12397 sh_type
= bgp_show_type_prefix_list
;
12398 output_arg
= plist
;
12401 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12402 const char *rmap_str
= argv
[++idx
]->arg
;
12403 struct route_map
*rmap
;
12405 rmap
= route_map_lookup_by_name(rmap_str
);
12407 vty_out(vty
, "%% %s is not a valid route-map name\n",
12409 return CMD_WARNING
;
12412 sh_type
= bgp_show_type_route_map
;
12416 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12417 sh_type
= bgp_show_type_rpki
;
12418 if (argv_find(argv
, argc
, "valid", &idx
))
12419 rpki_target_state
= RPKI_VALID
;
12420 else if (argv_find(argv
, argc
, "invalid", &idx
))
12421 rpki_target_state
= RPKI_INVALID
;
12424 /* Display prefixes with matching version numbers */
12425 if (argv_find(argv
, argc
, "version", &idx
)) {
12426 sh_type
= bgp_show_type_prefix_version
;
12427 output_arg
= argv
[idx
+ 1]->arg
;
12430 /* Display prefixes with matching BGP community alias */
12431 if (argv_find(argv
, argc
, "alias", &idx
)) {
12432 sh_type
= bgp_show_type_community_alias
;
12433 output_arg
= argv
[idx
+ 1]->arg
;
12436 /* prefix-longer */
12437 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12438 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12439 const char *prefix_str
= argv
[idx
]->arg
;
12441 if (!str2prefix(prefix_str
, &p
)) {
12442 vty_out(vty
, "%% Malformed Prefix\n");
12443 return CMD_WARNING
;
12446 sh_type
= bgp_show_type_prefix_longer
;
12451 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12453 return bgp_show_community(vty
, bgp
, community
,
12454 exact_match
, afi
, safi
,
12457 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12458 output_arg
, show_flags
,
12459 rpki_target_state
);
12461 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12465 vty_out(vty
, "{\n");
12467 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12468 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12469 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12472 FOREACH_SAFI (safi
) {
12473 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12480 vty_out(vty
, ",\n");
12481 vty_out(vty
, "\"%s\":{\n",
12482 get_afi_safi_str(afi
, safi
,
12486 "\nFor address family: %s\n",
12487 get_afi_safi_str(afi
, safi
,
12491 bgp_show_community(vty
, bgp
, community
,
12495 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12496 output_arg
, show_flags
,
12497 rpki_target_state
);
12499 vty_out(vty
, "}\n");
12502 /* show <ip> bgp all: for each AFI and SAFI*/
12503 FOREACH_AFI_SAFI (afi
, safi
) {
12504 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12511 vty_out(vty
, ",\n");
12513 vty_out(vty
, "\"%s\":{\n",
12514 get_afi_safi_str(afi
, safi
,
12518 "\nFor address family: %s\n",
12519 get_afi_safi_str(afi
, safi
,
12523 bgp_show_community(vty
, bgp
, community
,
12527 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12528 output_arg
, show_flags
,
12529 rpki_target_state
);
12531 vty_out(vty
, "}\n");
12535 vty_out(vty
, "}\n");
12537 return CMD_SUCCESS
;
12540 DEFUN (show_ip_bgp_route
,
12541 show_ip_bgp_route_cmd
,
12542 "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]",
12546 BGP_INSTANCE_HELP_STR
12548 BGP_SAFI_WITH_LABEL_HELP_STR
12549 "Network in the BGP routing table to display\n"
12551 "Network in the BGP routing table to display\n"
12553 "Display only the bestpath\n"
12554 "Display only multipaths\n"
12555 "Display only paths that match the specified rpki state\n"
12556 "A valid path as determined by rpki\n"
12557 "A invalid path as determined by rpki\n"
12558 "A path that has no rpki data\n"
12561 int prefix_check
= 0;
12563 afi_t afi
= AFI_IP6
;
12564 safi_t safi
= SAFI_UNICAST
;
12565 char *prefix
= NULL
;
12566 struct bgp
*bgp
= NULL
;
12567 enum bgp_path_type path_type
;
12568 bool uj
= use_json(argc
, argv
);
12572 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12575 return CMD_WARNING
;
12579 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12580 return CMD_WARNING
;
12583 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12584 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12585 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12587 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12588 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12591 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12592 && afi
!= AFI_IP6
) {
12594 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12595 return CMD_WARNING
;
12597 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12598 && afi
!= AFI_IP
) {
12600 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12601 return CMD_WARNING
;
12604 prefix
= argv
[idx
]->arg
;
12606 /* [<bestpath|multipath>] */
12607 if (argv_find(argv
, argc
, "bestpath", &idx
))
12608 path_type
= BGP_PATH_SHOW_BESTPATH
;
12609 else if (argv_find(argv
, argc
, "multipath", &idx
))
12610 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12612 path_type
= BGP_PATH_SHOW_ALL
;
12614 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12615 path_type
, RPKI_NOT_BEING_USED
, uj
);
12618 DEFUN (show_ip_bgp_regexp
,
12619 show_ip_bgp_regexp_cmd
,
12620 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12624 BGP_INSTANCE_HELP_STR
12626 BGP_SAFI_WITH_LABEL_HELP_STR
12627 "Display routes matching the AS path regular expression\n"
12628 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12631 afi_t afi
= AFI_IP6
;
12632 safi_t safi
= SAFI_UNICAST
;
12633 struct bgp
*bgp
= NULL
;
12634 bool uj
= use_json(argc
, argv
);
12635 char *regstr
= NULL
;
12638 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12641 return CMD_WARNING
;
12643 // get index of regex
12644 if (argv_find(argv
, argc
, "REGEX", &idx
))
12645 regstr
= argv
[idx
]->arg
;
12648 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12649 bgp_show_type_regexp
, uj
);
12652 DEFPY (show_ip_bgp_instance_all
,
12653 show_ip_bgp_instance_all_cmd
,
12654 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12658 BGP_INSTANCE_ALL_HELP_STR
12660 BGP_SAFI_WITH_LABEL_HELP_STR
12662 "Increase table width for longer prefixes\n")
12664 afi_t afi
= AFI_IP6
;
12665 safi_t safi
= SAFI_UNICAST
;
12666 struct bgp
*bgp
= NULL
;
12668 uint16_t show_flags
= 0;
12672 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12676 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12678 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12681 return CMD_WARNING
;
12683 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12684 return CMD_SUCCESS
;
12687 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12688 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12693 uint16_t show_flags
= 0;
12696 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12698 if (!config_bgp_aspath_validate(regstr
)) {
12699 vty_out(vty
, "Invalid character in REGEX %s\n",
12701 return CMD_WARNING_CONFIG_FAILED
;
12704 regex
= bgp_regcomp(regstr
);
12706 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12707 return CMD_WARNING
;
12710 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
12711 RPKI_NOT_BEING_USED
);
12712 bgp_regex_free(regex
);
12716 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12717 const char *comstr
, int exact
, afi_t afi
,
12718 safi_t safi
, uint16_t show_flags
)
12720 struct community
*com
;
12723 com
= community_str2com(comstr
);
12725 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12726 return CMD_WARNING
;
12729 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12730 (exact
? bgp_show_type_community_exact
12731 : bgp_show_type_community
),
12732 com
, show_flags
, RPKI_NOT_BEING_USED
);
12733 community_free(&com
);
12739 BGP_STATS_MAXBITLEN
= 0,
12741 BGP_STATS_PREFIXES
,
12743 BGP_STATS_UNAGGREGATEABLE
,
12744 BGP_STATS_MAX_AGGREGATEABLE
,
12745 BGP_STATS_AGGREGATES
,
12747 BGP_STATS_ASPATH_COUNT
,
12748 BGP_STATS_ASPATH_MAXHOPS
,
12749 BGP_STATS_ASPATH_TOTHOPS
,
12750 BGP_STATS_ASPATH_MAXSIZE
,
12751 BGP_STATS_ASPATH_TOTSIZE
,
12752 BGP_STATS_ASN_HIGHEST
,
12756 #define TABLE_STATS_IDX_VTY 0
12757 #define TABLE_STATS_IDX_JSON 1
12759 static const char *table_stats_strs
[][2] = {
12760 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12761 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12762 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12763 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12764 "unaggregateablePrefixes"},
12765 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12766 "maximumAggregateablePrefixes"},
12767 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12768 "bgpAggregateAdvertisements"},
12769 [BGP_STATS_SPACE
] = {"Address space advertised",
12770 "addressSpaceAdvertised"},
12771 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12772 "advertisementsWithPaths"},
12773 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12775 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12777 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12778 "averageAsPathLengthHops"},
12779 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12780 "averageAsPathSizeBytes"},
12781 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12782 [BGP_STATS_MAX
] = {NULL
, NULL
}
12785 struct bgp_table_stats
{
12786 struct bgp_table
*table
;
12787 unsigned long long counts
[BGP_STATS_MAX
];
12788 double total_space
;
12791 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
12792 struct bgp_table_stats
*ts
, unsigned int space
)
12794 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
12795 struct bgp_path_info
*pi
;
12796 const struct prefix
*rn_p
;
12798 if (!bgp_dest_has_bgp_path_info_data(dest
))
12801 rn_p
= bgp_dest_get_prefix(dest
);
12802 ts
->counts
[BGP_STATS_PREFIXES
]++;
12803 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
12805 /* check if the prefix is included by any other announcements */
12806 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
12807 pdest
= bgp_dest_parent_nolock(pdest
);
12809 if (pdest
== NULL
|| pdest
== top
) {
12810 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
12811 /* announced address space */
12813 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
12814 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
12815 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
12818 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
12819 ts
->counts
[BGP_STATS_RIB
]++;
12821 if (CHECK_FLAG(pi
->attr
->flag
,
12822 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
12823 ts
->counts
[BGP_STATS_AGGREGATES
]++;
12825 /* as-path stats */
12826 if (pi
->attr
->aspath
) {
12827 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
12828 unsigned int size
= aspath_size(pi
->attr
->aspath
);
12829 as_t highest
= aspath_highest(pi
->attr
->aspath
);
12831 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
12833 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
12834 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
12836 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
12837 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
12839 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
12840 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
12841 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
12842 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
12847 static void bgp_table_stats_walker(struct thread
*t
)
12849 struct bgp_dest
*dest
, *ndest
;
12850 struct bgp_dest
*top
;
12851 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
12852 unsigned int space
= 0;
12854 if (!(top
= bgp_table_top(ts
->table
)))
12857 switch (ts
->table
->afi
) {
12859 space
= IPV4_MAX_BITLEN
;
12862 space
= IPV6_MAX_BITLEN
;
12865 space
= EVPN_ROUTE_PREFIXLEN
;
12871 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
12873 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
12874 if (ts
->table
->safi
== SAFI_MPLS_VPN
12875 || ts
->table
->safi
== SAFI_ENCAP
12876 || ts
->table
->safi
== SAFI_EVPN
) {
12877 struct bgp_table
*table
;
12879 table
= bgp_dest_get_bgp_table_info(dest
);
12883 top
= bgp_table_top(table
);
12884 for (ndest
= bgp_table_top(table
); ndest
;
12885 ndest
= bgp_route_next(ndest
))
12886 bgp_table_stats_rn(ndest
, top
, ts
, space
);
12888 bgp_table_stats_rn(dest
, top
, ts
, space
);
12893 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
12894 struct json_object
*json_array
)
12896 struct listnode
*node
, *nnode
;
12899 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
12900 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12903 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12904 safi_t safi
, struct json_object
*json_array
)
12906 struct bgp_table_stats ts
;
12908 int ret
= CMD_SUCCESS
;
12910 struct json_object
*json
= NULL
;
12913 json
= json_object_new_object();
12915 if (!bgp
->rib
[afi
][safi
]) {
12916 char warning_msg
[50];
12918 snprintf(warning_msg
, sizeof(warning_msg
),
12919 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
12923 vty_out(vty
, "%s\n", warning_msg
);
12925 json_object_string_add(json
, "warning", warning_msg
);
12928 goto end_table_stats
;
12932 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
12933 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
12935 json_object_string_add(json
, "instance", bgp
->name_pretty
);
12937 /* labeled-unicast routes live in the unicast table */
12938 if (safi
== SAFI_LABELED_UNICAST
)
12939 safi
= SAFI_UNICAST
;
12941 memset(&ts
, 0, sizeof(ts
));
12942 ts
.table
= bgp
->rib
[afi
][safi
];
12943 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
12945 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
12946 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
12947 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
12951 case BGP_STATS_ASPATH_TOTHOPS
:
12952 case BGP_STATS_ASPATH_TOTSIZE
:
12955 temp_buf
, sizeof(temp_buf
), "%12.2f",
12957 ? (float)ts
.counts
[i
]
12959 [BGP_STATS_ASPATH_COUNT
]
12961 vty_out(vty
, "%-30s: %s",
12962 table_stats_strs
[i
]
12963 [TABLE_STATS_IDX_VTY
],
12966 json_object_double_add(
12968 table_stats_strs
[i
]
12969 [TABLE_STATS_IDX_JSON
],
12971 ? (double)ts
.counts
[i
]
12972 / (double)ts
.counts
12973 [BGP_STATS_ASPATH_COUNT
]
12977 case BGP_STATS_TOTPLEN
:
12980 temp_buf
, sizeof(temp_buf
), "%12.2f",
12982 ? (float)ts
.counts
[i
]
12984 [BGP_STATS_PREFIXES
]
12986 vty_out(vty
, "%-30s: %s",
12987 table_stats_strs
[i
]
12988 [TABLE_STATS_IDX_VTY
],
12991 json_object_double_add(
12993 table_stats_strs
[i
]
12994 [TABLE_STATS_IDX_JSON
],
12996 ? (double)ts
.counts
[i
]
12997 / (double)ts
.counts
12998 [BGP_STATS_PREFIXES
]
13002 case BGP_STATS_SPACE
:
13004 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13006 vty_out(vty
, "%-30s: %s\n",
13007 table_stats_strs
[i
]
13008 [TABLE_STATS_IDX_VTY
],
13011 json_object_double_add(
13013 table_stats_strs
[i
]
13014 [TABLE_STATS_IDX_JSON
],
13015 (double)ts
.total_space
);
13017 if (afi
== AFI_IP6
) {
13019 snprintf(temp_buf
, sizeof(temp_buf
),
13022 * pow(2.0, -128 + 32));
13023 vty_out(vty
, "%30s: %s\n",
13024 "/32 equivalent %s\n",
13027 json_object_double_add(
13028 json
, "/32equivalent",
13029 (double)(ts
.total_space
13034 snprintf(temp_buf
, sizeof(temp_buf
),
13037 * pow(2.0, -128 + 48));
13038 vty_out(vty
, "%30s: %s\n",
13039 "/48 equivalent %s\n",
13042 json_object_double_add(
13043 json
, "/48equivalent",
13044 (double)(ts
.total_space
13050 snprintf(temp_buf
, sizeof(temp_buf
),
13052 ts
.total_space
* 100.
13054 vty_out(vty
, "%30s: %s\n",
13055 "% announced ", temp_buf
);
13057 json_object_double_add(
13058 json
, "%announced",
13059 (double)(ts
.total_space
* 100.
13063 snprintf(temp_buf
, sizeof(temp_buf
),
13066 * pow(2.0, -32 + 8));
13067 vty_out(vty
, "%30s: %s\n",
13068 "/8 equivalent ", temp_buf
);
13070 json_object_double_add(
13071 json
, "/8equivalent",
13072 (double)(ts
.total_space
13073 * pow(2.0, -32 + 8)));
13076 snprintf(temp_buf
, sizeof(temp_buf
),
13079 * pow(2.0, -32 + 24));
13080 vty_out(vty
, "%30s: %s\n",
13081 "/24 equivalent ", temp_buf
);
13083 json_object_double_add(
13084 json
, "/24equivalent",
13085 (double)(ts
.total_space
13086 * pow(2.0, -32 + 24)));
13092 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13094 vty_out(vty
, "%-30s: %s",
13095 table_stats_strs
[i
]
13096 [TABLE_STATS_IDX_VTY
],
13099 json_object_int_add(
13101 table_stats_strs
[i
]
13102 [TABLE_STATS_IDX_JSON
],
13107 vty_out(vty
, "\n");
13111 json_object_array_add(json_array
, json
);
13115 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13116 safi_t safi
, struct json_object
*json_array
)
13119 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13120 return CMD_SUCCESS
;
13123 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13135 PCOUNT_BPATH_SELECTED
,
13136 PCOUNT_PFCNT
, /* the figure we display to users */
13140 static const char *const pcount_strs
[] = {
13141 [PCOUNT_ADJ_IN
] = "Adj-in",
13142 [PCOUNT_DAMPED
] = "Damped",
13143 [PCOUNT_REMOVED
] = "Removed",
13144 [PCOUNT_HISTORY
] = "History",
13145 [PCOUNT_STALE
] = "Stale",
13146 [PCOUNT_VALID
] = "Valid",
13147 [PCOUNT_ALL
] = "All RIB",
13148 [PCOUNT_COUNTED
] = "PfxCt counted",
13149 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13150 [PCOUNT_PFCNT
] = "Useable",
13151 [PCOUNT_MAX
] = NULL
,
13154 struct peer_pcounts
{
13155 unsigned int count
[PCOUNT_MAX
];
13156 const struct peer
*peer
;
13157 const struct bgp_table
*table
;
13161 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13163 const struct bgp_adj_in
*ain
;
13164 const struct bgp_path_info
*pi
;
13165 const struct peer
*peer
= pc
->peer
;
13167 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13168 if (ain
->peer
== peer
)
13169 pc
->count
[PCOUNT_ADJ_IN
]++;
13171 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13173 if (pi
->peer
!= peer
)
13176 pc
->count
[PCOUNT_ALL
]++;
13178 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13179 pc
->count
[PCOUNT_DAMPED
]++;
13180 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13181 pc
->count
[PCOUNT_HISTORY
]++;
13182 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13183 pc
->count
[PCOUNT_REMOVED
]++;
13184 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13185 pc
->count
[PCOUNT_STALE
]++;
13186 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13187 pc
->count
[PCOUNT_VALID
]++;
13188 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13189 pc
->count
[PCOUNT_PFCNT
]++;
13190 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13191 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13193 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13194 pc
->count
[PCOUNT_COUNTED
]++;
13195 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13197 EC_LIB_DEVELOPMENT
,
13198 "Attempting to count but flags say it is unusable");
13200 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13202 EC_LIB_DEVELOPMENT
,
13203 "Not counted but flags say we should");
13208 static void bgp_peer_count_walker(struct thread
*t
)
13210 struct bgp_dest
*rn
, *rm
;
13211 const struct bgp_table
*table
;
13212 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13214 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13215 || pc
->safi
== SAFI_EVPN
) {
13216 /* Special handling for 2-level routing tables. */
13217 for (rn
= bgp_table_top(pc
->table
); rn
;
13218 rn
= bgp_route_next(rn
)) {
13219 table
= bgp_dest_get_bgp_table_info(rn
);
13221 for (rm
= bgp_table_top(table
); rm
;
13222 rm
= bgp_route_next(rm
))
13223 bgp_peer_count_proc(rm
, pc
);
13226 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13227 bgp_peer_count_proc(rn
, pc
);
13230 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13231 safi_t safi
, bool use_json
)
13233 struct peer_pcounts pcounts
= {.peer
= peer
};
13235 json_object
*json
= NULL
;
13236 json_object
*json_loop
= NULL
;
13239 json
= json_object_new_object();
13240 json_loop
= json_object_new_object();
13243 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13244 || !peer
->bgp
->rib
[afi
][safi
]) {
13246 json_object_string_add(
13248 "No such neighbor or address family");
13249 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13250 json_object_free(json
);
13251 json_object_free(json_loop
);
13253 vty_out(vty
, "%% No such neighbor or address family\n");
13255 return CMD_WARNING
;
13258 memset(&pcounts
, 0, sizeof(pcounts
));
13259 pcounts
.peer
= peer
;
13260 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13261 pcounts
.safi
= safi
;
13263 /* in-place call via thread subsystem so as to record execution time
13264 * stats for the thread-walk (i.e. ensure this can't be blamed on
13265 * on just vty_read()).
13267 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13270 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13271 json_object_string_add(json
, "multiProtocol",
13272 get_afi_safi_str(afi
, safi
, true));
13273 json_object_int_add(json
, "pfxCounter",
13274 peer
->pcount
[afi
][safi
]);
13276 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13277 json_object_int_add(json_loop
, pcount_strs
[i
],
13280 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13282 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13283 json_object_string_add(json
, "pfxctDriftFor",
13285 json_object_string_add(
13286 json
, "recommended",
13287 "Please report this bug, with the above command output");
13289 vty_json(vty
, json
);
13293 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13294 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13295 peer
->hostname
, peer
->host
,
13296 get_afi_safi_str(afi
, safi
, false));
13298 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13299 get_afi_safi_str(afi
, safi
, false));
13302 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13303 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13305 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13306 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13309 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13310 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13312 "Please report this bug, with the above command output\n");
13316 return CMD_SUCCESS
;
13319 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13320 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13321 "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]",
13325 BGP_INSTANCE_HELP_STR
13328 "Detailed information on TCP and BGP neighbor connections\n"
13329 "Neighbor to display information about\n"
13330 "Neighbor to display information about\n"
13331 "Neighbor on BGP configured interface\n"
13332 "Display detailed prefix count information\n"
13335 afi_t afi
= AFI_IP6
;
13336 safi_t safi
= SAFI_UNICAST
;
13339 struct bgp
*bgp
= NULL
;
13340 bool uj
= use_json(argc
, argv
);
13345 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13348 return CMD_WARNING
;
13350 argv_find(argv
, argc
, "neighbors", &idx
);
13351 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13353 return CMD_WARNING
;
13355 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13358 #ifdef KEEP_OLD_VPN_COMMANDS
13359 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13360 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13361 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13366 "Display information about all VPNv4 NLRIs\n"
13367 "Detailed information on TCP and BGP neighbor connections\n"
13368 "Neighbor to display information about\n"
13369 "Neighbor to display information about\n"
13370 "Neighbor on BGP configured interface\n"
13371 "Display detailed prefix count information\n"
13376 bool uj
= use_json(argc
, argv
);
13378 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13380 return CMD_WARNING
;
13382 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13385 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13386 show_ip_bgp_vpn_all_route_prefix_cmd
,
13387 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13392 "Display information about all VPNv4 NLRIs\n"
13393 "Network in the BGP routing table to display\n"
13394 "Network in the BGP routing table to display\n"
13398 char *network
= NULL
;
13399 struct bgp
*bgp
= bgp_get_default();
13401 vty_out(vty
, "Can't find default instance\n");
13402 return CMD_WARNING
;
13405 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13406 network
= argv
[idx
]->arg
;
13407 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13408 network
= argv
[idx
]->arg
;
13410 vty_out(vty
, "Unable to figure out Network\n");
13411 return CMD_WARNING
;
13414 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13415 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13416 use_json(argc
, argv
));
13418 #endif /* KEEP_OLD_VPN_COMMANDS */
13420 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13421 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13422 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13427 "Network in the BGP routing table to display\n"
13428 "Network in the BGP routing table to display\n"
13429 "Network in the BGP routing table to display\n"
13430 "Network in the BGP routing table to display\n"
13434 char *network
= NULL
;
13435 int prefix_check
= 0;
13437 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13438 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13439 network
= argv
[idx
]->arg
;
13440 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13441 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13442 network
= argv
[idx
]->arg
;
13445 vty_out(vty
, "Unable to figure out Network\n");
13446 return CMD_WARNING
;
13448 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13449 prefix_check
, BGP_PATH_SHOW_ALL
,
13450 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13453 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
13454 struct bgp_table
*table
, int *header1
,
13455 int *header2
, json_object
*json
,
13456 json_object
*json_scode
,
13457 json_object
*json_ocode
, bool wide
)
13459 uint64_t version
= table
? table
->version
: 0;
13463 json_object_int_add(json
, "bgpTableVersion", version
);
13464 json_object_string_addf(json
, "bgpLocalRouterId",
13465 "%pI4", &bgp
->router_id
);
13466 json_object_int_add(json
, "defaultLocPrf",
13467 bgp
->default_local_pref
);
13468 json_object_int_add(json
, "localAS", bgp
->as
);
13469 json_object_object_add(json
, "bgpStatusCodes",
13471 json_object_object_add(json
, "bgpOriginCodes",
13475 "BGP table version is %" PRIu64
13476 ", local router ID is %pI4, vrf id ",
13477 version
, &bgp
->router_id
);
13478 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13479 vty_out(vty
, "%s", VRFID_NONE_STR
);
13481 vty_out(vty
, "%u", bgp
->vrf_id
);
13482 vty_out(vty
, "\n");
13483 vty_out(vty
, "Default local pref %u, ",
13484 bgp
->default_local_pref
);
13485 vty_out(vty
, "local AS %u\n", bgp
->as
);
13486 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13487 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13488 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13489 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13495 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13496 : BGP_SHOW_HEADER
));
13502 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13503 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13504 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13505 json_object
*json_scode
, json_object
*json_ocode
,
13506 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13507 unsigned long *output_count
, unsigned long *filtered_count
)
13509 struct bgp_adj_in
*ain
;
13510 struct bgp_adj_out
*adj
;
13511 struct bgp_dest
*dest
;
13515 struct update_subgroup
*subgrp
;
13516 struct peer_af
*paf
;
13517 bool route_filtered
;
13518 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13519 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13520 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13521 || (safi
== SAFI_EVPN
))
13527 subgrp
= peer_subgroup(peer
, afi
, safi
);
13529 if (type
== bgp_show_adj_route_advertised
&& subgrp
13530 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13532 json_object_int_add(json
, "bgpTableVersion",
13534 json_object_string_addf(json
, "bgpLocalRouterId",
13535 "%pI4", &bgp
->router_id
);
13536 json_object_int_add(json
, "defaultLocPrf",
13537 bgp
->default_local_pref
);
13538 json_object_int_add(json
, "localAS", bgp
->as
);
13539 json_object_object_add(json
, "bgpStatusCodes",
13541 json_object_object_add(json
, "bgpOriginCodes",
13543 json_object_string_add(
13544 json
, "bgpOriginatingDefaultNetwork",
13545 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13548 "BGP table version is %" PRIu64
13549 ", local router ID is %pI4, vrf id ",
13550 table
->version
, &bgp
->router_id
);
13551 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13552 vty_out(vty
, "%s", VRFID_NONE_STR
);
13554 vty_out(vty
, "%u", bgp
->vrf_id
);
13555 vty_out(vty
, "\n");
13556 vty_out(vty
, "Default local pref %u, ",
13557 bgp
->default_local_pref
);
13558 vty_out(vty
, "local AS %u\n", bgp
->as
);
13559 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13560 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13561 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13562 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13564 vty_out(vty
, "Originating default network %s\n\n",
13565 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13570 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13571 if (type
== bgp_show_adj_route_received
13572 || type
== bgp_show_adj_route_filtered
) {
13573 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13574 if (ain
->peer
!= peer
)
13577 show_adj_route_header(vty
, bgp
, table
, header1
,
13578 header2
, json
, json_scode
,
13581 if ((safi
== SAFI_MPLS_VPN
)
13582 || (safi
== SAFI_ENCAP
)
13583 || (safi
== SAFI_EVPN
)) {
13585 json_object_string_add(
13586 json_ar
, "rd", rd_str
);
13587 else if (show_rd
&& rd_str
) {
13589 "Route Distinguisher: %s\n",
13596 route_filtered
= false;
13598 /* Filter prefix using distribute list,
13599 * filter list or prefix list
13601 const struct prefix
*rn_p
=
13602 bgp_dest_get_prefix(dest
);
13603 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13606 route_filtered
= true;
13608 /* Filter prefix using route-map */
13609 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13610 safi
, rmap_name
, NULL
,
13613 if (type
== bgp_show_adj_route_filtered
&&
13614 !route_filtered
&& ret
!= RMAP_DENY
) {
13615 bgp_attr_flush(&attr
);
13619 if (type
== bgp_show_adj_route_received
13620 && (route_filtered
|| ret
== RMAP_DENY
))
13621 (*filtered_count
)++;
13623 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
13624 use_json
, json_ar
, wide
);
13625 bgp_attr_flush(&attr
);
13628 } else if (type
== bgp_show_adj_route_advertised
) {
13629 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13630 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13631 if (paf
->peer
!= peer
|| !adj
->attr
)
13634 show_adj_route_header(vty
, bgp
, table
,
13639 const struct prefix
*rn_p
=
13640 bgp_dest_get_prefix(dest
);
13643 ret
= bgp_output_modifier(
13644 peer
, rn_p
, &attr
, afi
, safi
,
13647 if (ret
!= RMAP_DENY
) {
13648 if ((safi
== SAFI_MPLS_VPN
)
13649 || (safi
== SAFI_ENCAP
)
13650 || (safi
== SAFI_EVPN
)) {
13652 json_object_string_add(
13659 "Route Distinguisher: %s\n",
13665 vty
, dest
, rn_p
, &attr
,
13666 safi
, use_json
, json_ar
,
13670 (*filtered_count
)++;
13673 bgp_attr_flush(&attr
);
13675 } else if (type
== bgp_show_adj_route_bestpath
) {
13676 struct bgp_path_info
*pi
;
13678 show_adj_route_header(vty
, bgp
, table
, header1
, header2
,
13679 json
, json_scode
, json_ocode
,
13682 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13684 if (pi
->peer
!= peer
)
13687 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13690 route_vty_out_tmp(vty
, dest
,
13691 bgp_dest_get_prefix(dest
),
13692 pi
->attr
, safi
, use_json
,
13700 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13701 safi_t safi
, enum bgp_show_adj_route_type type
,
13702 const char *rmap_name
, uint16_t show_flags
)
13705 struct bgp_table
*table
;
13706 json_object
*json
= NULL
;
13707 json_object
*json_scode
= NULL
;
13708 json_object
*json_ocode
= NULL
;
13709 json_object
*json_ar
= NULL
;
13710 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13712 /* Init BGP headers here so they're only displayed once
13713 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13719 * Initialize variables for each RD
13720 * All prefixes under an RD is aggregated within "json_routes"
13722 char rd_str
[BUFSIZ
] = {0};
13723 json_object
*json_routes
= NULL
;
13726 /* For 2-tier tables, prefix counts need to be
13727 * maintained across multiple runs of show_adj_route()
13729 unsigned long output_count_per_rd
;
13730 unsigned long filtered_count_per_rd
;
13731 unsigned long output_count
= 0;
13732 unsigned long filtered_count
= 0;
13735 json
= json_object_new_object();
13736 json_ar
= json_object_new_object();
13737 json_scode
= json_object_new_object();
13738 json_ocode
= json_object_new_object();
13740 json_object_string_add(json_scode
, "suppressed", "s");
13741 json_object_string_add(json_scode
, "damped", "d");
13742 json_object_string_add(json_scode
, "history", "h");
13743 json_object_string_add(json_scode
, "valid", "*");
13744 json_object_string_add(json_scode
, "best", ">");
13745 json_object_string_add(json_scode
, "multipath", "=");
13746 json_object_string_add(json_scode
, "internal", "i");
13747 json_object_string_add(json_scode
, "ribFailure", "r");
13748 json_object_string_add(json_scode
, "stale", "S");
13749 json_object_string_add(json_scode
, "removed", "R");
13751 json_object_string_add(json_ocode
, "igp", "i");
13752 json_object_string_add(json_ocode
, "egp", "e");
13753 json_object_string_add(json_ocode
, "incomplete", "?");
13756 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13758 json_object_string_add(
13760 "No such neighbor or address family");
13761 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13762 json_object_free(json
);
13763 json_object_free(json_ar
);
13764 json_object_free(json_scode
);
13765 json_object_free(json_ocode
);
13767 vty_out(vty
, "%% No such neighbor or address family\n");
13769 return CMD_WARNING
;
13772 if ((type
== bgp_show_adj_route_received
13773 || type
== bgp_show_adj_route_filtered
)
13774 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
13775 PEER_FLAG_SOFT_RECONFIG
)) {
13777 json_object_string_add(
13779 "Inbound soft reconfiguration not enabled");
13780 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13781 json_object_free(json
);
13782 json_object_free(json_ar
);
13783 json_object_free(json_scode
);
13784 json_object_free(json_ocode
);
13787 "%% Inbound soft reconfiguration not enabled\n");
13789 return CMD_WARNING
;
13794 /* labeled-unicast routes live in the unicast table */
13795 if (safi
== SAFI_LABELED_UNICAST
)
13796 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
13798 table
= bgp
->rib
[afi
][safi
];
13800 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13801 || (safi
== SAFI_EVPN
)) {
13803 struct bgp_dest
*dest
;
13805 for (dest
= bgp_table_top(table
); dest
;
13806 dest
= bgp_route_next(dest
)) {
13807 table
= bgp_dest_get_bgp_table_info(dest
);
13811 output_count_per_rd
= 0;
13812 filtered_count_per_rd
= 0;
13815 json_routes
= json_object_new_object();
13817 const struct prefix_rd
*prd
;
13818 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13821 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
13823 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
13824 rmap_name
, json
, json_routes
, json_scode
,
13825 json_ocode
, show_flags
, &header1
,
13826 &header2
, rd_str
, &output_count_per_rd
,
13827 &filtered_count_per_rd
);
13829 /* Don't include an empty RD in the output! */
13830 if (json_routes
&& (output_count_per_rd
> 0))
13831 json_object_object_add(json_ar
, rd_str
,
13834 output_count
+= output_count_per_rd
;
13835 filtered_count
+= filtered_count_per_rd
;
13838 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
13839 json
, json_ar
, json_scode
, json_ocode
,
13840 show_flags
, &header1
, &header2
, rd_str
,
13841 &output_count
, &filtered_count
);
13844 if (type
== bgp_show_adj_route_advertised
)
13845 json_object_object_add(json
, "advertisedRoutes",
13848 json_object_object_add(json
, "receivedRoutes", json_ar
);
13849 json_object_int_add(json
, "totalPrefixCounter", output_count
);
13850 json_object_int_add(json
, "filteredPrefixCounter",
13854 * These fields only give up ownership to `json` when `header1`
13855 * is used (set to zero). See code in `show_adj_route` and
13856 * `show_adj_route_header`.
13858 if (header1
== 1) {
13859 json_object_free(json_scode
);
13860 json_object_free(json_ocode
);
13863 vty_json(vty
, json
);
13864 } else if (output_count
> 0) {
13865 if (filtered_count
> 0)
13867 "\nTotal number of prefixes %ld (%ld filtered)\n",
13868 output_count
, filtered_count
);
13870 vty_out(vty
, "\nTotal number of prefixes %ld\n",
13874 return CMD_SUCCESS
;
13877 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
13878 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
13879 "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]",
13883 BGP_INSTANCE_HELP_STR
13885 BGP_SAFI_WITH_LABEL_HELP_STR
13886 "Detailed information on TCP and BGP neighbor connections\n"
13887 "Neighbor to display information about\n"
13888 "Neighbor to display information about\n"
13889 "Neighbor on BGP configured interface\n"
13890 "Display the routes selected by best path\n"
13892 "Increase table width for longer prefixes\n")
13894 afi_t afi
= AFI_IP6
;
13895 safi_t safi
= SAFI_UNICAST
;
13896 char *rmap_name
= NULL
;
13897 char *peerstr
= NULL
;
13898 struct bgp
*bgp
= NULL
;
13900 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
13902 uint16_t show_flags
= 0;
13905 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13908 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13910 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13914 return CMD_WARNING
;
13916 argv_find(argv
, argc
, "neighbors", &idx
);
13917 peerstr
= argv
[++idx
]->arg
;
13919 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13921 return CMD_WARNING
;
13923 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13927 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
13928 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
13929 "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]",
13933 BGP_INSTANCE_HELP_STR
13935 BGP_SAFI_WITH_LABEL_HELP_STR
13936 "Display the entries for all address families\n"
13937 "Detailed information on TCP and BGP neighbor connections\n"
13938 "Neighbor to display information about\n"
13939 "Neighbor to display information about\n"
13940 "Neighbor on BGP configured interface\n"
13941 "Display the routes advertised to a BGP neighbor\n"
13942 "Display the received routes from neighbor\n"
13943 "Display the filtered routes received from neighbor\n"
13944 "Route-map to modify the attributes\n"
13945 "Name of the route map\n"
13947 "Increase table width for longer prefixes\n")
13949 afi_t afi
= AFI_IP6
;
13950 safi_t safi
= SAFI_UNICAST
;
13951 char *rmap_name
= NULL
;
13952 char *peerstr
= NULL
;
13953 struct bgp
*bgp
= NULL
;
13955 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
13958 uint16_t show_flags
= 0;
13962 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13966 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
13967 if (argv_find(argv
, argc
, "ipv4", &idx
))
13968 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
13970 if (argv_find(argv
, argc
, "ipv6", &idx
))
13971 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
13975 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13977 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13980 return CMD_WARNING
;
13982 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13983 argv_find(argv
, argc
, "neighbors", &idx
);
13984 peerstr
= argv
[++idx
]->arg
;
13986 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13988 return CMD_WARNING
;
13990 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
13991 type
= bgp_show_adj_route_advertised
;
13992 else if (argv_find(argv
, argc
, "received-routes", &idx
))
13993 type
= bgp_show_adj_route_received
;
13994 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
13995 type
= bgp_show_adj_route_filtered
;
13997 if (argv_find(argv
, argc
, "route-map", &idx
))
13998 rmap_name
= argv
[++idx
]->arg
;
14001 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14004 vty_out(vty
, "{\n");
14006 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14007 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14008 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14010 FOREACH_SAFI (safi
) {
14011 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
14018 vty_out(vty
, ",\n");
14019 vty_out(vty
, "\"%s\":",
14020 get_afi_safi_str(afi
, safi
, true));
14022 vty_out(vty
, "\nFor address family: %s\n",
14023 get_afi_safi_str(afi
, safi
, false));
14025 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14029 FOREACH_AFI_SAFI (afi
, safi
) {
14030 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
14037 vty_out(vty
, ",\n");
14038 vty_out(vty
, "\"%s\":",
14039 get_afi_safi_str(afi
, safi
, true));
14041 vty_out(vty
, "\nFor address family: %s\n",
14042 get_afi_safi_str(afi
, safi
, false));
14044 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14049 vty_out(vty
, "}\n");
14051 return CMD_SUCCESS
;
14054 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14055 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14056 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14060 BGP_INSTANCE_HELP_STR
14063 "Address Family modifier\n"
14064 "Detailed information on TCP and BGP neighbor connections\n"
14065 "Neighbor to display information about\n"
14066 "Neighbor to display information about\n"
14067 "Neighbor on BGP configured interface\n"
14068 "Display information received from a BGP neighbor\n"
14069 "Display the prefixlist filter\n"
14072 afi_t afi
= AFI_IP6
;
14073 safi_t safi
= SAFI_UNICAST
;
14074 char *peerstr
= NULL
;
14079 struct bgp
*bgp
= NULL
;
14080 bool uj
= use_json(argc
, argv
);
14085 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14088 return CMD_WARNING
;
14090 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14091 argv_find(argv
, argc
, "neighbors", &idx
);
14092 peerstr
= argv
[++idx
]->arg
;
14094 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14096 return CMD_WARNING
;
14098 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14099 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14102 vty_out(vty
, "Address Family: %s\n",
14103 get_afi_safi_str(afi
, safi
, false));
14104 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14107 vty_out(vty
, "{}\n");
14109 vty_out(vty
, "No functional output\n");
14112 return CMD_SUCCESS
;
14115 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14116 afi_t afi
, safi_t safi
,
14117 enum bgp_show_type type
, bool use_json
)
14119 uint16_t show_flags
= 0;
14122 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14124 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14126 json_object
*json_no
= NULL
;
14127 json_no
= json_object_new_object();
14128 json_object_string_add(
14129 json_no
, "warning",
14130 "No such neighbor or address family");
14131 vty_out(vty
, "%s\n",
14132 json_object_to_json_string(json_no
));
14133 json_object_free(json_no
);
14135 vty_out(vty
, "%% No such neighbor or address family\n");
14136 return CMD_WARNING
;
14139 /* labeled-unicast routes live in the unicast table */
14140 if (safi
== SAFI_LABELED_UNICAST
)
14141 safi
= SAFI_UNICAST
;
14143 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14144 RPKI_NOT_BEING_USED
);
14147 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14148 show_ip_bgp_flowspec_routes_detailed_cmd
,
14149 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14153 BGP_INSTANCE_HELP_STR
14156 "Detailed information on flowspec entries\n"
14159 afi_t afi
= AFI_IP6
;
14160 safi_t safi
= SAFI_UNICAST
;
14161 struct bgp
*bgp
= NULL
;
14163 bool uj
= use_json(argc
, argv
);
14164 uint16_t show_flags
= BGP_SHOW_OPT_DETAIL
;
14168 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14171 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14174 return CMD_WARNING
;
14176 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14177 show_flags
, RPKI_NOT_BEING_USED
);
14180 DEFUN (show_ip_bgp_neighbor_routes
,
14181 show_ip_bgp_neighbor_routes_cmd
,
14182 "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]",
14186 BGP_INSTANCE_HELP_STR
14188 BGP_SAFI_WITH_LABEL_HELP_STR
14189 "Detailed information on TCP and BGP neighbor connections\n"
14190 "Neighbor to display information about\n"
14191 "Neighbor to display information about\n"
14192 "Neighbor on BGP configured interface\n"
14193 "Display flap statistics of the routes learned from neighbor\n"
14194 "Display the dampened routes received from neighbor\n"
14195 "Display routes learned from neighbor\n"
14198 char *peerstr
= NULL
;
14199 struct bgp
*bgp
= NULL
;
14200 afi_t afi
= AFI_IP6
;
14201 safi_t safi
= SAFI_UNICAST
;
14203 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14205 bool uj
= use_json(argc
, argv
);
14210 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14213 return CMD_WARNING
;
14215 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14216 argv_find(argv
, argc
, "neighbors", &idx
);
14217 peerstr
= argv
[++idx
]->arg
;
14219 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14221 return CMD_WARNING
;
14223 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14224 sh_type
= bgp_show_type_flap_neighbor
;
14225 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14226 sh_type
= bgp_show_type_damp_neighbor
;
14227 else if (argv_find(argv
, argc
, "routes", &idx
))
14228 sh_type
= bgp_show_type_neighbor
;
14230 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14233 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14235 struct bgp_distance
{
14236 /* Distance value for the IP source prefix. */
14239 /* Name of the access-list to be matched. */
14243 DEFUN (show_bgp_afi_vpn_rd_route
,
14244 show_bgp_afi_vpn_rd_route_cmd
,
14245 "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]",
14249 "Address Family modifier\n"
14250 "Display information for a route distinguisher\n"
14251 "Route Distinguisher\n"
14252 "All Route Distinguishers\n"
14253 "Network in the BGP routing table to display\n"
14254 "Network in the BGP routing table to display\n"
14258 struct prefix_rd prd
;
14259 afi_t afi
= AFI_MAX
;
14262 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14263 vty_out(vty
, "%% Malformed Address Family\n");
14264 return CMD_WARNING
;
14267 if (!strcmp(argv
[5]->arg
, "all"))
14268 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14269 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14270 RPKI_NOT_BEING_USED
,
14271 use_json(argc
, argv
));
14273 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14275 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14276 return CMD_WARNING
;
14279 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14280 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14281 use_json(argc
, argv
));
14284 static struct bgp_distance
*bgp_distance_new(void)
14286 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14289 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14291 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14294 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14295 const char *ip_str
, const char *access_list_str
)
14302 struct bgp_dest
*dest
;
14303 struct bgp_distance
*bdistance
;
14305 afi
= bgp_node_afi(vty
);
14306 safi
= bgp_node_safi(vty
);
14308 ret
= str2prefix(ip_str
, &p
);
14310 vty_out(vty
, "Malformed prefix\n");
14311 return CMD_WARNING_CONFIG_FAILED
;
14314 distance
= atoi(distance_str
);
14316 /* Get BGP distance node. */
14317 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14318 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14320 bgp_dest_unlock_node(dest
);
14322 bdistance
= bgp_distance_new();
14323 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14326 /* Set distance value. */
14327 bdistance
->distance
= distance
;
14329 /* Reset access-list configuration. */
14330 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14331 if (access_list_str
)
14332 bdistance
->access_list
=
14333 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14335 return CMD_SUCCESS
;
14338 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14339 const char *ip_str
, const char *access_list_str
)
14346 struct bgp_dest
*dest
;
14347 struct bgp_distance
*bdistance
;
14349 afi
= bgp_node_afi(vty
);
14350 safi
= bgp_node_safi(vty
);
14352 ret
= str2prefix(ip_str
, &p
);
14354 vty_out(vty
, "Malformed prefix\n");
14355 return CMD_WARNING_CONFIG_FAILED
;
14358 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14360 vty_out(vty
, "Can't find specified prefix\n");
14361 return CMD_WARNING_CONFIG_FAILED
;
14364 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14365 distance
= atoi(distance_str
);
14367 if (bdistance
->distance
!= distance
) {
14368 vty_out(vty
, "Distance does not match configured\n");
14369 bgp_dest_unlock_node(dest
);
14370 return CMD_WARNING_CONFIG_FAILED
;
14373 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14374 bgp_distance_free(bdistance
);
14376 bgp_dest_set_bgp_path_info(dest
, NULL
);
14377 bgp_dest_unlock_node(dest
);
14378 bgp_dest_unlock_node(dest
);
14380 return CMD_SUCCESS
;
14383 /* Apply BGP information to distance method. */
14384 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14385 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14387 struct bgp_dest
*dest
;
14388 struct prefix q
= {0};
14390 struct bgp_distance
*bdistance
;
14391 struct access_list
*alist
;
14392 struct bgp_static
*bgp_static
;
14397 peer
= pinfo
->peer
;
14399 if (pinfo
->attr
->distance
)
14400 return pinfo
->attr
->distance
;
14402 /* Check source address.
14403 * Note: for aggregate route, peer can have unspec af type.
14405 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14406 && !sockunion2hostprefix(&peer
->su
, &q
))
14409 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14411 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14412 bgp_dest_unlock_node(dest
);
14414 if (bdistance
->access_list
) {
14415 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14417 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14418 return bdistance
->distance
;
14420 return bdistance
->distance
;
14423 /* Backdoor check. */
14424 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14426 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14427 bgp_dest_unlock_node(dest
);
14429 if (bgp_static
->backdoor
) {
14430 if (bgp
->distance_local
[afi
][safi
])
14431 return bgp
->distance_local
[afi
][safi
];
14433 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14437 if (peer
->sort
== BGP_PEER_EBGP
) {
14438 if (bgp
->distance_ebgp
[afi
][safi
])
14439 return bgp
->distance_ebgp
[afi
][safi
];
14440 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14441 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14442 if (bgp
->distance_ibgp
[afi
][safi
])
14443 return bgp
->distance_ibgp
[afi
][safi
];
14444 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14446 if (bgp
->distance_local
[afi
][safi
])
14447 return bgp
->distance_local
[afi
][safi
];
14448 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14452 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14453 * we should tell ZEBRA update the routes for a specific
14454 * AFI/SAFI to reflect changes in RIB.
14456 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
14458 safi_t update_safi
)
14463 FOREACH_AFI_SAFI (afi
, safi
) {
14464 if (!bgp_fibupd_safi(safi
))
14467 if (afi
!= update_afi
&& safi
!= update_safi
)
14470 if (BGP_DEBUG(zebra
, ZEBRA
))
14472 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14473 __func__
, afi
, safi
);
14474 bgp_zebra_announce_table(bgp
, afi
, safi
);
14478 DEFUN (bgp_distance
,
14480 "distance bgp (1-255) (1-255) (1-255)",
14481 "Define an administrative distance\n"
14483 "Distance for routes external to the AS\n"
14484 "Distance for routes internal to the AS\n"
14485 "Distance for local routes\n")
14487 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14488 int idx_number
= 2;
14489 int idx_number_2
= 3;
14490 int idx_number_3
= 4;
14491 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
14492 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
14493 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
14497 afi
= bgp_node_afi(vty
);
14498 safi
= bgp_node_safi(vty
);
14500 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
14501 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
14502 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
14503 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
14504 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
14505 bgp
->distance_local
[afi
][safi
] = distance_local
;
14506 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14508 return CMD_SUCCESS
;
14511 DEFUN (no_bgp_distance
,
14512 no_bgp_distance_cmd
,
14513 "no distance bgp [(1-255) (1-255) (1-255)]",
14515 "Define an administrative distance\n"
14517 "Distance for routes external to the AS\n"
14518 "Distance for routes internal to the AS\n"
14519 "Distance for local routes\n")
14521 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14525 afi
= bgp_node_afi(vty
);
14526 safi
= bgp_node_safi(vty
);
14528 if (bgp
->distance_ebgp
[afi
][safi
] != 0
14529 || bgp
->distance_ibgp
[afi
][safi
] != 0
14530 || bgp
->distance_local
[afi
][safi
] != 0) {
14531 bgp
->distance_ebgp
[afi
][safi
] = 0;
14532 bgp
->distance_ibgp
[afi
][safi
] = 0;
14533 bgp
->distance_local
[afi
][safi
] = 0;
14534 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14536 return CMD_SUCCESS
;
14540 DEFUN (bgp_distance_source
,
14541 bgp_distance_source_cmd
,
14542 "distance (1-255) A.B.C.D/M",
14543 "Define an administrative distance\n"
14544 "Administrative distance\n"
14545 "IP source prefix\n")
14547 int idx_number
= 1;
14548 int idx_ipv4_prefixlen
= 2;
14549 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14550 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14551 return CMD_SUCCESS
;
14554 DEFUN (no_bgp_distance_source
,
14555 no_bgp_distance_source_cmd
,
14556 "no distance (1-255) A.B.C.D/M",
14558 "Define an administrative distance\n"
14559 "Administrative distance\n"
14560 "IP source prefix\n")
14562 int idx_number
= 2;
14563 int idx_ipv4_prefixlen
= 3;
14564 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14565 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14566 return CMD_SUCCESS
;
14569 DEFUN (bgp_distance_source_access_list
,
14570 bgp_distance_source_access_list_cmd
,
14571 "distance (1-255) A.B.C.D/M WORD",
14572 "Define an administrative distance\n"
14573 "Administrative distance\n"
14574 "IP source prefix\n"
14575 "Access list name\n")
14577 int idx_number
= 1;
14578 int idx_ipv4_prefixlen
= 2;
14580 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14581 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14582 return CMD_SUCCESS
;
14585 DEFUN (no_bgp_distance_source_access_list
,
14586 no_bgp_distance_source_access_list_cmd
,
14587 "no distance (1-255) A.B.C.D/M WORD",
14589 "Define an administrative distance\n"
14590 "Administrative distance\n"
14591 "IP source prefix\n"
14592 "Access list name\n")
14594 int idx_number
= 2;
14595 int idx_ipv4_prefixlen
= 3;
14597 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14598 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14599 return CMD_SUCCESS
;
14602 DEFUN (ipv6_bgp_distance_source
,
14603 ipv6_bgp_distance_source_cmd
,
14604 "distance (1-255) X:X::X:X/M",
14605 "Define an administrative distance\n"
14606 "Administrative distance\n"
14607 "IP source prefix\n")
14609 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
14610 return CMD_SUCCESS
;
14613 DEFUN (no_ipv6_bgp_distance_source
,
14614 no_ipv6_bgp_distance_source_cmd
,
14615 "no distance (1-255) X:X::X:X/M",
14617 "Define an administrative distance\n"
14618 "Administrative distance\n"
14619 "IP source prefix\n")
14621 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
14622 return CMD_SUCCESS
;
14625 DEFUN (ipv6_bgp_distance_source_access_list
,
14626 ipv6_bgp_distance_source_access_list_cmd
,
14627 "distance (1-255) X:X::X:X/M WORD",
14628 "Define an administrative distance\n"
14629 "Administrative distance\n"
14630 "IP source prefix\n"
14631 "Access list name\n")
14633 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
14634 return CMD_SUCCESS
;
14637 DEFUN (no_ipv6_bgp_distance_source_access_list
,
14638 no_ipv6_bgp_distance_source_access_list_cmd
,
14639 "no distance (1-255) X:X::X:X/M WORD",
14641 "Define an administrative distance\n"
14642 "Administrative distance\n"
14643 "IP source prefix\n"
14644 "Access list name\n")
14646 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
14647 return CMD_SUCCESS
;
14650 DEFUN (bgp_damp_set
,
14652 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
14653 "BGP Specific commands\n"
14654 "Enable route-flap dampening\n"
14655 "Half-life time for the penalty\n"
14656 "Value to start reusing a route\n"
14657 "Value to start suppressing a route\n"
14658 "Maximum duration to suppress a stable route\n")
14660 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14661 int idx_half_life
= 2;
14663 int idx_suppress
= 4;
14664 int idx_max_suppress
= 5;
14665 int half
= DEFAULT_HALF_LIFE
* 60;
14666 int reuse
= DEFAULT_REUSE
;
14667 int suppress
= DEFAULT_SUPPRESS
;
14668 int max
= 4 * half
;
14671 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14672 reuse
= atoi(argv
[idx_reuse
]->arg
);
14673 suppress
= atoi(argv
[idx_suppress
]->arg
);
14674 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
14675 } else if (argc
== 3) {
14676 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14681 * These can't be 0 but our SA doesn't understand the
14682 * way our cli is constructed
14686 if (suppress
< reuse
) {
14688 "Suppress value cannot be less than reuse value \n");
14692 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
14693 reuse
, suppress
, max
);
14696 DEFUN (bgp_damp_unset
,
14697 bgp_damp_unset_cmd
,
14698 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
14700 "BGP Specific commands\n"
14701 "Enable route-flap dampening\n"
14702 "Half-life time for the penalty\n"
14703 "Value to start reusing a route\n"
14704 "Value to start suppressing a route\n"
14705 "Maximum duration to suppress a stable route\n")
14707 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14708 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
14711 /* Display specified route of BGP table. */
14712 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14713 const char *ip_str
, afi_t afi
, safi_t safi
,
14714 struct prefix_rd
*prd
, int prefix_check
)
14717 struct prefix match
;
14718 struct bgp_dest
*dest
;
14719 struct bgp_dest
*rm
;
14720 struct bgp_path_info
*pi
;
14721 struct bgp_path_info
*pi_temp
;
14723 struct bgp_table
*table
;
14725 /* BGP structure lookup. */
14727 bgp
= bgp_lookup_by_name(view_name
);
14729 vty_out(vty
, "%% Can't find BGP instance %s\n",
14731 return CMD_WARNING
;
14734 bgp
= bgp_get_default();
14736 vty_out(vty
, "%% No BGP process is configured\n");
14737 return CMD_WARNING
;
14741 /* Check IP address argument. */
14742 ret
= str2prefix(ip_str
, &match
);
14744 vty_out(vty
, "%% address is malformed\n");
14745 return CMD_WARNING
;
14748 match
.family
= afi2family(afi
);
14750 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14751 || (safi
== SAFI_EVPN
)) {
14752 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
14753 dest
= bgp_route_next(dest
)) {
14754 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14756 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
14758 table
= bgp_dest_get_bgp_table_info(dest
);
14761 rm
= bgp_node_match(table
, &match
);
14765 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
14768 || rm_p
->prefixlen
== match
.prefixlen
) {
14769 pi
= bgp_dest_get_bgp_path_info(rm
);
14771 if (pi
->extra
&& pi
->extra
->damp_info
) {
14772 pi_temp
= pi
->next
;
14773 bgp_damp_info_free(
14774 pi
->extra
->damp_info
,
14782 bgp_dest_unlock_node(rm
);
14785 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
14786 if (dest
!= NULL
) {
14787 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14790 || dest_p
->prefixlen
== match
.prefixlen
) {
14791 pi
= bgp_dest_get_bgp_path_info(dest
);
14793 if (pi
->extra
&& pi
->extra
->damp_info
) {
14794 pi_temp
= pi
->next
;
14795 bgp_damp_info_free(
14796 pi
->extra
->damp_info
,
14804 bgp_dest_unlock_node(dest
);
14808 return CMD_SUCCESS
;
14811 DEFUN (clear_ip_bgp_dampening
,
14812 clear_ip_bgp_dampening_cmd
,
14813 "clear ip bgp dampening",
14817 "Clear route flap dampening information\n")
14819 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
14820 return CMD_SUCCESS
;
14823 DEFUN (clear_ip_bgp_dampening_prefix
,
14824 clear_ip_bgp_dampening_prefix_cmd
,
14825 "clear ip bgp dampening A.B.C.D/M",
14829 "Clear route flap dampening information\n"
14832 int idx_ipv4_prefixlen
= 4;
14833 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
14834 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
14837 DEFUN (clear_ip_bgp_dampening_address
,
14838 clear_ip_bgp_dampening_address_cmd
,
14839 "clear ip bgp dampening A.B.C.D",
14843 "Clear route flap dampening information\n"
14844 "Network to clear damping information\n")
14847 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
14848 SAFI_UNICAST
, NULL
, 0);
14851 DEFUN (clear_ip_bgp_dampening_address_mask
,
14852 clear_ip_bgp_dampening_address_mask_cmd
,
14853 "clear ip bgp dampening A.B.C.D A.B.C.D",
14857 "Clear route flap dampening information\n"
14858 "Network to clear damping information\n"
14862 int idx_ipv4_2
= 5;
14864 char prefix_str
[BUFSIZ
];
14866 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
14867 prefix_str
, sizeof(prefix_str
));
14869 vty_out(vty
, "%% Inconsistent address and mask\n");
14870 return CMD_WARNING
;
14873 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
14877 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
14879 struct vty
*vty
= arg
;
14880 struct peer
*peer
= bucket
->data
;
14881 char buf
[SU_ADDRSTRLEN
];
14883 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
14884 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
14887 DEFUN (show_bgp_listeners
,
14888 show_bgp_listeners_cmd
,
14889 "show bgp listeners",
14892 "Display Listen Sockets and who created them\n")
14894 bgp_dump_listener_info(vty
);
14896 return CMD_SUCCESS
;
14899 DEFUN (show_bgp_peerhash
,
14900 show_bgp_peerhash_cmd
,
14901 "show bgp peerhash",
14904 "Display information about the BGP peerhash\n")
14906 struct list
*instances
= bm
->bgp
;
14907 struct listnode
*node
;
14910 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
14911 vty_out(vty
, "BGP: %s\n", bgp
->name
);
14912 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
14916 return CMD_SUCCESS
;
14919 /* also used for encap safi */
14920 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
14921 afi_t afi
, safi_t safi
)
14923 struct bgp_dest
*pdest
;
14924 struct bgp_dest
*dest
;
14925 struct bgp_table
*table
;
14926 const struct prefix
*p
;
14927 const struct prefix_rd
*prd
;
14928 struct bgp_static
*bgp_static
;
14929 mpls_label_t label
;
14930 char rdbuf
[RD_ADDRSTRLEN
];
14932 /* Network configuration. */
14933 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14934 pdest
= bgp_route_next(pdest
)) {
14935 table
= bgp_dest_get_bgp_table_info(pdest
);
14939 for (dest
= bgp_table_top(table
); dest
;
14940 dest
= bgp_route_next(dest
)) {
14941 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14942 if (bgp_static
== NULL
)
14945 p
= bgp_dest_get_prefix(dest
);
14946 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14949 /* "network" configuration display. */
14950 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14951 label
= decode_label(&bgp_static
->label
);
14953 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
14954 if (safi
== SAFI_MPLS_VPN
)
14955 vty_out(vty
, " label %u", label
);
14957 if (bgp_static
->rmap
.name
)
14958 vty_out(vty
, " route-map %s",
14959 bgp_static
->rmap
.name
);
14961 if (bgp_static
->backdoor
)
14962 vty_out(vty
, " backdoor");
14964 vty_out(vty
, "\n");
14969 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
14970 afi_t afi
, safi_t safi
)
14972 struct bgp_dest
*pdest
;
14973 struct bgp_dest
*dest
;
14974 struct bgp_table
*table
;
14975 const struct prefix
*p
;
14976 const struct prefix_rd
*prd
;
14977 struct bgp_static
*bgp_static
;
14978 char buf
[PREFIX_STRLEN
* 2];
14979 char buf2
[SU_ADDRSTRLEN
];
14980 char rdbuf
[RD_ADDRSTRLEN
];
14981 char esi_buf
[ESI_BYTES
];
14983 /* Network configuration. */
14984 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14985 pdest
= bgp_route_next(pdest
)) {
14986 table
= bgp_dest_get_bgp_table_info(pdest
);
14990 for (dest
= bgp_table_top(table
); dest
;
14991 dest
= bgp_route_next(dest
)) {
14992 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14993 if (bgp_static
== NULL
)
14996 char *macrouter
= NULL
;
14998 if (bgp_static
->router_mac
)
14999 macrouter
= prefix_mac2str(
15000 bgp_static
->router_mac
, NULL
, 0);
15001 if (bgp_static
->eth_s_id
)
15002 esi_to_str(bgp_static
->eth_s_id
,
15003 esi_buf
, sizeof(esi_buf
));
15004 p
= bgp_dest_get_prefix(dest
);
15005 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15007 /* "network" configuration display. */
15008 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
15009 if (p
->u
.prefix_evpn
.route_type
== 5) {
15010 char local_buf
[PREFIX_STRLEN
];
15011 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15012 struct prefix_evpn
*)p
)
15016 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
15017 local_buf
, PREFIX_STRLEN
);
15018 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15019 p
->u
.prefix_evpn
.prefix_addr
15020 .ip_prefix_length
);
15022 prefix2str(p
, buf
, sizeof(buf
));
15025 if (bgp_static
->gatewayIp
.family
== AF_INET
15026 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15027 inet_ntop(bgp_static
->gatewayIp
.family
,
15028 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15031 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15033 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15034 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15037 XFREE(MTYPE_TMP
, macrouter
);
15042 /* Configuration of static route announcement and aggregate
15044 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15047 struct bgp_dest
*dest
;
15048 const struct prefix
*p
;
15049 struct bgp_static
*bgp_static
;
15050 struct bgp_aggregate
*bgp_aggregate
;
15052 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15053 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15057 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15058 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15062 /* Network configuration. */
15063 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15064 dest
= bgp_route_next(dest
)) {
15065 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15066 if (bgp_static
== NULL
)
15069 p
= bgp_dest_get_prefix(dest
);
15071 vty_out(vty
, " network %pFX", p
);
15073 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15074 vty_out(vty
, " label-index %u",
15075 bgp_static
->label_index
);
15077 if (bgp_static
->rmap
.name
)
15078 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15080 if (bgp_static
->backdoor
)
15081 vty_out(vty
, " backdoor");
15083 vty_out(vty
, "\n");
15086 /* Aggregate-address configuration. */
15087 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15088 dest
= bgp_route_next(dest
)) {
15089 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15090 if (bgp_aggregate
== NULL
)
15093 p
= bgp_dest_get_prefix(dest
);
15095 vty_out(vty
, " aggregate-address %pFX", p
);
15097 if (bgp_aggregate
->as_set
)
15098 vty_out(vty
, " as-set");
15100 if (bgp_aggregate
->summary_only
)
15101 vty_out(vty
, " summary-only");
15103 if (bgp_aggregate
->rmap
.name
)
15104 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15106 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15107 vty_out(vty
, " origin %s",
15108 bgp_origin2str(bgp_aggregate
->origin
));
15110 if (bgp_aggregate
->match_med
)
15111 vty_out(vty
, " matching-MED-only");
15113 if (bgp_aggregate
->suppress_map_name
)
15114 vty_out(vty
, " suppress-map %s",
15115 bgp_aggregate
->suppress_map_name
);
15117 vty_out(vty
, "\n");
15121 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15124 struct bgp_dest
*dest
;
15125 struct bgp_distance
*bdistance
;
15127 /* Distance configuration. */
15128 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15129 && bgp
->distance_local
[afi
][safi
]
15130 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15131 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15132 || bgp
->distance_local
[afi
][safi
]
15133 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15134 vty_out(vty
, " distance bgp %d %d %d\n",
15135 bgp
->distance_ebgp
[afi
][safi
],
15136 bgp
->distance_ibgp
[afi
][safi
],
15137 bgp
->distance_local
[afi
][safi
]);
15140 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15141 dest
= bgp_route_next(dest
)) {
15142 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15143 if (bdistance
!= NULL
)
15144 vty_out(vty
, " distance %d %pBD %s\n",
15145 bdistance
->distance
, dest
,
15146 bdistance
->access_list
? bdistance
->access_list
15151 /* Allocate routing table structure and install commands. */
15152 void bgp_route_init(void)
15157 /* Init BGP distance table. */
15158 FOREACH_AFI_SAFI (afi
, safi
)
15159 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15161 /* IPv4 BGP commands. */
15162 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15163 install_element(BGP_NODE
, &bgp_network_cmd
);
15164 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15166 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15168 /* IPv4 unicast configuration. */
15169 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15170 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15171 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15173 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15175 /* IPv4 multicast configuration. */
15176 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15177 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15178 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15179 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15181 /* IPv4 labeled-unicast configuration. */
15182 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15183 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15185 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15186 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15187 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15188 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15189 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15190 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15191 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15192 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15194 install_element(VIEW_NODE
,
15195 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15196 install_element(VIEW_NODE
,
15197 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15198 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15199 install_element(VIEW_NODE
,
15200 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15201 #ifdef KEEP_OLD_VPN_COMMANDS
15202 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15203 #endif /* KEEP_OLD_VPN_COMMANDS */
15204 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15205 install_element(VIEW_NODE
,
15206 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15208 /* BGP dampening clear commands */
15209 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15210 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15212 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15213 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15216 install_element(ENABLE_NODE
,
15217 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15218 #ifdef KEEP_OLD_VPN_COMMANDS
15219 install_element(ENABLE_NODE
,
15220 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15221 #endif /* KEEP_OLD_VPN_COMMANDS */
15223 /* New config IPv6 BGP commands. */
15224 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15225 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15226 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15228 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15230 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15232 /* IPv6 labeled unicast address family. */
15233 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15234 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15236 install_element(BGP_NODE
, &bgp_distance_cmd
);
15237 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15238 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15239 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15240 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15241 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15242 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15243 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15244 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15245 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15246 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15247 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15248 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15249 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15250 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15251 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15252 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15253 install_element(BGP_IPV4M_NODE
,
15254 &no_bgp_distance_source_access_list_cmd
);
15255 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15256 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15257 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15258 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15259 install_element(BGP_IPV6_NODE
,
15260 &ipv6_bgp_distance_source_access_list_cmd
);
15261 install_element(BGP_IPV6_NODE
,
15262 &no_ipv6_bgp_distance_source_access_list_cmd
);
15263 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15264 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15265 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15266 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15267 install_element(BGP_IPV6M_NODE
,
15268 &ipv6_bgp_distance_source_access_list_cmd
);
15269 install_element(BGP_IPV6M_NODE
,
15270 &no_ipv6_bgp_distance_source_access_list_cmd
);
15272 /* BGP dampening */
15273 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15274 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15275 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15276 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15277 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15278 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15279 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15280 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15281 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15282 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15283 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15284 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15285 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15286 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15288 /* Large Communities */
15289 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15290 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15292 /* show bgp ipv4 flowspec detailed */
15293 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15295 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15296 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15299 void bgp_route_finish(void)
15304 FOREACH_AFI_SAFI (afi
, safi
) {
15305 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15306 bgp_distance_table
[afi
][safi
] = NULL
;