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 enum bgp_peer_sort new_sort
;
569 enum bgp_peer_sort 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 comparison. */
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 comparison, 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 comparison. */
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 comparison. */
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 structure 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 structure 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);
1774 void bgp_attr_add_gshut_community(struct attr
*attr
)
1776 struct community
*old
;
1777 struct community
*new;
1778 struct community
*merge
;
1779 struct community
*gshut
;
1781 old
= bgp_attr_get_community(attr
);
1782 gshut
= community_str2com("graceful-shutdown");
1787 merge
= community_merge(community_dup(old
), gshut
);
1789 if (old
->refcnt
== 0)
1790 community_free(&old
);
1792 new = community_uniq_sort(merge
);
1793 community_free(&merge
);
1795 new = community_dup(gshut
);
1798 community_free(&gshut
);
1799 bgp_attr_set_community(attr
, new);
1801 /* When we add the graceful-shutdown community we must also
1802 * lower the local-preference */
1803 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1804 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1808 /* Notify BGP Conditional advertisement scanner process. */
1809 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1811 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1812 afi_t afi
= SUBGRP_AFI(subgrp
);
1813 safi_t safi
= SUBGRP_SAFI(subgrp
);
1814 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1816 if (!ADVERTISE_MAP_NAME(filter
))
1819 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1822 peer
->advmap_table_change
= true;
1826 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1828 if (family
== AF_INET
) {
1829 attr
->nexthop
.s_addr
= INADDR_ANY
;
1830 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1832 if (family
== AF_INET6
)
1833 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1834 if (family
== AF_EVPN
)
1835 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1838 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1839 struct update_subgroup
*subgrp
,
1840 const struct prefix
*p
, struct attr
*attr
,
1841 struct attr
*post_attr
)
1843 struct bgp_filter
*filter
;
1846 struct peer
*onlypeer
;
1848 struct attr
*piattr
;
1849 route_map_result_t ret
;
1854 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1855 bool nh_reset
= false;
1858 if (DISABLE_BGP_ANNOUNCE
)
1861 afi
= SUBGRP_AFI(subgrp
);
1862 safi
= SUBGRP_SAFI(subgrp
);
1863 peer
= SUBGRP_PEER(subgrp
);
1865 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1866 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1869 filter
= &peer
->filter
[afi
][safi
];
1870 bgp
= SUBGRP_INST(subgrp
);
1871 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1874 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
1875 peer
->pmax_out
[afi
][safi
] != 0 &&
1876 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
1877 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
1878 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
1879 zlog_debug("%s reached maximum prefix to be send (%u)",
1880 peer
->host
, peer
->pmax_out
[afi
][safi
]);
1885 #ifdef ENABLE_BGP_VNC
1886 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1887 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1888 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1891 * direct and direct_ext type routes originate internally even
1892 * though they can have peer pointers that reference other
1895 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1901 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1902 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1903 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1904 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1906 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1911 /* With addpath we may be asked to TX all kinds of paths so make sure
1913 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1914 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1915 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1919 /* If this is not the bestpath then check to see if there is an enabled
1921 * feature that requires us to advertise it */
1922 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1923 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1928 /* Aggregate-address suppress check. */
1929 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
1933 * If we are doing VRF 2 VRF leaking via the import
1934 * statement, we want to prevent the route going
1935 * off box as that the RT and RD created are localy
1936 * significant and globaly useless.
1938 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1939 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1942 /* If it's labeled safi, make sure the route has a valid label. */
1943 if (safi
== SAFI_LABELED_UNICAST
) {
1944 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1945 if (!bgp_is_valid_label(&label
)) {
1946 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1947 zlog_debug("u%" PRIu64
":s%" PRIu64
1948 " %pFX is filtered - no label (%p)",
1949 subgrp
->update_group
->id
, subgrp
->id
,
1955 /* Do not send back route to sender. */
1956 if (onlypeer
&& from
== onlypeer
) {
1960 /* Do not send the default route in the BGP table if the neighbor is
1961 * configured for default-originate */
1962 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1963 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1964 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1966 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1970 /* Transparency check. */
1971 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1972 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1977 /* If community is not disabled check the no-export and local. */
1978 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1979 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1980 zlog_debug("%s: community filter check fail for %pFX",
1985 /* If the attribute has originator-id and it is same as remote
1987 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1988 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1989 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1991 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1996 /* ORF prefix-list filter check */
1997 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1998 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1999 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2000 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2001 if (peer
->orf_plist
[afi
][safi
]) {
2002 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2004 if (bgp_debug_update(NULL
, p
,
2005 subgrp
->update_group
, 0))
2007 "%s [Update:SEND] %pFX is filtered via ORF",
2013 /* Output filter check. */
2014 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2015 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2016 zlog_debug("%s [Update:SEND] %pFX is filtered",
2021 /* AS path loop check. */
2022 if (onlypeer
&& onlypeer
->as_path_loop_detection
2023 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
2024 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2026 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2027 onlypeer
->host
, onlypeer
->as
);
2031 /* If we're a CONFED we need to loop check the CONFED ID too */
2032 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2033 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
2034 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2036 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
2037 peer
->host
, bgp
->confed_id
);
2042 /* Route-Reflect check. */
2043 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2048 /* IBGP reflection check. */
2049 if (reflect
&& !samepeer_safe
) {
2050 /* A route from a Client peer. */
2051 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2052 PEER_FLAG_REFLECTOR_CLIENT
)) {
2053 /* Reflect to all the Non-Client peers and also to the
2054 Client peers other than the originator. Originator
2056 is already done. So there is noting to do. */
2057 /* no bgp client-to-client reflection check. */
2058 if (CHECK_FLAG(bgp
->flags
,
2059 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2060 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2061 PEER_FLAG_REFLECTOR_CLIENT
))
2064 /* A route from a Non-client peer. Reflect to all other
2066 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2067 PEER_FLAG_REFLECTOR_CLIENT
))
2072 /* For modify attribute, copy it to temporary structure.
2073 * post_attr comes from BGP conditional advertisements, where
2074 * attributes are already processed by advertise-map route-map,
2075 * and this needs to be saved instead of overwriting from the
2083 /* If local-preference is not set. */
2084 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2085 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2086 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2087 attr
->local_pref
= bgp
->default_local_pref
;
2090 /* If originator-id is not set and the route is to be reflected,
2091 set the originator id */
2093 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2094 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2095 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2098 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2100 if (peer
->sort
== BGP_PEER_EBGP
2101 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2102 if (from
!= bgp
->peer_self
&& !transparent
2103 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2104 PEER_FLAG_MED_UNCHANGED
))
2106 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2109 /* Since the nexthop attribute can vary per peer, it is not explicitly
2111 * in announce check, only certain flags and length (or number of
2113 * -- for IPv6/MP_REACH) are set here in order to guide the update
2115 * code in setting the nexthop(s) on a per peer basis in
2117 * Typically, the source nexthop in the attribute is preserved but in
2119 * scenarios where we know it will always be overwritten, we reset the
2120 * nexthop to "0" in an attempt to achieve better Update packing. An
2121 * example of this is when a prefix from each of 2 IBGP peers needs to
2123 * announced to an EBGP peer (and they have the same attributes barring
2127 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2129 #define NEXTHOP_IS_V6 \
2130 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2131 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2132 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2133 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2135 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2137 * the peer (group) is configured to receive link-local nexthop
2139 * and it is available in the prefix OR we're not reflecting the route,
2140 * link-local nexthop address is valid and
2141 * the peer (group) to whom we're going to announce is on a shared
2143 * and this is either a self-originated route or the peer is EBGP.
2144 * By checking if nexthop LL address is valid we are sure that
2145 * we do not announce LL address as `::`.
2147 if (NEXTHOP_IS_V6
) {
2148 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2149 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2150 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2151 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2152 || (!reflect
&& !transparent
2153 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2154 && peer
->shared_network
2155 && (from
== bgp
->peer_self
2156 || peer
->sort
== BGP_PEER_EBGP
))) {
2157 attr
->mp_nexthop_len
=
2158 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2161 /* Clear off link-local nexthop in source, whenever it is not
2163 * ensure more prefixes share the same attribute for
2166 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2167 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2168 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2171 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2172 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2174 /* Route map & unsuppress-map apply. */
2176 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2177 struct bgp_path_info rmap_path
= {0};
2178 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2179 struct attr dummy_attr
= {0};
2181 /* Fill temp path_info */
2182 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2185 /* don't confuse inbound and outbound setting */
2186 RESET_FLAG(attr
->rmap_change_flags
);
2189 * The route reflector is not allowed to modify the attributes
2190 * of the reflected IBGP routes unless explicitly allowed.
2192 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2193 && !CHECK_FLAG(bgp
->flags
,
2194 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2196 rmap_path
.attr
= &dummy_attr
;
2199 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2201 if (bgp_path_suppressed(pi
))
2202 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2205 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2208 bgp_attr_flush(&dummy_attr
);
2209 peer
->rmap_type
= 0;
2211 if (ret
== RMAP_DENYMATCH
) {
2212 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2214 "%s [Update:SEND] %pFX is filtered by route-map '%s'",
2216 ROUTE_MAP_OUT_NAME(filter
));
2222 /* RFC 8212 to prevent route leaks.
2223 * This specification intends to improve this situation by requiring the
2224 * explicit configuration of both BGP Import and Export Policies for any
2225 * External BGP (EBGP) session such as customers, peers, or
2226 * confederation boundaries for all enabled address families. Through
2227 * codification of the aforementioned requirement, operators will
2228 * benefit from consistent behavior across different BGP
2231 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2232 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2233 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2234 NULL
) > FIFTEENMINUTE2USEC
||
2235 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2237 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2238 monotime(&bgp
->ebgprequirespolicywarning
);
2243 /* draft-ietf-idr-deprecate-as-set-confed-set
2244 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2245 * Eventually, This document (if approved) updates RFC 4271
2246 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2247 * and obsoletes RFC 6472.
2249 if (peer
->bgp
->reject_as_sets
)
2250 if (aspath_check_as_sets(attr
->aspath
))
2253 /* Codification of AS 0 Processing */
2254 if (aspath_check_as_zero(attr
->aspath
))
2257 if (bgp_in_graceful_shutdown(bgp
)) {
2258 if (peer
->sort
== BGP_PEER_IBGP
2259 || peer
->sort
== BGP_PEER_CONFED
) {
2260 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2261 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2263 bgp_attr_add_gshut_community(attr
);
2267 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2268 * Capability" to a neighbor MUST perform the following upon receiving
2269 * a route from that neighbor with the "LLGR_STALE" community, or upon
2270 * attaching the "LLGR_STALE" community itself per Section 4.2:
2272 * The route SHOULD NOT be advertised to any neighbor from which the
2273 * Long-lived Graceful Restart Capability has not been received.
2275 if (bgp_attr_get_community(attr
) &&
2276 community_include(bgp_attr_get_community(attr
),
2277 COMMUNITY_LLGR_STALE
) &&
2278 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2279 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2282 /* After route-map has been applied, we check to see if the nexthop to
2283 * be carried in the attribute (that is used for the announcement) can
2284 * be cleared off or not. We do this in all cases where we would be
2285 * setting the nexthop to "ourselves". For IPv6, we only need to
2287 * the global nexthop here; the link-local nexthop would have been
2289 * already, and if not, it is required by the update formation code.
2290 * Also see earlier comments in this function.
2293 * If route-map has performed some operation on the nexthop or the peer
2294 * configuration says to pass it unchanged, we cannot reset the nexthop
2295 * here, so only attempt to do it if these aren't true. Note that the
2296 * route-map handler itself might have cleared the nexthop, if for
2298 * it is configured as 'peer-address'.
2300 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2301 piattr
->rmap_change_flags
)
2303 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2304 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2305 /* We can reset the nexthop, if setting (or forcing) it to
2307 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2308 PEER_FLAG_NEXTHOP_SELF
)
2309 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2310 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2312 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2313 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2314 subgroup_announce_reset_nhop(
2315 (peer_cap_enhe(peer
, afi
, safi
)
2321 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2322 /* Can also reset the nexthop if announcing to EBGP, but
2324 * no peer in the subgroup is on a shared subnet.
2325 * Note: 3rd party nexthop currently implemented for
2328 if ((p
->family
== AF_INET
) &&
2329 (!bgp_subgrp_multiaccess_check_v4(
2332 subgroup_announce_reset_nhop(
2333 (peer_cap_enhe(peer
, afi
, safi
)
2340 if ((p
->family
== AF_INET6
) &&
2341 (!bgp_subgrp_multiaccess_check_v6(
2342 piattr
->mp_nexthop_global
,
2344 subgroup_announce_reset_nhop(
2345 (peer_cap_enhe(peer
, afi
, safi
)
2354 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2356 * This flag is used for leaked vpn-vrf routes
2358 int family
= p
->family
;
2360 if (peer_cap_enhe(peer
, afi
, safi
))
2363 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2365 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2366 __func__
, family2str(family
));
2367 subgroup_announce_reset_nhop(family
, attr
);
2372 /* If IPv6/MP and nexthop does not have any override and happens
2374 * be a link-local address, reset it so that we don't pass along
2376 * source's link-local IPv6 address to recipients who may not be
2378 * the same interface.
2380 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2381 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2382 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2388 * When the next hop is set to ourselves, if all multipaths have
2389 * link-bandwidth announce the cumulative bandwidth as that makes
2390 * the most sense. However, don't modify if the link-bandwidth has
2391 * been explicitly set by user policy.
2394 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2395 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2396 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2397 bgp_attr_set_ecommunity(
2399 ecommunity_replace_linkbw(
2400 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2403 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2408 static void bgp_route_select_timer_expire(struct thread
*thread
)
2410 struct afi_safi_info
*info
;
2415 info
= THREAD_ARG(thread
);
2420 if (BGP_DEBUG(update
, UPDATE_OUT
))
2421 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2424 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2426 XFREE(MTYPE_TMP
, info
);
2428 /* Best path selection */
2429 bgp_best_path_select_defer(bgp
, afi
, safi
);
2432 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2433 struct bgp_maxpaths_cfg
*mpath_cfg
,
2434 struct bgp_path_info_pair
*result
, afi_t afi
,
2437 struct bgp_path_info
*new_select
;
2438 struct bgp_path_info
*old_select
;
2439 struct bgp_path_info
*pi
;
2440 struct bgp_path_info
*pi1
;
2441 struct bgp_path_info
*pi2
;
2442 struct bgp_path_info
*nextpi
= NULL
;
2443 int paths_eq
, do_mpath
, debug
;
2444 struct list mp_list
;
2445 char pfx_buf
[PREFIX2STR_BUFFER
];
2446 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2448 bgp_mp_list_init(&mp_list
);
2450 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2452 debug
= bgp_debug_bestpath(dest
);
2455 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2457 dest
->reason
= bgp_path_selection_none
;
2458 /* bgp deterministic-med */
2460 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2462 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2463 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2465 bgp_path_info_unset_flag(dest
, pi1
,
2466 BGP_PATH_DMED_SELECTED
);
2468 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2470 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2472 if (BGP_PATH_HOLDDOWN(pi1
))
2474 if (pi1
->peer
!= bgp
->peer_self
)
2475 if (!peer_established(pi1
->peer
))
2480 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2481 if (CHECK_FLAG(pi2
->flags
,
2482 BGP_PATH_DMED_CHECK
))
2484 if (BGP_PATH_HOLDDOWN(pi2
))
2486 if (pi2
->peer
!= bgp
->peer_self
2489 PEER_STATUS_NSF_WAIT
))
2490 if (pi2
->peer
->status
2494 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2496 && !aspath_cmp_left_confed(
2501 if (bgp_path_info_cmp(
2502 bgp
, pi2
, new_select
,
2503 &paths_eq
, mpath_cfg
, debug
,
2506 bgp_path_info_unset_flag(
2508 BGP_PATH_DMED_SELECTED
);
2512 bgp_path_info_set_flag(
2513 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2516 bgp_path_info_set_flag(dest
, new_select
,
2517 BGP_PATH_DMED_CHECK
);
2518 bgp_path_info_set_flag(dest
, new_select
,
2519 BGP_PATH_DMED_SELECTED
);
2522 bgp_path_info_path_with_addpath_rx_str(
2523 new_select
, path_buf
, sizeof(path_buf
));
2525 "%pBD(%s): %s is the bestpath from AS %u",
2526 dest
, bgp
->name_pretty
, path_buf
,
2527 aspath_get_first_as(
2528 new_select
->attr
->aspath
));
2533 /* Check old selected route and new selected route. */
2536 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2537 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2538 enum bgp_path_selection_reason reason
;
2540 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2543 if (BGP_PATH_HOLDDOWN(pi
)) {
2544 /* reap REMOVED routes, if needs be
2545 * selected route must stay for a while longer though
2547 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2548 && (pi
!= old_select
))
2549 bgp_path_info_reap(dest
, pi
);
2552 zlog_debug("%s: pi %p in holddown", __func__
,
2558 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2559 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2560 if (!peer_established(pi
->peer
)) {
2564 "%s: pi %p non self peer %s not estab state",
2565 __func__
, pi
, pi
->peer
->host
);
2570 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2571 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2572 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2574 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2578 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2580 reason
= dest
->reason
;
2581 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2582 debug
, pfx_buf
, afi
, safi
,
2584 if (new_select
== NULL
&&
2585 reason
!= bgp_path_selection_none
)
2586 dest
->reason
= reason
;
2591 /* Now that we know which path is the bestpath see if any of the other
2593 * qualify as multipaths
2597 bgp_path_info_path_with_addpath_rx_str(
2598 new_select
, path_buf
, sizeof(path_buf
));
2600 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2602 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2603 dest
, bgp
->name_pretty
, path_buf
,
2604 old_select
? old_select
->peer
->host
: "NONE");
2607 if (do_mpath
&& new_select
) {
2608 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2609 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2612 bgp_path_info_path_with_addpath_rx_str(
2613 pi
, path_buf
, sizeof(path_buf
));
2615 if (pi
== new_select
) {
2618 "%pBD(%s): %s is the bestpath, add to the multipath list",
2619 dest
, bgp
->name_pretty
,
2621 bgp_mp_list_add(&mp_list
, pi
);
2625 if (BGP_PATH_HOLDDOWN(pi
))
2628 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2629 && !CHECK_FLAG(pi
->peer
->sflags
,
2630 PEER_STATUS_NSF_WAIT
))
2631 if (!peer_established(pi
->peer
))
2634 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2637 "%pBD: %s has the same nexthop as the bestpath, skip it",
2642 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2643 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2649 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2651 bgp_mp_list_add(&mp_list
, pi
);
2656 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2658 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2659 bgp_mp_list_clear(&mp_list
);
2661 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2663 result
->old
= old_select
;
2664 result
->new = new_select
;
2670 * A new route/change in bestpath of an existing route. Evaluate the path
2671 * for advertisement to the subgroup.
2673 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2674 struct bgp_path_info
*selected
,
2675 struct bgp_dest
*dest
,
2676 uint32_t addpath_tx_id
)
2678 const struct prefix
*p
;
2679 struct peer
*onlypeer
;
2686 p
= bgp_dest_get_prefix(dest
);
2687 afi
= SUBGRP_AFI(subgrp
);
2688 safi
= SUBGRP_SAFI(subgrp
);
2689 bgp
= SUBGRP_INST(subgrp
);
2690 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2693 if (BGP_DEBUG(update
, UPDATE_OUT
))
2694 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2696 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2697 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2698 PEER_STATUS_ORF_WAIT_REFRESH
))
2701 memset(&attr
, 0, sizeof(struct attr
));
2702 /* It's initialized in bgp_announce_check() */
2704 /* Announcement to the subgroup. If the route is filtered withdraw it.
2705 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2706 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2709 advertise
= bgp_check_advertise(bgp
, dest
);
2712 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2714 /* Route is selected, if the route is already installed
2715 * in FIB, then it is advertised
2718 if (!bgp_check_withdrawal(bgp
, dest
))
2719 bgp_adj_out_set_subgroup(
2720 dest
, subgrp
, &attr
, selected
);
2722 bgp_adj_out_unset_subgroup(
2723 dest
, subgrp
, 1, addpath_tx_id
);
2726 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2730 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2732 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2737 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2738 * This is called at the end of route processing.
2740 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2742 struct bgp_path_info
*pi
;
2744 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2745 if (BGP_PATH_HOLDDOWN(pi
))
2747 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2748 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2753 * Has the route changed from the RIB's perspective? This is invoked only
2754 * if the route selection returns the same best route as earlier - to
2755 * determine if we need to update zebra or not.
2757 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2759 struct bgp_path_info
*mpinfo
;
2761 /* If this is multipath, check all selected paths for any nexthop
2762 * change or attribute change. Some attribute changes (e.g., community)
2763 * aren't of relevance to the RIB, but we'll update zebra to ensure
2764 * we handle the case of BGP nexthop change. This is the behavior
2765 * when the best path has an attribute change anyway.
2767 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2768 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2769 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2773 * If this is multipath, check all selected paths for any nexthop change
2775 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2776 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2777 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2778 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2782 /* Nothing has changed from the RIB's perspective. */
2786 struct bgp_process_queue
{
2788 STAILQ_HEAD(, bgp_dest
) pqueue
;
2789 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2791 unsigned int queued
;
2794 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2795 safi_t safi
, struct bgp_dest
*dest
,
2796 struct bgp_path_info
*new_select
,
2797 struct bgp_path_info
*old_select
)
2799 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2801 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2804 if (advertise_type5_routes(bgp
, afi
) && new_select
2805 && is_route_injectable_into_evpn(new_select
)) {
2807 /* apply the route-map */
2808 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2809 route_map_result_t ret
;
2810 struct bgp_path_info rmap_path
;
2811 struct bgp_path_info_extra rmap_path_extra
;
2812 struct attr dummy_attr
;
2814 dummy_attr
= *new_select
->attr
;
2816 /* Fill temp path_info */
2817 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2818 new_select
, new_select
->peer
,
2821 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2823 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2826 if (ret
== RMAP_DENYMATCH
) {
2827 bgp_attr_flush(&dummy_attr
);
2828 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2831 bgp_evpn_advertise_type5_route(
2832 bgp
, p
, &dummy_attr
, afi
, safi
);
2834 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2837 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2838 && is_route_injectable_into_evpn(old_select
))
2839 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2843 * Utility to determine whether a particular path_info should use
2844 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2845 * in a path where we basically _know_ this is a BGP-LU route.
2847 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
2849 /* Certain types get imp null; so do paths where the nexthop is
2852 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2853 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2854 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
2856 else if (new_select
->extra
== NULL
||
2857 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
2858 /* TODO -- should be configurable? */
2865 * old_select = The old best path
2866 * new_select = the new best path
2868 * if (!old_select && new_select)
2869 * We are sending new information on.
2871 * if (old_select && new_select) {
2872 * if (new_select != old_select)
2873 * We have a new best path send a change
2875 * We've received a update with new attributes that needs
2879 * if (old_select && !new_select)
2880 * We have no eligible route that we can announce or the rn
2883 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2884 afi_t afi
, safi_t safi
)
2886 struct bgp_path_info
*new_select
;
2887 struct bgp_path_info
*old_select
;
2888 struct bgp_path_info_pair old_and_new
;
2891 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2893 debug
= bgp_debug_bestpath(dest
);
2896 "%s: bgp delete in progress, ignoring event, p=%pBD",
2900 /* Is it end of initial update? (after startup) */
2902 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2903 sizeof(bgp
->update_delay_zebra_resume_time
));
2905 bgp
->main_zebra_update_hold
= 0;
2906 FOREACH_AFI_SAFI (afi
, safi
) {
2907 if (bgp_fibupd_safi(safi
))
2908 bgp_zebra_announce_table(bgp
, afi
, safi
);
2910 bgp
->main_peers_update_hold
= 0;
2912 bgp_start_routeadv(bgp
);
2916 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2918 debug
= bgp_debug_bestpath(dest
);
2920 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__
,
2921 dest
, bgp
->name_pretty
, afi2str(afi
),
2924 /* The best path calculation for the route is deferred if
2925 * BGP_NODE_SELECT_DEFER is set
2927 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2928 if (BGP_DEBUG(update
, UPDATE_OUT
))
2929 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
2933 /* Best path selection. */
2934 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2936 old_select
= old_and_new
.old
;
2937 new_select
= old_and_new
.new;
2939 /* Do we need to allocate or free labels?
2940 * Right now, since we only deal with per-prefix labels, it is not
2941 * necessary to do this upon changes to best path. Exceptions:
2942 * - label index has changed -> recalculate resulting label
2943 * - path_info sub_type changed -> switch to/from implicit-null
2944 * - no valid label (due to removed static label binding) -> get new one
2946 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2949 || bgp_label_index_differs(new_select
, old_select
)
2950 || new_select
->sub_type
!= old_select
->sub_type
2951 || !bgp_is_valid_label(&dest
->local_label
)) {
2952 /* Enforced penultimate hop popping:
2953 * implicit-null for local routes, aggregate
2954 * and redistributed routes
2956 if (bgp_lu_need_imp_null(new_select
)) {
2959 BGP_NODE_REGISTERED_FOR_LABEL
)
2962 BGP_NODE_LABEL_REQUESTED
))
2963 bgp_unregister_for_label(dest
);
2964 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2965 &dest
->local_label
);
2966 bgp_set_valid_label(&dest
->local_label
);
2968 bgp_register_for_label(dest
,
2971 } else if (CHECK_FLAG(dest
->flags
,
2972 BGP_NODE_REGISTERED_FOR_LABEL
)
2973 || CHECK_FLAG(dest
->flags
,
2974 BGP_NODE_LABEL_REQUESTED
)) {
2975 bgp_unregister_for_label(dest
);
2977 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
2978 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
2979 bgp_unregister_for_label(dest
);
2984 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
2985 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
2986 safi2str(safi
), old_select
, new_select
);
2988 /* If best route remains the same and this is not due to user-initiated
2989 * clear, see exactly what needs to be done.
2991 if (old_select
&& old_select
== new_select
2992 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2993 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2994 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2995 if (bgp_zebra_has_route_changed(old_select
)) {
2996 #ifdef ENABLE_BGP_VNC
2997 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2998 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3000 if (bgp_fibupd_safi(safi
)
3001 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3003 if (BGP_SUPPRESS_FIB_ENABLED(bgp
)
3004 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
3005 SET_FLAG(dest
->flags
,
3006 BGP_NODE_FIB_INSTALL_PENDING
);
3008 if (new_select
->type
== ZEBRA_ROUTE_BGP
3009 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3010 || new_select
->sub_type
3011 == BGP_ROUTE_IMPORTED
))
3013 bgp_zebra_announce(dest
, p
, old_select
,
3018 /* If there is a change of interest to peers, reannounce the
3020 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3021 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3022 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3023 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3025 /* unicast routes must also be annouced to
3026 * labeled-unicast update-groups */
3027 if (safi
== SAFI_UNICAST
)
3028 group_announce_route(bgp
, afi
,
3029 SAFI_LABELED_UNICAST
, dest
,
3032 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3033 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3036 /* advertise/withdraw type-5 routes */
3037 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3038 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3039 bgp_process_evpn_route_injection(
3040 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3042 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3043 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3044 bgp_zebra_clear_route_change_flags(dest
);
3045 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3049 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3051 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3053 /* bestpath has changed; bump version */
3054 if (old_select
|| new_select
) {
3055 bgp_bump_version(dest
);
3057 if (!bgp
->t_rmap_def_originate_eval
) {
3061 update_group_refresh_default_originate_route_map
,
3062 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3063 &bgp
->t_rmap_def_originate_eval
);
3068 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3071 zlog_debug("%s: setting SELECTED flag", __func__
);
3072 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3073 bgp_path_info_unset_flag(dest
, new_select
,
3074 BGP_PATH_ATTR_CHANGED
);
3075 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3076 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3079 #ifdef ENABLE_BGP_VNC
3080 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3081 if (old_select
!= new_select
) {
3083 vnc_import_bgp_exterior_del_route(bgp
, p
,
3085 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3088 vnc_import_bgp_exterior_add_route(bgp
, p
,
3090 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3096 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3098 /* unicast routes must also be annouced to labeled-unicast update-groups
3100 if (safi
== SAFI_UNICAST
)
3101 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3105 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3106 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3108 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3109 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3110 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3111 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3113 if (BGP_SUPPRESS_FIB_ENABLED(bgp
))
3114 SET_FLAG(dest
->flags
,
3115 BGP_NODE_FIB_INSTALL_PENDING
);
3117 /* if this is an evpn imported type-5 prefix,
3118 * we need to withdraw the route first to clear
3119 * the nh neigh and the RMAC entry.
3122 is_route_parent_evpn(old_select
))
3123 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3125 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3127 /* Withdraw the route from the kernel. */
3128 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3129 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3130 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3131 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3133 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3137 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3140 /* Clear any route change flags. */
3141 bgp_zebra_clear_route_change_flags(dest
);
3143 /* Reap old select bgp_path_info, if it has been removed */
3144 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3145 bgp_path_info_reap(dest
, old_select
);
3147 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3151 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3152 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3154 struct bgp_dest
*dest
;
3156 struct afi_safi_info
*thread_info
;
3158 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3159 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3161 thread_info
= THREAD_ARG(t
);
3162 XFREE(MTYPE_TMP
, thread_info
);
3163 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3166 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3167 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3168 get_afi_safi_str(afi
, safi
, false),
3169 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3172 /* Process the route list */
3173 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3174 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3175 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3176 dest
= bgp_route_next(dest
)) {
3177 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3180 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3181 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3182 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3185 /* If iteration stopped before the entire table was traversed then the
3186 * node needs to be unlocked.
3189 bgp_dest_unlock_node(dest
);
3193 /* Send EOR message when all routes are processed */
3194 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3195 bgp_send_delayed_eor(bgp
);
3196 /* Send route processing complete message to RIB */
3197 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3198 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3202 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3204 thread_info
->afi
= afi
;
3205 thread_info
->safi
= safi
;
3206 thread_info
->bgp
= bgp
;
3208 /* If there are more routes to be processed, start the
3211 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3212 BGP_ROUTE_SELECT_DELAY
,
3213 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3217 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3219 struct bgp_process_queue
*pqnode
= data
;
3220 struct bgp
*bgp
= pqnode
->bgp
;
3221 struct bgp_table
*table
;
3222 struct bgp_dest
*dest
;
3225 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3226 bgp_process_main_one(bgp
, NULL
, 0, 0);
3227 /* should always have dedicated wq call */
3228 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3232 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3233 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3234 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3235 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3236 table
= bgp_dest_table(dest
);
3237 /* note, new DESTs may be added as part of processing */
3238 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3240 bgp_dest_unlock_node(dest
);
3241 bgp_table_unlock(table
);
3247 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3249 struct bgp_process_queue
*pqnode
= data
;
3251 bgp_unlock(pqnode
->bgp
);
3253 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3256 void bgp_process_queue_init(struct bgp
*bgp
)
3258 if (!bgp
->process_queue
) {
3261 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3262 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3265 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3266 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3267 bgp
->process_queue
->spec
.max_retries
= 0;
3268 bgp
->process_queue
->spec
.hold
= 50;
3269 /* Use a higher yield value of 50ms for main queue processing */
3270 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3273 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3275 struct bgp_process_queue
*pqnode
;
3277 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3278 sizeof(struct bgp_process_queue
));
3280 /* unlocked in bgp_processq_del */
3281 pqnode
->bgp
= bgp_lock(bgp
);
3282 STAILQ_INIT(&pqnode
->pqueue
);
3287 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3289 #define ARBITRARY_PROCESS_QLEN 10000
3290 struct work_queue
*wq
= bgp
->process_queue
;
3291 struct bgp_process_queue
*pqnode
;
3292 int pqnode_reuse
= 0;
3294 /* already scheduled for processing? */
3295 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3298 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3301 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3302 if (BGP_DEBUG(update
, UPDATE_OUT
))
3303 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3308 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3309 if (BGP_DEBUG(update
, UPDATE_OUT
))
3311 "Soft reconfigure table in progress for route %p",
3319 /* Add route nodes to an existing work queue item until reaching the
3320 limit only if is from the same BGP view and it's not an EOIU marker
3322 if (work_queue_item_count(wq
)) {
3323 struct work_queue_item
*item
= work_queue_last_item(wq
);
3324 pqnode
= item
->data
;
3326 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3327 || pqnode
->bgp
!= bgp
3328 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3329 pqnode
= bgp_processq_alloc(bgp
);
3333 pqnode
= bgp_processq_alloc(bgp
);
3334 /* all unlocked in bgp_process_wq */
3335 bgp_table_lock(bgp_dest_table(dest
));
3337 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3338 bgp_dest_lock_node(dest
);
3340 /* can't be enqueued twice */
3341 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3342 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3346 work_queue_add(wq
, pqnode
);
3351 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3353 struct bgp_process_queue
*pqnode
;
3355 if (bgp
->process_queue
== NULL
)
3358 pqnode
= bgp_processq_alloc(bgp
);
3360 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3361 work_queue_add(bgp
->process_queue
, pqnode
);
3364 static void bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3368 peer
= THREAD_ARG(thread
);
3369 peer
->t_pmax_restart
= NULL
;
3371 if (bgp_debug_neighbor_events(peer
))
3373 "%s Maximum-prefix restart timer expired, restore peering",
3376 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3377 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3380 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3384 bool filtered
= false;
3385 struct bgp_dest
*dest
;
3386 struct bgp_adj_in
*ain
;
3387 struct attr attr
= {};
3388 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3390 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3391 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3392 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3396 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3400 if (bgp_input_modifier(
3401 peer
, rn_p
, &attr
, afi
, safi
,
3402 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3410 bgp_attr_flush(&attr
);
3417 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3421 iana_safi_t pkt_safi
;
3422 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3423 PEER_FLAG_MAX_PREFIX_FORCE
))
3424 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3425 + peer
->pcount
[afi
][safi
]
3426 : peer
->pcount
[afi
][safi
];
3428 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3431 if (pcount
> peer
->pmax
[afi
][safi
]) {
3432 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3433 PEER_STATUS_PREFIX_LIMIT
)
3438 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3439 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3440 peer
->pmax
[afi
][safi
]);
3441 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3443 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3444 PEER_FLAG_MAX_PREFIX_WARNING
))
3447 /* Convert AFI, SAFI to values for packet. */
3448 pkt_afi
= afi_int2iana(afi
);
3449 pkt_safi
= safi_int2iana(safi
);
3453 ndata
[0] = (pkt_afi
>> 8);
3455 ndata
[2] = pkt_safi
;
3456 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3457 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3458 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3459 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3461 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3462 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3463 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3467 /* Dynamic peers will just close their connection. */
3468 if (peer_dynamic_neighbor(peer
))
3471 /* restart timer start */
3472 if (peer
->pmax_restart
[afi
][safi
]) {
3473 peer
->v_pmax_restart
=
3474 peer
->pmax_restart
[afi
][safi
] * 60;
3476 if (bgp_debug_neighbor_events(peer
))
3478 "%pBP Maximum-prefix restart timer started for %d secs",
3479 peer
, peer
->v_pmax_restart
);
3481 BGP_TIMER_ON(peer
->t_pmax_restart
,
3482 bgp_maximum_prefix_restart_timer
,
3483 peer
->v_pmax_restart
);
3488 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3489 PEER_STATUS_PREFIX_LIMIT
);
3492 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3493 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3494 PEER_STATUS_PREFIX_THRESHOLD
)
3499 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3500 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3501 peer
->pmax
[afi
][safi
]);
3502 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3503 PEER_STATUS_PREFIX_THRESHOLD
);
3505 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3506 PEER_STATUS_PREFIX_THRESHOLD
);
3510 /* Unconditionally remove the route from the RIB, without taking
3511 * damping into consideration (eg, because the session went down)
3513 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3514 struct peer
*peer
, afi_t afi
, safi_t safi
)
3517 struct bgp
*bgp
= NULL
;
3518 bool delete_route
= false;
3520 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3523 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3524 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3526 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3529 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3530 delete_route
= true;
3531 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3532 delete_route
= true;
3534 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3535 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3536 bgp
= pi
->peer
->bgp
;
3537 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3542 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3543 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3546 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3547 struct peer
*peer
, afi_t afi
, safi_t safi
,
3548 struct prefix_rd
*prd
)
3550 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3552 /* apply dampening, if result is suppressed, we'll be retaining
3553 * the bgp_path_info in the RIB for historical reference.
3555 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3556 && peer
->sort
== BGP_PEER_EBGP
)
3557 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3558 == BGP_DAMP_SUPPRESSED
) {
3559 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3564 #ifdef ENABLE_BGP_VNC
3565 if (safi
== SAFI_MPLS_VPN
) {
3566 struct bgp_dest
*pdest
= NULL
;
3567 struct bgp_table
*table
= NULL
;
3569 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3570 (struct prefix
*)prd
);
3571 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3572 table
= bgp_dest_get_bgp_table_info(pdest
);
3574 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3575 peer
->bgp
, prd
, table
, p
, pi
);
3577 bgp_dest_unlock_node(pdest
);
3579 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3580 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3582 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3583 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3588 /* If this is an EVPN route, process for un-import. */
3589 if (safi
== SAFI_EVPN
)
3590 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3592 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3595 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3596 struct peer
*peer
, struct attr
*attr
,
3597 struct bgp_dest
*dest
)
3599 struct bgp_path_info
*new;
3601 /* Make new BGP info. */
3602 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3604 new->instance
= instance
;
3605 new->sub_type
= sub_type
;
3608 new->uptime
= bgp_clock();
3613 /* Check if received nexthop is valid or not. */
3614 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3615 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3616 struct bgp_dest
*dest
)
3619 bool is_bgp_static_route
=
3620 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3624 * Only validated for unicast and multicast currently.
3625 * Also valid for EVPN where the nexthop is an IP address.
3626 * If we are a bgp static route being checked then there is
3627 * no need to check to see if the nexthop is martian as
3628 * that it should be ok.
3630 if (is_bgp_static_route
||
3631 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3634 /* If NEXT_HOP is present, validate it. */
3635 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3636 if (attr
->nexthop
.s_addr
== INADDR_ANY
3637 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3638 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3642 /* If MP_NEXTHOP is present, validate it. */
3643 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3644 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3645 * it is not an IPv6 link-local address.
3647 * If we receive an UPDATE with nexthop length set to 32 bytes
3648 * we shouldn't discard an UPDATE if it's set to (::).
3649 * The link-local (2st) is validated along the code path later.
3651 if (attr
->mp_nexthop_len
) {
3652 switch (attr
->mp_nexthop_len
) {
3653 case BGP_ATTR_NHLEN_IPV4
:
3654 case BGP_ATTR_NHLEN_VPNV4
:
3655 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3657 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3658 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3662 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3663 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3664 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3665 &attr
->mp_nexthop_global
)
3666 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3667 || IN6_IS_ADDR_MULTICAST(
3668 &attr
->mp_nexthop_global
)
3669 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3672 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3673 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3674 || IN6_IS_ADDR_MULTICAST(
3675 &attr
->mp_nexthop_global
)
3676 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3689 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3691 struct community
*old
;
3692 struct community
*new;
3693 struct community
*merge
;
3694 struct community
*no_export
;
3696 old
= bgp_attr_get_community(attr
);
3697 no_export
= community_str2com("no-export");
3702 merge
= community_merge(community_dup(old
), no_export
);
3705 community_free(&old
);
3707 new = community_uniq_sort(merge
);
3708 community_free(&merge
);
3710 new = community_dup(no_export
);
3713 community_free(&no_export
);
3715 bgp_attr_set_community(attr
, new);
3718 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3719 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3720 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3721 uint32_t num_labels
, int soft_reconfig
,
3722 struct bgp_route_evpn
*evpn
)
3725 int aspath_loop_count
= 0;
3726 struct bgp_dest
*dest
;
3728 struct attr new_attr
;
3729 struct attr
*attr_new
;
3730 struct bgp_path_info
*pi
;
3731 struct bgp_path_info
*new;
3732 struct bgp_path_info_extra
*extra
;
3734 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3736 int do_loop_check
= 1;
3737 int has_valid_label
= 0;
3739 uint8_t pi_type
= 0;
3740 uint8_t pi_sub_type
= 0;
3741 bool force_evpn_import
= false;
3742 safi_t orig_safi
= safi
;
3744 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3745 char pfxprint
[PREFIX2STR_BUFFER
];
3747 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3748 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3752 #ifdef ENABLE_BGP_VNC
3753 int vnc_implicit_withdraw
= 0;
3757 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3758 if (orig_safi
== SAFI_LABELED_UNICAST
)
3759 safi
= SAFI_UNICAST
;
3761 memset(&new_attr
, 0, sizeof(struct attr
));
3762 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3763 new_attr
.label
= MPLS_INVALID_LABEL
;
3766 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3767 /* TODO: Check to see if we can get rid of "is_valid_label" */
3768 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3769 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3771 has_valid_label
= bgp_is_valid_label(label
);
3773 if (has_valid_label
)
3774 assert(label
!= NULL
);
3776 /* Update overlay index of the attribute */
3777 if (afi
== AFI_L2VPN
&& evpn
)
3778 memcpy(&attr
->evpn_overlay
, evpn
,
3779 sizeof(struct bgp_route_evpn
));
3781 /* When peer's soft reconfiguration enabled. Record input packet in
3784 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3785 && peer
!= bgp
->peer_self
)
3786 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3788 /* Check previously received route. */
3789 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3790 if (pi
->peer
== peer
&& pi
->type
== type
3791 && pi
->sub_type
== sub_type
3792 && pi
->addpath_rx_id
== addpath_id
)
3795 /* AS path local-as loop check. */
3796 if (peer
->change_local_as
) {
3797 if (peer
->allowas_in
[afi
][safi
])
3798 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3799 else if (!CHECK_FLAG(peer
->flags
,
3800 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3801 aspath_loop_count
= 1;
3803 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3804 > aspath_loop_count
) {
3805 peer
->stat_pfx_aspath_loop
++;
3806 reason
= "as-path contains our own AS;";
3811 /* If the peer is configured for "allowas-in origin" and the last ASN in
3813 * as-path is our ASN then we do not need to call aspath_loop_check
3815 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3816 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3819 /* AS path loop check. */
3820 if (do_loop_check
) {
3821 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3822 > peer
->allowas_in
[afi
][safi
]
3823 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3824 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3825 > peer
->allowas_in
[afi
][safi
])) {
3826 peer
->stat_pfx_aspath_loop
++;
3827 reason
= "as-path contains our own AS;";
3832 /* Route reflector originator ID check. */
3833 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3834 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3835 peer
->stat_pfx_originator_loop
++;
3836 reason
= "originator is us;";
3840 /* Route reflector cluster ID check. */
3841 if (bgp_cluster_filter(peer
, attr
)) {
3842 peer
->stat_pfx_cluster_loop
++;
3843 reason
= "reflected from the same cluster;";
3847 /* Apply incoming filter. */
3848 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
3849 peer
->stat_pfx_filter
++;
3854 /* RFC 8212 to prevent route leaks.
3855 * This specification intends to improve this situation by requiring the
3856 * explicit configuration of both BGP Import and Export Policies for any
3857 * External BGP (EBGP) session such as customers, peers, or
3858 * confederation boundaries for all enabled address families. Through
3859 * codification of the aforementioned requirement, operators will
3860 * benefit from consistent behavior across different BGP
3863 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3864 if (!bgp_inbound_policy_exists(peer
,
3865 &peer
->filter
[afi
][safi
])) {
3866 reason
= "inbound policy missing";
3867 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
3868 NULL
) > FIFTEENMINUTE2USEC
||
3869 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
3871 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3872 monotime(&bgp
->ebgprequirespolicywarning
);
3877 /* draft-ietf-idr-deprecate-as-set-confed-set
3878 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3879 * Eventually, This document (if approved) updates RFC 4271
3880 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3881 * and obsoletes RFC 6472.
3883 if (peer
->bgp
->reject_as_sets
)
3884 if (aspath_check_as_sets(attr
->aspath
)) {
3886 "as-path contains AS_SET or AS_CONFED_SET type;";
3892 /* Apply incoming route-map.
3893 * NB: new_attr may now contain newly allocated values from route-map
3895 * commands, so we need bgp_attr_flush in the error paths, until we
3897 * the attr (which takes over the memory references) */
3898 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
3901 peer
->stat_pfx_filter
++;
3902 reason
= "route-map;";
3903 bgp_attr_flush(&new_attr
);
3907 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3908 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3909 /* remove from RIB previous entry */
3910 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3913 if (peer
->sort
== BGP_PEER_EBGP
) {
3916 * A BGP speaker receiving an announcement tagged with the
3917 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3918 * NO_EXPORT community as defined in RFC1997, or a
3919 * similar community, to prevent propagation of the
3920 * prefix outside the local AS. The community to prevent
3921 * propagation SHOULD be chosen according to the operator's
3924 if (bgp_attr_get_community(&new_attr
) &&
3925 community_include(bgp_attr_get_community(&new_attr
),
3926 COMMUNITY_BLACKHOLE
))
3927 bgp_attr_add_no_export_community(&new_attr
);
3929 /* If we receive the graceful-shutdown community from an eBGP
3930 * peer we must lower local-preference */
3931 if (bgp_attr_get_community(&new_attr
) &&
3932 community_include(bgp_attr_get_community(&new_attr
),
3934 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3935 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3937 /* If graceful-shutdown is configured then add the GSHUT
3938 * community to all paths received from eBGP peers */
3939 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3940 bgp_attr_add_gshut_community(&new_attr
);
3945 pi_sub_type
= pi
->sub_type
;
3948 /* next hop check. */
3949 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3950 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3952 peer
->stat_pfx_nh_invalid
++;
3953 reason
= "martian or self next-hop;";
3954 bgp_attr_flush(&new_attr
);
3958 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3959 peer
->stat_pfx_nh_invalid
++;
3960 reason
= "self mac;";
3961 bgp_attr_flush(&new_attr
);
3965 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3967 * Suppress fib is enabled
3968 * BGP_OPT_NO_FIB is not enabled
3969 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3970 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3972 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
3973 && (sub_type
== BGP_ROUTE_NORMAL
)
3974 && (!bgp_option_check(BGP_OPT_NO_FIB
))
3975 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
3976 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
3978 /* If maximum prefix count is configured and current prefix
3981 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
3982 bgp_attr_flush(&new_attr
);
3986 attr_new
= bgp_attr_intern(&new_attr
);
3988 /* If the update is implicit withdraw. */
3990 pi
->uptime
= bgp_clock();
3991 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3993 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3995 /* Same attribute comes in. */
3996 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3998 && (!has_valid_label
3999 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4000 num_labels
* sizeof(mpls_label_t
))
4002 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4003 BGP_CONFIG_DAMPENING
)
4004 && peer
->sort
== BGP_PEER_EBGP
4005 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4006 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4007 bgp_debug_rdpfxpath2str(
4008 afi
, safi
, prd
, p
, label
,
4009 num_labels
, addpath_id
? 1 : 0,
4010 addpath_id
, evpn
, pfx_buf
,
4012 zlog_debug("%pBP rcvd %s", peer
,
4016 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4017 != BGP_DAMP_SUPPRESSED
) {
4018 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4020 bgp_process(bgp
, dest
, afi
, safi
);
4022 } else /* Duplicate - odd */
4024 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4025 if (!peer
->rcvd_attr_printed
) {
4027 "%pBP rcvd UPDATE w/ attr: %s",
4029 peer
->rcvd_attr_str
);
4030 peer
->rcvd_attr_printed
= 1;
4033 bgp_debug_rdpfxpath2str(
4034 afi
, safi
, prd
, p
, label
,
4035 num_labels
, addpath_id
? 1 : 0,
4036 addpath_id
, evpn
, pfx_buf
,
4039 "%pBP rcvd %s...duplicate ignored",
4043 /* graceful restart STALE flag unset. */
4044 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4045 bgp_path_info_unset_flag(
4046 dest
, pi
, BGP_PATH_STALE
);
4047 bgp_dest_set_defer_flag(dest
, false);
4048 bgp_process(bgp
, dest
, afi
, safi
);
4052 bgp_dest_unlock_node(dest
);
4053 bgp_attr_unintern(&attr_new
);
4058 /* Withdraw/Announce before we fully processed the withdraw */
4059 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4060 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4061 bgp_debug_rdpfxpath2str(
4062 afi
, safi
, prd
, p
, label
, num_labels
,
4063 addpath_id
? 1 : 0, addpath_id
, evpn
,
4064 pfx_buf
, sizeof(pfx_buf
));
4066 "%pBP rcvd %s, flapped quicker than processing",
4070 bgp_path_info_restore(dest
, pi
);
4073 * If the BGP_PATH_REMOVED flag is set, then EVPN
4074 * routes would have been unimported already when a
4075 * prior BGP withdraw processing happened. Such routes
4076 * need to be imported again, so flag accordingly.
4078 force_evpn_import
= true;
4081 /* Received Logging. */
4082 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4083 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4084 num_labels
, addpath_id
? 1 : 0,
4085 addpath_id
, evpn
, pfx_buf
,
4087 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4090 /* graceful restart STALE flag unset. */
4091 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4092 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4093 bgp_dest_set_defer_flag(dest
, false);
4096 /* The attribute is changed. */
4097 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4099 /* implicit withdraw, decrement aggregate and pcount here.
4100 * only if update is accepted, they'll increment below.
4102 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4104 /* Update bgp route dampening information. */
4105 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4106 && peer
->sort
== BGP_PEER_EBGP
) {
4107 /* This is implicit withdraw so we should update
4110 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4111 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4113 #ifdef ENABLE_BGP_VNC
4114 if (safi
== SAFI_MPLS_VPN
) {
4115 struct bgp_dest
*pdest
= NULL
;
4116 struct bgp_table
*table
= NULL
;
4118 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4119 (struct prefix
*)prd
);
4120 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4121 table
= bgp_dest_get_bgp_table_info(pdest
);
4123 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4124 bgp
, prd
, table
, p
, pi
);
4126 bgp_dest_unlock_node(pdest
);
4128 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4129 && (safi
== SAFI_UNICAST
)) {
4130 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4132 * Implicit withdraw case.
4134 ++vnc_implicit_withdraw
;
4135 vnc_import_bgp_del_route(bgp
, p
, pi
);
4136 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4141 /* Special handling for EVPN update of an existing route. If the
4142 * extended community attribute has changed, we need to
4144 * the route using its existing extended community. It will be
4145 * subsequently processed for import with the new extended
4148 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4151 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4153 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4156 cmp
= ecommunity_cmp(
4157 bgp_attr_get_ecommunity(pi
->attr
),
4158 bgp_attr_get_ecommunity(attr_new
));
4160 if (bgp_debug_update(peer
, p
, NULL
, 1))
4162 "Change in EXT-COMM, existing %s new %s",
4164 bgp_attr_get_ecommunity(
4167 bgp_attr_get_ecommunity(
4169 if (safi
== SAFI_EVPN
)
4170 bgp_evpn_unimport_route(
4171 bgp
, afi
, safi
, p
, pi
);
4172 else /* SAFI_MPLS_VPN */
4173 vpn_leak_to_vrf_withdraw(bgp
,
4179 /* Update to new attribute. */
4180 bgp_attr_unintern(&pi
->attr
);
4181 pi
->attr
= attr_new
;
4183 /* Update MPLS label */
4184 if (has_valid_label
) {
4185 extra
= bgp_path_info_extra_get(pi
);
4186 if (extra
->label
!= label
) {
4187 memcpy(&extra
->label
, label
,
4188 num_labels
* sizeof(mpls_label_t
));
4189 extra
->num_labels
= num_labels
;
4191 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4192 bgp_set_valid_label(&extra
->label
[0]);
4195 /* Update SRv6 SID */
4196 if (attr
->srv6_l3vpn
) {
4197 extra
= bgp_path_info_extra_get(pi
);
4198 if (sid_diff(&extra
->sid
[0].sid
,
4199 &attr
->srv6_l3vpn
->sid
)) {
4200 sid_copy(&extra
->sid
[0].sid
,
4201 &attr
->srv6_l3vpn
->sid
);
4202 extra
->num_sids
= 1;
4204 extra
->sid
[0].loc_block_len
= 0;
4205 extra
->sid
[0].loc_node_len
= 0;
4206 extra
->sid
[0].func_len
= 0;
4207 extra
->sid
[0].arg_len
= 0;
4208 extra
->sid
[0].transposition_len
= 0;
4209 extra
->sid
[0].transposition_offset
= 0;
4211 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4212 extra
->sid
[0].loc_block_len
=
4213 attr
->srv6_l3vpn
->loc_block_len
;
4214 extra
->sid
[0].loc_node_len
=
4215 attr
->srv6_l3vpn
->loc_node_len
;
4216 extra
->sid
[0].func_len
=
4217 attr
->srv6_l3vpn
->func_len
;
4218 extra
->sid
[0].arg_len
=
4219 attr
->srv6_l3vpn
->arg_len
;
4220 extra
->sid
[0].transposition_len
=
4222 ->transposition_len
;
4223 extra
->sid
[0].transposition_offset
=
4225 ->transposition_offset
;
4228 } else if (attr
->srv6_vpn
) {
4229 extra
= bgp_path_info_extra_get(pi
);
4230 if (sid_diff(&extra
->sid
[0].sid
,
4231 &attr
->srv6_vpn
->sid
)) {
4232 sid_copy(&extra
->sid
[0].sid
,
4233 &attr
->srv6_vpn
->sid
);
4234 extra
->num_sids
= 1;
4238 #ifdef ENABLE_BGP_VNC
4239 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4240 && (safi
== SAFI_UNICAST
)) {
4241 if (vnc_implicit_withdraw
) {
4243 * Add back the route with its new attributes
4245 * The route is still selected, until the route
4247 * queued by bgp_process actually runs. We have
4249 * update to the VNC side immediately to avoid
4251 * configuration changes (e.g., route-map
4253 * trigger re-importation of the entire RIB.
4255 vnc_import_bgp_add_route(bgp
, p
, pi
);
4256 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4261 /* Update bgp route dampening information. */
4262 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4263 && peer
->sort
== BGP_PEER_EBGP
) {
4264 /* Now we do normal update dampening. */
4265 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4266 if (ret
== BGP_DAMP_SUPPRESSED
) {
4267 bgp_dest_unlock_node(dest
);
4272 /* Nexthop reachability check - for unicast and
4273 * labeled-unicast.. */
4274 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4275 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4276 || (safi
== SAFI_EVPN
&&
4277 bgp_evpn_is_prefix_nht_supported(p
))) {
4278 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4279 && peer
->ttl
== BGP_DEFAULT_TTL
4280 && !CHECK_FLAG(peer
->flags
,
4281 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4282 && !CHECK_FLAG(bgp
->flags
,
4283 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4288 struct bgp
*bgp_nexthop
= bgp
;
4290 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4291 bgp_nexthop
= pi
->extra
->bgp_orig
;
4293 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4295 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4296 safi
, pi
, NULL
, connected
,
4298 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4299 bgp_path_info_set_flag(dest
, pi
,
4302 if (BGP_DEBUG(nht
, NHT
)) {
4303 zlog_debug("%s(%pI4): NH unresolved",
4305 (in_addr_t
*)&attr_new
->nexthop
);
4307 bgp_path_info_unset_flag(dest
, pi
,
4311 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4313 #ifdef ENABLE_BGP_VNC
4314 if (safi
== SAFI_MPLS_VPN
) {
4315 struct bgp_dest
*pdest
= NULL
;
4316 struct bgp_table
*table
= NULL
;
4318 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4319 (struct prefix
*)prd
);
4320 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4321 table
= bgp_dest_get_bgp_table_info(pdest
);
4323 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4324 bgp
, prd
, table
, p
, pi
);
4326 bgp_dest_unlock_node(pdest
);
4330 /* If this is an EVPN route and some attribute has changed,
4331 * or we are explicitly told to perform a route import, process
4332 * route for import. If the extended community has changed, we
4334 * have done the un-import earlier and the import would result
4336 * route getting injected into appropriate L2 VNIs. If it is
4338 * some other attribute change, the import will result in
4340 * the attributes for the route in the VNI(s).
4342 if (safi
== SAFI_EVPN
&&
4343 (!same_attr
|| force_evpn_import
) &&
4344 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4345 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4347 /* Process change. */
4348 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4350 bgp_process(bgp
, dest
, afi
, safi
);
4351 bgp_dest_unlock_node(dest
);
4353 if (SAFI_UNICAST
== safi
4354 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4355 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4357 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4359 if ((SAFI_MPLS_VPN
== safi
)
4360 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4362 vpn_leak_to_vrf_update(bgp
, pi
);
4365 #ifdef ENABLE_BGP_VNC
4366 if (SAFI_MPLS_VPN
== safi
) {
4367 mpls_label_t label_decoded
= decode_label(label
);
4369 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4370 type
, sub_type
, &label_decoded
);
4372 if (SAFI_ENCAP
== safi
) {
4373 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4374 type
, sub_type
, NULL
);
4379 } // End of implicit withdraw
4381 /* Received Logging. */
4382 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4383 if (!peer
->rcvd_attr_printed
) {
4384 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4385 peer
->rcvd_attr_str
);
4386 peer
->rcvd_attr_printed
= 1;
4389 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4390 addpath_id
? 1 : 0, addpath_id
, evpn
,
4391 pfx_buf
, sizeof(pfx_buf
));
4392 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4395 /* Make new BGP info. */
4396 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4398 /* Update MPLS label */
4399 if (has_valid_label
) {
4400 extra
= bgp_path_info_extra_get(new);
4401 if (extra
->label
!= label
) {
4402 memcpy(&extra
->label
, label
,
4403 num_labels
* sizeof(mpls_label_t
));
4404 extra
->num_labels
= num_labels
;
4406 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4407 bgp_set_valid_label(&extra
->label
[0]);
4410 /* Update SRv6 SID */
4411 if (safi
== SAFI_MPLS_VPN
) {
4412 extra
= bgp_path_info_extra_get(new);
4413 if (attr
->srv6_l3vpn
) {
4414 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4415 extra
->num_sids
= 1;
4417 extra
->sid
[0].loc_block_len
=
4418 attr
->srv6_l3vpn
->loc_block_len
;
4419 extra
->sid
[0].loc_node_len
=
4420 attr
->srv6_l3vpn
->loc_node_len
;
4421 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4422 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4423 extra
->sid
[0].transposition_len
=
4424 attr
->srv6_l3vpn
->transposition_len
;
4425 extra
->sid
[0].transposition_offset
=
4426 attr
->srv6_l3vpn
->transposition_offset
;
4427 } else if (attr
->srv6_vpn
) {
4428 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4429 extra
->num_sids
= 1;
4433 /* Nexthop reachability check. */
4434 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4435 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4436 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4437 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4438 && peer
->ttl
== BGP_DEFAULT_TTL
4439 && !CHECK_FLAG(peer
->flags
,
4440 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4441 && !CHECK_FLAG(bgp
->flags
,
4442 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4447 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4449 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4451 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4452 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4454 if (BGP_DEBUG(nht
, NHT
)) {
4455 char buf1
[INET6_ADDRSTRLEN
];
4457 (const void *)&attr_new
->nexthop
,
4458 buf1
, INET6_ADDRSTRLEN
);
4459 zlog_debug("%s(%s): NH unresolved", __func__
,
4462 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4465 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4468 new->addpath_rx_id
= addpath_id
;
4470 /* Increment prefix */
4471 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4473 /* Register new BGP information. */
4474 bgp_path_info_add(dest
, new);
4476 /* route_node_get lock */
4477 bgp_dest_unlock_node(dest
);
4479 #ifdef ENABLE_BGP_VNC
4480 if (safi
== SAFI_MPLS_VPN
) {
4481 struct bgp_dest
*pdest
= NULL
;
4482 struct bgp_table
*table
= NULL
;
4484 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4485 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4486 table
= bgp_dest_get_bgp_table_info(pdest
);
4488 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4489 bgp
, prd
, table
, p
, new);
4491 bgp_dest_unlock_node(pdest
);
4495 /* If this is an EVPN route, process for import. */
4496 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4497 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4499 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4501 /* Process change. */
4502 bgp_process(bgp
, dest
, afi
, safi
);
4504 if (SAFI_UNICAST
== safi
4505 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4506 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4507 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4509 if ((SAFI_MPLS_VPN
== safi
)
4510 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4512 vpn_leak_to_vrf_update(bgp
, new);
4514 #ifdef ENABLE_BGP_VNC
4515 if (SAFI_MPLS_VPN
== safi
) {
4516 mpls_label_t label_decoded
= decode_label(label
);
4518 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4519 sub_type
, &label_decoded
);
4521 if (SAFI_ENCAP
== safi
) {
4522 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4529 /* This BGP update is filtered. Log the reason then update BGP
4532 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4534 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4535 if (!peer
->rcvd_attr_printed
) {
4536 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4537 peer
->rcvd_attr_str
);
4538 peer
->rcvd_attr_printed
= 1;
4541 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4542 addpath_id
? 1 : 0, addpath_id
, evpn
,
4543 pfx_buf
, sizeof(pfx_buf
));
4544 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4545 peer
, pfx_buf
, reason
);
4549 /* If this is an EVPN route, un-import it as it is now filtered.
4551 if (safi
== SAFI_EVPN
)
4552 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4554 if (SAFI_UNICAST
== safi
4555 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4556 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4558 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4560 if ((SAFI_MPLS_VPN
== safi
)
4561 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4563 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4566 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4569 bgp_dest_unlock_node(dest
);
4571 #ifdef ENABLE_BGP_VNC
4573 * Filtered update is treated as an implicit withdrawal (see
4575 * a few lines above)
4577 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4578 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4586 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4587 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4588 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4589 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4592 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4593 struct bgp_dest
*dest
;
4594 struct bgp_path_info
*pi
;
4596 #ifdef ENABLE_BGP_VNC
4597 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4598 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4606 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4608 /* If peer is soft reconfiguration enabled. Record input packet for
4609 * further calculation.
4611 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4612 * routes that are filtered. This tanks out Quagga RS pretty badly due
4614 * the iteration over all RS clients.
4615 * Since we need to remove the entry from adj_in anyway, do that first
4617 * if there was no entry, we don't need to do anything more.
4619 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4620 && peer
!= bgp
->peer_self
)
4621 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4622 peer
->stat_pfx_dup_withdraw
++;
4624 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4625 bgp_debug_rdpfxpath2str(
4626 afi
, safi
, prd
, p
, label
, num_labels
,
4627 addpath_id
? 1 : 0, addpath_id
, NULL
,
4628 pfx_buf
, sizeof(pfx_buf
));
4630 "%s withdrawing route %s not in adj-in",
4631 peer
->host
, pfx_buf
);
4633 bgp_dest_unlock_node(dest
);
4637 /* Lookup withdrawn route. */
4638 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4639 if (pi
->peer
== peer
&& pi
->type
== type
4640 && pi
->sub_type
== sub_type
4641 && pi
->addpath_rx_id
== addpath_id
)
4645 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4646 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4647 addpath_id
? 1 : 0, addpath_id
, NULL
,
4648 pfx_buf
, sizeof(pfx_buf
));
4649 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
4653 /* Withdraw specified route from routing table. */
4654 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4655 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4656 if (SAFI_UNICAST
== safi
4657 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4658 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4659 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4661 if ((SAFI_MPLS_VPN
== safi
)
4662 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4664 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4666 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4667 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4668 addpath_id
? 1 : 0, addpath_id
, NULL
,
4669 pfx_buf
, sizeof(pfx_buf
));
4670 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4673 /* Unlock bgp_node_get() lock. */
4674 bgp_dest_unlock_node(dest
);
4679 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4682 struct update_subgroup
*subgrp
;
4683 subgrp
= peer_subgroup(peer
, afi
, safi
);
4684 subgroup_default_originate(subgrp
, withdraw
);
4689 * bgp_stop_announce_route_timer
4691 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4693 if (!paf
->t_announce_route
)
4696 thread_cancel(&paf
->t_announce_route
);
4700 * bgp_announce_route_timer_expired
4702 * Callback that is invoked when the route announcement timer for a
4705 static void bgp_announce_route_timer_expired(struct thread
*t
)
4707 struct peer_af
*paf
;
4710 paf
= THREAD_ARG(t
);
4713 if (!peer_established(peer
))
4716 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4719 peer_af_announce_route(paf
, 1);
4721 /* Notify BGP conditional advertisement scanner percess */
4722 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
4726 * bgp_announce_route
4728 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4730 * if force is true we will force an update even if the update
4731 * limiting code is attempted to kick in.
4733 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
4735 struct peer_af
*paf
;
4736 struct update_subgroup
*subgrp
;
4738 paf
= peer_af_find(peer
, afi
, safi
);
4741 subgrp
= PAF_SUBGRP(paf
);
4744 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4745 * or a refresh has already been triggered.
4747 if (!subgrp
|| paf
->t_announce_route
)
4751 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
4754 * Start a timer to stagger/delay the announce. This serves
4755 * two purposes - announcement can potentially be combined for
4756 * multiple peers and the announcement doesn't happen in the
4759 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4760 (subgrp
->peer_count
== 1)
4761 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4762 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4763 &paf
->t_announce_route
);
4767 * Announce routes from all AF tables to a peer.
4769 * This should ONLY be called when there is a need to refresh the
4770 * routes to the peer based on a policy change for this peer alone
4771 * or a route refresh request received from the peer.
4772 * The operation will result in splitting the peer from its existing
4773 * subgroups and putting it in new subgroups.
4775 void bgp_announce_route_all(struct peer
*peer
)
4780 FOREACH_AFI_SAFI (afi
, safi
)
4781 bgp_announce_route(peer
, afi
, safi
, false);
4784 /* Flag or unflag bgp_dest to determine whether it should be treated by
4785 * bgp_soft_reconfig_table_task.
4786 * Flag if flag is true. Unflag if flag is false.
4788 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
4790 struct bgp_dest
*dest
;
4791 struct bgp_adj_in
*ain
;
4796 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4797 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4798 if (ain
->peer
!= NULL
)
4801 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
4802 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4804 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4808 static int bgp_soft_reconfig_table_update(struct peer
*peer
,
4809 struct bgp_dest
*dest
,
4810 struct bgp_adj_in
*ain
, afi_t afi
,
4811 safi_t safi
, struct prefix_rd
*prd
)
4813 struct bgp_path_info
*pi
;
4814 uint32_t num_labels
= 0;
4815 mpls_label_t
*label_pnt
= NULL
;
4816 struct bgp_route_evpn evpn
;
4818 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4819 if (pi
->peer
== peer
)
4822 if (pi
&& pi
->extra
)
4823 num_labels
= pi
->extra
->num_labels
;
4825 label_pnt
= &pi
->extra
->label
[0];
4827 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
4830 memset(&evpn
, 0, sizeof(evpn
));
4832 return bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
4833 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
4834 BGP_ROUTE_NORMAL
, prd
, label_pnt
, num_labels
, 1,
4838 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4839 struct bgp_table
*table
,
4840 struct prefix_rd
*prd
)
4843 struct bgp_dest
*dest
;
4844 struct bgp_adj_in
*ain
;
4847 table
= peer
->bgp
->rib
[afi
][safi
];
4849 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4850 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4851 if (ain
->peer
!= peer
)
4854 ret
= bgp_soft_reconfig_table_update(peer
, dest
, ain
,
4858 bgp_dest_unlock_node(dest
);
4864 /* Do soft reconfig table per bgp table.
4865 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4866 * when BGP_NODE_SOFT_RECONFIG is set,
4867 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4868 * Schedule a new thread to continue the job.
4869 * Without splitting the full job into several part,
4870 * vtysh waits for the job to finish before responding to a BGP command
4872 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
4874 uint32_t iter
, max_iter
;
4876 struct bgp_dest
*dest
;
4877 struct bgp_adj_in
*ain
;
4879 struct bgp_table
*table
;
4880 struct prefix_rd
*prd
;
4881 struct listnode
*node
, *nnode
;
4883 table
= THREAD_ARG(thread
);
4886 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
4887 if (table
->soft_reconfig_init
) {
4888 /* first call of the function with a new srta structure.
4889 * Don't do any treatment this time on nodes
4890 * in order vtysh to respond quickly
4895 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
4896 dest
= bgp_route_next(dest
)) {
4897 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
4900 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4902 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4903 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
4905 if (ain
->peer
!= peer
)
4908 ret
= bgp_soft_reconfig_table_update(
4909 peer
, dest
, ain
, table
->afi
,
4914 bgp_dest_unlock_node(dest
);
4916 table
->soft_reconfig_peers
,
4918 bgp_announce_route(peer
, table
->afi
,
4919 table
->safi
, false);
4921 table
->soft_reconfig_peers
)) {
4923 &table
->soft_reconfig_peers
);
4924 bgp_soft_reconfig_table_flag(
4933 /* we're either starting the initial iteration,
4934 * or we're going to continue an ongoing iteration
4936 if (dest
|| table
->soft_reconfig_init
) {
4937 table
->soft_reconfig_init
= false;
4938 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
4939 table
, 0, &table
->soft_reconfig_thread
);
4942 /* we're done, clean up the background iteration context info and
4943 schedule route annoucement
4945 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
4946 listnode_delete(table
->soft_reconfig_peers
, peer
);
4947 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
4950 list_delete(&table
->soft_reconfig_peers
);
4954 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4956 * - bgp cannot be NULL
4957 * - if table and peer are NULL, cancel all threads within the bgp instance
4958 * - if table is NULL and peer is not,
4959 * remove peer in all threads within the bgp instance
4960 * - if peer is NULL, cancel all threads matching table within the bgp instance
4962 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
4963 const struct bgp_table
*table
,
4964 const struct peer
*peer
)
4967 struct listnode
*node
, *nnode
;
4969 struct bgp_table
*ntable
;
4974 FOREACH_AFI_SAFI (afi
, safi
) {
4975 ntable
= bgp
->rib
[afi
][safi
];
4978 if (table
&& table
!= ntable
)
4981 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
4983 if (peer
&& peer
!= npeer
)
4985 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
4988 if (!ntable
->soft_reconfig_peers
4989 || !list_isempty(ntable
->soft_reconfig_peers
))
4992 list_delete(&ntable
->soft_reconfig_peers
);
4993 bgp_soft_reconfig_table_flag(ntable
, false);
4994 BGP_TIMER_OFF(ntable
->soft_reconfig_thread
);
4998 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5000 struct bgp_dest
*dest
;
5001 struct bgp_table
*table
;
5002 struct listnode
*node
, *nnode
;
5004 struct peer_af
*paf
;
5006 if (!peer_established(peer
))
5009 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5010 && (safi
!= SAFI_EVPN
)) {
5011 table
= peer
->bgp
->rib
[afi
][safi
];
5015 table
->soft_reconfig_init
= true;
5017 if (!table
->soft_reconfig_peers
)
5018 table
->soft_reconfig_peers
= list_new();
5020 /* add peer to the table soft_reconfig_peers if not already
5023 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5029 listnode_add(table
->soft_reconfig_peers
, peer
);
5031 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5032 * on table would start back at the beginning.
5034 bgp_soft_reconfig_table_flag(table
, true);
5036 if (!table
->soft_reconfig_thread
)
5037 thread_add_event(bm
->master
,
5038 bgp_soft_reconfig_table_task
, table
, 0,
5039 &table
->soft_reconfig_thread
);
5040 /* Cancel bgp_announce_route_timer_expired threads.
5041 * bgp_announce_route_timer_expired threads have been scheduled
5042 * to announce routes as soon as the soft_reconfigure process
5044 * In this case, soft_reconfigure is also scheduled by using
5045 * a thread but is planned after the
5046 * bgp_announce_route_timer_expired threads. It means that,
5047 * without cancelling the threads, the route announcement task
5048 * would run before the soft reconfiguration one. That would
5049 * useless and would block vtysh during several seconds. Route
5050 * announcements are rescheduled as soon as the soft_reconfigure
5053 paf
= peer_af_find(peer
, afi
, safi
);
5055 bgp_stop_announce_route_timer(paf
);
5057 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5058 dest
= bgp_route_next(dest
)) {
5059 table
= bgp_dest_get_bgp_table_info(dest
);
5064 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5065 struct prefix_rd prd
;
5067 prd
.family
= AF_UNSPEC
;
5069 memcpy(&prd
.val
, p
->u
.val
, 8);
5071 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5076 struct bgp_clear_node_queue
{
5077 struct bgp_dest
*dest
;
5080 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5082 struct bgp_clear_node_queue
*cnq
= data
;
5083 struct bgp_dest
*dest
= cnq
->dest
;
5084 struct peer
*peer
= wq
->spec
.data
;
5085 struct bgp_path_info
*pi
;
5087 afi_t afi
= bgp_dest_table(dest
)->afi
;
5088 safi_t safi
= bgp_dest_table(dest
)->safi
;
5090 assert(dest
&& peer
);
5093 /* It is possible that we have multiple paths for a prefix from a peer
5094 * if that peer is using AddPath.
5096 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5097 if (pi
->peer
!= peer
)
5100 /* graceful restart STALE flag set. */
5101 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5102 && peer
->nsf
[afi
][safi
])
5103 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5104 PEER_STATUS_ENHANCED_REFRESH
))
5105 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5106 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5107 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5109 /* If this is an EVPN route, process for
5111 if (safi
== SAFI_EVPN
)
5112 bgp_evpn_unimport_route(
5114 bgp_dest_get_prefix(dest
), pi
);
5115 /* Handle withdraw for VRF route-leaking and L3VPN */
5116 if (SAFI_UNICAST
== safi
5117 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5118 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5119 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5122 if (SAFI_MPLS_VPN
== safi
&&
5123 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5124 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5127 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5133 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5135 struct bgp_clear_node_queue
*cnq
= data
;
5136 struct bgp_dest
*dest
= cnq
->dest
;
5137 struct bgp_table
*table
= bgp_dest_table(dest
);
5139 bgp_dest_unlock_node(dest
);
5140 bgp_table_unlock(table
);
5141 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5144 static void bgp_clear_node_complete(struct work_queue
*wq
)
5146 struct peer
*peer
= wq
->spec
.data
;
5148 /* Tickle FSM to start moving again */
5149 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5151 peer_unlock(peer
); /* bgp_clear_route */
5154 static void bgp_clear_node_queue_init(struct peer
*peer
)
5156 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5158 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5159 #undef CLEAR_QUEUE_NAME_LEN
5161 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5162 peer
->clear_node_queue
->spec
.hold
= 10;
5163 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5164 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5165 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5166 peer
->clear_node_queue
->spec
.max_retries
= 0;
5168 /* we only 'lock' this peer reference when the queue is actually active
5170 peer
->clear_node_queue
->spec
.data
= peer
;
5173 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5174 struct bgp_table
*table
)
5176 struct bgp_dest
*dest
;
5177 int force
= peer
->bgp
->process_queue
? 0 : 1;
5180 table
= peer
->bgp
->rib
[afi
][safi
];
5182 /* If still no table => afi/safi isn't configured at all or smth. */
5186 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5187 struct bgp_path_info
*pi
, *next
;
5188 struct bgp_adj_in
*ain
;
5189 struct bgp_adj_in
*ain_next
;
5191 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5192 * queued for every clearing peer, regardless of whether it is
5193 * relevant to the peer at hand.
5195 * Overview: There are 3 different indices which need to be
5196 * scrubbed, potentially, when a peer is removed:
5198 * 1 peer's routes visible via the RIB (ie accepted routes)
5199 * 2 peer's routes visible by the (optional) peer's adj-in index
5200 * 3 other routes visible by the peer's adj-out index
5202 * 3 there is no hurry in scrubbing, once the struct peer is
5203 * removed from bgp->peer, we could just GC such deleted peer's
5204 * adj-outs at our leisure.
5206 * 1 and 2 must be 'scrubbed' in some way, at least made
5207 * invisible via RIB index before peer session is allowed to be
5208 * brought back up. So one needs to know when such a 'search' is
5213 * - there'd be a single global queue or a single RIB walker
5214 * - rather than tracking which route_nodes still need to be
5215 * examined on a peer basis, we'd track which peers still
5218 * Given that our per-peer prefix-counts now should be reliable,
5219 * this may actually be achievable. It doesn't seem to be a huge
5220 * problem at this time,
5222 * It is possible that we have multiple paths for a prefix from
5224 * if that peer is using AddPath.
5228 ain_next
= ain
->next
;
5230 if (ain
->peer
== peer
)
5231 bgp_adj_in_remove(dest
, ain
);
5236 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5238 if (pi
->peer
!= peer
)
5242 bgp_path_info_reap(dest
, pi
);
5244 struct bgp_clear_node_queue
*cnq
;
5246 /* both unlocked in bgp_clear_node_queue_del */
5247 bgp_table_lock(bgp_dest_table(dest
));
5248 bgp_dest_lock_node(dest
);
5250 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5251 sizeof(struct bgp_clear_node_queue
));
5253 work_queue_add(peer
->clear_node_queue
, cnq
);
5261 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5263 struct bgp_dest
*dest
;
5264 struct bgp_table
*table
;
5266 if (peer
->clear_node_queue
== NULL
)
5267 bgp_clear_node_queue_init(peer
);
5269 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5270 * Idle until it receives a Clearing_Completed event. This protects
5271 * against peers which flap faster than we can we clear, which could
5274 * a) race with routes from the new session being installed before
5275 * clear_route_node visits the node (to delete the route of that
5277 * b) resource exhaustion, clear_route_node likely leads to an entry
5278 * on the process_main queue. Fast-flapping could cause that queue
5282 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5283 * the unlock will happen upon work-queue completion; other wise, the
5284 * unlock happens at the end of this function.
5286 if (!peer
->clear_node_queue
->thread
)
5289 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5290 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5292 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5293 dest
= bgp_route_next(dest
)) {
5294 table
= bgp_dest_get_bgp_table_info(dest
);
5298 bgp_clear_route_table(peer
, afi
, safi
, table
);
5301 /* unlock if no nodes got added to the clear-node-queue. */
5302 if (!peer
->clear_node_queue
->thread
)
5306 void bgp_clear_route_all(struct peer
*peer
)
5311 FOREACH_AFI_SAFI (afi
, safi
)
5312 bgp_clear_route(peer
, afi
, safi
);
5314 #ifdef ENABLE_BGP_VNC
5315 rfapiProcessPeerDown(peer
);
5319 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5321 struct bgp_table
*table
;
5322 struct bgp_dest
*dest
;
5323 struct bgp_adj_in
*ain
;
5324 struct bgp_adj_in
*ain_next
;
5326 table
= peer
->bgp
->rib
[afi
][safi
];
5328 /* It is possible that we have multiple paths for a prefix from a peer
5329 * if that peer is using AddPath.
5331 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5335 ain_next
= ain
->next
;
5337 if (ain
->peer
== peer
)
5338 bgp_adj_in_remove(dest
, ain
);
5345 /* If any of the routes from the peer have been marked with the NO_LLGR
5346 * community, either as sent by the peer, or as the result of a configured
5347 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5348 * operation of [RFC4271].
5350 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5352 struct bgp_dest
*dest
;
5353 struct bgp_path_info
*pi
;
5354 struct bgp_table
*table
;
5356 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5357 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5358 dest
= bgp_route_next(dest
)) {
5359 struct bgp_dest
*rm
;
5361 /* look for neighbor in tables */
5362 table
= bgp_dest_get_bgp_table_info(dest
);
5366 for (rm
= bgp_table_top(table
); rm
;
5367 rm
= bgp_route_next(rm
))
5368 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5370 if (pi
->peer
!= peer
)
5373 peer
->af_sflags
[afi
][safi
],
5374 PEER_STATUS_LLGR_WAIT
) &&
5375 bgp_attr_get_community(pi
->attr
) &&
5377 bgp_attr_get_community(
5381 if (!CHECK_FLAG(pi
->flags
,
5386 * If this is VRF leaked route
5387 * process for withdraw.
5390 BGP_ROUTE_IMPORTED
&&
5391 peer
->bgp
->inst_type
==
5392 BGP_INSTANCE_TYPE_DEFAULT
)
5393 vpn_leak_to_vrf_withdraw(
5396 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5401 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5402 dest
= bgp_route_next(dest
))
5403 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5405 if (pi
->peer
!= peer
)
5407 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5408 PEER_STATUS_LLGR_WAIT
) &&
5409 bgp_attr_get_community(pi
->attr
) &&
5411 bgp_attr_get_community(pi
->attr
),
5414 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5416 if (safi
== SAFI_UNICAST
&&
5417 (peer
->bgp
->inst_type
==
5418 BGP_INSTANCE_TYPE_VRF
||
5419 peer
->bgp
->inst_type
==
5420 BGP_INSTANCE_TYPE_DEFAULT
))
5421 vpn_leak_from_vrf_withdraw(
5422 bgp_get_default(), peer
->bgp
,
5425 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5431 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5433 struct bgp_dest
*dest
, *ndest
;
5434 struct bgp_path_info
*pi
;
5435 struct bgp_table
*table
;
5437 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5438 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5439 dest
= bgp_route_next(dest
)) {
5440 table
= bgp_dest_get_bgp_table_info(dest
);
5444 for (ndest
= bgp_table_top(table
); ndest
;
5445 ndest
= bgp_route_next(ndest
)) {
5446 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5448 if (pi
->peer
!= peer
)
5452 peer
->af_sflags
[afi
][safi
],
5453 PEER_STATUS_ENHANCED_REFRESH
))
5454 && !CHECK_FLAG(pi
->flags
,
5458 BGP_PATH_UNUSEABLE
)) {
5459 if (bgp_debug_neighbor_events(
5462 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5466 bgp_dest_get_prefix(
5469 bgp_path_info_set_flag(
5477 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5478 dest
= bgp_route_next(dest
)) {
5479 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5481 if (pi
->peer
!= peer
)
5484 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5485 PEER_STATUS_ENHANCED_REFRESH
))
5486 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5487 && !CHECK_FLAG(pi
->flags
,
5488 BGP_PATH_UNUSEABLE
)) {
5489 if (bgp_debug_neighbor_events(peer
))
5491 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5495 bgp_dest_get_prefix(
5498 bgp_path_info_set_flag(dest
, pi
,
5506 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5508 if (peer
->sort
== BGP_PEER_IBGP
)
5511 if (peer
->sort
== BGP_PEER_EBGP
5512 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5513 || FILTER_LIST_OUT_NAME(filter
)
5514 || DISTRIBUTE_OUT_NAME(filter
)))
5519 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5521 if (peer
->sort
== BGP_PEER_IBGP
)
5524 if (peer
->sort
== BGP_PEER_EBGP
5525 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5526 || FILTER_LIST_IN_NAME(filter
)
5527 || DISTRIBUTE_IN_NAME(filter
)))
5532 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5535 struct bgp_dest
*dest
;
5536 struct bgp_path_info
*pi
;
5537 struct bgp_path_info
*next
;
5539 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5540 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5541 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5545 /* Unimport EVPN routes from VRFs */
5546 if (safi
== SAFI_EVPN
)
5547 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5550 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5551 && pi
->type
== ZEBRA_ROUTE_BGP
5552 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5553 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5554 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5556 if (bgp_fibupd_safi(safi
))
5557 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5560 bgp_path_info_reap(dest
, pi
);
5564 /* Delete all kernel routes. */
5565 void bgp_cleanup_routes(struct bgp
*bgp
)
5568 struct bgp_dest
*dest
;
5569 struct bgp_table
*table
;
5571 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5572 if (afi
== AFI_L2VPN
)
5574 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5577 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5579 if (afi
!= AFI_L2VPN
) {
5581 safi
= SAFI_MPLS_VPN
;
5582 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5583 dest
= bgp_route_next(dest
)) {
5584 table
= bgp_dest_get_bgp_table_info(dest
);
5585 if (table
!= NULL
) {
5586 bgp_cleanup_table(bgp
, table
, safi
);
5587 bgp_table_finish(&table
);
5588 bgp_dest_set_bgp_table_info(dest
, NULL
);
5589 bgp_dest_unlock_node(dest
);
5593 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5594 dest
= bgp_route_next(dest
)) {
5595 table
= bgp_dest_get_bgp_table_info(dest
);
5596 if (table
!= NULL
) {
5597 bgp_cleanup_table(bgp
, table
, safi
);
5598 bgp_table_finish(&table
);
5599 bgp_dest_set_bgp_table_info(dest
, NULL
);
5600 bgp_dest_unlock_node(dest
);
5605 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5606 dest
= bgp_route_next(dest
)) {
5607 table
= bgp_dest_get_bgp_table_info(dest
);
5608 if (table
!= NULL
) {
5609 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5610 bgp_table_finish(&table
);
5611 bgp_dest_set_bgp_table_info(dest
, NULL
);
5612 bgp_dest_unlock_node(dest
);
5617 void bgp_reset(void)
5620 bgp_zclient_reset();
5621 access_list_reset();
5622 prefix_list_reset();
5625 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5627 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5628 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5629 PEER_CAP_ADDPATH_AF_TX_RCV
));
5632 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5634 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5635 struct bgp_nlri
*packet
)
5644 bool addpath_capable
;
5645 uint32_t addpath_id
;
5648 lim
= pnt
+ packet
->length
;
5650 safi
= packet
->safi
;
5652 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5654 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5655 syntactic validity. If the field is syntactically incorrect,
5656 then the Error Subcode is set to Invalid Network Field. */
5657 for (; pnt
< lim
; pnt
+= psize
) {
5658 /* Clear prefix structure. */
5659 memset(&p
, 0, sizeof(struct prefix
));
5661 if (addpath_capable
) {
5663 /* When packet overflow occurs return immediately. */
5664 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5665 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5667 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5668 addpath_id
= ntohl(addpath_id
);
5669 pnt
+= BGP_ADDPATH_ID_LEN
;
5672 /* Fetch prefix length. */
5673 p
.prefixlen
= *pnt
++;
5674 /* afi/safi validity already verified by caller,
5675 * bgp_update_receive */
5676 p
.family
= afi2family(afi
);
5678 /* Prefix length check. */
5679 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5682 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5683 peer
->host
, p
.prefixlen
, packet
->afi
);
5684 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5687 /* Packet size overflow check. */
5688 psize
= PSIZE(p
.prefixlen
);
5690 /* When packet overflow occur return immediately. */
5691 if (pnt
+ psize
> lim
) {
5694 "%s [Error] Update packet error (prefix length %d overflows packet)",
5695 peer
->host
, p
.prefixlen
);
5696 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5699 /* Defensive coding, double-check the psize fits in a struct
5701 if (psize
> (ssize_t
)sizeof(p
.u
)) {
5704 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5705 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
5706 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5709 /* Fetch prefix from NLRI packet. */
5710 memcpy(p
.u
.val
, pnt
, psize
);
5712 /* Check address. */
5713 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5714 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5715 /* From RFC4271 Section 6.3:
5717 * If a prefix in the NLRI field is semantically
5719 * (e.g., an unexpected multicast IP address),
5721 * be logged locally, and the prefix SHOULD be
5726 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5727 peer
->host
, &p
.u
.prefix4
);
5732 /* Check address. */
5733 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5734 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5737 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5738 peer
->host
, &p
.u
.prefix6
);
5742 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5745 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5746 peer
->host
, &p
.u
.prefix6
);
5752 /* Normal process. */
5754 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5755 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5756 NULL
, NULL
, 0, 0, NULL
);
5758 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5759 safi
, ZEBRA_ROUTE_BGP
,
5760 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5763 /* Do not send BGP notification twice when maximum-prefix count
5765 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5766 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5768 /* Address family configuration mismatch. */
5770 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5773 /* Packet length consistency check. */
5777 "%s [Error] Update packet error (prefix length mismatch with total length)",
5779 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5782 return BGP_NLRI_PARSE_OK
;
5785 static struct bgp_static
*bgp_static_new(void)
5787 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5790 static void bgp_static_free(struct bgp_static
*bgp_static
)
5792 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5793 route_map_counter_decrement(bgp_static
->rmap
.map
);
5795 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5796 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5799 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5800 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5802 struct bgp_dest
*dest
;
5803 struct bgp_path_info
*pi
;
5804 struct bgp_path_info
*new;
5805 struct bgp_path_info rmap_path
;
5807 struct attr
*attr_new
;
5808 route_map_result_t ret
;
5809 #ifdef ENABLE_BGP_VNC
5810 int vnc_implicit_withdraw
= 0;
5815 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5817 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5819 attr
.nexthop
= bgp_static
->igpnexthop
;
5820 attr
.med
= bgp_static
->igpmetric
;
5821 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5823 if (bgp_static
->atomic
)
5824 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5826 /* Store label index, if required. */
5827 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5828 attr
.label_index
= bgp_static
->label_index
;
5829 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5832 /* Apply route-map. */
5833 if (bgp_static
->rmap
.name
) {
5834 struct attr attr_tmp
= attr
;
5836 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5837 rmap_path
.peer
= bgp
->peer_self
;
5838 rmap_path
.attr
= &attr_tmp
;
5840 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5842 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5844 bgp
->peer_self
->rmap_type
= 0;
5846 if (ret
== RMAP_DENYMATCH
) {
5847 /* Free uninterned attribute. */
5848 bgp_attr_flush(&attr_tmp
);
5850 /* Unintern original. */
5851 aspath_unintern(&attr
.aspath
);
5852 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5856 if (bgp_in_graceful_shutdown(bgp
))
5857 bgp_attr_add_gshut_community(&attr_tmp
);
5859 attr_new
= bgp_attr_intern(&attr_tmp
);
5862 if (bgp_in_graceful_shutdown(bgp
))
5863 bgp_attr_add_gshut_community(&attr
);
5865 attr_new
= bgp_attr_intern(&attr
);
5868 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5869 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5870 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5874 if (attrhash_cmp(pi
->attr
, attr_new
)
5875 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5876 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5877 bgp_dest_unlock_node(dest
);
5878 bgp_attr_unintern(&attr_new
);
5879 aspath_unintern(&attr
.aspath
);
5882 /* The attribute is changed. */
5883 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5885 /* Rewrite BGP route information. */
5886 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5887 bgp_path_info_restore(dest
, pi
);
5889 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5890 #ifdef ENABLE_BGP_VNC
5891 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5892 && (safi
== SAFI_UNICAST
)) {
5893 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5895 * Implicit withdraw case.
5896 * We have to do this before pi is
5899 ++vnc_implicit_withdraw
;
5900 vnc_import_bgp_del_route(bgp
, p
, pi
);
5901 vnc_import_bgp_exterior_del_route(
5906 bgp_attr_unintern(&pi
->attr
);
5907 pi
->attr
= attr_new
;
5908 pi
->uptime
= bgp_clock();
5909 #ifdef ENABLE_BGP_VNC
5910 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5911 && (safi
== SAFI_UNICAST
)) {
5912 if (vnc_implicit_withdraw
) {
5913 vnc_import_bgp_add_route(bgp
, p
, pi
);
5914 vnc_import_bgp_exterior_add_route(
5920 /* Nexthop reachability check. */
5921 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5922 && (safi
== SAFI_UNICAST
5923 || safi
== SAFI_LABELED_UNICAST
)) {
5925 struct bgp
*bgp_nexthop
= bgp
;
5927 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5928 bgp_nexthop
= pi
->extra
->bgp_orig
;
5930 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5931 afi
, safi
, pi
, NULL
,
5933 bgp_path_info_set_flag(dest
, pi
,
5936 if (BGP_DEBUG(nht
, NHT
)) {
5937 char buf1
[INET6_ADDRSTRLEN
];
5938 inet_ntop(p
->family
,
5942 "%s(%s): Route not in table, not advertising",
5945 bgp_path_info_unset_flag(
5946 dest
, pi
, BGP_PATH_VALID
);
5949 /* Delete the NHT structure if any, if we're
5951 * enabling/disabling import check. We
5952 * deregister the route
5953 * from NHT to avoid overloading NHT and the
5954 * process interaction
5956 bgp_unlink_nexthop(pi
);
5957 bgp_path_info_set_flag(dest
, pi
,
5960 /* Process change. */
5961 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5962 bgp_process(bgp
, dest
, afi
, safi
);
5964 if (SAFI_UNICAST
== safi
5965 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5967 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5968 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5972 bgp_dest_unlock_node(dest
);
5973 aspath_unintern(&attr
.aspath
);
5978 /* Make new BGP info. */
5979 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5981 /* Nexthop reachability check. */
5982 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5983 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5984 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
5986 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5988 if (BGP_DEBUG(nht
, NHT
)) {
5989 char buf1
[INET6_ADDRSTRLEN
];
5990 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5993 "%s(%s): Route not in table, not advertising",
5996 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5999 /* Delete the NHT structure if any, if we're toggling between
6000 * enabling/disabling import check. We deregister the route
6001 * from NHT to avoid overloading NHT and the process interaction
6003 bgp_unlink_nexthop(new);
6005 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6008 /* Aggregate address increment. */
6009 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6011 /* Register new BGP information. */
6012 bgp_path_info_add(dest
, new);
6014 /* route_node_get lock */
6015 bgp_dest_unlock_node(dest
);
6017 /* Process change. */
6018 bgp_process(bgp
, dest
, afi
, safi
);
6020 if (SAFI_UNICAST
== safi
6021 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6022 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6023 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6026 /* Unintern original. */
6027 aspath_unintern(&attr
.aspath
);
6030 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6033 struct bgp_dest
*dest
;
6034 struct bgp_path_info
*pi
;
6036 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6038 /* Check selected route and self inserted route. */
6039 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6040 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6041 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6044 /* Withdraw static BGP route from routing table. */
6046 if (SAFI_UNICAST
== safi
6047 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6048 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6049 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6051 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6052 bgp_unlink_nexthop(pi
);
6053 bgp_path_info_delete(dest
, pi
);
6054 bgp_process(bgp
, dest
, afi
, safi
);
6057 /* Unlock bgp_node_lookup. */
6058 bgp_dest_unlock_node(dest
);
6062 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6064 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6065 afi_t afi
, safi_t safi
,
6066 struct prefix_rd
*prd
)
6068 struct bgp_dest
*dest
;
6069 struct bgp_path_info
*pi
;
6071 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6073 /* Check selected route and self inserted route. */
6074 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6075 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6076 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6079 /* Withdraw static BGP route from routing table. */
6081 #ifdef ENABLE_BGP_VNC
6082 rfapiProcessWithdraw(
6083 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6084 1); /* Kill, since it is an administrative change */
6086 if (SAFI_MPLS_VPN
== safi
6087 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6088 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6090 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6091 bgp_path_info_delete(dest
, pi
);
6092 bgp_process(bgp
, dest
, afi
, safi
);
6095 /* Unlock bgp_node_lookup. */
6096 bgp_dest_unlock_node(dest
);
6099 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6100 struct bgp_static
*bgp_static
, afi_t afi
,
6103 struct bgp_dest
*dest
;
6104 struct bgp_path_info
*new;
6105 struct attr
*attr_new
;
6106 struct attr attr
= {0};
6107 struct bgp_path_info
*pi
;
6108 #ifdef ENABLE_BGP_VNC
6109 mpls_label_t label
= 0;
6111 uint32_t num_labels
= 0;
6115 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6117 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6120 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
6122 attr
.nexthop
= bgp_static
->igpnexthop
;
6123 attr
.med
= bgp_static
->igpmetric
;
6124 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6126 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6127 || (safi
== SAFI_ENCAP
)) {
6128 if (afi
== AFI_IP
) {
6129 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6130 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6133 if (afi
== AFI_L2VPN
) {
6134 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6135 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6136 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6137 &bgp_static
->gatewayIp
.u
.prefix4
,
6139 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6140 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6141 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6142 &bgp_static
->gatewayIp
.u
.prefix6
,
6145 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6146 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6147 struct bgp_encap_type_vxlan bet
;
6148 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
6149 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6150 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6152 if (bgp_static
->router_mac
) {
6153 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6156 /* Apply route-map. */
6157 if (bgp_static
->rmap
.name
) {
6158 struct attr attr_tmp
= attr
;
6159 struct bgp_path_info rmap_path
;
6160 route_map_result_t ret
;
6162 rmap_path
.peer
= bgp
->peer_self
;
6163 rmap_path
.attr
= &attr_tmp
;
6165 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6167 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6169 bgp
->peer_self
->rmap_type
= 0;
6171 if (ret
== RMAP_DENYMATCH
) {
6172 /* Free uninterned attribute. */
6173 bgp_attr_flush(&attr_tmp
);
6175 /* Unintern original. */
6176 aspath_unintern(&attr
.aspath
);
6177 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6182 attr_new
= bgp_attr_intern(&attr_tmp
);
6184 attr_new
= bgp_attr_intern(&attr
);
6187 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6188 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6189 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6193 if (attrhash_cmp(pi
->attr
, attr_new
)
6194 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6195 bgp_dest_unlock_node(dest
);
6196 bgp_attr_unintern(&attr_new
);
6197 aspath_unintern(&attr
.aspath
);
6200 /* The attribute is changed. */
6201 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6203 /* Rewrite BGP route information. */
6204 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6205 bgp_path_info_restore(dest
, pi
);
6207 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6208 bgp_attr_unintern(&pi
->attr
);
6209 pi
->attr
= attr_new
;
6210 pi
->uptime
= bgp_clock();
6211 #ifdef ENABLE_BGP_VNC
6213 label
= decode_label(&pi
->extra
->label
[0]);
6216 /* Process change. */
6217 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6218 bgp_process(bgp
, dest
, afi
, safi
);
6220 if (SAFI_MPLS_VPN
== safi
6221 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6222 vpn_leak_to_vrf_update(bgp
, pi
);
6224 #ifdef ENABLE_BGP_VNC
6225 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6226 pi
->attr
, afi
, safi
, pi
->type
,
6227 pi
->sub_type
, &label
);
6229 bgp_dest_unlock_node(dest
);
6230 aspath_unintern(&attr
.aspath
);
6236 /* Make new BGP info. */
6237 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6239 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6240 bgp_path_info_extra_get(new);
6242 new->extra
->label
[0] = bgp_static
->label
;
6243 new->extra
->num_labels
= num_labels
;
6245 #ifdef ENABLE_BGP_VNC
6246 label
= decode_label(&bgp_static
->label
);
6249 /* Aggregate address increment. */
6250 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6252 /* Register new BGP information. */
6253 bgp_path_info_add(dest
, new);
6254 /* route_node_get lock */
6255 bgp_dest_unlock_node(dest
);
6257 /* Process change. */
6258 bgp_process(bgp
, dest
, afi
, safi
);
6260 if (SAFI_MPLS_VPN
== safi
6261 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6262 vpn_leak_to_vrf_update(bgp
, new);
6264 #ifdef ENABLE_BGP_VNC
6265 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6266 safi
, new->type
, new->sub_type
, &label
);
6269 /* Unintern original. */
6270 aspath_unintern(&attr
.aspath
);
6273 /* Configure static BGP network. When user don't run zebra, static
6274 route should be installed as valid. */
6275 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6276 const char *ip_str
, afi_t afi
, safi_t safi
,
6277 const char *rmap
, int backdoor
, uint32_t label_index
)
6279 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6282 struct bgp_static
*bgp_static
;
6283 struct bgp_dest
*dest
;
6284 uint8_t need_update
= 0;
6286 /* Convert IP prefix string to struct prefix. */
6287 ret
= str2prefix(ip_str
, &p
);
6289 vty_out(vty
, "%% Malformed prefix\n");
6290 return CMD_WARNING_CONFIG_FAILED
;
6292 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6293 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6294 return CMD_WARNING_CONFIG_FAILED
;
6301 /* Set BGP static route configuration. */
6302 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6305 vty_out(vty
, "%% Can't find static route specified\n");
6306 return CMD_WARNING_CONFIG_FAILED
;
6309 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6311 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6312 && (label_index
!= bgp_static
->label_index
)) {
6314 "%% label-index doesn't match static route\n");
6315 bgp_dest_unlock_node(dest
);
6316 return CMD_WARNING_CONFIG_FAILED
;
6319 if ((rmap
&& bgp_static
->rmap
.name
)
6320 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6322 "%% route-map name doesn't match static route\n");
6323 bgp_dest_unlock_node(dest
);
6324 return CMD_WARNING_CONFIG_FAILED
;
6327 /* Update BGP RIB. */
6328 if (!bgp_static
->backdoor
)
6329 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6331 /* Clear configuration. */
6332 bgp_static_free(bgp_static
);
6333 bgp_dest_set_bgp_static_info(dest
, NULL
);
6334 bgp_dest_unlock_node(dest
);
6335 bgp_dest_unlock_node(dest
);
6338 /* Set BGP static route configuration. */
6339 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6340 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6342 /* Configuration change. */
6343 /* Label index cannot be changed. */
6344 if (bgp_static
->label_index
!= label_index
) {
6345 vty_out(vty
, "%% cannot change label-index\n");
6346 return CMD_WARNING_CONFIG_FAILED
;
6349 /* Check previous routes are installed into BGP. */
6350 if (bgp_static
->valid
6351 && bgp_static
->backdoor
!= backdoor
)
6354 bgp_static
->backdoor
= backdoor
;
6357 XFREE(MTYPE_ROUTE_MAP_NAME
,
6358 bgp_static
->rmap
.name
);
6359 route_map_counter_decrement(
6360 bgp_static
->rmap
.map
);
6361 bgp_static
->rmap
.name
=
6362 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6363 bgp_static
->rmap
.map
=
6364 route_map_lookup_by_name(rmap
);
6365 route_map_counter_increment(
6366 bgp_static
->rmap
.map
);
6368 XFREE(MTYPE_ROUTE_MAP_NAME
,
6369 bgp_static
->rmap
.name
);
6370 route_map_counter_decrement(
6371 bgp_static
->rmap
.map
);
6372 bgp_static
->rmap
.map
= NULL
;
6373 bgp_static
->valid
= 0;
6375 bgp_dest_unlock_node(dest
);
6377 /* New configuration. */
6378 bgp_static
= bgp_static_new();
6379 bgp_static
->backdoor
= backdoor
;
6380 bgp_static
->valid
= 0;
6381 bgp_static
->igpmetric
= 0;
6382 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6383 bgp_static
->label_index
= label_index
;
6386 XFREE(MTYPE_ROUTE_MAP_NAME
,
6387 bgp_static
->rmap
.name
);
6388 route_map_counter_decrement(
6389 bgp_static
->rmap
.map
);
6390 bgp_static
->rmap
.name
=
6391 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6392 bgp_static
->rmap
.map
=
6393 route_map_lookup_by_name(rmap
);
6394 route_map_counter_increment(
6395 bgp_static
->rmap
.map
);
6397 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6400 bgp_static
->valid
= 1;
6402 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6404 if (!bgp_static
->backdoor
)
6405 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6411 void bgp_static_add(struct bgp
*bgp
)
6415 struct bgp_dest
*dest
;
6416 struct bgp_dest
*rm
;
6417 struct bgp_table
*table
;
6418 struct bgp_static
*bgp_static
;
6420 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6421 FOREACH_AFI_SAFI (afi
, safi
)
6422 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6423 dest
= bgp_route_next(dest
)) {
6424 if (!bgp_dest_has_bgp_path_info_data(dest
))
6427 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6428 || (safi
== SAFI_EVPN
)) {
6429 table
= bgp_dest_get_bgp_table_info(dest
);
6431 for (rm
= bgp_table_top(table
); rm
;
6432 rm
= bgp_route_next(rm
)) {
6434 bgp_dest_get_bgp_static_info(
6436 bgp_static_update_safi(
6437 bgp
, bgp_dest_get_prefix(rm
),
6438 bgp_static
, afi
, safi
);
6442 bgp
, bgp_dest_get_prefix(dest
),
6443 bgp_dest_get_bgp_static_info(dest
), afi
,
6447 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6450 /* Called from bgp_delete(). Delete all static routes from the BGP
6452 void bgp_static_delete(struct bgp
*bgp
)
6456 struct bgp_dest
*dest
;
6457 struct bgp_dest
*rm
;
6458 struct bgp_table
*table
;
6459 struct bgp_static
*bgp_static
;
6461 FOREACH_AFI_SAFI (afi
, safi
)
6462 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6463 dest
= bgp_route_next(dest
)) {
6464 if (!bgp_dest_has_bgp_path_info_data(dest
))
6467 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6468 || (safi
== SAFI_EVPN
)) {
6469 table
= bgp_dest_get_bgp_table_info(dest
);
6471 for (rm
= bgp_table_top(table
); rm
;
6472 rm
= bgp_route_next(rm
)) {
6474 bgp_dest_get_bgp_static_info(
6479 bgp_static_withdraw_safi(
6480 bgp
, bgp_dest_get_prefix(rm
),
6482 (struct prefix_rd
*)
6483 bgp_dest_get_prefix(
6485 bgp_static_free(bgp_static
);
6486 bgp_dest_set_bgp_static_info(rm
,
6488 bgp_dest_unlock_node(rm
);
6491 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6492 bgp_static_withdraw(bgp
,
6493 bgp_dest_get_prefix(dest
),
6495 bgp_static_free(bgp_static
);
6496 bgp_dest_set_bgp_static_info(dest
, NULL
);
6497 bgp_dest_unlock_node(dest
);
6502 void bgp_static_redo_import_check(struct bgp
*bgp
)
6506 struct bgp_dest
*dest
;
6507 struct bgp_dest
*rm
;
6508 struct bgp_table
*table
;
6509 struct bgp_static
*bgp_static
;
6511 /* Use this flag to force reprocessing of the route */
6512 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6513 FOREACH_AFI_SAFI (afi
, safi
) {
6514 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6515 dest
= bgp_route_next(dest
)) {
6516 if (!bgp_dest_has_bgp_path_info_data(dest
))
6519 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6520 || (safi
== SAFI_EVPN
)) {
6521 table
= bgp_dest_get_bgp_table_info(dest
);
6523 for (rm
= bgp_table_top(table
); rm
;
6524 rm
= bgp_route_next(rm
)) {
6526 bgp_dest_get_bgp_static_info(
6528 bgp_static_update_safi(
6529 bgp
, bgp_dest_get_prefix(rm
),
6530 bgp_static
, afi
, safi
);
6533 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6534 bgp_static_update(bgp
,
6535 bgp_dest_get_prefix(dest
),
6536 bgp_static
, afi
, safi
);
6540 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6543 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6546 struct bgp_table
*table
;
6547 struct bgp_dest
*dest
;
6548 struct bgp_path_info
*pi
;
6550 /* Do not install the aggregate route if BGP is in the
6551 * process of termination.
6553 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6554 || (bgp
->peer_self
== NULL
))
6557 table
= bgp
->rib
[afi
][safi
];
6558 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6559 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6560 if (pi
->peer
== bgp
->peer_self
6561 && ((pi
->type
== ZEBRA_ROUTE_BGP
6562 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6563 || (pi
->type
!= ZEBRA_ROUTE_BGP
6565 == BGP_ROUTE_REDISTRIBUTE
))) {
6566 bgp_aggregate_decrement(
6567 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6569 bgp_unlink_nexthop(pi
);
6570 bgp_path_info_delete(dest
, pi
);
6571 bgp_process(bgp
, dest
, afi
, safi
);
6578 * Purge all networks and redistributed routes from routing table.
6579 * Invoked upon the instance going down.
6581 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6586 FOREACH_AFI_SAFI (afi
, safi
)
6587 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6592 * Currently this is used to set static routes for VPN and ENCAP.
6593 * I think it can probably be factored with bgp_static_set.
6595 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6596 const char *ip_str
, const char *rd_str
,
6597 const char *label_str
, const char *rmap_str
,
6598 int evpn_type
, const char *esi
, const char *gwip
,
6599 const char *ethtag
, const char *routermac
)
6601 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6604 struct prefix_rd prd
;
6605 struct bgp_dest
*pdest
;
6606 struct bgp_dest
*dest
;
6607 struct bgp_table
*table
;
6608 struct bgp_static
*bgp_static
;
6609 mpls_label_t label
= MPLS_INVALID_LABEL
;
6610 struct prefix gw_ip
;
6612 /* validate ip prefix */
6613 ret
= str2prefix(ip_str
, &p
);
6615 vty_out(vty
, "%% Malformed prefix\n");
6616 return CMD_WARNING_CONFIG_FAILED
;
6619 if ((afi
== AFI_L2VPN
)
6620 && (bgp_build_evpn_prefix(evpn_type
,
6621 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6622 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6623 return CMD_WARNING_CONFIG_FAILED
;
6626 ret
= str2prefix_rd(rd_str
, &prd
);
6628 vty_out(vty
, "%% Malformed rd\n");
6629 return CMD_WARNING_CONFIG_FAILED
;
6633 unsigned long label_val
;
6634 label_val
= strtoul(label_str
, NULL
, 10);
6635 encode_label(label_val
, &label
);
6638 if (safi
== SAFI_EVPN
) {
6639 if (esi
&& str2esi(esi
, NULL
) == 0) {
6640 vty_out(vty
, "%% Malformed ESI\n");
6641 return CMD_WARNING_CONFIG_FAILED
;
6643 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6644 vty_out(vty
, "%% Malformed Router MAC\n");
6645 return CMD_WARNING_CONFIG_FAILED
;
6648 memset(&gw_ip
, 0, sizeof(struct prefix
));
6649 ret
= str2prefix(gwip
, &gw_ip
);
6651 vty_out(vty
, "%% Malformed GatewayIp\n");
6652 return CMD_WARNING_CONFIG_FAILED
;
6654 if ((gw_ip
.family
== AF_INET
6655 && is_evpn_prefix_ipaddr_v6(
6656 (struct prefix_evpn
*)&p
))
6657 || (gw_ip
.family
== AF_INET6
6658 && is_evpn_prefix_ipaddr_v4(
6659 (struct prefix_evpn
*)&p
))) {
6661 "%% GatewayIp family differs with IP prefix\n");
6662 return CMD_WARNING_CONFIG_FAILED
;
6666 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6667 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6668 bgp_dest_set_bgp_table_info(pdest
,
6669 bgp_table_init(bgp
, afi
, safi
));
6670 table
= bgp_dest_get_bgp_table_info(pdest
);
6672 dest
= bgp_node_get(table
, &p
);
6674 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6675 vty_out(vty
, "%% Same network configuration exists\n");
6676 bgp_dest_unlock_node(dest
);
6678 /* New configuration. */
6679 bgp_static
= bgp_static_new();
6680 bgp_static
->backdoor
= 0;
6681 bgp_static
->valid
= 0;
6682 bgp_static
->igpmetric
= 0;
6683 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6684 bgp_static
->label
= label
;
6685 bgp_static
->prd
= prd
;
6688 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6689 route_map_counter_decrement(bgp_static
->rmap
.map
);
6690 bgp_static
->rmap
.name
=
6691 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6692 bgp_static
->rmap
.map
=
6693 route_map_lookup_by_name(rmap_str
);
6694 route_map_counter_increment(bgp_static
->rmap
.map
);
6697 if (safi
== SAFI_EVPN
) {
6699 bgp_static
->eth_s_id
=
6702 str2esi(esi
, bgp_static
->eth_s_id
);
6705 bgp_static
->router_mac
=
6706 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
6707 (void)prefix_str2mac(routermac
,
6708 bgp_static
->router_mac
);
6711 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
6713 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6715 bgp_static
->valid
= 1;
6716 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
6722 /* Configure static BGP network. */
6723 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6724 const char *ip_str
, const char *rd_str
,
6725 const char *label_str
, int evpn_type
, const char *esi
,
6726 const char *gwip
, const char *ethtag
)
6728 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6731 struct prefix_rd prd
;
6732 struct bgp_dest
*pdest
;
6733 struct bgp_dest
*dest
;
6734 struct bgp_table
*table
;
6735 struct bgp_static
*bgp_static
;
6736 mpls_label_t label
= MPLS_INVALID_LABEL
;
6738 /* Convert IP prefix string to struct prefix. */
6739 ret
= str2prefix(ip_str
, &p
);
6741 vty_out(vty
, "%% Malformed prefix\n");
6742 return CMD_WARNING_CONFIG_FAILED
;
6745 if ((afi
== AFI_L2VPN
)
6746 && (bgp_build_evpn_prefix(evpn_type
,
6747 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6748 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6749 return CMD_WARNING_CONFIG_FAILED
;
6751 ret
= str2prefix_rd(rd_str
, &prd
);
6753 vty_out(vty
, "%% Malformed rd\n");
6754 return CMD_WARNING_CONFIG_FAILED
;
6758 unsigned long label_val
;
6759 label_val
= strtoul(label_str
, NULL
, 10);
6760 encode_label(label_val
, &label
);
6763 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6764 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6765 bgp_dest_set_bgp_table_info(pdest
,
6766 bgp_table_init(bgp
, afi
, safi
));
6768 bgp_dest_unlock_node(pdest
);
6769 table
= bgp_dest_get_bgp_table_info(pdest
);
6771 dest
= bgp_node_lookup(table
, &p
);
6774 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6776 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6777 bgp_static_free(bgp_static
);
6778 bgp_dest_set_bgp_static_info(dest
, NULL
);
6779 bgp_dest_unlock_node(dest
);
6780 bgp_dest_unlock_node(dest
);
6782 vty_out(vty
, "%% Can't find the route\n");
6787 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6788 const char *rmap_name
)
6790 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6791 struct bgp_rmap
*rmap
;
6793 rmap
= &bgp
->table_map
[afi
][safi
];
6795 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6796 route_map_counter_decrement(rmap
->map
);
6797 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6798 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6799 route_map_counter_increment(rmap
->map
);
6801 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6802 route_map_counter_decrement(rmap
->map
);
6806 if (bgp_fibupd_safi(safi
))
6807 bgp_zebra_announce_table(bgp
, afi
, safi
);
6812 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6813 const char *rmap_name
)
6815 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6816 struct bgp_rmap
*rmap
;
6818 rmap
= &bgp
->table_map
[afi
][safi
];
6819 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6820 route_map_counter_decrement(rmap
->map
);
6823 if (bgp_fibupd_safi(safi
))
6824 bgp_zebra_announce_table(bgp
, afi
, safi
);
6829 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6832 if (bgp
->table_map
[afi
][safi
].name
) {
6833 vty_out(vty
, " table-map %s\n",
6834 bgp
->table_map
[afi
][safi
].name
);
6838 DEFUN (bgp_table_map
,
6841 "BGP table to RIB route download filter\n"
6842 "Name of the route map\n")
6845 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6846 argv
[idx_word
]->arg
);
6848 DEFUN (no_bgp_table_map
,
6849 no_bgp_table_map_cmd
,
6850 "no table-map WORD",
6852 "BGP table to RIB route download filter\n"
6853 "Name of the route map\n")
6856 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6857 argv
[idx_word
]->arg
);
6863 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6864 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6865 backdoor$backdoor}]",
6867 "Specify a network to announce via BGP\n"
6872 "Route-map to modify the attributes\n"
6873 "Name of the route map\n"
6874 "Label index to associate with the prefix\n"
6875 "Label index value\n"
6876 "Specify a BGP backdoor route\n")
6878 char addr_prefix_str
[BUFSIZ
];
6883 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6885 sizeof(addr_prefix_str
));
6887 vty_out(vty
, "%% Inconsistent address and mask\n");
6888 return CMD_WARNING_CONFIG_FAILED
;
6892 return bgp_static_set(
6893 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
6894 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
6895 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6898 DEFPY(ipv6_bgp_network
,
6899 ipv6_bgp_network_cmd
,
6900 "[no] network X:X::X:X/M$prefix \
6901 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6903 "Specify a network to announce via BGP\n"
6905 "Route-map to modify the attributes\n"
6906 "Name of the route map\n"
6907 "Label index to associate with the prefix\n"
6908 "Label index value\n")
6910 return bgp_static_set(
6911 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
6912 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6915 static struct bgp_aggregate
*bgp_aggregate_new(void)
6917 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6920 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6922 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
6923 route_map_counter_decrement(aggregate
->suppress_map
);
6924 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6925 route_map_counter_decrement(aggregate
->rmap
.map
);
6926 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6930 * Helper function to avoid repeated code: prepare variables for a
6931 * `route_map_apply` call.
6933 * \returns `true` on route map match, otherwise `false`.
6935 static bool aggr_suppress_map_test(struct bgp
*bgp
,
6936 struct bgp_aggregate
*aggregate
,
6937 struct bgp_path_info
*pi
)
6939 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
6940 route_map_result_t rmr
= RMAP_DENYMATCH
;
6941 struct bgp_path_info rmap_path
= {};
6942 struct attr attr
= {};
6944 /* No route map entries created, just don't match. */
6945 if (aggregate
->suppress_map
== NULL
)
6948 /* Call route map matching and return result. */
6949 attr
.aspath
= aspath_empty();
6950 rmap_path
.peer
= bgp
->peer_self
;
6951 rmap_path
.attr
= &attr
;
6953 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
6954 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
6955 bgp
->peer_self
->rmap_type
= 0;
6957 bgp_attr_flush(&attr
);
6958 aspath_unintern(&attr
.aspath
);
6960 return rmr
== RMAP_PERMITMATCH
;
6963 /** Test whether the aggregation has suppressed this path or not. */
6964 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
6965 struct bgp_path_info
*pi
)
6967 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
6970 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
6974 * Suppress this path and keep the reference.
6976 * \returns `true` if needs processing otherwise `false`.
6978 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
6979 struct bgp_path_info
*pi
)
6981 struct bgp_path_info_extra
*pie
;
6983 /* Path is already suppressed by this aggregation. */
6984 if (aggr_suppress_exists(aggregate
, pi
))
6987 pie
= bgp_path_info_extra_get(pi
);
6989 /* This is the first suppression, allocate memory and list it. */
6990 if (pie
->aggr_suppressors
== NULL
)
6991 pie
->aggr_suppressors
= list_new();
6993 listnode_add(pie
->aggr_suppressors
, aggregate
);
6995 /* Only mark for processing if suppressed. */
6996 if (listcount(pie
->aggr_suppressors
) == 1) {
6997 if (BGP_DEBUG(update
, UPDATE_OUT
))
6998 zlog_debug("aggregate-address suppressing: %pFX",
6999 bgp_dest_get_prefix(pi
->net
));
7001 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7009 * Unsuppress this path and remove the reference.
7011 * \returns `true` if needs processing otherwise `false`.
7013 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7014 struct bgp_path_info
*pi
)
7016 /* Path wasn't suppressed. */
7017 if (!aggr_suppress_exists(aggregate
, pi
))
7020 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7022 /* Unsuppress and free extra memory if last item. */
7023 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7024 if (BGP_DEBUG(update
, UPDATE_OUT
))
7025 zlog_debug("aggregate-address unsuppressing: %pFX",
7026 bgp_dest_get_prefix(pi
->net
));
7028 list_delete(&pi
->extra
->aggr_suppressors
);
7029 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7036 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7037 struct aspath
*aspath
,
7038 struct community
*comm
,
7039 struct ecommunity
*ecomm
,
7040 struct lcommunity
*lcomm
)
7042 static struct aspath
*ae
= NULL
;
7045 ae
= aspath_empty();
7050 if (origin
!= pi
->attr
->origin
)
7053 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7056 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7059 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7062 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7065 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7071 static void bgp_aggregate_install(
7072 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7073 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7074 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7075 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7077 struct bgp_dest
*dest
;
7078 struct bgp_table
*table
;
7079 struct bgp_path_info
*pi
, *orig
, *new;
7082 table
= bgp
->rib
[afi
][safi
];
7084 dest
= bgp_node_get(table
, p
);
7086 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7087 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7088 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7092 * If we have paths with different MEDs, then don't install
7093 * (or uninstall) the aggregate route.
7095 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7096 goto uninstall_aggregate_route
;
7098 if (aggregate
->count
> 0) {
7100 * If the aggregate information has not changed
7101 * no need to re-install it again.
7103 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7104 ecommunity
, lcommunity
)) {
7105 bgp_dest_unlock_node(dest
);
7108 aspath_free(aspath
);
7110 community_free(&community
);
7112 ecommunity_free(&ecommunity
);
7114 lcommunity_free(&lcommunity
);
7120 * Mark the old as unusable
7123 bgp_path_info_delete(dest
, pi
);
7125 attr
= bgp_attr_aggregate_intern(
7126 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7127 aggregate
, atomic_aggregate
, p
);
7130 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7131 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7132 zlog_debug("%s: %pFX null attribute", __func__
,
7137 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7138 bgp
->peer_self
, attr
, dest
);
7140 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7142 bgp_path_info_add(dest
, new);
7143 bgp_process(bgp
, dest
, afi
, safi
);
7145 uninstall_aggregate_route
:
7146 for (pi
= orig
; pi
; pi
= pi
->next
)
7147 if (pi
->peer
== bgp
->peer_self
7148 && pi
->type
== ZEBRA_ROUTE_BGP
7149 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7152 /* Withdraw static BGP route from routing table. */
7154 bgp_path_info_delete(dest
, pi
);
7155 bgp_process(bgp
, dest
, afi
, safi
);
7159 bgp_dest_unlock_node(dest
);
7163 * Check if the current path has different MED than other known paths.
7165 * \returns `true` if the MED matched the others else `false`.
7167 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7168 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7170 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7172 /* This is the first route being analyzed. */
7173 if (!aggregate
->med_initialized
) {
7174 aggregate
->med_initialized
= true;
7175 aggregate
->med_mismatched
= false;
7176 aggregate
->med_matched_value
= cur_med
;
7178 /* Check if routes with different MED showed up. */
7179 if (cur_med
!= aggregate
->med_matched_value
)
7180 aggregate
->med_mismatched
= true;
7183 return !aggregate
->med_mismatched
;
7187 * Initializes and tests all routes in the aggregate address path for MED
7190 * \returns `true` if all MEDs are the same otherwise `false`.
7192 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7193 struct bgp
*bgp
, const struct prefix
*p
,
7194 afi_t afi
, safi_t safi
)
7196 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7197 const struct prefix
*dest_p
;
7198 struct bgp_dest
*dest
, *top
;
7199 struct bgp_path_info
*pi
;
7200 bool med_matched
= true;
7202 aggregate
->med_initialized
= false;
7204 top
= bgp_node_get(table
, p
);
7205 for (dest
= bgp_node_get(table
, p
); dest
;
7206 dest
= bgp_route_next_until(dest
, top
)) {
7207 dest_p
= bgp_dest_get_prefix(dest
);
7208 if (dest_p
->prefixlen
<= p
->prefixlen
)
7211 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7212 if (BGP_PATH_HOLDDOWN(pi
))
7214 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7216 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7217 med_matched
= false;
7224 bgp_dest_unlock_node(top
);
7230 * Toggles the route suppression status for this aggregate address
7233 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7234 struct bgp
*bgp
, const struct prefix
*p
,
7235 afi_t afi
, safi_t safi
, bool suppress
)
7237 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7238 const struct prefix
*dest_p
;
7239 struct bgp_dest
*dest
, *top
;
7240 struct bgp_path_info
*pi
;
7241 bool toggle_suppression
;
7243 /* We've found a different MED we must revert any suppressed routes. */
7244 top
= bgp_node_get(table
, p
);
7245 for (dest
= bgp_node_get(table
, p
); dest
;
7246 dest
= bgp_route_next_until(dest
, top
)) {
7247 dest_p
= bgp_dest_get_prefix(dest
);
7248 if (dest_p
->prefixlen
<= p
->prefixlen
)
7251 toggle_suppression
= false;
7252 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7253 if (BGP_PATH_HOLDDOWN(pi
))
7255 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7258 /* We are toggling suppression back. */
7260 /* Suppress route if not suppressed already. */
7261 if (aggr_suppress_path(aggregate
, pi
))
7262 toggle_suppression
= true;
7266 /* Install route if there is no more suppression. */
7267 if (aggr_unsuppress_path(aggregate
, pi
))
7268 toggle_suppression
= true;
7271 if (toggle_suppression
)
7272 bgp_process(bgp
, dest
, afi
, safi
);
7274 bgp_dest_unlock_node(top
);
7278 * Aggregate address MED matching incremental test: this function is called
7279 * when the initial aggregation occurred and we are only testing a single
7282 * In addition to testing and setting the MED validity it also installs back
7283 * suppressed routes (if summary is configured).
7285 * Must not be called in `bgp_aggregate_route`.
7287 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7288 struct bgp
*bgp
, const struct prefix
*p
,
7289 afi_t afi
, safi_t safi
,
7290 struct bgp_path_info
*pi
, bool is_adding
)
7292 /* MED matching disabled. */
7293 if (!aggregate
->match_med
)
7296 /* Aggregation with different MED, nothing to do. */
7297 if (aggregate
->med_mismatched
)
7301 * Test the current entry:
7303 * is_adding == true: if the new entry doesn't match then we must
7304 * install all suppressed routes.
7306 * is_adding == false: if the entry being removed was the last
7307 * unmatching entry then we can suppress all routes.
7310 if (bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
)
7311 && aggregate
->summary_only
)
7312 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
,
7315 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7317 /* No mismatches, just quit. */
7318 if (!aggregate
->med_mismatched
)
7321 /* Route summarization is disabled. */
7322 if (!aggregate
->summary_only
)
7325 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7328 /* Update an aggregate as routes are added/removed from the BGP table */
7329 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7330 safi_t safi
, struct bgp_aggregate
*aggregate
)
7332 struct bgp_table
*table
;
7333 struct bgp_dest
*top
;
7334 struct bgp_dest
*dest
;
7336 struct aspath
*aspath
= NULL
;
7337 struct community
*community
= NULL
;
7338 struct ecommunity
*ecommunity
= NULL
;
7339 struct lcommunity
*lcommunity
= NULL
;
7340 struct bgp_path_info
*pi
;
7341 unsigned long match
= 0;
7342 uint8_t atomic_aggregate
= 0;
7344 /* If the bgp instance is being deleted or self peer is deleted
7345 * then do not create aggregate route
7347 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7348 || (bgp
->peer_self
== NULL
))
7351 /* Initialize and test routes for MED difference. */
7352 if (aggregate
->match_med
)
7353 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7356 * Reset aggregate count: we might've been called from route map
7357 * update so in that case we must retest all more specific routes.
7359 * \see `bgp_route_map_process_update`.
7361 aggregate
->count
= 0;
7362 aggregate
->incomplete_origin_count
= 0;
7363 aggregate
->incomplete_origin_count
= 0;
7364 aggregate
->egp_origin_count
= 0;
7366 /* ORIGIN attribute: If at least one route among routes that are
7367 aggregated has ORIGIN with the value INCOMPLETE, then the
7368 aggregated route must have the ORIGIN attribute with the value
7369 INCOMPLETE. Otherwise, if at least one route among routes that
7370 are aggregated has ORIGIN with the value EGP, then the aggregated
7371 route must have the origin attribute with the value EGP. In all
7372 other case the value of the ORIGIN attribute of the aggregated
7373 route is INTERNAL. */
7374 origin
= BGP_ORIGIN_IGP
;
7376 table
= bgp
->rib
[afi
][safi
];
7378 top
= bgp_node_get(table
, p
);
7379 for (dest
= bgp_node_get(table
, p
); dest
;
7380 dest
= bgp_route_next_until(dest
, top
)) {
7381 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7383 if (dest_p
->prefixlen
<= p
->prefixlen
)
7386 /* If suppress fib is enabled and route not installed
7387 * in FIB, skip the route
7389 if (!bgp_check_advertise(bgp
, dest
))
7394 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7395 if (BGP_PATH_HOLDDOWN(pi
))
7399 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7400 atomic_aggregate
= 1;
7402 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7406 * summary-only aggregate route suppress
7407 * aggregated route announcements.
7410 * Don't create summaries if MED didn't match
7411 * otherwise neither the specific routes and the
7412 * aggregation will be announced.
7414 if (aggregate
->summary_only
7415 && AGGREGATE_MED_VALID(aggregate
)) {
7416 if (aggr_suppress_path(aggregate
, pi
))
7421 * Suppress more specific routes that match the route
7425 * Don't suppress routes if MED matching is enabled and
7426 * it mismatched otherwise we might end up with no
7427 * routes for this path.
7429 if (aggregate
->suppress_map_name
7430 && AGGREGATE_MED_VALID(aggregate
)
7431 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7432 if (aggr_suppress_path(aggregate
, pi
))
7439 * If at least one route among routes that are
7440 * aggregated has ORIGIN with the value INCOMPLETE,
7441 * then the aggregated route MUST have the ORIGIN
7442 * attribute with the value INCOMPLETE. Otherwise, if
7443 * at least one route among routes that are aggregated
7444 * has ORIGIN with the value EGP, then the aggregated
7445 * route MUST have the ORIGIN attribute with the value
7448 switch (pi
->attr
->origin
) {
7449 case BGP_ORIGIN_INCOMPLETE
:
7450 aggregate
->incomplete_origin_count
++;
7452 case BGP_ORIGIN_EGP
:
7453 aggregate
->egp_origin_count
++;
7461 if (!aggregate
->as_set
)
7465 * as-set aggregate route generate origin, as path,
7466 * and community aggregation.
7468 /* Compute aggregate route's as-path.
7470 bgp_compute_aggregate_aspath_hash(aggregate
,
7473 /* Compute aggregate route's community.
7475 if (bgp_attr_get_community(pi
->attr
))
7476 bgp_compute_aggregate_community_hash(
7478 bgp_attr_get_community(pi
->attr
));
7480 /* Compute aggregate route's extended community.
7482 if (bgp_attr_get_ecommunity(pi
->attr
))
7483 bgp_compute_aggregate_ecommunity_hash(
7485 bgp_attr_get_ecommunity(pi
->attr
));
7487 /* Compute aggregate route's large community.
7489 if (bgp_attr_get_lcommunity(pi
->attr
))
7490 bgp_compute_aggregate_lcommunity_hash(
7492 bgp_attr_get_lcommunity(pi
->attr
));
7495 bgp_process(bgp
, dest
, afi
, safi
);
7497 if (aggregate
->as_set
) {
7498 bgp_compute_aggregate_aspath_val(aggregate
);
7499 bgp_compute_aggregate_community_val(aggregate
);
7500 bgp_compute_aggregate_ecommunity_val(aggregate
);
7501 bgp_compute_aggregate_lcommunity_val(aggregate
);
7505 bgp_dest_unlock_node(top
);
7508 if (aggregate
->incomplete_origin_count
> 0)
7509 origin
= BGP_ORIGIN_INCOMPLETE
;
7510 else if (aggregate
->egp_origin_count
> 0)
7511 origin
= BGP_ORIGIN_EGP
;
7513 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7514 origin
= aggregate
->origin
;
7516 if (aggregate
->as_set
) {
7517 if (aggregate
->aspath
)
7518 /* Retrieve aggregate route's as-path.
7520 aspath
= aspath_dup(aggregate
->aspath
);
7522 if (aggregate
->community
)
7523 /* Retrieve aggregate route's community.
7525 community
= community_dup(aggregate
->community
);
7527 if (aggregate
->ecommunity
)
7528 /* Retrieve aggregate route's ecommunity.
7530 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7532 if (aggregate
->lcommunity
)
7533 /* Retrieve aggregate route's lcommunity.
7535 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7538 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7539 ecommunity
, lcommunity
, atomic_aggregate
,
7543 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7544 safi_t safi
, struct bgp_aggregate
*aggregate
)
7546 struct bgp_table
*table
;
7547 struct bgp_dest
*top
;
7548 struct bgp_dest
*dest
;
7549 struct bgp_path_info
*pi
;
7550 unsigned long match
;
7552 table
= bgp
->rib
[afi
][safi
];
7554 /* If routes exists below this node, generate aggregate routes. */
7555 top
= bgp_node_get(table
, p
);
7556 for (dest
= bgp_node_get(table
, p
); dest
;
7557 dest
= bgp_route_next_until(dest
, top
)) {
7558 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7560 if (dest_p
->prefixlen
<= p
->prefixlen
)
7564 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7565 if (BGP_PATH_HOLDDOWN(pi
))
7568 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7572 * This route is suppressed: attempt to unsuppress it.
7574 * `aggr_unsuppress_path` will fail if this particular
7575 * aggregate route was not the suppressor.
7577 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7578 listcount(pi
->extra
->aggr_suppressors
)) {
7579 if (aggr_unsuppress_path(aggregate
, pi
))
7585 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7586 aggregate
->incomplete_origin_count
--;
7587 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7588 aggregate
->egp_origin_count
--;
7590 if (aggregate
->as_set
) {
7591 /* Remove as-path from aggregate.
7593 bgp_remove_aspath_from_aggregate_hash(
7597 if (bgp_attr_get_community(pi
->attr
))
7598 /* Remove community from aggregate.
7600 bgp_remove_comm_from_aggregate_hash(
7602 bgp_attr_get_community(
7605 if (bgp_attr_get_ecommunity(pi
->attr
))
7606 /* Remove ecommunity from aggregate.
7608 bgp_remove_ecomm_from_aggregate_hash(
7610 bgp_attr_get_ecommunity(
7613 if (bgp_attr_get_lcommunity(pi
->attr
))
7614 /* Remove lcommunity from aggregate.
7616 bgp_remove_lcomm_from_aggregate_hash(
7618 bgp_attr_get_lcommunity(
7623 /* If this node was suppressed, process the change. */
7625 bgp_process(bgp
, dest
, afi
, safi
);
7627 if (aggregate
->as_set
) {
7628 aspath_free(aggregate
->aspath
);
7629 aggregate
->aspath
= NULL
;
7630 if (aggregate
->community
)
7631 community_free(&aggregate
->community
);
7632 if (aggregate
->ecommunity
)
7633 ecommunity_free(&aggregate
->ecommunity
);
7634 if (aggregate
->lcommunity
)
7635 lcommunity_free(&aggregate
->lcommunity
);
7638 bgp_dest_unlock_node(top
);
7641 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7642 const struct prefix
*aggr_p
,
7643 struct bgp_path_info
*pinew
, afi_t afi
,
7645 struct bgp_aggregate
*aggregate
)
7648 struct aspath
*aspath
= NULL
;
7649 uint8_t atomic_aggregate
= 0;
7650 struct community
*community
= NULL
;
7651 struct ecommunity
*ecommunity
= NULL
;
7652 struct lcommunity
*lcommunity
= NULL
;
7654 /* If the bgp instance is being deleted or self peer is deleted
7655 * then do not create aggregate route
7657 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7658 || (bgp
->peer_self
== NULL
))
7661 /* ORIGIN attribute: If at least one route among routes that are
7662 * aggregated has ORIGIN with the value INCOMPLETE, then the
7663 * aggregated route must have the ORIGIN attribute with the value
7664 * INCOMPLETE. Otherwise, if at least one route among routes that
7665 * are aggregated has ORIGIN with the value EGP, then the aggregated
7666 * route must have the origin attribute with the value EGP. In all
7667 * other case the value of the ORIGIN attribute of the aggregated
7668 * route is INTERNAL.
7670 origin
= BGP_ORIGIN_IGP
;
7675 * This must be called before `summary` check to avoid
7676 * "suppressing" twice.
7678 if (aggregate
->match_med
)
7679 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7682 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7683 aggr_suppress_path(aggregate
, pinew
);
7685 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7686 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7687 aggr_suppress_path(aggregate
, pinew
);
7689 switch (pinew
->attr
->origin
) {
7690 case BGP_ORIGIN_INCOMPLETE
:
7691 aggregate
->incomplete_origin_count
++;
7693 case BGP_ORIGIN_EGP
:
7694 aggregate
->egp_origin_count
++;
7702 if (aggregate
->incomplete_origin_count
> 0)
7703 origin
= BGP_ORIGIN_INCOMPLETE
;
7704 else if (aggregate
->egp_origin_count
> 0)
7705 origin
= BGP_ORIGIN_EGP
;
7707 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7708 origin
= aggregate
->origin
;
7710 if (aggregate
->as_set
) {
7711 /* Compute aggregate route's as-path.
7713 bgp_compute_aggregate_aspath(aggregate
,
7714 pinew
->attr
->aspath
);
7716 /* Compute aggregate route's community.
7718 if (bgp_attr_get_community(pinew
->attr
))
7719 bgp_compute_aggregate_community(
7720 aggregate
, bgp_attr_get_community(pinew
->attr
));
7722 /* Compute aggregate route's extended community.
7724 if (bgp_attr_get_ecommunity(pinew
->attr
))
7725 bgp_compute_aggregate_ecommunity(
7727 bgp_attr_get_ecommunity(pinew
->attr
));
7729 /* Compute aggregate route's large community.
7731 if (bgp_attr_get_lcommunity(pinew
->attr
))
7732 bgp_compute_aggregate_lcommunity(
7734 bgp_attr_get_lcommunity(pinew
->attr
));
7736 /* Retrieve aggregate route's as-path.
7738 if (aggregate
->aspath
)
7739 aspath
= aspath_dup(aggregate
->aspath
);
7741 /* Retrieve aggregate route's community.
7743 if (aggregate
->community
)
7744 community
= community_dup(aggregate
->community
);
7746 /* Retrieve aggregate route's ecommunity.
7748 if (aggregate
->ecommunity
)
7749 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7751 /* Retrieve aggregate route's lcommunity.
7753 if (aggregate
->lcommunity
)
7754 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7757 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7758 aspath
, community
, ecommunity
,
7759 lcommunity
, atomic_aggregate
, aggregate
);
7762 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7764 struct bgp_path_info
*pi
,
7765 struct bgp_aggregate
*aggregate
,
7766 const struct prefix
*aggr_p
)
7769 struct aspath
*aspath
= NULL
;
7770 uint8_t atomic_aggregate
= 0;
7771 struct community
*community
= NULL
;
7772 struct ecommunity
*ecommunity
= NULL
;
7773 struct lcommunity
*lcommunity
= NULL
;
7774 unsigned long match
= 0;
7776 /* If the bgp instance is being deleted or self peer is deleted
7777 * then do not create aggregate route
7779 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7780 || (bgp
->peer_self
== NULL
))
7783 if (BGP_PATH_HOLDDOWN(pi
))
7786 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7789 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7790 if (aggr_unsuppress_path(aggregate
, pi
))
7793 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7794 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7795 if (aggr_unsuppress_path(aggregate
, pi
))
7799 * This must be called after `summary`, `suppress-map` check to avoid
7800 * "unsuppressing" twice.
7802 if (aggregate
->match_med
)
7803 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
,
7806 if (aggregate
->count
> 0)
7809 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7810 aggregate
->incomplete_origin_count
--;
7811 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7812 aggregate
->egp_origin_count
--;
7814 if (aggregate
->as_set
) {
7815 /* Remove as-path from aggregate.
7817 bgp_remove_aspath_from_aggregate(aggregate
,
7820 if (bgp_attr_get_community(pi
->attr
))
7821 /* Remove community from aggregate.
7823 bgp_remove_community_from_aggregate(
7824 aggregate
, bgp_attr_get_community(pi
->attr
));
7826 if (bgp_attr_get_ecommunity(pi
->attr
))
7827 /* Remove ecommunity from aggregate.
7829 bgp_remove_ecommunity_from_aggregate(
7830 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
7832 if (bgp_attr_get_lcommunity(pi
->attr
))
7833 /* Remove lcommunity from aggregate.
7835 bgp_remove_lcommunity_from_aggregate(
7836 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
7839 /* If this node was suppressed, process the change. */
7841 bgp_process(bgp
, pi
->net
, afi
, safi
);
7843 origin
= BGP_ORIGIN_IGP
;
7844 if (aggregate
->incomplete_origin_count
> 0)
7845 origin
= BGP_ORIGIN_INCOMPLETE
;
7846 else if (aggregate
->egp_origin_count
> 0)
7847 origin
= BGP_ORIGIN_EGP
;
7849 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7850 origin
= aggregate
->origin
;
7852 if (aggregate
->as_set
) {
7853 /* Retrieve aggregate route's as-path.
7855 if (aggregate
->aspath
)
7856 aspath
= aspath_dup(aggregate
->aspath
);
7858 /* Retrieve aggregate route's community.
7860 if (aggregate
->community
)
7861 community
= community_dup(aggregate
->community
);
7863 /* Retrieve aggregate route's ecommunity.
7865 if (aggregate
->ecommunity
)
7866 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7868 /* Retrieve aggregate route's lcommunity.
7870 if (aggregate
->lcommunity
)
7871 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7874 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7875 aspath
, community
, ecommunity
,
7876 lcommunity
, atomic_aggregate
, aggregate
);
7879 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
7880 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
7882 struct bgp_dest
*child
;
7883 struct bgp_dest
*dest
;
7884 struct bgp_aggregate
*aggregate
;
7885 struct bgp_table
*table
;
7887 table
= bgp
->aggregate
[afi
][safi
];
7889 /* No aggregates configured. */
7890 if (bgp_table_top_nolock(table
) == NULL
)
7893 if (p
->prefixlen
== 0)
7896 if (BGP_PATH_HOLDDOWN(pi
))
7899 /* If suppress fib is enabled and route not installed
7900 * in FIB, do not update the aggregate route
7902 if (!bgp_check_advertise(bgp
, pi
->net
))
7905 child
= bgp_node_get(table
, p
);
7907 /* Aggregate address configuration check. */
7908 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7909 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7911 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7912 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7913 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
7917 bgp_dest_unlock_node(child
);
7920 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
7921 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
7923 struct bgp_dest
*child
;
7924 struct bgp_dest
*dest
;
7925 struct bgp_aggregate
*aggregate
;
7926 struct bgp_table
*table
;
7928 table
= bgp
->aggregate
[afi
][safi
];
7930 /* No aggregates configured. */
7931 if (bgp_table_top_nolock(table
) == NULL
)
7934 if (p
->prefixlen
== 0)
7937 child
= bgp_node_get(table
, p
);
7939 /* Aggregate address configuration check. */
7940 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7941 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7943 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7944 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7945 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
7949 bgp_dest_unlock_node(child
);
7952 /* Aggregate route attribute. */
7953 #define AGGREGATE_SUMMARY_ONLY 1
7954 #define AGGREGATE_AS_SET 1
7955 #define AGGREGATE_AS_UNSET 0
7957 static const char *bgp_origin2str(uint8_t origin
)
7960 case BGP_ORIGIN_IGP
:
7962 case BGP_ORIGIN_EGP
:
7964 case BGP_ORIGIN_INCOMPLETE
:
7965 return "incomplete";
7970 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
7973 case RPKI_NOT_BEING_USED
:
7983 assert(!"We should never get here this is a dev escape");
7987 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
7988 afi_t afi
, safi_t safi
)
7990 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7993 struct bgp_dest
*dest
;
7994 struct bgp_aggregate
*aggregate
;
7996 /* Convert string to prefix structure. */
7997 ret
= str2prefix(prefix_str
, &p
);
7999 vty_out(vty
, "Malformed prefix\n");
8000 return CMD_WARNING_CONFIG_FAILED
;
8004 /* Old configuration check. */
8005 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8008 "%% There is no aggregate-address configuration.\n");
8009 return CMD_WARNING_CONFIG_FAILED
;
8012 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8013 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8014 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8015 NULL
, NULL
, 0, aggregate
);
8017 /* Unlock aggregate address configuration. */
8018 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8020 if (aggregate
->community
)
8021 community_free(&aggregate
->community
);
8023 if (aggregate
->community_hash
) {
8024 /* Delete all communities in the hash.
8026 hash_clean(aggregate
->community_hash
,
8027 bgp_aggr_community_remove
);
8028 /* Free up the community_hash.
8030 hash_free(aggregate
->community_hash
);
8033 if (aggregate
->ecommunity
)
8034 ecommunity_free(&aggregate
->ecommunity
);
8036 if (aggregate
->ecommunity_hash
) {
8037 /* Delete all ecommunities in the hash.
8039 hash_clean(aggregate
->ecommunity_hash
,
8040 bgp_aggr_ecommunity_remove
);
8041 /* Free up the ecommunity_hash.
8043 hash_free(aggregate
->ecommunity_hash
);
8046 if (aggregate
->lcommunity
)
8047 lcommunity_free(&aggregate
->lcommunity
);
8049 if (aggregate
->lcommunity_hash
) {
8050 /* Delete all lcommunities in the hash.
8052 hash_clean(aggregate
->lcommunity_hash
,
8053 bgp_aggr_lcommunity_remove
);
8054 /* Free up the lcommunity_hash.
8056 hash_free(aggregate
->lcommunity_hash
);
8059 if (aggregate
->aspath
)
8060 aspath_free(aggregate
->aspath
);
8062 if (aggregate
->aspath_hash
) {
8063 /* Delete all as-paths in the hash.
8065 hash_clean(aggregate
->aspath_hash
,
8066 bgp_aggr_aspath_remove
);
8067 /* Free up the aspath_hash.
8069 hash_free(aggregate
->aspath_hash
);
8072 bgp_aggregate_free(aggregate
);
8073 bgp_dest_unlock_node(dest
);
8074 bgp_dest_unlock_node(dest
);
8079 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8080 safi_t safi
, const char *rmap
,
8081 uint8_t summary_only
, uint8_t as_set
,
8082 uint8_t origin
, bool match_med
,
8083 const char *suppress_map
)
8085 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8088 struct bgp_dest
*dest
;
8089 struct bgp_aggregate
*aggregate
;
8090 uint8_t as_set_new
= as_set
;
8092 if (suppress_map
&& summary_only
) {
8094 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8095 return CMD_WARNING_CONFIG_FAILED
;
8098 /* Convert string to prefix structure. */
8099 ret
= str2prefix(prefix_str
, &p
);
8101 vty_out(vty
, "Malformed prefix\n");
8102 return CMD_WARNING_CONFIG_FAILED
;
8106 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8107 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8108 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8110 return CMD_WARNING_CONFIG_FAILED
;
8113 /* Old configuration check. */
8114 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8115 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8118 vty_out(vty
, "There is already same aggregate network.\n");
8119 /* try to remove the old entry */
8120 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8122 vty_out(vty
, "Error deleting aggregate.\n");
8123 bgp_dest_unlock_node(dest
);
8124 return CMD_WARNING_CONFIG_FAILED
;
8128 /* Make aggregate address structure. */
8129 aggregate
= bgp_aggregate_new();
8130 aggregate
->summary_only
= summary_only
;
8131 aggregate
->match_med
= match_med
;
8133 /* Network operators MUST NOT locally generate any new
8134 * announcements containing AS_SET or AS_CONFED_SET. If they have
8135 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8136 * SHOULD withdraw those routes and re-announce routes for the
8137 * aggregate or component prefixes (i.e., the more-specific routes
8138 * subsumed by the previously aggregated route) without AS_SET
8139 * or AS_CONFED_SET in the updates.
8141 if (bgp
->reject_as_sets
) {
8142 if (as_set
== AGGREGATE_AS_SET
) {
8143 as_set_new
= AGGREGATE_AS_UNSET
;
8145 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8148 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8152 aggregate
->as_set
= as_set_new
;
8153 aggregate
->safi
= safi
;
8154 /* Override ORIGIN attribute if defined.
8155 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8156 * to IGP which is not what rfc4271 says.
8157 * This enables the same behavior, optionally.
8159 aggregate
->origin
= origin
;
8162 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8163 route_map_counter_decrement(aggregate
->rmap
.map
);
8164 aggregate
->rmap
.name
=
8165 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8166 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8167 route_map_counter_increment(aggregate
->rmap
.map
);
8171 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8172 route_map_counter_decrement(aggregate
->suppress_map
);
8174 aggregate
->suppress_map_name
=
8175 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8176 aggregate
->suppress_map
=
8177 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8178 route_map_counter_increment(aggregate
->suppress_map
);
8181 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8183 /* Aggregate address insert into BGP routing table. */
8184 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8189 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8190 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8192 "|summary-only$summary_only"
8193 "|route-map RMAP_NAME$rmap_name"
8194 "|origin <egp|igp|incomplete>$origin_s"
8195 "|matching-MED-only$match_med"
8196 "|suppress-map RMAP_NAME$suppress_map"
8199 "Configure BGP aggregate entries\n"
8200 "Aggregate prefix\n"
8201 "Aggregate address\n"
8203 "Generate AS set path information\n"
8204 "Filter more specific routes from updates\n"
8205 "Apply route map to aggregate network\n"
8210 "Unknown heritage\n"
8211 "Only aggregate routes with matching MED\n"
8212 "Suppress the selected more specific routes\n"
8213 "Route map with the route selectors\n")
8215 const char *prefix_s
= NULL
;
8216 safi_t safi
= bgp_node_safi(vty
);
8217 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8218 int as_set
= AGGREGATE_AS_UNSET
;
8219 char prefix_buf
[PREFIX2STR_BUFFER
];
8222 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8225 vty_out(vty
, "%% Inconsistent address and mask\n");
8226 return CMD_WARNING_CONFIG_FAILED
;
8228 prefix_s
= prefix_buf
;
8230 prefix_s
= prefix_str
;
8233 if (strcmp(origin_s
, "egp") == 0)
8234 origin
= BGP_ORIGIN_EGP
;
8235 else if (strcmp(origin_s
, "igp") == 0)
8236 origin
= BGP_ORIGIN_IGP
;
8237 else if (strcmp(origin_s
, "incomplete") == 0)
8238 origin
= BGP_ORIGIN_INCOMPLETE
;
8242 as_set
= AGGREGATE_AS_SET
;
8244 /* Handle configuration removal, otherwise installation. */
8246 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8248 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8249 summary_only
!= NULL
, as_set
, origin
,
8250 match_med
!= NULL
, suppress_map
);
8253 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8254 "[no] aggregate-address X:X::X:X/M$prefix [{"
8256 "|summary-only$summary_only"
8257 "|route-map RMAP_NAME$rmap_name"
8258 "|origin <egp|igp|incomplete>$origin_s"
8259 "|matching-MED-only$match_med"
8260 "|suppress-map RMAP_NAME$suppress_map"
8263 "Configure BGP aggregate entries\n"
8264 "Aggregate prefix\n"
8265 "Generate AS set path information\n"
8266 "Filter more specific routes from updates\n"
8267 "Apply route map to aggregate network\n"
8272 "Unknown heritage\n"
8273 "Only aggregate routes with matching MED\n"
8274 "Suppress the selected more specific routes\n"
8275 "Route map with the route selectors\n")
8277 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8278 int as_set
= AGGREGATE_AS_UNSET
;
8281 if (strcmp(origin_s
, "egp") == 0)
8282 origin
= BGP_ORIGIN_EGP
;
8283 else if (strcmp(origin_s
, "igp") == 0)
8284 origin
= BGP_ORIGIN_IGP
;
8285 else if (strcmp(origin_s
, "incomplete") == 0)
8286 origin
= BGP_ORIGIN_INCOMPLETE
;
8290 as_set
= AGGREGATE_AS_SET
;
8292 /* Handle configuration removal, otherwise installation. */
8294 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8297 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8298 rmap_name
, summary_only
!= NULL
, as_set
,
8299 origin
, match_med
!= NULL
, suppress_map
);
8302 /* Redistribute route treatment. */
8303 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8304 const union g_addr
*nexthop
, ifindex_t ifindex
,
8305 enum nexthop_types_t nhtype
, uint8_t distance
,
8306 enum blackhole_type bhtype
, uint32_t metric
,
8307 uint8_t type
, unsigned short instance
,
8310 struct bgp_path_info
*new;
8311 struct bgp_path_info
*bpi
;
8312 struct bgp_path_info rmap_path
;
8313 struct bgp_dest
*bn
;
8315 struct attr
*new_attr
;
8317 route_map_result_t ret
;
8318 struct bgp_redist
*red
;
8320 /* Make default attribute. */
8321 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
8323 * This must not be NULL to satisfy Coverity SA
8325 assert(attr
.aspath
);
8328 case NEXTHOP_TYPE_IFINDEX
:
8330 case NEXTHOP_TYPE_IPV4
:
8331 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8332 attr
.nexthop
= nexthop
->ipv4
;
8334 case NEXTHOP_TYPE_IPV6
:
8335 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8336 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8337 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8339 case NEXTHOP_TYPE_BLACKHOLE
:
8340 switch (p
->family
) {
8342 attr
.nexthop
.s_addr
= INADDR_ANY
;
8345 memset(&attr
.mp_nexthop_global
, 0,
8346 sizeof(attr
.mp_nexthop_global
));
8347 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8350 attr
.bh_type
= bhtype
;
8353 attr
.nh_type
= nhtype
;
8354 attr
.nh_ifindex
= ifindex
;
8357 attr
.distance
= distance
;
8358 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8361 afi
= family2afi(p
->family
);
8363 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8365 struct attr attr_new
;
8367 /* Copy attribute for modification. */
8370 if (red
->redist_metric_flag
)
8371 attr_new
.med
= red
->redist_metric
;
8373 /* Apply route-map. */
8374 if (red
->rmap
.name
) {
8375 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
8376 rmap_path
.peer
= bgp
->peer_self
;
8377 rmap_path
.attr
= &attr_new
;
8379 SET_FLAG(bgp
->peer_self
->rmap_type
,
8380 PEER_RMAP_TYPE_REDISTRIBUTE
);
8382 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8384 bgp
->peer_self
->rmap_type
= 0;
8386 if (ret
== RMAP_DENYMATCH
) {
8387 /* Free uninterned attribute. */
8388 bgp_attr_flush(&attr_new
);
8390 /* Unintern original. */
8391 aspath_unintern(&attr
.aspath
);
8392 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8397 if (bgp_in_graceful_shutdown(bgp
))
8398 bgp_attr_add_gshut_community(&attr_new
);
8400 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8401 SAFI_UNICAST
, p
, NULL
);
8403 new_attr
= bgp_attr_intern(&attr_new
);
8405 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8406 if (bpi
->peer
== bgp
->peer_self
8407 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8411 /* Ensure the (source route) type is updated. */
8413 if (attrhash_cmp(bpi
->attr
, new_attr
)
8414 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8415 bgp_attr_unintern(&new_attr
);
8416 aspath_unintern(&attr
.aspath
);
8417 bgp_dest_unlock_node(bn
);
8420 /* The attribute is changed. */
8421 bgp_path_info_set_flag(bn
, bpi
,
8422 BGP_PATH_ATTR_CHANGED
);
8424 /* Rewrite BGP route information. */
8425 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8426 bgp_path_info_restore(bn
, bpi
);
8428 bgp_aggregate_decrement(
8429 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8430 bgp_attr_unintern(&bpi
->attr
);
8431 bpi
->attr
= new_attr
;
8432 bpi
->uptime
= bgp_clock();
8434 /* Process change. */
8435 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8437 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8438 bgp_dest_unlock_node(bn
);
8439 aspath_unintern(&attr
.aspath
);
8441 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8443 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8445 vpn_leak_from_vrf_update(
8446 bgp_get_default(), bgp
, bpi
);
8452 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8453 bgp
->peer_self
, new_attr
, bn
);
8454 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8456 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8457 bgp_path_info_add(bn
, new);
8458 bgp_dest_unlock_node(bn
);
8459 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8460 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8462 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8463 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8465 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8469 /* Unintern original. */
8470 aspath_unintern(&attr
.aspath
);
8473 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8474 unsigned short instance
)
8477 struct bgp_dest
*dest
;
8478 struct bgp_path_info
*pi
;
8479 struct bgp_redist
*red
;
8481 afi
= family2afi(p
->family
);
8483 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8485 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8486 SAFI_UNICAST
, p
, NULL
);
8488 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8489 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8493 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8494 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8496 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8499 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8500 bgp_path_info_delete(dest
, pi
);
8501 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8503 bgp_dest_unlock_node(dest
);
8507 /* Withdraw specified route type's route. */
8508 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8509 unsigned short instance
)
8511 struct bgp_dest
*dest
;
8512 struct bgp_path_info
*pi
;
8513 struct bgp_table
*table
;
8515 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8517 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8518 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8519 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8520 && pi
->instance
== instance
)
8524 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8525 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8527 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8530 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8531 pi
, afi
, SAFI_UNICAST
);
8532 bgp_path_info_delete(dest
, pi
);
8533 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8538 /* Static function to display route. */
8539 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8540 struct vty
*vty
, json_object
*json
, bool wide
)
8545 if (p
->family
== AF_INET
) {
8547 len
= vty_out(vty
, "%pFX", p
);
8549 json_object_string_add(json
, "prefix",
8550 inet_ntop(p
->family
,
8553 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8554 json_object_string_addf(json
, "network", "%pFX", p
);
8555 json_object_int_add(json
, "version", dest
->version
);
8557 } else if (p
->family
== AF_ETHERNET
) {
8558 len
= vty_out(vty
, "%pFX", p
);
8559 } else if (p
->family
== AF_EVPN
) {
8561 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8563 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8564 } else if (p
->family
== AF_FLOWSPEC
) {
8565 route_vty_out_flowspec(vty
, p
, NULL
,
8567 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8568 NLRI_STRING_FORMAT_MIN
, json
);
8571 len
= vty_out(vty
, "%pFX", p
);
8573 json_object_string_add(json
, "prefix",
8574 inet_ntop(p
->family
,
8577 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8578 json_object_string_addf(json
, "network", "%pFX", p
);
8579 json_object_int_add(json
, "version", dest
->version
);
8584 len
= wide
? (45 - len
) : (17 - len
);
8586 vty_out(vty
, "\n%*s", 20, " ");
8588 vty_out(vty
, "%*s", len
, " ");
8592 enum bgp_display_type
{
8596 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8599 case bgp_path_selection_none
:
8600 return "Nothing to Select";
8601 case bgp_path_selection_first
:
8602 return "First path received";
8603 case bgp_path_selection_evpn_sticky_mac
:
8604 return "EVPN Sticky Mac";
8605 case bgp_path_selection_evpn_seq
:
8606 return "EVPN sequence number";
8607 case bgp_path_selection_evpn_lower_ip
:
8608 return "EVPN lower IP";
8609 case bgp_path_selection_evpn_local_path
:
8610 return "EVPN local ES path";
8611 case bgp_path_selection_evpn_non_proxy
:
8612 return "EVPN non proxy";
8613 case bgp_path_selection_weight
:
8615 case bgp_path_selection_local_pref
:
8616 return "Local Pref";
8617 case bgp_path_selection_local_route
:
8618 return "Local Route";
8619 case bgp_path_selection_confed_as_path
:
8620 return "Confederation based AS Path";
8621 case bgp_path_selection_as_path
:
8623 case bgp_path_selection_origin
:
8625 case bgp_path_selection_med
:
8627 case bgp_path_selection_peer
:
8629 case bgp_path_selection_confed
:
8630 return "Confed Peer Type";
8631 case bgp_path_selection_igp_metric
:
8632 return "IGP Metric";
8633 case bgp_path_selection_older
:
8634 return "Older Path";
8635 case bgp_path_selection_router_id
:
8637 case bgp_path_selection_cluster_length
:
8638 return "Cluster length";
8639 case bgp_path_selection_stale
:
8640 return "Path Staleness";
8641 case bgp_path_selection_local_configured
:
8642 return "Locally configured route";
8643 case bgp_path_selection_neighbor_ip
:
8644 return "Neighbor IP";
8645 case bgp_path_selection_default
:
8646 return "Nothing left to compare";
8648 return "Invalid (internal error)";
8651 /* Print the short form route status for a bgp_path_info */
8652 static void route_vty_short_status_out(struct vty
*vty
,
8653 struct bgp_path_info
*path
,
8654 const struct prefix
*p
,
8655 json_object
*json_path
)
8657 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8661 /* Route status display. */
8662 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8663 json_object_boolean_true_add(json_path
, "removed");
8665 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8666 json_object_boolean_true_add(json_path
, "stale");
8668 if (path
->extra
&& bgp_path_suppressed(path
))
8669 json_object_boolean_true_add(json_path
, "suppressed");
8671 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8672 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8673 json_object_boolean_true_add(json_path
, "valid");
8676 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8677 json_object_boolean_true_add(json_path
, "history");
8679 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8680 json_object_boolean_true_add(json_path
, "damped");
8682 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8683 json_object_boolean_true_add(json_path
, "bestpath");
8684 json_object_string_add(json_path
, "selectionReason",
8685 bgp_path_selection_reason2str(
8686 path
->net
->reason
));
8689 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8690 json_object_boolean_true_add(json_path
, "multipath");
8692 /* Internal route. */
8693 if ((path
->peer
->as
)
8694 && (path
->peer
->as
== path
->peer
->local_as
))
8695 json_object_string_add(json_path
, "pathFrom",
8698 json_object_string_add(json_path
, "pathFrom",
8704 /* RPKI validation state */
8706 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
8708 if (rpki_state
== RPKI_VALID
)
8710 else if (rpki_state
== RPKI_INVALID
)
8712 else if (rpki_state
== RPKI_NOTFOUND
)
8715 /* Route status display. */
8716 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8718 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8720 else if (bgp_path_suppressed(path
))
8722 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8723 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8729 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8731 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8733 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8735 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8740 /* Internal route. */
8741 if (path
->peer
&& (path
->peer
->as
)
8742 && (path
->peer
->as
== path
->peer
->local_as
))
8748 static char *bgp_nexthop_hostname(struct peer
*peer
,
8749 struct bgp_nexthop_cache
*bnc
)
8752 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8753 return peer
->hostname
;
8757 /* called from terminal list command */
8758 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8759 struct bgp_path_info
*path
, int display
, safi_t safi
,
8760 json_object
*json_paths
, bool wide
)
8763 struct attr
*attr
= path
->attr
;
8764 json_object
*json_path
= NULL
;
8765 json_object
*json_nexthops
= NULL
;
8766 json_object
*json_nexthop_global
= NULL
;
8767 json_object
*json_nexthop_ll
= NULL
;
8768 json_object
*json_ext_community
= NULL
;
8769 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8771 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8772 bool nexthop_othervrf
= false;
8773 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8774 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8775 char *nexthop_hostname
=
8776 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8777 char esi_buf
[ESI_STR_LEN
];
8780 json_path
= json_object_new_object();
8782 /* short status lead text */
8783 route_vty_short_status_out(vty
, path
, p
, json_path
);
8786 /* print prefix and mask */
8788 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8790 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8792 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8796 * If vrf id of nexthop is different from that of prefix,
8797 * set up printable string to append
8799 if (path
->extra
&& path
->extra
->bgp_orig
) {
8800 const char *self
= "";
8805 nexthop_othervrf
= true;
8806 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8808 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8809 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8810 "@%s%s", VRFID_NONE_STR
, self
);
8812 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8813 path
->extra
->bgp_orig
->vrf_id
, self
);
8815 if (path
->extra
->bgp_orig
->inst_type
8816 != BGP_INSTANCE_TYPE_DEFAULT
)
8818 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8820 const char *self
= "";
8825 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8829 * For ENCAP and EVPN routes, nexthop address family is not
8830 * neccessarily the same as the prefix address family.
8831 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8832 * EVPN routes are also exchanged with a MP nexthop. Currently,
8834 * is only IPv4, the value will be present in either
8836 * attr->mp_nexthop_global_in
8838 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
8841 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8845 snprintf(nexthop
, sizeof(nexthop
), "%s",
8846 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
8850 snprintf(nexthop
, sizeof(nexthop
), "%s",
8851 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
8855 snprintf(nexthop
, sizeof(nexthop
), "?");
8860 json_nexthop_global
= json_object_new_object();
8862 json_object_string_add(json_nexthop_global
, "ip",
8865 if (path
->peer
->hostname
)
8866 json_object_string_add(json_nexthop_global
,
8868 path
->peer
->hostname
);
8870 json_object_string_add(json_nexthop_global
, "afi",
8871 (af
== AF_INET
) ? "ipv4"
8873 json_object_boolean_true_add(json_nexthop_global
,
8876 if (nexthop_hostname
)
8877 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
8878 nexthop_hostname
, vrf_id_str
);
8880 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
8882 len
= wide
? (41 - len
) : (16 - len
);
8884 vty_out(vty
, "\n%*s", 36, " ");
8886 vty_out(vty
, "%*s", len
, " ");
8888 } else if (safi
== SAFI_EVPN
) {
8890 json_nexthop_global
= json_object_new_object();
8892 json_object_string_addf(json_nexthop_global
, "ip",
8893 "%pI4", &attr
->nexthop
);
8895 if (path
->peer
->hostname
)
8896 json_object_string_add(json_nexthop_global
,
8898 path
->peer
->hostname
);
8900 json_object_string_add(json_nexthop_global
, "afi",
8902 json_object_boolean_true_add(json_nexthop_global
,
8905 if (nexthop_hostname
)
8906 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8907 nexthop_hostname
, vrf_id_str
);
8909 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8912 len
= wide
? (41 - len
) : (16 - len
);
8914 vty_out(vty
, "\n%*s", 36, " ");
8916 vty_out(vty
, "%*s", len
, " ");
8918 } else if (safi
== SAFI_FLOWSPEC
) {
8919 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
8921 json_nexthop_global
= json_object_new_object();
8923 json_object_string_add(json_nexthop_global
,
8925 json_object_string_addf(json_nexthop_global
,
8929 if (path
->peer
->hostname
)
8930 json_object_string_add(
8931 json_nexthop_global
, "hostname",
8932 path
->peer
->hostname
);
8934 json_object_boolean_true_add(
8935 json_nexthop_global
,
8938 if (nexthop_hostname
)
8939 len
= vty_out(vty
, "%pI4(%s)%s",
8944 len
= vty_out(vty
, "%pI4%s",
8948 len
= wide
? (41 - len
) : (16 - len
);
8950 vty_out(vty
, "\n%*s", 36, " ");
8952 vty_out(vty
, "%*s", len
, " ");
8955 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8957 json_nexthop_global
= json_object_new_object();
8959 json_object_string_addf(json_nexthop_global
, "ip",
8960 "%pI4", &attr
->nexthop
);
8962 if (path
->peer
->hostname
)
8963 json_object_string_add(json_nexthop_global
,
8965 path
->peer
->hostname
);
8967 json_object_string_add(json_nexthop_global
, "afi",
8969 json_object_boolean_true_add(json_nexthop_global
,
8972 if (nexthop_hostname
)
8973 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8974 nexthop_hostname
, vrf_id_str
);
8976 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8979 len
= wide
? (41 - len
) : (16 - len
);
8981 vty_out(vty
, "\n%*s", 36, " ");
8983 vty_out(vty
, "%*s", len
, " ");
8988 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8990 json_nexthop_global
= json_object_new_object();
8991 json_object_string_addf(json_nexthop_global
, "ip",
8993 &attr
->mp_nexthop_global
);
8995 if (path
->peer
->hostname
)
8996 json_object_string_add(json_nexthop_global
,
8998 path
->peer
->hostname
);
9000 json_object_string_add(json_nexthop_global
, "afi",
9002 json_object_string_add(json_nexthop_global
, "scope",
9005 /* We display both LL & GL if both have been
9007 if ((attr
->mp_nexthop_len
9008 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9009 || (path
->peer
->conf_if
)) {
9010 json_nexthop_ll
= json_object_new_object();
9011 json_object_string_addf(
9012 json_nexthop_ll
, "ip", "%pI6",
9013 &attr
->mp_nexthop_local
);
9015 if (path
->peer
->hostname
)
9016 json_object_string_add(
9017 json_nexthop_ll
, "hostname",
9018 path
->peer
->hostname
);
9020 json_object_string_add(json_nexthop_ll
, "afi",
9022 json_object_string_add(json_nexthop_ll
, "scope",
9025 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9026 &attr
->mp_nexthop_local
)
9028 && !attr
->mp_nexthop_prefer_global
)
9029 json_object_boolean_true_add(
9030 json_nexthop_ll
, "used");
9032 json_object_boolean_true_add(
9033 json_nexthop_global
, "used");
9035 json_object_boolean_true_add(
9036 json_nexthop_global
, "used");
9038 /* Display LL if LL/Global both in table unless
9039 * prefer-global is set */
9040 if (((attr
->mp_nexthop_len
9041 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9042 && !attr
->mp_nexthop_prefer_global
)
9043 || (path
->peer
->conf_if
)) {
9044 if (path
->peer
->conf_if
) {
9045 len
= vty_out(vty
, "%s",
9046 path
->peer
->conf_if
);
9047 /* len of IPv6 addr + max len of def
9049 len
= wide
? (41 - len
) : (16 - len
);
9052 vty_out(vty
, "\n%*s", 36, " ");
9054 vty_out(vty
, "%*s", len
, " ");
9056 if (nexthop_hostname
)
9059 &attr
->mp_nexthop_local
,
9065 &attr
->mp_nexthop_local
,
9068 len
= wide
? (41 - len
) : (16 - len
);
9071 vty_out(vty
, "\n%*s", 36, " ");
9073 vty_out(vty
, "%*s", len
, " ");
9076 if (nexthop_hostname
)
9077 len
= vty_out(vty
, "%pI6(%s)%s",
9078 &attr
->mp_nexthop_global
,
9082 len
= vty_out(vty
, "%pI6%s",
9083 &attr
->mp_nexthop_global
,
9086 len
= wide
? (41 - len
) : (16 - len
);
9089 vty_out(vty
, "\n%*s", 36, " ");
9091 vty_out(vty
, "%*s", len
, " ");
9097 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9099 json_object_int_add(json_path
, "metric", attr
->med
);
9101 vty_out(vty
, "%7u", attr
->med
);
9103 vty_out(vty
, "%10u", attr
->med
);
9104 else if (!json_paths
) {
9106 vty_out(vty
, "%*s", 7, " ");
9108 vty_out(vty
, "%*s", 10, " ");
9112 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9114 json_object_int_add(json_path
, "locPrf",
9117 vty_out(vty
, "%7u", attr
->local_pref
);
9118 else if (!json_paths
)
9122 json_object_int_add(json_path
, "weight", attr
->weight
);
9124 vty_out(vty
, "%7u ", attr
->weight
);
9128 json_object_string_add(
9129 json_path
, "peerId",
9130 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
9136 json_object_string_add(json_path
, "path",
9139 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9144 json_object_string_add(json_path
, "origin",
9145 bgp_origin_long_str
[attr
->origin
]);
9147 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9150 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9151 json_object_string_add(json_path
, "esi",
9152 esi_to_str(&attr
->esi
,
9153 esi_buf
, sizeof(esi_buf
)));
9155 if (safi
== SAFI_EVPN
&&
9156 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9157 json_ext_community
= json_object_new_object();
9158 json_object_string_add(
9159 json_ext_community
, "string",
9160 bgp_attr_get_ecommunity(attr
)->str
);
9161 json_object_object_add(json_path
,
9162 "extendedCommunity",
9163 json_ext_community
);
9167 json_object_boolean_true_add(json_path
,
9168 "announceNexthopSelf");
9169 if (nexthop_othervrf
) {
9170 json_object_string_add(json_path
, "nhVrfName",
9173 json_object_int_add(json_path
, "nhVrfId",
9174 ((nexthop_vrfid
== VRF_UNKNOWN
)
9176 : (int)nexthop_vrfid
));
9181 if (json_nexthop_global
|| json_nexthop_ll
) {
9182 json_nexthops
= json_object_new_array();
9184 if (json_nexthop_global
)
9185 json_object_array_add(json_nexthops
,
9186 json_nexthop_global
);
9188 if (json_nexthop_ll
)
9189 json_object_array_add(json_nexthops
,
9192 json_object_object_add(json_path
, "nexthops",
9196 json_object_array_add(json_paths
, json_path
);
9200 if (safi
== SAFI_EVPN
) {
9201 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9202 /* XXX - add these params to the json out */
9203 vty_out(vty
, "%*s", 20, " ");
9204 vty_out(vty
, "ESI:%s",
9205 esi_to_str(&attr
->esi
, esi_buf
,
9211 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9212 vty_out(vty
, "%*s", 20, " ");
9213 vty_out(vty
, "%s\n",
9214 bgp_attr_get_ecommunity(attr
)->str
);
9218 #ifdef ENABLE_BGP_VNC
9219 /* prints an additional line, indented, with VNC info, if
9221 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9222 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9227 /* called from terminal list command */
9228 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9229 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9230 bool use_json
, json_object
*json_ar
, bool wide
)
9232 json_object
*json_status
= NULL
;
9233 json_object
*json_net
= NULL
;
9237 /* Route status display. */
9239 json_status
= json_object_new_object();
9240 json_net
= json_object_new_object();
9247 /* print prefix and mask */
9249 if (safi
== SAFI_EVPN
)
9250 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9251 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9252 json_object_string_add(
9253 json_net
, "addrPrefix",
9254 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9256 json_object_int_add(json_net
, "prefixLen",
9258 json_object_string_addf(json_net
, "network", "%pFX", p
);
9261 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9263 /* Print attribute */
9266 if (p
->family
== AF_INET
9267 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9268 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9269 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9270 json_object_string_addf(
9271 json_net
, "nextHop", "%pI4",
9272 &attr
->mp_nexthop_global_in
);
9274 json_object_string_addf(
9275 json_net
, "nextHop", "%pI4",
9277 } else if (p
->family
== AF_INET6
9278 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9279 json_object_string_addf(
9280 json_net
, "nextHopGlobal", "%pI6",
9281 &attr
->mp_nexthop_global
);
9282 } else if (p
->family
== AF_EVPN
9283 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9284 json_object_string_addf(
9285 json_net
, "nextHop", "%pI4",
9286 &attr
->mp_nexthop_global_in
);
9290 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9291 json_object_int_add(json_net
, "metric",
9294 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9295 json_object_int_add(json_net
, "locPrf",
9298 json_object_int_add(json_net
, "weight", attr
->weight
);
9302 json_object_string_add(json_net
, "path",
9306 json_object_string_add(json_net
, "bgpOriginCode",
9307 bgp_origin_str
[attr
->origin
]);
9309 if (p
->family
== AF_INET
9310 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9311 || safi
== SAFI_EVPN
9312 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9313 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9314 || safi
== SAFI_EVPN
)
9315 vty_out(vty
, "%-16pI4",
9316 &attr
->mp_nexthop_global_in
);
9318 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9320 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9321 } else if (p
->family
== AF_INET6
9322 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9328 &attr
->mp_nexthop_global
, buf
,
9330 len
= wide
? (41 - len
) : (16 - len
);
9332 vty_out(vty
, "\n%*s", 36, " ");
9334 vty_out(vty
, "%*s", len
, " ");
9337 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9339 vty_out(vty
, "%7u", attr
->med
);
9341 vty_out(vty
, "%10u", attr
->med
);
9347 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9348 vty_out(vty
, "%7u", attr
->local_pref
);
9352 vty_out(vty
, "%7u ", attr
->weight
);
9356 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9359 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9363 json_object_boolean_true_add(json_status
, "*");
9364 json_object_boolean_true_add(json_status
, ">");
9365 json_object_object_add(json_net
, "appliedStatusSymbols",
9368 prefix2str(p
, buff
, PREFIX_STRLEN
);
9369 json_object_object_add(json_ar
, buff
, json_net
);
9374 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9375 struct bgp_path_info
*path
, int display
, safi_t safi
,
9378 json_object
*json_out
= NULL
;
9380 mpls_label_t label
= MPLS_INVALID_LABEL
;
9386 json_out
= json_object_new_object();
9388 /* short status lead text */
9389 route_vty_short_status_out(vty
, path
, p
, json_out
);
9391 /* print prefix and mask */
9394 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9396 vty_out(vty
, "%*s", 17, " ");
9399 /* Print attribute */
9401 if (((p
->family
== AF_INET
)
9402 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9403 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9404 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9405 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9406 || safi
== SAFI_EVPN
) {
9408 json_object_string_addf(
9409 json_out
, "mpNexthopGlobalIn", "%pI4",
9410 &attr
->mp_nexthop_global_in
);
9412 vty_out(vty
, "%-16pI4",
9413 &attr
->mp_nexthop_global_in
);
9416 json_object_string_addf(json_out
, "nexthop",
9417 "%pI4", &attr
->nexthop
);
9419 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9421 } else if (((p
->family
== AF_INET6
)
9422 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9423 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9424 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9427 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9429 json_object_string_addf(
9430 json_out
, "mpNexthopGlobalIn", "%pI6",
9431 &attr
->mp_nexthop_global
);
9435 &attr
->mp_nexthop_global
,
9436 buf_a
, sizeof(buf_a
)));
9437 } else if (attr
->mp_nexthop_len
9438 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9439 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9440 &attr
->mp_nexthop_global
,
9441 &attr
->mp_nexthop_local
);
9443 json_object_string_add(json_out
,
9444 "mpNexthopGlobalLocal",
9447 vty_out(vty
, "%s", buf_a
);
9451 label
= decode_label(&path
->extra
->label
[0]);
9453 if (bgp_is_valid_label(&label
)) {
9455 json_object_int_add(json_out
, "notag", label
);
9456 json_object_array_add(json
, json_out
);
9458 vty_out(vty
, "notag/%d", label
);
9465 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9466 struct bgp_path_info
*path
, int display
,
9467 json_object
*json_paths
)
9470 json_object
*json_path
= NULL
;
9471 json_object
*json_nexthop
= NULL
;
9472 json_object
*json_overlay
= NULL
;
9478 json_path
= json_object_new_object();
9479 json_overlay
= json_object_new_object();
9480 json_nexthop
= json_object_new_object();
9483 /* short status lead text */
9484 route_vty_short_status_out(vty
, path
, p
, json_path
);
9486 /* print prefix and mask */
9488 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9490 vty_out(vty
, "%*s", 17, " ");
9492 /* Print attribute */
9494 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9499 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9501 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9502 &attr
->mp_nexthop_global_in
);
9504 json_object_string_add(json_nexthop
, "afi", "ipv4");
9506 json_object_object_add(json_path
, "nexthop",
9512 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9513 &attr
->mp_nexthop_local
);
9515 json_object_string_addf(json_nexthop
, "ipv6Global",
9517 &attr
->mp_nexthop_global
);
9519 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9521 &attr
->mp_nexthop_local
);
9523 json_object_string_add(json_nexthop
, "afi", "ipv6");
9525 json_object_object_add(json_path
, "nexthop",
9533 json_object_string_add(json_nexthop
, "Error",
9534 "Unsupported address-family");
9535 json_object_string_add(json_nexthop
, "error",
9536 "Unsupported address-family");
9540 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9543 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9545 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9547 if (bgp_attr_get_ecommunity(attr
)) {
9549 struct ecommunity_val
*routermac
= ecommunity_lookup(
9550 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9551 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9554 mac
= ecom_mac2str((char *)routermac
->val
);
9557 vty_out(vty
, "/%s", mac
);
9559 json_object_string_add(json_overlay
, "rmac",
9562 XFREE(MTYPE_TMP
, mac
);
9569 json_object_object_add(json_path
, "overlay", json_overlay
);
9571 json_object_array_add(json_paths
, json_path
);
9575 /* dampening route */
9576 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9577 struct bgp_path_info
*path
, int display
,
9578 afi_t afi
, safi_t safi
, bool use_json
,
9579 json_object
*json_paths
)
9581 struct attr
*attr
= path
->attr
;
9583 char timebuf
[BGP_UPTIME_LEN
];
9584 json_object
*json_path
= NULL
;
9587 json_path
= json_object_new_object();
9589 /* short status lead text */
9590 route_vty_short_status_out(vty
, path
, p
, json_path
);
9592 /* print prefix and mask */
9595 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9597 vty_out(vty
, "%*s", 17, " ");
9599 len
= vty_out(vty
, "%s", path
->peer
->host
);
9603 vty_out(vty
, "\n%*s", 34, " ");
9605 vty_out(vty
, "%*s", len
, " ");
9608 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9609 BGP_UPTIME_LEN
, afi
, safi
,
9613 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9615 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9619 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9620 safi
, use_json
, json_path
);
9623 json_object_string_add(json_path
, "asPath",
9626 json_object_string_add(json_path
, "origin",
9627 bgp_origin_str
[attr
->origin
]);
9628 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9630 json_object_array_add(json_paths
, json_path
);
9635 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9636 struct bgp_path_info
*path
, int display
,
9637 afi_t afi
, safi_t safi
, bool use_json
,
9638 json_object
*json_paths
)
9640 struct attr
*attr
= path
->attr
;
9641 struct bgp_damp_info
*bdi
;
9642 char timebuf
[BGP_UPTIME_LEN
];
9644 json_object
*json_path
= NULL
;
9650 json_path
= json_object_new_object();
9652 bdi
= path
->extra
->damp_info
;
9654 /* short status lead text */
9655 route_vty_short_status_out(vty
, path
, p
, json_path
);
9659 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9661 vty_out(vty
, "%*s", 17, " ");
9663 len
= vty_out(vty
, "%s", path
->peer
->host
);
9666 vty_out(vty
, "\n%*s", 33, " ");
9668 vty_out(vty
, "%*s", len
, " ");
9670 len
= vty_out(vty
, "%d", bdi
->flap
);
9675 vty_out(vty
, "%*s", len
, " ");
9677 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9678 BGP_UPTIME_LEN
, 0, NULL
));
9680 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9681 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9683 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9684 BGP_UPTIME_LEN
, afi
,
9685 safi
, use_json
, NULL
));
9687 vty_out(vty
, "%*s ", 8, " ");
9690 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9692 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9696 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9697 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
9699 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9702 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9703 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9704 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9705 BGP_UPTIME_LEN
, afi
, safi
,
9706 use_json
, json_path
);
9709 json_object_string_add(json_path
, "asPath",
9712 json_object_string_add(json_path
, "origin",
9713 bgp_origin_str
[attr
->origin
]);
9715 json_object_array_add(json_paths
, json_path
);
9719 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9720 int *first
, const char *header
,
9721 json_object
*json_adv_to
)
9723 char buf1
[INET6_ADDRSTRLEN
];
9724 json_object
*json_peer
= NULL
;
9727 /* 'advertised-to' is a dictionary of peers we have advertised
9729 * prefix too. The key is the peer's IP or swpX, the value is
9731 * hostname if we know it and "" if not.
9733 json_peer
= json_object_new_object();
9736 json_object_string_add(json_peer
, "hostname",
9740 json_object_object_add(json_adv_to
, peer
->conf_if
,
9743 json_object_object_add(
9745 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
9749 vty_out(vty
, "%s", header
);
9754 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9756 vty_out(vty
, " %s(%s)", peer
->hostname
,
9759 vty_out(vty
, " %s(%s)", peer
->hostname
,
9760 sockunion2str(&peer
->su
, buf1
,
9764 vty_out(vty
, " %s", peer
->conf_if
);
9767 sockunion2str(&peer
->su
, buf1
,
9773 static void route_vty_out_tx_ids(struct vty
*vty
,
9774 struct bgp_addpath_info_data
*d
)
9778 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9779 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9780 d
->addpath_tx_id
[i
],
9781 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9785 static void route_vty_out_detail_es_info(struct vty
*vty
,
9786 struct bgp_path_info
*pi
,
9788 json_object
*json_path
)
9790 char esi_buf
[ESI_STR_LEN
];
9791 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9792 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9793 ATTR_ES_PEER_ROUTER
);
9794 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9795 ATTR_ES_PEER_ACTIVE
);
9796 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9797 ATTR_ES_PEER_PROXY
);
9798 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9800 json_object
*json_es_info
= NULL
;
9802 json_object_string_add(
9805 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9806 json_es_info
= json_object_new_object();
9808 json_object_boolean_true_add(
9809 json_es_info
, "localEs");
9811 json_object_boolean_true_add(
9812 json_es_info
, "peerActive");
9814 json_object_boolean_true_add(
9815 json_es_info
, "peerProxy");
9817 json_object_boolean_true_add(
9818 json_es_info
, "peerRouter");
9819 if (attr
->mm_sync_seqnum
)
9820 json_object_int_add(
9821 json_es_info
, "peerSeq",
9822 attr
->mm_sync_seqnum
);
9823 json_object_object_add(
9824 json_path
, "es_info",
9828 if (bgp_evpn_attr_is_sync(attr
))
9830 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9832 es_local
? "local-es":"",
9833 peer_proxy
? "proxy " : "",
9834 peer_active
? "active ":"",
9835 peer_router
? "router ":"",
9836 attr
->mm_sync_seqnum
);
9838 vty_out(vty
, " ESI %s %s\n",
9840 es_local
? "local-es":"");
9844 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
9845 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
9846 enum rpki_states rpki_curr_state
,
9847 json_object
*json_paths
)
9849 char buf
[INET6_ADDRSTRLEN
];
9851 struct attr
*attr
= path
->attr
;
9852 int sockunion_vty_out(struct vty
*, union sockunion
*);
9854 json_object
*json_bestpath
= NULL
;
9855 json_object
*json_cluster_list
= NULL
;
9856 json_object
*json_cluster_list_list
= NULL
;
9857 json_object
*json_ext_community
= NULL
;
9858 json_object
*json_last_update
= NULL
;
9859 json_object
*json_pmsi
= NULL
;
9860 json_object
*json_nexthop_global
= NULL
;
9861 json_object
*json_nexthop_ll
= NULL
;
9862 json_object
*json_nexthops
= NULL
;
9863 json_object
*json_path
= NULL
;
9864 json_object
*json_peer
= NULL
;
9865 json_object
*json_string
= NULL
;
9866 json_object
*json_adv_to
= NULL
;
9868 struct listnode
*node
, *nnode
;
9870 bool addpath_capable
;
9872 unsigned int first_as
;
9874 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9876 char *nexthop_hostname
=
9877 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9880 json_path
= json_object_new_object();
9881 json_peer
= json_object_new_object();
9882 json_nexthop_global
= json_object_new_object();
9885 if (safi
== SAFI_EVPN
) {
9887 vty_out(vty
, " Route %pRN", bn
);
9894 if (path
->extra
&& path
->extra
->num_labels
) {
9895 bgp_evpn_label2str(path
->extra
->label
,
9896 path
->extra
->num_labels
, tag_buf
,
9899 if (safi
== SAFI_EVPN
) {
9901 if (tag_buf
[0] != '\0')
9902 vty_out(vty
, " VNI %s", tag_buf
);
9905 json_object_string_add(json_path
, "VNI",
9907 json_object_string_add(json_path
, "vni",
9913 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9914 struct bgp_path_info
*parent_ri
;
9915 struct bgp_dest
*dest
, *pdest
;
9917 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9918 dest
= parent_ri
->net
;
9919 if (dest
&& dest
->pdest
) {
9920 pdest
= dest
->pdest
;
9922 (struct prefix_rd
*)bgp_dest_get_prefix(
9924 buf1
, sizeof(buf1
));
9925 if (is_pi_family_evpn(parent_ri
)) {
9927 " Imported from %s:%pFX, VNI %s",
9929 (struct prefix_evpn
*)
9930 bgp_dest_get_prefix(
9933 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
9934 vty_out(vty
, ", L3NHG %s",
9936 & ATTR_ES_L3_NHG_ACTIVE
)
9943 " Imported from %s:%pFX\n",
9945 (struct prefix_evpn
*)
9946 bgp_dest_get_prefix(
9952 if (safi
== SAFI_EVPN
9953 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
9954 char gwip_buf
[INET6_ADDRSTRLEN
];
9956 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
9960 json_object_string_add(json_path
, "gatewayIP",
9963 vty_out(vty
, " Gateway IP %s", gwip_buf
);
9966 if (safi
== SAFI_EVPN
)
9969 /* Line1 display AS-path, Aggregator */
9972 if (!attr
->aspath
->json
)
9973 aspath_str_update(attr
->aspath
, true);
9974 json_object_lock(attr
->aspath
->json
);
9975 json_object_object_add(json_path
, "aspath",
9976 attr
->aspath
->json
);
9978 if (attr
->aspath
->segments
)
9979 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9981 vty_out(vty
, " Local");
9985 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9987 json_object_boolean_true_add(json_path
, "removed");
9989 vty_out(vty
, ", (removed)");
9992 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9994 json_object_boolean_true_add(json_path
, "stale");
9996 vty_out(vty
, ", (stale)");
9999 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10001 json_object_int_add(json_path
, "aggregatorAs",
10002 attr
->aggregator_as
);
10003 json_object_string_addf(json_path
, "aggregatorId",
10004 "%pI4", &attr
->aggregator_addr
);
10006 vty_out(vty
, ", (aggregated by %u %pI4)",
10007 attr
->aggregator_as
, &attr
->aggregator_addr
);
10011 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10012 PEER_FLAG_REFLECTOR_CLIENT
)) {
10014 json_object_boolean_true_add(json_path
,
10015 "rxedFromRrClient");
10017 vty_out(vty
, ", (Received from a RR-client)");
10020 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10021 PEER_FLAG_RSERVER_CLIENT
)) {
10023 json_object_boolean_true_add(json_path
,
10024 "rxedFromRsClient");
10026 vty_out(vty
, ", (Received from a RS-client)");
10029 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10031 json_object_boolean_true_add(json_path
,
10032 "dampeningHistoryEntry");
10034 vty_out(vty
, ", (history entry)");
10035 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10037 json_object_boolean_true_add(json_path
,
10038 "dampeningSuppressed");
10040 vty_out(vty
, ", (suppressed due to dampening)");
10044 vty_out(vty
, "\n");
10046 /* Line2 display Next-hop, Neighbor, Router-id */
10047 /* Display the nexthop */
10048 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
10050 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
10051 || bn_p
->family
== AF_EVPN
)
10052 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
10053 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
10054 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10055 || safi
== SAFI_EVPN
) {
10057 json_object_string_addf(
10058 json_nexthop_global
, "ip", "%pI4",
10059 &attr
->mp_nexthop_global_in
);
10061 if (path
->peer
->hostname
)
10062 json_object_string_add(
10063 json_nexthop_global
, "hostname",
10064 path
->peer
->hostname
);
10066 if (nexthop_hostname
)
10067 vty_out(vty
, " %pI4(%s)",
10068 &attr
->mp_nexthop_global_in
,
10071 vty_out(vty
, " %pI4",
10072 &attr
->mp_nexthop_global_in
);
10076 json_object_string_addf(json_nexthop_global
,
10080 if (path
->peer
->hostname
)
10081 json_object_string_add(
10082 json_nexthop_global
, "hostname",
10083 path
->peer
->hostname
);
10085 if (nexthop_hostname
)
10086 vty_out(vty
, " %pI4(%s)",
10090 vty_out(vty
, " %pI4",
10096 json_object_string_add(json_nexthop_global
, "afi",
10100 json_object_string_addf(json_nexthop_global
, "ip",
10102 &attr
->mp_nexthop_global
);
10104 if (path
->peer
->hostname
)
10105 json_object_string_add(json_nexthop_global
,
10107 path
->peer
->hostname
);
10109 json_object_string_add(json_nexthop_global
, "afi",
10111 json_object_string_add(json_nexthop_global
, "scope",
10114 if (nexthop_hostname
)
10115 vty_out(vty
, " %pI6(%s)",
10116 &attr
->mp_nexthop_global
,
10119 vty_out(vty
, " %pI6",
10120 &attr
->mp_nexthop_global
);
10124 /* Display the IGP cost or 'inaccessible' */
10125 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10127 json_object_boolean_false_add(json_nexthop_global
,
10130 vty_out(vty
, " (inaccessible)");
10132 if (path
->extra
&& path
->extra
->igpmetric
) {
10134 json_object_int_add(json_nexthop_global
,
10136 path
->extra
->igpmetric
);
10138 vty_out(vty
, " (metric %u)",
10139 path
->extra
->igpmetric
);
10142 /* IGP cost is 0, display this only for json */
10145 json_object_int_add(json_nexthop_global
,
10150 json_object_boolean_true_add(json_nexthop_global
,
10154 /* Display peer "from" output */
10155 /* This path was originated locally */
10156 if (path
->peer
== bgp
->peer_self
) {
10158 if (safi
== SAFI_EVPN
10159 || (bn_p
->family
== AF_INET
10160 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
10162 json_object_string_add(json_peer
, "peerId",
10165 vty_out(vty
, " from 0.0.0.0 ");
10168 json_object_string_add(json_peer
, "peerId",
10171 vty_out(vty
, " from :: ");
10175 json_object_string_addf(json_peer
, "routerId", "%pI4",
10178 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10181 /* We RXed this path from one of our peers */
10185 json_object_string_add(json_peer
, "peerId",
10186 sockunion2str(&path
->peer
->su
,
10189 json_object_string_addf(json_peer
, "routerId", "%pI4",
10190 &path
->peer
->remote_id
);
10192 if (path
->peer
->hostname
)
10193 json_object_string_add(json_peer
, "hostname",
10194 path
->peer
->hostname
);
10196 if (path
->peer
->domainname
)
10197 json_object_string_add(json_peer
, "domainname",
10198 path
->peer
->domainname
);
10200 if (path
->peer
->conf_if
)
10201 json_object_string_add(json_peer
, "interface",
10202 path
->peer
->conf_if
);
10204 if (path
->peer
->conf_if
) {
10205 if (path
->peer
->hostname
10206 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10207 BGP_FLAG_SHOW_HOSTNAME
))
10208 vty_out(vty
, " from %s(%s)",
10209 path
->peer
->hostname
,
10210 path
->peer
->conf_if
);
10212 vty_out(vty
, " from %s",
10213 path
->peer
->conf_if
);
10215 if (path
->peer
->hostname
10216 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10217 BGP_FLAG_SHOW_HOSTNAME
))
10218 vty_out(vty
, " from %s(%s)",
10219 path
->peer
->hostname
,
10222 vty_out(vty
, " from %s",
10223 sockunion2str(&path
->peer
->su
,
10228 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10229 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10231 vty_out(vty
, " (%s)",
10233 &path
->peer
->remote_id
, buf1
,
10239 * Note when vrfid of nexthop is different from that of prefix
10241 if (path
->extra
&& path
->extra
->bgp_orig
) {
10242 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10247 if (path
->extra
->bgp_orig
->inst_type
10248 == BGP_INSTANCE_TYPE_DEFAULT
)
10249 vn
= VRF_DEFAULT_NAME
;
10251 vn
= path
->extra
->bgp_orig
->name
;
10253 json_object_string_add(json_path
, "nhVrfName", vn
);
10255 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10256 json_object_int_add(json_path
, "nhVrfId", -1);
10258 json_object_int_add(json_path
, "nhVrfId",
10259 (int)nexthop_vrfid
);
10262 if (nexthop_vrfid
== VRF_UNKNOWN
)
10263 vty_out(vty
, " vrf ?");
10267 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10268 vty_out(vty
, " vrf %s(%u)",
10269 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10274 if (nexthop_self
) {
10276 json_object_boolean_true_add(json_path
,
10277 "announceNexthopSelf");
10279 vty_out(vty
, " announce-nh-self");
10284 vty_out(vty
, "\n");
10286 /* display the link-local nexthop */
10287 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10289 json_nexthop_ll
= json_object_new_object();
10290 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10291 &attr
->mp_nexthop_local
);
10293 if (path
->peer
->hostname
)
10294 json_object_string_add(json_nexthop_ll
,
10296 path
->peer
->hostname
);
10298 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10299 json_object_string_add(json_nexthop_ll
, "scope",
10302 json_object_boolean_true_add(json_nexthop_ll
,
10305 if (!attr
->mp_nexthop_prefer_global
)
10306 json_object_boolean_true_add(json_nexthop_ll
,
10309 json_object_boolean_true_add(
10310 json_nexthop_global
, "used");
10312 vty_out(vty
, " (%s) %s\n",
10313 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10314 buf
, INET6_ADDRSTRLEN
),
10315 attr
->mp_nexthop_prefer_global
10316 ? "(prefer-global)"
10320 /* If we do not have a link-local nexthop then we must flag the
10321 global as "used" */
10324 json_object_boolean_true_add(json_nexthop_global
,
10328 if (safi
== SAFI_EVPN
&&
10329 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10330 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10333 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10334 * Int/Ext/Local, Atomic, best */
10336 json_object_string_add(json_path
, "origin",
10337 bgp_origin_long_str
[attr
->origin
]);
10339 vty_out(vty
, " Origin %s",
10340 bgp_origin_long_str
[attr
->origin
]);
10342 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10344 json_object_int_add(json_path
, "metric", attr
->med
);
10346 vty_out(vty
, ", metric %u", attr
->med
);
10349 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10351 json_object_int_add(json_path
, "locPrf",
10354 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10357 if (attr
->weight
!= 0) {
10359 json_object_int_add(json_path
, "weight", attr
->weight
);
10361 vty_out(vty
, ", weight %u", attr
->weight
);
10364 if (attr
->tag
!= 0) {
10366 json_object_int_add(json_path
, "tag", attr
->tag
);
10368 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10371 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10373 json_object_boolean_false_add(json_path
, "valid");
10375 vty_out(vty
, ", invalid");
10376 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10378 json_object_boolean_true_add(json_path
, "valid");
10380 vty_out(vty
, ", valid");
10384 json_object_int_add(json_path
, "version", bn
->version
);
10386 if (path
->peer
!= bgp
->peer_self
) {
10387 if (path
->peer
->as
== path
->peer
->local_as
) {
10388 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10390 json_object_string_add(
10392 "confed-internal");
10394 vty_out(vty
, ", confed-internal");
10397 json_object_string_add(
10398 json_peer
, "type", "internal");
10400 vty_out(vty
, ", internal");
10403 if (bgp_confederation_peers_check(bgp
,
10406 json_object_string_add(
10408 "confed-external");
10410 vty_out(vty
, ", confed-external");
10413 json_object_string_add(
10414 json_peer
, "type", "external");
10416 vty_out(vty
, ", external");
10419 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10421 json_object_boolean_true_add(json_path
, "aggregated");
10422 json_object_boolean_true_add(json_path
, "local");
10424 vty_out(vty
, ", aggregated, local");
10426 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10428 json_object_boolean_true_add(json_path
, "sourced");
10430 vty_out(vty
, ", sourced");
10433 json_object_boolean_true_add(json_path
, "sourced");
10434 json_object_boolean_true_add(json_path
, "local");
10436 vty_out(vty
, ", sourced, local");
10440 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10442 json_object_boolean_true_add(json_path
,
10443 "atomicAggregate");
10445 vty_out(vty
, ", atomic-aggregate");
10448 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10449 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10450 && bgp_path_info_mpath_count(path
))) {
10452 json_object_boolean_true_add(json_path
, "multipath");
10454 vty_out(vty
, ", multipath");
10457 // Mark the bestpath(s)
10458 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10459 first_as
= aspath_get_first_as(attr
->aspath
);
10462 if (!json_bestpath
)
10463 json_bestpath
= json_object_new_object();
10464 json_object_int_add(json_bestpath
, "bestpathFromAs",
10468 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10470 vty_out(vty
, ", bestpath-from-AS Local");
10474 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10476 if (!json_bestpath
)
10477 json_bestpath
= json_object_new_object();
10478 json_object_boolean_true_add(json_bestpath
, "overall");
10479 json_object_string_add(
10480 json_bestpath
, "selectionReason",
10481 bgp_path_selection_reason2str(bn
->reason
));
10483 vty_out(vty
, ", best");
10484 vty_out(vty
, " (%s)",
10485 bgp_path_selection_reason2str(bn
->reason
));
10489 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10491 json_object_string_add(
10492 json_path
, "rpkiValidationState",
10493 bgp_rpki_validation2str(rpki_curr_state
));
10495 vty_out(vty
, ", rpki validation-state: %s",
10496 bgp_rpki_validation2str(rpki_curr_state
));
10500 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10503 vty_out(vty
, "\n");
10505 /* Line 4 display Community */
10506 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10508 if (!bgp_attr_get_community(attr
)->json
)
10509 community_str(bgp_attr_get_community(attr
),
10511 json_object_lock(bgp_attr_get_community(attr
)->json
);
10512 json_object_object_add(
10513 json_path
, "community",
10514 bgp_attr_get_community(attr
)->json
);
10516 vty_out(vty
, " Community: %s\n",
10517 bgp_attr_get_community(attr
)->str
);
10521 /* Line 5 display Extended-community */
10522 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10524 json_ext_community
= json_object_new_object();
10525 json_object_string_add(
10526 json_ext_community
, "string",
10527 bgp_attr_get_ecommunity(attr
)->str
);
10528 json_object_object_add(json_path
, "extendedCommunity",
10529 json_ext_community
);
10531 vty_out(vty
, " Extended Community: %s\n",
10532 bgp_attr_get_ecommunity(attr
)->str
);
10536 /* Line 6 display Large community */
10537 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10539 if (!bgp_attr_get_lcommunity(attr
)->json
)
10540 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10542 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10543 json_object_object_add(
10544 json_path
, "largeCommunity",
10545 bgp_attr_get_lcommunity(attr
)->json
);
10547 vty_out(vty
, " Large Community: %s\n",
10548 bgp_attr_get_lcommunity(attr
)->str
);
10552 /* Line 7 display Originator, Cluster-id */
10553 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10554 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10555 char buf
[BUFSIZ
] = {0};
10557 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10559 json_object_string_addf(json_path
,
10560 "originatorId", "%pI4",
10561 &attr
->originator_id
);
10563 vty_out(vty
, " Originator: %pI4",
10564 &attr
->originator_id
);
10567 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10568 struct cluster_list
*cluster
=
10569 bgp_attr_get_cluster(attr
);
10573 json_cluster_list
= json_object_new_object();
10574 json_cluster_list_list
=
10575 json_object_new_array();
10577 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10578 json_string
= json_object_new_string(
10581 buf
, sizeof(buf
)));
10582 json_object_array_add(
10583 json_cluster_list_list
,
10588 * struct cluster_list does not have
10589 * "str" variable like aspath and community
10590 * do. Add this someday if someone asks
10592 * json_object_string_add(json_cluster_list,
10593 * "string", cluster->str);
10595 json_object_object_add(json_cluster_list
,
10597 json_cluster_list_list
);
10598 json_object_object_add(json_path
, "clusterList",
10599 json_cluster_list
);
10601 vty_out(vty
, ", Cluster list: ");
10603 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10604 vty_out(vty
, "%pI4 ",
10605 &cluster
->list
[i
]);
10611 vty_out(vty
, "\n");
10614 if (path
->extra
&& path
->extra
->damp_info
)
10615 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10618 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10619 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10620 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
10623 json_object_int_add(json_path
, "remoteLabel", label
);
10625 vty_out(vty
, " Remote label: %d\n", label
);
10629 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10630 inet_ntop(AF_INET6
, &path
->extra
->sid
[0].sid
, buf
, sizeof(buf
));
10632 json_object_string_add(json_path
, "remoteSid", buf
);
10634 vty_out(vty
, " Remote SID: %s\n", buf
);
10638 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10640 json_object_int_add(json_path
, "labelIndex",
10641 attr
->label_index
);
10643 vty_out(vty
, " Label Index: %d\n",
10644 attr
->label_index
);
10647 /* Line 8 display Addpath IDs */
10648 if (path
->addpath_rx_id
10649 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10651 json_object_int_add(json_path
, "addpathRxId",
10652 path
->addpath_rx_id
);
10654 /* Keep backwards compatibility with the old API
10655 * by putting TX All's ID in the old field
10657 json_object_int_add(
10658 json_path
, "addpathTxId",
10660 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10662 /* ... but create a specific field for each
10665 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10666 json_object_int_add(
10668 bgp_addpath_names(i
)->id_json_name
,
10669 path
->tx_addpath
.addpath_tx_id
[i
]);
10672 vty_out(vty
, " AddPath ID: RX %u, ",
10673 path
->addpath_rx_id
);
10675 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10679 /* If we used addpath to TX a non-bestpath we need to display
10680 * "Advertised to" on a path-by-path basis
10682 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10685 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10687 bgp_addpath_encode_tx(peer
, afi
, safi
);
10688 has_adj
= bgp_adj_out_lookup(
10690 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10691 &path
->tx_addpath
));
10693 if ((addpath_capable
&& has_adj
)
10694 || (!addpath_capable
&& has_adj
10695 && CHECK_FLAG(path
->flags
,
10696 BGP_PATH_SELECTED
))) {
10697 if (json_path
&& !json_adv_to
)
10698 json_adv_to
= json_object_new_object();
10700 route_vty_out_advertised_to(
10702 " Advertised to:", json_adv_to
);
10708 json_object_object_add(
10709 json_path
, "advertisedTo", json_adv_to
);
10713 vty_out(vty
, "\n");
10718 /* Line 9 display Uptime */
10719 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
10721 json_last_update
= json_object_new_object();
10722 json_object_int_add(json_last_update
, "epoch", tbuf
);
10723 json_object_string_add(json_last_update
, "string",
10725 json_object_object_add(json_path
, "lastUpdate",
10728 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10730 /* Line 10 display PMSI tunnel attribute, if present */
10731 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10732 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10733 bgp_attr_get_pmsi_tnl_type(attr
),
10734 PMSI_TNLTYPE_STR_DEFAULT
);
10737 json_pmsi
= json_object_new_object();
10738 json_object_string_add(json_pmsi
, "tunnelType", str
);
10739 json_object_int_add(json_pmsi
, "label",
10740 label2vni(&attr
->label
));
10741 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10743 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10744 str
, label2vni(&attr
->label
));
10747 if (path
->peer
->t_gr_restart
&&
10748 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10749 unsigned long gr_remaining
=
10750 thread_timer_remain_second(path
->peer
->t_gr_restart
);
10753 json_object_int_add(json_path
,
10754 "gracefulRestartSecondsRemaining",
10758 " Time until Graceful Restart stale route deleted: %lu\n",
10762 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
10763 bgp_attr_get_community(attr
) &&
10764 community_include(bgp_attr_get_community(attr
),
10765 COMMUNITY_LLGR_STALE
)) {
10766 unsigned long llgr_remaining
= thread_timer_remain_second(
10767 path
->peer
->t_llgr_stale
[afi
][safi
]);
10770 json_object_int_add(json_path
, "llgrSecondsRemaining",
10774 " Time until Long-lived stale route deleted: %lu\n",
10778 /* Output some debug about internal state of the dest flags */
10780 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10781 json_object_boolean_true_add(json_path
, "processScheduled");
10782 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10783 json_object_boolean_true_add(json_path
, "userCleared");
10784 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10785 json_object_boolean_true_add(json_path
, "labelChanged");
10786 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10787 json_object_boolean_true_add(json_path
, "registeredForLabel");
10788 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10789 json_object_boolean_true_add(json_path
, "selectDefered");
10790 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10791 json_object_boolean_true_add(json_path
, "fibInstalled");
10792 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10793 json_object_boolean_true_add(json_path
, "fibPending");
10795 if (json_nexthop_global
|| json_nexthop_ll
) {
10796 json_nexthops
= json_object_new_array();
10798 if (json_nexthop_global
)
10799 json_object_array_add(json_nexthops
,
10800 json_nexthop_global
);
10802 if (json_nexthop_ll
)
10803 json_object_array_add(json_nexthops
,
10806 json_object_object_add(json_path
, "nexthops",
10810 json_object_object_add(json_path
, "peer", json_peer
);
10811 json_object_array_add(json_paths
, json_path
);
10815 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10816 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10817 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10819 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10820 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10822 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10823 const char *comstr
, int exact
, afi_t afi
,
10824 safi_t safi
, uint16_t show_flags
);
10826 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10827 struct bgp_table
*table
, enum bgp_show_type type
,
10828 void *output_arg
, const char *rd
, int is_last
,
10829 unsigned long *output_cum
, unsigned long *total_cum
,
10830 unsigned long *json_header_depth
, uint16_t show_flags
,
10831 enum rpki_states rpki_target_state
)
10833 struct bgp_path_info
*pi
;
10834 struct bgp_dest
*dest
;
10835 bool header
= true;
10836 bool json_detail_header
= false;
10838 unsigned long output_count
= 0;
10839 unsigned long total_count
= 0;
10841 json_object
*json_paths
= NULL
;
10843 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10844 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
10845 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10847 if (output_cum
&& *output_cum
!= 0)
10850 if (use_json
&& !*json_header_depth
) {
10852 *json_header_depth
= 1;
10854 vty_out(vty
, "{\n");
10855 *json_header_depth
= 2;
10859 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10860 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10861 " \"localAS\": %u,\n \"routes\": { ",
10862 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
10863 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
10866 table
->version
, &bgp
->router_id
,
10867 bgp
->default_local_pref
, bgp
->as
);
10869 vty_out(vty
, " \"routeDistinguishers\" : {");
10870 ++*json_header_depth
;
10874 if (use_json
&& rd
) {
10875 vty_out(vty
, " \"%s\" : { ", rd
);
10878 /* Check for 'json detail', where we need header output once per dest */
10879 if (use_json
&& CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
) &&
10880 type
!= bgp_show_type_dampend_paths
&&
10881 type
!= bgp_show_type_damp_neighbor
&&
10882 type
!= bgp_show_type_flap_statistics
&&
10883 type
!= bgp_show_type_flap_neighbor
)
10884 json_detail_header
= true;
10886 /* Start processing of routes. */
10887 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
10888 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10889 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
10890 bool json_detail
= json_detail_header
;
10892 pi
= bgp_dest_get_bgp_path_info(dest
);
10898 json_paths
= json_object_new_array();
10902 for (; pi
; pi
= pi
->next
) {
10903 struct community
*picomm
= NULL
;
10905 picomm
= bgp_attr_get_community(pi
->attr
);
10909 if (type
== bgp_show_type_prefix_version
) {
10911 strtoul(output_arg
, NULL
, 10);
10912 if (dest
->version
< version
)
10916 if (type
== bgp_show_type_community_alias
) {
10917 char *alias
= output_arg
;
10918 char **communities
;
10920 bool found
= false;
10923 frrstr_split(picomm
->str
, " ",
10924 &communities
, &num
);
10925 for (int i
= 0; i
< num
; i
++) {
10926 const char *com2alias
=
10927 bgp_community2alias(
10930 && strcmp(alias
, com2alias
)
10936 XFREE(MTYPE_TMP
, communities
);
10940 bgp_attr_get_lcommunity(pi
->attr
)) {
10941 frrstr_split(bgp_attr_get_lcommunity(
10944 " ", &communities
, &num
);
10945 for (int i
= 0; i
< num
; i
++) {
10946 const char *com2alias
=
10947 bgp_community2alias(
10950 && strcmp(alias
, com2alias
)
10956 XFREE(MTYPE_TMP
, communities
);
10963 if (type
== bgp_show_type_rpki
) {
10964 if (dest_p
->family
== AF_INET
10965 || dest_p
->family
== AF_INET6
)
10966 rpki_curr_state
= hook_call(
10967 bgp_rpki_prefix_status
,
10968 pi
->peer
, pi
->attr
, dest_p
);
10969 if (rpki_target_state
!= RPKI_NOT_BEING_USED
10970 && rpki_curr_state
!= rpki_target_state
)
10974 if (type
== bgp_show_type_flap_statistics
10975 || type
== bgp_show_type_flap_neighbor
10976 || type
== bgp_show_type_dampend_paths
10977 || type
== bgp_show_type_damp_neighbor
) {
10978 if (!(pi
->extra
&& pi
->extra
->damp_info
))
10981 if (type
== bgp_show_type_regexp
) {
10982 regex_t
*regex
= output_arg
;
10984 if (bgp_regexec(regex
, pi
->attr
->aspath
)
10988 if (type
== bgp_show_type_prefix_list
) {
10989 struct prefix_list
*plist
= output_arg
;
10991 if (prefix_list_apply(plist
, dest_p
)
10995 if (type
== bgp_show_type_filter_list
) {
10996 struct as_list
*as_list
= output_arg
;
10998 if (as_list_apply(as_list
, pi
->attr
->aspath
)
10999 != AS_FILTER_PERMIT
)
11002 if (type
== bgp_show_type_route_map
) {
11003 struct route_map
*rmap
= output_arg
;
11004 struct bgp_path_info path
;
11005 struct attr dummy_attr
;
11006 route_map_result_t ret
;
11008 dummy_attr
= *pi
->attr
;
11010 path
.peer
= pi
->peer
;
11011 path
.attr
= &dummy_attr
;
11013 ret
= route_map_apply(rmap
, dest_p
, &path
);
11014 bgp_attr_flush(&dummy_attr
);
11015 if (ret
== RMAP_DENYMATCH
)
11018 if (type
== bgp_show_type_neighbor
11019 || type
== bgp_show_type_flap_neighbor
11020 || type
== bgp_show_type_damp_neighbor
) {
11021 union sockunion
*su
= output_arg
;
11023 if (pi
->peer
== NULL
11024 || pi
->peer
->su_remote
== NULL
11025 || !sockunion_same(pi
->peer
->su_remote
, su
))
11028 if (type
== bgp_show_type_cidr_only
) {
11029 uint32_t destination
;
11031 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11032 if (IN_CLASSC(destination
)
11033 && dest_p
->prefixlen
== 24)
11035 if (IN_CLASSB(destination
)
11036 && dest_p
->prefixlen
== 16)
11038 if (IN_CLASSA(destination
)
11039 && dest_p
->prefixlen
== 8)
11042 if (type
== bgp_show_type_prefix_longer
) {
11044 if (!prefix_match(p
, dest_p
))
11047 if (type
== bgp_show_type_community_all
) {
11051 if (type
== bgp_show_type_community
) {
11052 struct community
*com
= output_arg
;
11054 if (!picomm
|| !community_match(picomm
, com
))
11057 if (type
== bgp_show_type_community_exact
) {
11058 struct community
*com
= output_arg
;
11060 if (!picomm
|| !community_cmp(picomm
, com
))
11063 if (type
== bgp_show_type_community_list
) {
11064 struct community_list
*list
= output_arg
;
11066 if (!community_list_match(picomm
, list
))
11069 if (type
== bgp_show_type_community_list_exact
) {
11070 struct community_list
*list
= output_arg
;
11072 if (!community_list_exact_match(picomm
, list
))
11075 if (type
== bgp_show_type_lcommunity
) {
11076 struct lcommunity
*lcom
= output_arg
;
11078 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11080 bgp_attr_get_lcommunity(pi
->attr
),
11085 if (type
== bgp_show_type_lcommunity_exact
) {
11086 struct lcommunity
*lcom
= output_arg
;
11088 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11090 bgp_attr_get_lcommunity(pi
->attr
),
11094 if (type
== bgp_show_type_lcommunity_list
) {
11095 struct community_list
*list
= output_arg
;
11097 if (!lcommunity_list_match(
11098 bgp_attr_get_lcommunity(pi
->attr
),
11103 == bgp_show_type_lcommunity_list_exact
) {
11104 struct community_list
*list
= output_arg
;
11106 if (!lcommunity_list_exact_match(
11107 bgp_attr_get_lcommunity(pi
->attr
),
11111 if (type
== bgp_show_type_lcommunity_all
) {
11112 if (!bgp_attr_get_lcommunity(pi
->attr
))
11115 if (type
== bgp_show_type_dampend_paths
11116 || type
== bgp_show_type_damp_neighbor
) {
11117 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11118 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11122 if (!use_json
&& header
) {
11124 "BGP table version is %" PRIu64
11125 ", local router ID is %pI4, vrf id ",
11126 table
->version
, &bgp
->router_id
);
11127 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11128 vty_out(vty
, "%s", VRFID_NONE_STR
);
11130 vty_out(vty
, "%u", bgp
->vrf_id
);
11131 vty_out(vty
, "\n");
11132 vty_out(vty
, "Default local pref %u, ",
11133 bgp
->default_local_pref
);
11134 vty_out(vty
, "local AS %u\n", bgp
->as
);
11135 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11136 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11137 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11138 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11139 if (type
== bgp_show_type_dampend_paths
11140 || type
== bgp_show_type_damp_neighbor
)
11141 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11142 else if (type
== bgp_show_type_flap_statistics
11143 || type
== bgp_show_type_flap_neighbor
)
11144 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11146 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11147 : BGP_SHOW_HEADER
));
11150 } else if (json_detail
&& json_paths
!= NULL
) {
11151 const struct prefix_rd
*prd
;
11152 json_object
*jtemp
;
11154 /* Use common detail header, for most types;
11155 * need a json 'object'.
11158 jtemp
= json_object_new_object();
11159 prd
= bgp_rd_from_dest(dest
, safi
);
11161 route_vty_out_detail_header(
11162 vty
, bgp
, dest
, prd
, table
->afi
,
11165 json_object_array_add(json_paths
, jtemp
);
11167 json_detail
= false;
11170 if (rd
!= NULL
&& !display
&& !output_count
) {
11173 "Route Distinguisher: %s\n",
11176 if (type
== bgp_show_type_dampend_paths
11177 || type
== bgp_show_type_damp_neighbor
)
11178 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11179 AFI_IP
, safi
, use_json
,
11181 else if (type
== bgp_show_type_flap_statistics
11182 || type
== bgp_show_type_flap_neighbor
)
11183 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11184 AFI_IP
, safi
, use_json
,
11187 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
11188 route_vty_out_detail(
11189 vty
, bgp
, dest
, pi
,
11190 family2afi(dest_p
->family
),
11191 safi
, RPKI_NOT_BEING_USED
,
11194 route_vty_out(vty
, dest_p
, pi
, display
,
11195 safi
, json_paths
, wide
);
11205 /* encode prefix */
11206 if (dest_p
->family
== AF_FLOWSPEC
) {
11207 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11210 bgp_fs_nlri_get_string(
11212 dest_p
->u
.prefix_flowspec
.ptr
,
11213 dest_p
->u
.prefix_flowspec
.prefixlen
,
11214 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11215 family2afi(dest_p
->u
11216 .prefix_flowspec
.family
));
11218 vty_out(vty
, "\"%s/%d\": ", retstr
,
11219 dest_p
->u
.prefix_flowspec
11222 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11223 dest_p
->u
.prefix_flowspec
11227 vty_out(vty
, "\"%pFX\": ", dest_p
);
11229 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11231 vty_json(vty
, json_paths
);
11235 json_object_free(json_paths
);
11239 output_count
+= *output_cum
;
11240 *output_cum
= output_count
;
11243 total_count
+= *total_cum
;
11244 *total_cum
= total_count
;
11248 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11252 for (i
= 0; i
< *json_header_depth
; ++i
)
11253 vty_out(vty
, " } ");
11255 vty_out(vty
, "\n");
11259 /* No route is displayed */
11260 if (output_count
== 0) {
11261 if (type
== bgp_show_type_normal
)
11263 "No BGP prefixes displayed, %ld exist\n",
11267 "\nDisplayed %ld routes and %ld total paths\n",
11268 output_count
, total_count
);
11272 return CMD_SUCCESS
;
11275 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11276 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11277 enum bgp_show_type type
, void *output_arg
, bool use_json
)
11279 struct bgp_dest
*dest
, *next
;
11280 unsigned long output_cum
= 0;
11281 unsigned long total_cum
= 0;
11282 unsigned long json_header_depth
= 0;
11283 struct bgp_table
*itable
;
11285 uint16_t show_flags
= 0;
11287 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11290 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11292 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11293 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11295 next
= bgp_route_next(dest
);
11296 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11299 itable
= bgp_dest_get_bgp_table_info(dest
);
11300 if (itable
!= NULL
) {
11301 struct prefix_rd prd
;
11302 char rd
[RD_ADDRSTRLEN
];
11304 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11305 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11306 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11307 rd
, next
== NULL
, &output_cum
,
11308 &total_cum
, &json_header_depth
,
11309 show_flags
, RPKI_NOT_BEING_USED
);
11315 if (output_cum
== 0)
11316 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11320 "\nDisplayed %ld routes and %ld total paths\n",
11321 output_cum
, total_cum
);
11323 return CMD_SUCCESS
;
11326 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11327 enum bgp_show_type type
, void *output_arg
,
11328 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11330 struct bgp_table
*table
;
11331 unsigned long json_header_depth
= 0;
11332 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11335 bgp
= bgp_get_default();
11340 vty_out(vty
, "No BGP process is configured\n");
11342 vty_out(vty
, "{}\n");
11343 return CMD_WARNING
;
11346 /* Labeled-unicast routes live in the unicast table. */
11347 if (safi
== SAFI_LABELED_UNICAST
)
11348 safi
= SAFI_UNICAST
;
11350 table
= bgp
->rib
[afi
][safi
];
11351 /* use MPLS and ENCAP specific shows until they are merged */
11352 if (safi
== SAFI_MPLS_VPN
) {
11353 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11354 output_arg
, use_json
);
11357 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11358 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11359 output_arg
, use_json
,
11363 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11364 NULL
, NULL
, &json_header_depth
, show_flags
,
11365 rpki_target_state
);
11368 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11369 safi_t safi
, uint16_t show_flags
)
11371 struct listnode
*node
, *nnode
;
11374 bool route_output
= false;
11375 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11378 vty_out(vty
, "{\n");
11380 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11381 route_output
= true;
11384 vty_out(vty
, ",\n");
11388 vty_out(vty
, "\"%s\":",
11389 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11393 vty_out(vty
, "\nInstance %s:\n",
11394 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11398 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11399 show_flags
, RPKI_NOT_BEING_USED
);
11403 vty_out(vty
, "}\n");
11404 else if (!route_output
)
11405 vty_out(vty
, "%% BGP instance not found\n");
11408 /* Header of detailed BGP route information */
11409 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11410 struct bgp_dest
*dest
,
11411 const struct prefix_rd
*prd
,
11412 afi_t afi
, safi_t safi
, json_object
*json
)
11414 struct bgp_path_info
*pi
;
11415 const struct prefix
*p
;
11417 struct listnode
*node
, *nnode
;
11418 char buf1
[RD_ADDRSTRLEN
];
11422 int accept_own
= 0;
11423 int route_filter_translated_v4
= 0;
11424 int route_filter_v4
= 0;
11425 int route_filter_translated_v6
= 0;
11426 int route_filter_v6
= 0;
11427 int llgr_stale
= 0;
11429 int accept_own_nexthop
= 0;
11432 int no_advertise
= 0;
11436 int has_valid_label
= 0;
11437 mpls_label_t label
= 0;
11438 json_object
*json_adv_to
= NULL
;
11440 p
= bgp_dest_get_prefix(dest
);
11441 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
11443 if (has_valid_label
)
11444 label
= label_pton(&dest
->local_label
);
11446 if (safi
== SAFI_EVPN
) {
11449 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11450 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11452 prd
? ":" : "", (struct prefix_evpn
*)p
);
11454 json_object_string_add(json
, "rd",
11455 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11457 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11462 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11464 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11465 ? prefix_rd2str(prd
, buf1
,
11468 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11472 json_object_string_addf(json
, "prefix", "%pFX", p
);
11473 json_object_int_add(json
, "version", dest
->version
);
11478 if (has_valid_label
) {
11480 json_object_int_add(json
, "localLabel", label
);
11482 vty_out(vty
, "Local label: %d\n", label
);
11486 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11487 vty_out(vty
, "not allocated\n");
11489 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11490 struct community
*picomm
= NULL
;
11492 picomm
= bgp_attr_get_community(pi
->attr
);
11495 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11497 if (bgp_path_suppressed(pi
))
11503 no_advertise
+= community_include(
11504 picomm
, COMMUNITY_NO_ADVERTISE
);
11506 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11508 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11510 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11511 route_filter_translated_v4
+= community_include(
11512 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11513 route_filter_translated_v6
+= community_include(
11514 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11515 route_filter_v4
+= community_include(
11516 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11517 route_filter_v6
+= community_include(
11518 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11520 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11521 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11522 accept_own_nexthop
+= community_include(
11523 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11525 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11526 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11531 vty_out(vty
, "Paths: (%d available", count
);
11533 vty_out(vty
, ", best #%d", best
);
11534 if (safi
== SAFI_UNICAST
) {
11535 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11536 vty_out(vty
, ", table %s",
11539 vty_out(vty
, ", vrf %s",
11543 vty_out(vty
, ", no best path");
11547 ", accept own local route exported and imported in different VRF");
11548 else if (route_filter_translated_v4
)
11550 ", mark translated RTs for VPNv4 route filtering");
11551 else if (route_filter_v4
)
11553 ", attach RT as-is for VPNv4 route filtering");
11554 else if (route_filter_translated_v6
)
11556 ", mark translated RTs for VPNv6 route filtering");
11557 else if (route_filter_v6
)
11559 ", attach RT as-is for VPNv6 route filtering");
11560 else if (llgr_stale
)
11562 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11565 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11566 else if (accept_own_nexthop
)
11568 ", accept local nexthop");
11569 else if (blackhole
)
11570 vty_out(vty
, ", inform peer to blackhole prefix");
11571 else if (no_export
)
11572 vty_out(vty
, ", not advertised to EBGP peer");
11573 else if (no_advertise
)
11574 vty_out(vty
, ", not advertised to any peer");
11576 vty_out(vty
, ", not advertised outside local AS");
11579 ", inform EBGP peer not to advertise to their EBGP peers");
11583 ", Advertisements suppressed by an aggregate.");
11584 vty_out(vty
, ")\n");
11587 /* If we are not using addpath then we can display Advertised to and
11589 * show what peers we advertised the bestpath to. If we are using
11591 * though then we must display Advertised to on a path-by-path basis. */
11592 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11593 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11594 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11595 if (json
&& !json_adv_to
)
11596 json_adv_to
= json_object_new_object();
11598 route_vty_out_advertised_to(
11600 " Advertised to non peer-group peers:\n ",
11607 json_object_object_add(json
, "advertisedTo",
11612 vty_out(vty
, " Not advertised to any peer");
11613 vty_out(vty
, "\n");
11618 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
11619 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11620 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11621 json_object
*json
, enum bgp_path_type pathtype
,
11622 int *display
, enum rpki_states rpki_target_state
)
11624 struct bgp_path_info
*pi
;
11626 char rdbuf
[RD_ADDRSTRLEN
];
11627 json_object
*json_header
= NULL
;
11628 json_object
*json_paths
= NULL
;
11629 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
11631 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11632 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11634 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
11635 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
11636 pi
->peer
, pi
->attr
, p
);
11638 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11639 && rpki_curr_state
!= rpki_target_state
)
11642 if (json
&& !json_paths
) {
11643 /* Instantiate json_paths only if path is valid */
11644 json_paths
= json_object_new_array();
11646 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11647 json_header
= json_object_new_object();
11649 json_header
= json
;
11653 route_vty_out_detail_header(
11654 vty
, bgp
, bgp_node
, pfx_rd
,
11655 AFI_IP
, safi
, json_header
);
11660 if (pathtype
== BGP_PATH_SHOW_ALL
11661 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11662 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11663 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11664 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11665 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11666 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
11667 safi
, rpki_curr_state
, json_paths
);
11670 if (json
&& json_paths
) {
11671 json_object_object_add(json_header
, "paths", json_paths
);
11674 json_object_object_add(json
, rdbuf
, json_header
);
11679 * Return rd based on safi
11681 static const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
11685 case SAFI_MPLS_VPN
:
11688 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
11695 /* Display specified route of BGP table. */
11696 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11697 struct bgp_table
*rib
, const char *ip_str
,
11698 afi_t afi
, safi_t safi
,
11699 enum rpki_states rpki_target_state
,
11700 struct prefix_rd
*prd
, int prefix_check
,
11701 enum bgp_path_type pathtype
, bool use_json
)
11705 struct prefix match
;
11706 struct bgp_dest
*dest
;
11707 struct bgp_dest
*rm
;
11708 struct bgp_table
*table
;
11709 json_object
*json
= NULL
;
11710 json_object
*json_paths
= NULL
;
11712 /* Check IP address argument. */
11713 ret
= str2prefix(ip_str
, &match
);
11715 vty_out(vty
, "address is malformed\n");
11716 return CMD_WARNING
;
11719 match
.family
= afi2family(afi
);
11722 json
= json_object_new_object();
11724 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11725 for (dest
= bgp_table_top(rib
); dest
;
11726 dest
= bgp_route_next(dest
)) {
11727 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11729 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11731 table
= bgp_dest_get_bgp_table_info(dest
);
11735 rm
= bgp_node_match(table
, &match
);
11739 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11741 && rm_p
->prefixlen
!= match
.prefixlen
) {
11742 bgp_dest_unlock_node(rm
);
11746 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11747 bgp
, afi
, safi
, json
, pathtype
,
11748 &display
, rpki_target_state
);
11750 bgp_dest_unlock_node(rm
);
11752 } else if (safi
== SAFI_EVPN
) {
11753 struct bgp_dest
*longest_pfx
;
11754 bool is_exact_pfxlen_match
= false;
11756 for (dest
= bgp_table_top(rib
); dest
;
11757 dest
= bgp_route_next(dest
)) {
11758 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11760 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11762 table
= bgp_dest_get_bgp_table_info(dest
);
11766 longest_pfx
= NULL
;
11767 is_exact_pfxlen_match
= false;
11769 * Search through all the prefixes for a match. The
11770 * pfx's are enumerated in ascending order of pfxlens.
11771 * So, the last pfx match is the longest match. Set
11772 * is_exact_pfxlen_match when we get exact pfxlen match
11774 for (rm
= bgp_table_top(table
); rm
;
11775 rm
= bgp_route_next(rm
)) {
11776 const struct prefix
*rm_p
=
11777 bgp_dest_get_prefix(rm
);
11779 * Get prefixlen of the ip-prefix within type5
11782 if (evpn_type5_prefix_match(rm_p
, &match
)
11786 bgp_evpn_get_type5_prefixlen(
11788 if (type5_pfxlen
== match
.prefixlen
) {
11789 is_exact_pfxlen_match
= true;
11790 bgp_dest_unlock_node(rm
);
11799 if (prefix_check
&& !is_exact_pfxlen_match
)
11803 bgp_dest_lock_node(rm
);
11805 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11806 bgp
, afi
, safi
, json
, pathtype
,
11807 &display
, rpki_target_state
);
11809 bgp_dest_unlock_node(rm
);
11811 } else if (safi
== SAFI_FLOWSPEC
) {
11813 json_paths
= json_object_new_array();
11815 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11816 &match
, prefix_check
,
11822 json_object_object_add(json
, "paths",
11825 json_object_free(json_paths
);
11828 dest
= bgp_node_match(rib
, &match
);
11829 if (dest
!= NULL
) {
11830 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11832 || dest_p
->prefixlen
== match
.prefixlen
) {
11833 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
11834 safi
, json
, pathtype
,
11835 &display
, rpki_target_state
);
11838 bgp_dest_unlock_node(dest
);
11843 vty_json(vty
, json
);
11846 vty_out(vty
, "%% Network not in table\n");
11847 return CMD_WARNING
;
11851 return CMD_SUCCESS
;
11854 /* Display specified route of Main RIB */
11855 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
11856 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
11857 int prefix_check
, enum bgp_path_type pathtype
,
11858 enum rpki_states rpki_target_state
, bool use_json
)
11861 bgp
= bgp_get_default();
11864 vty_out(vty
, "No BGP process is configured\n");
11866 vty_out(vty
, "{}\n");
11867 return CMD_WARNING
;
11871 /* labeled-unicast routes live in the unicast table */
11872 if (safi
== SAFI_LABELED_UNICAST
)
11873 safi
= SAFI_UNICAST
;
11875 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
11876 afi
, safi
, rpki_target_state
, prd
,
11877 prefix_check
, pathtype
, use_json
);
11880 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
11881 struct cmd_token
**argv
, bool exact
, afi_t afi
,
11882 safi_t safi
, bool uj
)
11884 struct lcommunity
*lcom
;
11889 uint16_t show_flags
= 0;
11893 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11895 b
= buffer_new(1024);
11896 for (i
= 0; i
< argc
; i
++) {
11898 buffer_putc(b
, ' ');
11900 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
11902 buffer_putstr(b
, argv
[i
]->arg
);
11906 buffer_putc(b
, '\0');
11908 str
= buffer_getstr(b
);
11911 lcom
= lcommunity_str2com(str
);
11912 XFREE(MTYPE_TMP
, str
);
11914 vty_out(vty
, "%% Large-community malformed\n");
11915 return CMD_WARNING
;
11918 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11919 (exact
? bgp_show_type_lcommunity_exact
11920 : bgp_show_type_lcommunity
),
11921 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
11923 lcommunity_free(&lcom
);
11927 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
11928 const char *lcom
, bool exact
, afi_t afi
,
11929 safi_t safi
, bool uj
)
11931 struct community_list
*list
;
11932 uint16_t show_flags
= 0;
11935 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11938 list
= community_list_lookup(bgp_clist
, lcom
, 0,
11939 LARGE_COMMUNITY_LIST_MASTER
);
11940 if (list
== NULL
) {
11941 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
11943 return CMD_WARNING
;
11946 return bgp_show(vty
, bgp
, afi
, safi
,
11947 (exact
? bgp_show_type_lcommunity_list_exact
11948 : bgp_show_type_lcommunity_list
),
11949 list
, show_flags
, RPKI_NOT_BEING_USED
);
11952 DEFUN (show_ip_bgp_large_community_list
,
11953 show_ip_bgp_large_community_list_cmd
,
11954 "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]",
11958 BGP_INSTANCE_HELP_STR
11960 BGP_SAFI_WITH_LABEL_HELP_STR
11961 "Display routes matching the large-community-list\n"
11962 "large-community-list number\n"
11963 "large-community-list name\n"
11964 "Exact match of the large-communities\n"
11967 afi_t afi
= AFI_IP6
;
11968 safi_t safi
= SAFI_UNICAST
;
11970 bool exact_match
= 0;
11971 struct bgp
*bgp
= NULL
;
11972 bool uj
= use_json(argc
, argv
);
11977 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11980 return CMD_WARNING
;
11982 argv_find(argv
, argc
, "large-community-list", &idx
);
11984 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11986 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11989 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
11990 exact_match
, afi
, safi
, uj
);
11992 DEFUN (show_ip_bgp_large_community
,
11993 show_ip_bgp_large_community_cmd
,
11994 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11998 BGP_INSTANCE_HELP_STR
12000 BGP_SAFI_WITH_LABEL_HELP_STR
12001 "Display routes matching the large-communities\n"
12002 "List of large-community numbers\n"
12003 "Exact match of the large-communities\n"
12006 afi_t afi
= AFI_IP6
;
12007 safi_t safi
= SAFI_UNICAST
;
12009 bool exact_match
= 0;
12010 struct bgp
*bgp
= NULL
;
12011 bool uj
= use_json(argc
, argv
);
12012 uint16_t show_flags
= 0;
12016 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12019 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12022 return CMD_WARNING
;
12024 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12025 if (argv_find(argv
, argc
, "exact-match", &idx
))
12027 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12028 exact_match
, afi
, safi
, uj
);
12030 return bgp_show(vty
, bgp
, afi
, safi
,
12031 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12032 RPKI_NOT_BEING_USED
);
12035 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12036 safi_t safi
, struct json_object
*json_array
);
12037 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12038 safi_t safi
, struct json_object
*json
);
12041 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12042 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12043 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12044 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12046 bool uj
= use_json(argc
, argv
);
12047 struct bgp
*bgp
= NULL
;
12048 safi_t safi
= SAFI_UNICAST
;
12049 afi_t afi
= AFI_IP6
;
12051 struct json_object
*json_all
= NULL
;
12052 struct json_object
*json_afi_safi
= NULL
;
12054 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12057 return CMD_WARNING
;
12060 json_all
= json_object_new_object();
12062 FOREACH_AFI_SAFI (afi
, safi
) {
12064 * So limit output to those afi/safi pairs that
12065 * actually have something interesting in them
12067 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12072 json_afi_safi
= json_object_new_array();
12073 json_object_object_add(
12075 get_afi_safi_str(afi
, safi
, true),
12078 json_afi_safi
= NULL
;
12081 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12085 vty_json(vty
, json_all
);
12087 return CMD_SUCCESS
;
12090 /* BGP route print out function without JSON */
12091 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12092 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12093 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12097 BGP_INSTANCE_HELP_STR
12100 "BGP RIB advertisement statistics\n"
12103 afi_t afi
= AFI_IP6
;
12104 safi_t safi
= SAFI_UNICAST
;
12105 struct bgp
*bgp
= NULL
;
12107 bool uj
= use_json(argc
, argv
);
12108 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12110 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12113 return CMD_WARNING
;
12116 json_afi_safi
= json_object_new_array();
12118 json_afi_safi
= NULL
;
12120 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12123 json
= json_object_new_object();
12124 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12126 vty_json(vty
, json
);
12131 /* BGP route print out function without JSON */
12132 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12133 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12134 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12136 statistics [json]",
12137 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12138 BGP_SAFI_WITH_LABEL_HELP_STR
12139 "BGP RIB advertisement statistics\n" JSON_STR
)
12141 afi_t afi
= AFI_IP6
;
12142 safi_t safi
= SAFI_UNICAST
;
12143 struct bgp
*bgp
= NULL
;
12145 bool uj
= use_json(argc
, argv
);
12146 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12148 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12151 return CMD_WARNING
;
12154 json_afi_safi
= json_object_new_array();
12156 json_afi_safi
= NULL
;
12158 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12161 json
= json_object_new_object();
12162 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12164 vty_json(vty
, json
);
12169 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12170 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12171 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12172 "]] [all$all] dampening parameters [json]",
12173 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12174 BGP_SAFI_WITH_LABEL_HELP_STR
12175 "Display the entries for all address families\n"
12176 "Display detailed information about dampening\n"
12177 "Display detail of configured dampening parameters\n"
12180 afi_t afi
= AFI_IP6
;
12181 safi_t safi
= SAFI_UNICAST
;
12182 struct bgp
*bgp
= NULL
;
12184 uint16_t show_flags
= 0;
12185 bool uj
= use_json(argc
, argv
);
12189 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12192 /* [<ipv4|ipv6> [all]] */
12194 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12195 if (argv_find(argv
, argc
, "ipv4", &idx
))
12196 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12198 if (argv_find(argv
, argc
, "ipv6", &idx
))
12199 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12202 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12205 return CMD_WARNING
;
12207 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12210 /* BGP route print out function */
12211 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12212 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12213 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12217 |dampening <flap-statistics|dampened-paths>\
12218 |community [AA:NN|local-AS|no-advertise|no-export\
12219 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12220 |accept-own|accept-own-nexthop|route-filter-v6\
12221 |route-filter-v4|route-filter-translated-v6\
12222 |route-filter-translated-v4] [exact-match]\
12223 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12224 |filter-list AS_PATH_FILTER_NAME\
12227 |rpki <invalid|valid|notfound>\
12228 |version (1-4294967295)\
12230 |A.B.C.D/M longer-prefixes\
12231 |X:X::X:X/M longer-prefixes\
12232 ] [json$uj [detail$detail] | wide$wide]",
12233 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12234 BGP_SAFI_WITH_LABEL_HELP_STR
12235 "Display the entries for all address families\n"
12236 "Display only routes with non-natural netmasks\n"
12237 "Display detailed information about dampening\n"
12238 "Display flap statistics of routes\n"
12239 "Display paths suppressed due to dampening\n"
12240 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12241 "Do not send outside local AS (well-known community)\n"
12242 "Do not advertise to any peer (well-known community)\n"
12243 "Do not export to next AS (well-known community)\n"
12244 "Graceful shutdown (well-known community)\n"
12245 "Do not export to any peer (well-known community)\n"
12246 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12247 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12248 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12249 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12250 "Should accept VPN route with local nexthop (well-known community)\n"
12251 "RT VPNv6 route filtering (well-known community)\n"
12252 "RT VPNv4 route filtering (well-known community)\n"
12253 "RT translated VPNv6 route filtering (well-known community)\n"
12254 "RT translated VPNv4 route filtering (well-known community)\n"
12255 "Exact match of the communities\n"
12256 "Community-list number\n"
12257 "Community-list name\n"
12258 "Display routes matching the community-list\n"
12259 "Exact match of the communities\n"
12260 "Display routes conforming to the filter-list\n"
12261 "Regular expression access list name\n"
12262 "Display routes conforming to the prefix-list\n"
12263 "Prefix-list name\n"
12264 "Display routes matching the route-map\n"
12265 "A route-map to match on\n"
12266 "RPKI route types\n"
12267 "A valid path as determined by rpki\n"
12268 "A invalid path as determined by rpki\n"
12269 "A path that has no rpki data\n"
12270 "Display prefixes with matching version numbers\n"
12271 "Version number and above\n"
12272 "Display prefixes with matching BGP community alias\n"
12273 "BGP community alias\n"
12275 "Display route and more specific routes\n"
12277 "Display route and more specific routes\n"
12279 "Display detailed version of JSON output\n"
12280 "Increase table width for longer prefixes\n")
12282 afi_t afi
= AFI_IP6
;
12283 safi_t safi
= SAFI_UNICAST
;
12284 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12285 void *output_arg
= NULL
;
12286 struct bgp
*bgp
= NULL
;
12288 int exact_match
= 0;
12289 char *community
= NULL
;
12291 uint16_t show_flags
= 0;
12292 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12297 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12301 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12303 /* [<ipv4|ipv6> [all]] */
12305 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12307 if (argv_find(argv
, argc
, "ipv4", &idx
))
12308 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12310 if (argv_find(argv
, argc
, "ipv6", &idx
))
12311 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12315 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12317 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12320 return CMD_WARNING
;
12322 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12323 sh_type
= bgp_show_type_cidr_only
;
12325 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12326 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12327 sh_type
= bgp_show_type_dampend_paths
;
12328 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12329 sh_type
= bgp_show_type_flap_statistics
;
12332 if (argv_find(argv
, argc
, "community", &idx
)) {
12333 char *maybecomm
= NULL
;
12335 if (idx
+ 1 < argc
) {
12336 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12337 maybecomm
= argv
[idx
+ 1]->arg
;
12339 maybecomm
= argv
[idx
+ 1]->text
;
12342 if (maybecomm
&& !strmatch(maybecomm
, "json")
12343 && !strmatch(maybecomm
, "exact-match"))
12344 community
= maybecomm
;
12346 if (argv_find(argv
, argc
, "exact-match", &idx
))
12350 sh_type
= bgp_show_type_community_all
;
12353 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12354 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12355 struct community_list
*list
;
12357 if (argv_find(argv
, argc
, "exact-match", &idx
))
12360 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12361 COMMUNITY_LIST_MASTER
);
12362 if (list
== NULL
) {
12364 "%% %s is not a valid community-list name\n",
12365 clist_number_or_name
);
12366 return CMD_WARNING
;
12370 sh_type
= bgp_show_type_community_list_exact
;
12372 sh_type
= bgp_show_type_community_list
;
12376 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12377 const char *filter
= argv
[++idx
]->arg
;
12378 struct as_list
*as_list
;
12380 as_list
= as_list_lookup(filter
);
12381 if (as_list
== NULL
) {
12383 "%% %s is not a valid AS-path access-list name\n",
12385 return CMD_WARNING
;
12388 sh_type
= bgp_show_type_filter_list
;
12389 output_arg
= as_list
;
12392 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12393 const char *prefix_list_str
= argv
[++idx
]->arg
;
12394 struct prefix_list
*plist
;
12396 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12397 if (plist
== NULL
) {
12398 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
12400 return CMD_WARNING
;
12403 sh_type
= bgp_show_type_prefix_list
;
12404 output_arg
= plist
;
12407 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12408 const char *rmap_str
= argv
[++idx
]->arg
;
12409 struct route_map
*rmap
;
12411 rmap
= route_map_lookup_by_name(rmap_str
);
12413 vty_out(vty
, "%% %s is not a valid route-map name\n",
12415 return CMD_WARNING
;
12418 sh_type
= bgp_show_type_route_map
;
12422 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12423 sh_type
= bgp_show_type_rpki
;
12424 if (argv_find(argv
, argc
, "valid", &idx
))
12425 rpki_target_state
= RPKI_VALID
;
12426 else if (argv_find(argv
, argc
, "invalid", &idx
))
12427 rpki_target_state
= RPKI_INVALID
;
12430 /* Display prefixes with matching version numbers */
12431 if (argv_find(argv
, argc
, "version", &idx
)) {
12432 sh_type
= bgp_show_type_prefix_version
;
12433 output_arg
= argv
[idx
+ 1]->arg
;
12436 /* Display prefixes with matching BGP community alias */
12437 if (argv_find(argv
, argc
, "alias", &idx
)) {
12438 sh_type
= bgp_show_type_community_alias
;
12439 output_arg
= argv
[idx
+ 1]->arg
;
12442 /* prefix-longer */
12443 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12444 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12445 const char *prefix_str
= argv
[idx
]->arg
;
12447 if (!str2prefix(prefix_str
, &p
)) {
12448 vty_out(vty
, "%% Malformed Prefix\n");
12449 return CMD_WARNING
;
12452 sh_type
= bgp_show_type_prefix_longer
;
12457 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12459 return bgp_show_community(vty
, bgp
, community
,
12460 exact_match
, afi
, safi
,
12463 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12464 output_arg
, show_flags
,
12465 rpki_target_state
);
12467 struct listnode
*node
;
12469 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12473 vty_out(vty
, "{\n");
12475 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12476 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12477 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12480 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12481 FOREACH_SAFI (safi
) {
12482 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12490 vty_out(vty
, ",\n");
12491 vty_out(vty
, "\"%s\":{\n",
12492 get_afi_safi_str(afi
,
12497 "\nFor address family: %s\n",
12503 bgp_show_community(
12504 vty
, abgp
, community
,
12505 exact_match
, afi
, safi
,
12508 bgp_show(vty
, abgp
, afi
, safi
,
12509 sh_type
, output_arg
,
12511 rpki_target_state
);
12513 vty_out(vty
, "}\n");
12517 /* show <ip> bgp all: for each AFI and SAFI*/
12518 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12519 FOREACH_AFI_SAFI (afi
, safi
) {
12520 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12528 vty_out(vty
, ",\n");
12530 vty_out(vty
, "\"%s\":{\n",
12531 get_afi_safi_str(afi
,
12536 "\nFor address family: %s\n",
12542 bgp_show_community(
12543 vty
, abgp
, community
,
12544 exact_match
, afi
, safi
,
12547 bgp_show(vty
, abgp
, afi
, safi
,
12548 sh_type
, output_arg
,
12550 rpki_target_state
);
12552 vty_out(vty
, "}\n");
12557 vty_out(vty
, "}\n");
12559 return CMD_SUCCESS
;
12562 DEFUN (show_ip_bgp_route
,
12563 show_ip_bgp_route_cmd
,
12564 "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]",
12568 BGP_INSTANCE_HELP_STR
12570 BGP_SAFI_WITH_LABEL_HELP_STR
12571 "Network in the BGP routing table to display\n"
12573 "Network in the BGP routing table to display\n"
12575 "Display only the bestpath\n"
12576 "Display only multipaths\n"
12577 "Display only paths that match the specified rpki state\n"
12578 "A valid path as determined by rpki\n"
12579 "A invalid path as determined by rpki\n"
12580 "A path that has no rpki data\n"
12583 int prefix_check
= 0;
12585 afi_t afi
= AFI_IP6
;
12586 safi_t safi
= SAFI_UNICAST
;
12587 char *prefix
= NULL
;
12588 struct bgp
*bgp
= NULL
;
12589 enum bgp_path_type path_type
;
12590 bool uj
= use_json(argc
, argv
);
12594 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12597 return CMD_WARNING
;
12601 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12602 return CMD_WARNING
;
12605 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12606 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12607 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12609 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12610 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12613 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12614 && afi
!= AFI_IP6
) {
12616 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12617 return CMD_WARNING
;
12619 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12620 && afi
!= AFI_IP
) {
12622 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12623 return CMD_WARNING
;
12626 prefix
= argv
[idx
]->arg
;
12628 /* [<bestpath|multipath>] */
12629 if (argv_find(argv
, argc
, "bestpath", &idx
))
12630 path_type
= BGP_PATH_SHOW_BESTPATH
;
12631 else if (argv_find(argv
, argc
, "multipath", &idx
))
12632 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12634 path_type
= BGP_PATH_SHOW_ALL
;
12636 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12637 path_type
, RPKI_NOT_BEING_USED
, uj
);
12640 DEFUN (show_ip_bgp_regexp
,
12641 show_ip_bgp_regexp_cmd
,
12642 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12646 BGP_INSTANCE_HELP_STR
12648 BGP_SAFI_WITH_LABEL_HELP_STR
12649 "Display routes matching the AS path regular expression\n"
12650 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12653 afi_t afi
= AFI_IP6
;
12654 safi_t safi
= SAFI_UNICAST
;
12655 struct bgp
*bgp
= NULL
;
12656 bool uj
= use_json(argc
, argv
);
12657 char *regstr
= NULL
;
12660 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12663 return CMD_WARNING
;
12665 // get index of regex
12666 if (argv_find(argv
, argc
, "REGEX", &idx
))
12667 regstr
= argv
[idx
]->arg
;
12670 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12671 bgp_show_type_regexp
, uj
);
12674 DEFPY (show_ip_bgp_instance_all
,
12675 show_ip_bgp_instance_all_cmd
,
12676 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12680 BGP_INSTANCE_ALL_HELP_STR
12682 BGP_SAFI_WITH_LABEL_HELP_STR
12684 "Increase table width for longer prefixes\n")
12686 afi_t afi
= AFI_IP6
;
12687 safi_t safi
= SAFI_UNICAST
;
12688 struct bgp
*bgp
= NULL
;
12690 uint16_t show_flags
= 0;
12694 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12698 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12700 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12703 return CMD_WARNING
;
12705 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12706 return CMD_SUCCESS
;
12709 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12710 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12715 uint16_t show_flags
= 0;
12718 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12720 if (!config_bgp_aspath_validate(regstr
)) {
12721 vty_out(vty
, "Invalid character in REGEX %s\n",
12723 return CMD_WARNING_CONFIG_FAILED
;
12726 regex
= bgp_regcomp(regstr
);
12728 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12729 return CMD_WARNING
;
12732 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
12733 RPKI_NOT_BEING_USED
);
12734 bgp_regex_free(regex
);
12738 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12739 const char *comstr
, int exact
, afi_t afi
,
12740 safi_t safi
, uint16_t show_flags
)
12742 struct community
*com
;
12745 com
= community_str2com(comstr
);
12747 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12748 return CMD_WARNING
;
12751 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12752 (exact
? bgp_show_type_community_exact
12753 : bgp_show_type_community
),
12754 com
, show_flags
, RPKI_NOT_BEING_USED
);
12755 community_free(&com
);
12761 BGP_STATS_MAXBITLEN
= 0,
12763 BGP_STATS_PREFIXES
,
12765 BGP_STATS_UNAGGREGATEABLE
,
12766 BGP_STATS_MAX_AGGREGATEABLE
,
12767 BGP_STATS_AGGREGATES
,
12769 BGP_STATS_ASPATH_COUNT
,
12770 BGP_STATS_ASPATH_MAXHOPS
,
12771 BGP_STATS_ASPATH_TOTHOPS
,
12772 BGP_STATS_ASPATH_MAXSIZE
,
12773 BGP_STATS_ASPATH_TOTSIZE
,
12774 BGP_STATS_ASN_HIGHEST
,
12778 #define TABLE_STATS_IDX_VTY 0
12779 #define TABLE_STATS_IDX_JSON 1
12781 static const char *table_stats_strs
[][2] = {
12782 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12783 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12784 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12785 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12786 "unaggregateablePrefixes"},
12787 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12788 "maximumAggregateablePrefixes"},
12789 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12790 "bgpAggregateAdvertisements"},
12791 [BGP_STATS_SPACE
] = {"Address space advertised",
12792 "addressSpaceAdvertised"},
12793 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12794 "advertisementsWithPaths"},
12795 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12797 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12799 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12800 "averageAsPathLengthHops"},
12801 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12802 "averageAsPathSizeBytes"},
12803 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12804 [BGP_STATS_MAX
] = {NULL
, NULL
}
12807 struct bgp_table_stats
{
12808 struct bgp_table
*table
;
12809 unsigned long long counts
[BGP_STATS_MAX
];
12810 double total_space
;
12813 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
12814 struct bgp_table_stats
*ts
, unsigned int space
)
12816 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
12817 struct bgp_path_info
*pi
;
12818 const struct prefix
*rn_p
;
12820 if (!bgp_dest_has_bgp_path_info_data(dest
))
12823 rn_p
= bgp_dest_get_prefix(dest
);
12824 ts
->counts
[BGP_STATS_PREFIXES
]++;
12825 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
12827 /* check if the prefix is included by any other announcements */
12828 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
12829 pdest
= bgp_dest_parent_nolock(pdest
);
12831 if (pdest
== NULL
|| pdest
== top
) {
12832 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
12833 /* announced address space */
12835 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
12836 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
12837 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
12840 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
12841 ts
->counts
[BGP_STATS_RIB
]++;
12843 if (CHECK_FLAG(pi
->attr
->flag
,
12844 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
12845 ts
->counts
[BGP_STATS_AGGREGATES
]++;
12847 /* as-path stats */
12848 if (pi
->attr
->aspath
) {
12849 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
12850 unsigned int size
= aspath_size(pi
->attr
->aspath
);
12851 as_t highest
= aspath_highest(pi
->attr
->aspath
);
12853 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
12855 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
12856 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
12858 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
12859 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
12861 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
12862 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
12863 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
12864 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
12869 static void bgp_table_stats_walker(struct thread
*t
)
12871 struct bgp_dest
*dest
, *ndest
;
12872 struct bgp_dest
*top
;
12873 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
12874 unsigned int space
= 0;
12876 if (!(top
= bgp_table_top(ts
->table
)))
12879 switch (ts
->table
->afi
) {
12881 space
= IPV4_MAX_BITLEN
;
12884 space
= IPV6_MAX_BITLEN
;
12887 space
= EVPN_ROUTE_PREFIXLEN
;
12893 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
12895 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
12896 if (ts
->table
->safi
== SAFI_MPLS_VPN
12897 || ts
->table
->safi
== SAFI_ENCAP
12898 || ts
->table
->safi
== SAFI_EVPN
) {
12899 struct bgp_table
*table
;
12901 table
= bgp_dest_get_bgp_table_info(dest
);
12905 top
= bgp_table_top(table
);
12906 for (ndest
= bgp_table_top(table
); ndest
;
12907 ndest
= bgp_route_next(ndest
))
12908 bgp_table_stats_rn(ndest
, top
, ts
, space
);
12910 bgp_table_stats_rn(dest
, top
, ts
, space
);
12915 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
12916 struct json_object
*json_array
)
12918 struct listnode
*node
, *nnode
;
12921 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
12922 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12925 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12926 safi_t safi
, struct json_object
*json_array
)
12928 struct bgp_table_stats ts
;
12930 int ret
= CMD_SUCCESS
;
12932 struct json_object
*json
= NULL
;
12935 json
= json_object_new_object();
12937 if (!bgp
->rib
[afi
][safi
]) {
12938 char warning_msg
[50];
12940 snprintf(warning_msg
, sizeof(warning_msg
),
12941 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
12945 vty_out(vty
, "%s\n", warning_msg
);
12947 json_object_string_add(json
, "warning", warning_msg
);
12950 goto end_table_stats
;
12954 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
12955 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
12957 json_object_string_add(json
, "instance", bgp
->name_pretty
);
12959 /* labeled-unicast routes live in the unicast table */
12960 if (safi
== SAFI_LABELED_UNICAST
)
12961 safi
= SAFI_UNICAST
;
12963 memset(&ts
, 0, sizeof(ts
));
12964 ts
.table
= bgp
->rib
[afi
][safi
];
12965 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
12967 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
12968 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
12969 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
12973 case BGP_STATS_ASPATH_TOTHOPS
:
12974 case BGP_STATS_ASPATH_TOTSIZE
:
12977 temp_buf
, sizeof(temp_buf
), "%12.2f",
12979 ? (float)ts
.counts
[i
]
12981 [BGP_STATS_ASPATH_COUNT
]
12983 vty_out(vty
, "%-30s: %s",
12984 table_stats_strs
[i
]
12985 [TABLE_STATS_IDX_VTY
],
12988 json_object_double_add(
12990 table_stats_strs
[i
]
12991 [TABLE_STATS_IDX_JSON
],
12993 ? (double)ts
.counts
[i
]
12994 / (double)ts
.counts
12995 [BGP_STATS_ASPATH_COUNT
]
12999 case BGP_STATS_TOTPLEN
:
13002 temp_buf
, sizeof(temp_buf
), "%12.2f",
13004 ? (float)ts
.counts
[i
]
13006 [BGP_STATS_PREFIXES
]
13008 vty_out(vty
, "%-30s: %s",
13009 table_stats_strs
[i
]
13010 [TABLE_STATS_IDX_VTY
],
13013 json_object_double_add(
13015 table_stats_strs
[i
]
13016 [TABLE_STATS_IDX_JSON
],
13018 ? (double)ts
.counts
[i
]
13019 / (double)ts
.counts
13020 [BGP_STATS_PREFIXES
]
13024 case BGP_STATS_SPACE
:
13026 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13028 vty_out(vty
, "%-30s: %s\n",
13029 table_stats_strs
[i
]
13030 [TABLE_STATS_IDX_VTY
],
13033 json_object_double_add(
13035 table_stats_strs
[i
]
13036 [TABLE_STATS_IDX_JSON
],
13037 (double)ts
.total_space
);
13039 if (afi
== AFI_IP6
) {
13041 snprintf(temp_buf
, sizeof(temp_buf
),
13044 * pow(2.0, -128 + 32));
13045 vty_out(vty
, "%30s: %s\n",
13046 "/32 equivalent %s\n",
13049 json_object_double_add(
13050 json
, "/32equivalent",
13051 (double)(ts
.total_space
13056 snprintf(temp_buf
, sizeof(temp_buf
),
13059 * pow(2.0, -128 + 48));
13060 vty_out(vty
, "%30s: %s\n",
13061 "/48 equivalent %s\n",
13064 json_object_double_add(
13065 json
, "/48equivalent",
13066 (double)(ts
.total_space
13072 snprintf(temp_buf
, sizeof(temp_buf
),
13074 ts
.total_space
* 100.
13076 vty_out(vty
, "%30s: %s\n",
13077 "% announced ", temp_buf
);
13079 json_object_double_add(
13080 json
, "%announced",
13081 (double)(ts
.total_space
* 100.
13085 snprintf(temp_buf
, sizeof(temp_buf
),
13088 * pow(2.0, -32 + 8));
13089 vty_out(vty
, "%30s: %s\n",
13090 "/8 equivalent ", temp_buf
);
13092 json_object_double_add(
13093 json
, "/8equivalent",
13094 (double)(ts
.total_space
13095 * pow(2.0, -32 + 8)));
13098 snprintf(temp_buf
, sizeof(temp_buf
),
13101 * pow(2.0, -32 + 24));
13102 vty_out(vty
, "%30s: %s\n",
13103 "/24 equivalent ", temp_buf
);
13105 json_object_double_add(
13106 json
, "/24equivalent",
13107 (double)(ts
.total_space
13108 * pow(2.0, -32 + 24)));
13114 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13116 vty_out(vty
, "%-30s: %s",
13117 table_stats_strs
[i
]
13118 [TABLE_STATS_IDX_VTY
],
13121 json_object_int_add(
13123 table_stats_strs
[i
]
13124 [TABLE_STATS_IDX_JSON
],
13129 vty_out(vty
, "\n");
13133 json_object_array_add(json_array
, json
);
13137 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13138 safi_t safi
, struct json_object
*json_array
)
13141 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13142 return CMD_SUCCESS
;
13145 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13157 PCOUNT_BPATH_SELECTED
,
13158 PCOUNT_PFCNT
, /* the figure we display to users */
13162 static const char *const pcount_strs
[] = {
13163 [PCOUNT_ADJ_IN
] = "Adj-in",
13164 [PCOUNT_DAMPED
] = "Damped",
13165 [PCOUNT_REMOVED
] = "Removed",
13166 [PCOUNT_HISTORY
] = "History",
13167 [PCOUNT_STALE
] = "Stale",
13168 [PCOUNT_VALID
] = "Valid",
13169 [PCOUNT_ALL
] = "All RIB",
13170 [PCOUNT_COUNTED
] = "PfxCt counted",
13171 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13172 [PCOUNT_PFCNT
] = "Useable",
13173 [PCOUNT_MAX
] = NULL
,
13176 struct peer_pcounts
{
13177 unsigned int count
[PCOUNT_MAX
];
13178 const struct peer
*peer
;
13179 const struct bgp_table
*table
;
13183 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13185 const struct bgp_adj_in
*ain
;
13186 const struct bgp_path_info
*pi
;
13187 const struct peer
*peer
= pc
->peer
;
13189 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13190 if (ain
->peer
== peer
)
13191 pc
->count
[PCOUNT_ADJ_IN
]++;
13193 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13195 if (pi
->peer
!= peer
)
13198 pc
->count
[PCOUNT_ALL
]++;
13200 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13201 pc
->count
[PCOUNT_DAMPED
]++;
13202 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13203 pc
->count
[PCOUNT_HISTORY
]++;
13204 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13205 pc
->count
[PCOUNT_REMOVED
]++;
13206 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13207 pc
->count
[PCOUNT_STALE
]++;
13208 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13209 pc
->count
[PCOUNT_VALID
]++;
13210 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13211 pc
->count
[PCOUNT_PFCNT
]++;
13212 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13213 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13215 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13216 pc
->count
[PCOUNT_COUNTED
]++;
13217 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13219 EC_LIB_DEVELOPMENT
,
13220 "Attempting to count but flags say it is unusable");
13222 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13224 EC_LIB_DEVELOPMENT
,
13225 "Not counted but flags say we should");
13230 static void bgp_peer_count_walker(struct thread
*t
)
13232 struct bgp_dest
*rn
, *rm
;
13233 const struct bgp_table
*table
;
13234 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13236 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13237 || pc
->safi
== SAFI_EVPN
) {
13238 /* Special handling for 2-level routing tables. */
13239 for (rn
= bgp_table_top(pc
->table
); rn
;
13240 rn
= bgp_route_next(rn
)) {
13241 table
= bgp_dest_get_bgp_table_info(rn
);
13243 for (rm
= bgp_table_top(table
); rm
;
13244 rm
= bgp_route_next(rm
))
13245 bgp_peer_count_proc(rm
, pc
);
13248 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13249 bgp_peer_count_proc(rn
, pc
);
13252 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13253 safi_t safi
, bool use_json
)
13255 struct peer_pcounts pcounts
= {.peer
= peer
};
13257 json_object
*json
= NULL
;
13258 json_object
*json_loop
= NULL
;
13261 json
= json_object_new_object();
13262 json_loop
= json_object_new_object();
13265 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13266 || !peer
->bgp
->rib
[afi
][safi
]) {
13268 json_object_string_add(
13270 "No such neighbor or address family");
13271 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13272 json_object_free(json
);
13273 json_object_free(json_loop
);
13275 vty_out(vty
, "%% No such neighbor or address family\n");
13277 return CMD_WARNING
;
13280 memset(&pcounts
, 0, sizeof(pcounts
));
13281 pcounts
.peer
= peer
;
13282 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13283 pcounts
.safi
= safi
;
13285 /* in-place call via thread subsystem so as to record execution time
13286 * stats for the thread-walk (i.e. ensure this can't be blamed on
13287 * on just vty_read()).
13289 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13292 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13293 json_object_string_add(json
, "multiProtocol",
13294 get_afi_safi_str(afi
, safi
, true));
13295 json_object_int_add(json
, "pfxCounter",
13296 peer
->pcount
[afi
][safi
]);
13298 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13299 json_object_int_add(json_loop
, pcount_strs
[i
],
13302 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13304 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13305 json_object_string_add(json
, "pfxctDriftFor",
13307 json_object_string_add(
13308 json
, "recommended",
13309 "Please report this bug, with the above command output");
13311 vty_json(vty
, json
);
13315 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13316 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13317 peer
->hostname
, peer
->host
,
13318 get_afi_safi_str(afi
, safi
, false));
13320 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13321 get_afi_safi_str(afi
, safi
, false));
13324 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13325 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13327 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13328 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13331 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13332 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13334 "Please report this bug, with the above command output\n");
13338 return CMD_SUCCESS
;
13341 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13342 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13343 "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]",
13347 BGP_INSTANCE_HELP_STR
13350 "Detailed information on TCP and BGP neighbor connections\n"
13351 "Neighbor to display information about\n"
13352 "Neighbor to display information about\n"
13353 "Neighbor on BGP configured interface\n"
13354 "Display detailed prefix count information\n"
13357 afi_t afi
= AFI_IP6
;
13358 safi_t safi
= SAFI_UNICAST
;
13361 struct bgp
*bgp
= NULL
;
13362 bool uj
= use_json(argc
, argv
);
13367 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13370 return CMD_WARNING
;
13372 argv_find(argv
, argc
, "neighbors", &idx
);
13373 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13375 return CMD_WARNING
;
13377 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13380 #ifdef KEEP_OLD_VPN_COMMANDS
13381 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13382 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13383 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13388 "Display information about all VPNv4 NLRIs\n"
13389 "Detailed information on TCP and BGP neighbor connections\n"
13390 "Neighbor to display information about\n"
13391 "Neighbor to display information about\n"
13392 "Neighbor on BGP configured interface\n"
13393 "Display detailed prefix count information\n"
13398 bool uj
= use_json(argc
, argv
);
13400 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13402 return CMD_WARNING
;
13404 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13407 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13408 show_ip_bgp_vpn_all_route_prefix_cmd
,
13409 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13414 "Display information about all VPNv4 NLRIs\n"
13415 "Network in the BGP routing table to display\n"
13416 "Network in the BGP routing table to display\n"
13420 char *network
= NULL
;
13421 struct bgp
*bgp
= bgp_get_default();
13423 vty_out(vty
, "Can't find default instance\n");
13424 return CMD_WARNING
;
13427 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13428 network
= argv
[idx
]->arg
;
13429 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13430 network
= argv
[idx
]->arg
;
13432 vty_out(vty
, "Unable to figure out Network\n");
13433 return CMD_WARNING
;
13436 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13437 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13438 use_json(argc
, argv
));
13440 #endif /* KEEP_OLD_VPN_COMMANDS */
13442 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13443 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13444 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13449 "Network in the BGP routing table to display\n"
13450 "Network in the BGP routing table to display\n"
13451 "Network in the BGP routing table to display\n"
13452 "Network in the BGP routing table to display\n"
13456 char *network
= NULL
;
13457 int prefix_check
= 0;
13459 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13460 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13461 network
= argv
[idx
]->arg
;
13462 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13463 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13464 network
= argv
[idx
]->arg
;
13467 vty_out(vty
, "Unable to figure out Network\n");
13468 return CMD_WARNING
;
13470 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13471 prefix_check
, BGP_PATH_SHOW_ALL
,
13472 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13475 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
13476 struct bgp_table
*table
, int *header1
,
13477 int *header2
, json_object
*json
,
13478 json_object
*json_scode
,
13479 json_object
*json_ocode
, bool wide
)
13481 uint64_t version
= table
? table
->version
: 0;
13485 json_object_int_add(json
, "bgpTableVersion", version
);
13486 json_object_string_addf(json
, "bgpLocalRouterId",
13487 "%pI4", &bgp
->router_id
);
13488 json_object_int_add(json
, "defaultLocPrf",
13489 bgp
->default_local_pref
);
13490 json_object_int_add(json
, "localAS", bgp
->as
);
13491 json_object_object_add(json
, "bgpStatusCodes",
13493 json_object_object_add(json
, "bgpOriginCodes",
13497 "BGP table version is %" PRIu64
13498 ", local router ID is %pI4, vrf id ",
13499 version
, &bgp
->router_id
);
13500 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13501 vty_out(vty
, "%s", VRFID_NONE_STR
);
13503 vty_out(vty
, "%u", bgp
->vrf_id
);
13504 vty_out(vty
, "\n");
13505 vty_out(vty
, "Default local pref %u, ",
13506 bgp
->default_local_pref
);
13507 vty_out(vty
, "local AS %u\n", bgp
->as
);
13508 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13509 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13510 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13511 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13517 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13518 : BGP_SHOW_HEADER
));
13524 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13525 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13526 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13527 json_object
*json_scode
, json_object
*json_ocode
,
13528 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13529 unsigned long *output_count
, unsigned long *filtered_count
)
13531 struct bgp_adj_in
*ain
;
13532 struct bgp_adj_out
*adj
;
13533 struct bgp_dest
*dest
;
13537 struct update_subgroup
*subgrp
;
13538 struct peer_af
*paf
;
13539 bool route_filtered
;
13540 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13541 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13542 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13543 || (safi
== SAFI_EVPN
))
13549 subgrp
= peer_subgroup(peer
, afi
, safi
);
13551 if (type
== bgp_show_adj_route_advertised
&& subgrp
13552 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13554 json_object_int_add(json
, "bgpTableVersion",
13556 json_object_string_addf(json
, "bgpLocalRouterId",
13557 "%pI4", &bgp
->router_id
);
13558 json_object_int_add(json
, "defaultLocPrf",
13559 bgp
->default_local_pref
);
13560 json_object_int_add(json
, "localAS", bgp
->as
);
13561 json_object_object_add(json
, "bgpStatusCodes",
13563 json_object_object_add(json
, "bgpOriginCodes",
13565 json_object_string_add(
13566 json
, "bgpOriginatingDefaultNetwork",
13567 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13570 "BGP table version is %" PRIu64
13571 ", local router ID is %pI4, vrf id ",
13572 table
->version
, &bgp
->router_id
);
13573 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13574 vty_out(vty
, "%s", VRFID_NONE_STR
);
13576 vty_out(vty
, "%u", bgp
->vrf_id
);
13577 vty_out(vty
, "\n");
13578 vty_out(vty
, "Default local pref %u, ",
13579 bgp
->default_local_pref
);
13580 vty_out(vty
, "local AS %u\n", bgp
->as
);
13581 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13582 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13583 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13584 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13586 vty_out(vty
, "Originating default network %s\n\n",
13587 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13592 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13593 if (type
== bgp_show_adj_route_received
13594 || type
== bgp_show_adj_route_filtered
) {
13595 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13596 if (ain
->peer
!= peer
)
13599 show_adj_route_header(vty
, bgp
, table
, header1
,
13600 header2
, json
, json_scode
,
13603 if ((safi
== SAFI_MPLS_VPN
)
13604 || (safi
== SAFI_ENCAP
)
13605 || (safi
== SAFI_EVPN
)) {
13607 json_object_string_add(
13608 json_ar
, "rd", rd_str
);
13609 else if (show_rd
&& rd_str
) {
13611 "Route Distinguisher: %s\n",
13618 route_filtered
= false;
13620 /* Filter prefix using distribute list,
13621 * filter list or prefix list
13623 const struct prefix
*rn_p
=
13624 bgp_dest_get_prefix(dest
);
13625 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13628 route_filtered
= true;
13630 /* Filter prefix using route-map */
13631 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13632 safi
, rmap_name
, NULL
,
13635 if (type
== bgp_show_adj_route_filtered
&&
13636 !route_filtered
&& ret
!= RMAP_DENY
) {
13637 bgp_attr_flush(&attr
);
13641 if (type
== bgp_show_adj_route_received
13642 && (route_filtered
|| ret
== RMAP_DENY
))
13643 (*filtered_count
)++;
13645 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
13646 use_json
, json_ar
, wide
);
13647 bgp_attr_flush(&attr
);
13650 } else if (type
== bgp_show_adj_route_advertised
) {
13651 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13652 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13653 if (paf
->peer
!= peer
|| !adj
->attr
)
13656 show_adj_route_header(vty
, bgp
, table
,
13661 const struct prefix
*rn_p
=
13662 bgp_dest_get_prefix(dest
);
13665 ret
= bgp_output_modifier(
13666 peer
, rn_p
, &attr
, afi
, safi
,
13669 if (ret
!= RMAP_DENY
) {
13670 if ((safi
== SAFI_MPLS_VPN
)
13671 || (safi
== SAFI_ENCAP
)
13672 || (safi
== SAFI_EVPN
)) {
13674 json_object_string_add(
13681 "Route Distinguisher: %s\n",
13687 vty
, dest
, rn_p
, &attr
,
13688 safi
, use_json
, json_ar
,
13692 (*filtered_count
)++;
13695 bgp_attr_flush(&attr
);
13697 } else if (type
== bgp_show_adj_route_bestpath
) {
13698 struct bgp_path_info
*pi
;
13700 show_adj_route_header(vty
, bgp
, table
, header1
, header2
,
13701 json
, json_scode
, json_ocode
,
13704 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13706 if (pi
->peer
!= peer
)
13709 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13712 route_vty_out_tmp(vty
, dest
,
13713 bgp_dest_get_prefix(dest
),
13714 pi
->attr
, safi
, use_json
,
13722 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13723 safi_t safi
, enum bgp_show_adj_route_type type
,
13724 const char *rmap_name
, uint16_t show_flags
)
13727 struct bgp_table
*table
;
13728 json_object
*json
= NULL
;
13729 json_object
*json_scode
= NULL
;
13730 json_object
*json_ocode
= NULL
;
13731 json_object
*json_ar
= NULL
;
13732 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13734 /* Init BGP headers here so they're only displayed once
13735 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13741 * Initialize variables for each RD
13742 * All prefixes under an RD is aggregated within "json_routes"
13744 char rd_str
[BUFSIZ
] = {0};
13745 json_object
*json_routes
= NULL
;
13748 /* For 2-tier tables, prefix counts need to be
13749 * maintained across multiple runs of show_adj_route()
13751 unsigned long output_count_per_rd
;
13752 unsigned long filtered_count_per_rd
;
13753 unsigned long output_count
= 0;
13754 unsigned long filtered_count
= 0;
13757 json
= json_object_new_object();
13758 json_ar
= json_object_new_object();
13759 json_scode
= json_object_new_object();
13760 json_ocode
= json_object_new_object();
13762 json_object_string_add(json_scode
, "suppressed", "s");
13763 json_object_string_add(json_scode
, "damped", "d");
13764 json_object_string_add(json_scode
, "history", "h");
13765 json_object_string_add(json_scode
, "valid", "*");
13766 json_object_string_add(json_scode
, "best", ">");
13767 json_object_string_add(json_scode
, "multipath", "=");
13768 json_object_string_add(json_scode
, "internal", "i");
13769 json_object_string_add(json_scode
, "ribFailure", "r");
13770 json_object_string_add(json_scode
, "stale", "S");
13771 json_object_string_add(json_scode
, "removed", "R");
13773 json_object_string_add(json_ocode
, "igp", "i");
13774 json_object_string_add(json_ocode
, "egp", "e");
13775 json_object_string_add(json_ocode
, "incomplete", "?");
13778 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13780 json_object_string_add(
13782 "No such neighbor or address family");
13783 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13784 json_object_free(json
);
13785 json_object_free(json_ar
);
13786 json_object_free(json_scode
);
13787 json_object_free(json_ocode
);
13789 vty_out(vty
, "%% No such neighbor or address family\n");
13791 return CMD_WARNING
;
13794 if ((type
== bgp_show_adj_route_received
13795 || type
== bgp_show_adj_route_filtered
)
13796 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
13797 PEER_FLAG_SOFT_RECONFIG
)) {
13799 json_object_string_add(
13801 "Inbound soft reconfiguration not enabled");
13802 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13803 json_object_free(json
);
13804 json_object_free(json_ar
);
13805 json_object_free(json_scode
);
13806 json_object_free(json_ocode
);
13809 "%% Inbound soft reconfiguration not enabled\n");
13811 return CMD_WARNING
;
13816 /* labeled-unicast routes live in the unicast table */
13817 if (safi
== SAFI_LABELED_UNICAST
)
13818 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
13820 table
= bgp
->rib
[afi
][safi
];
13822 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13823 || (safi
== SAFI_EVPN
)) {
13825 struct bgp_dest
*dest
;
13827 for (dest
= bgp_table_top(table
); dest
;
13828 dest
= bgp_route_next(dest
)) {
13829 table
= bgp_dest_get_bgp_table_info(dest
);
13833 output_count_per_rd
= 0;
13834 filtered_count_per_rd
= 0;
13837 json_routes
= json_object_new_object();
13839 const struct prefix_rd
*prd
;
13840 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13843 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
13845 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
13846 rmap_name
, json
, json_routes
, json_scode
,
13847 json_ocode
, show_flags
, &header1
,
13848 &header2
, rd_str
, &output_count_per_rd
,
13849 &filtered_count_per_rd
);
13851 /* Don't include an empty RD in the output! */
13852 if (json_routes
&& (output_count_per_rd
> 0))
13853 json_object_object_add(json_ar
, rd_str
,
13856 output_count
+= output_count_per_rd
;
13857 filtered_count
+= filtered_count_per_rd
;
13860 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
13861 json
, json_ar
, json_scode
, json_ocode
,
13862 show_flags
, &header1
, &header2
, rd_str
,
13863 &output_count
, &filtered_count
);
13866 if (type
== bgp_show_adj_route_advertised
)
13867 json_object_object_add(json
, "advertisedRoutes",
13870 json_object_object_add(json
, "receivedRoutes", json_ar
);
13871 json_object_int_add(json
, "totalPrefixCounter", output_count
);
13872 json_object_int_add(json
, "filteredPrefixCounter",
13876 * These fields only give up ownership to `json` when `header1`
13877 * is used (set to zero). See code in `show_adj_route` and
13878 * `show_adj_route_header`.
13880 if (header1
== 1) {
13881 json_object_free(json_scode
);
13882 json_object_free(json_ocode
);
13885 vty_json(vty
, json
);
13886 } else if (output_count
> 0) {
13887 if (filtered_count
> 0)
13889 "\nTotal number of prefixes %ld (%ld filtered)\n",
13890 output_count
, filtered_count
);
13892 vty_out(vty
, "\nTotal number of prefixes %ld\n",
13896 return CMD_SUCCESS
;
13899 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
13900 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
13901 "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]",
13905 BGP_INSTANCE_HELP_STR
13907 BGP_SAFI_WITH_LABEL_HELP_STR
13908 "Detailed information on TCP and BGP neighbor connections\n"
13909 "Neighbor to display information about\n"
13910 "Neighbor to display information about\n"
13911 "Neighbor on BGP configured interface\n"
13912 "Display the routes selected by best path\n"
13914 "Increase table width for longer prefixes\n")
13916 afi_t afi
= AFI_IP6
;
13917 safi_t safi
= SAFI_UNICAST
;
13918 char *rmap_name
= NULL
;
13919 char *peerstr
= NULL
;
13920 struct bgp
*bgp
= NULL
;
13922 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
13924 uint16_t show_flags
= 0;
13927 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13930 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13932 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13936 return CMD_WARNING
;
13938 argv_find(argv
, argc
, "neighbors", &idx
);
13939 peerstr
= argv
[++idx
]->arg
;
13941 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13943 return CMD_WARNING
;
13945 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13949 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
13950 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
13951 "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]",
13955 BGP_INSTANCE_HELP_STR
13957 BGP_SAFI_WITH_LABEL_HELP_STR
13958 "Display the entries for all address families\n"
13959 "Detailed information on TCP and BGP neighbor connections\n"
13960 "Neighbor to display information about\n"
13961 "Neighbor to display information about\n"
13962 "Neighbor on BGP configured interface\n"
13963 "Display the routes advertised to a BGP neighbor\n"
13964 "Display the received routes from neighbor\n"
13965 "Display the filtered routes received from neighbor\n"
13966 "Route-map to modify the attributes\n"
13967 "Name of the route map\n"
13969 "Increase table width for longer prefixes\n")
13971 afi_t afi
= AFI_IP6
;
13972 safi_t safi
= SAFI_UNICAST
;
13973 char *rmap_name
= NULL
;
13974 char *peerstr
= NULL
;
13975 struct bgp
*bgp
= NULL
;
13977 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
13980 uint16_t show_flags
= 0;
13981 struct listnode
*node
;
13986 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13990 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
13991 if (argv_find(argv
, argc
, "ipv4", &idx
))
13992 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
13994 if (argv_find(argv
, argc
, "ipv6", &idx
))
13995 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
13999 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14001 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14004 return CMD_WARNING
;
14006 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14007 argv_find(argv
, argc
, "neighbors", &idx
);
14008 peerstr
= argv
[++idx
]->arg
;
14010 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14012 return CMD_WARNING
;
14014 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14015 type
= bgp_show_adj_route_advertised
;
14016 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14017 type
= bgp_show_adj_route_received
;
14018 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14019 type
= bgp_show_adj_route_filtered
;
14021 if (argv_find(argv
, argc
, "route-map", &idx
))
14022 rmap_name
= argv
[++idx
]->arg
;
14025 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14028 vty_out(vty
, "{\n");
14030 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14031 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14032 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14034 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14035 FOREACH_SAFI (safi
) {
14036 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14043 vty_out(vty
, ",\n");
14044 vty_out(vty
, "\"%s\":",
14045 get_afi_safi_str(afi
, safi
,
14049 "\nFor address family: %s\n",
14050 get_afi_safi_str(afi
, safi
,
14053 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14054 rmap_name
, show_flags
);
14058 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14059 FOREACH_AFI_SAFI (afi
, safi
) {
14060 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14067 vty_out(vty
, ",\n");
14068 vty_out(vty
, "\"%s\":",
14069 get_afi_safi_str(afi
, safi
,
14073 "\nFor address family: %s\n",
14074 get_afi_safi_str(afi
, safi
,
14077 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14078 rmap_name
, show_flags
);
14083 vty_out(vty
, "}\n");
14085 return CMD_SUCCESS
;
14088 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14089 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14090 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14094 BGP_INSTANCE_HELP_STR
14097 "Address Family modifier\n"
14098 "Detailed information on TCP and BGP neighbor connections\n"
14099 "Neighbor to display information about\n"
14100 "Neighbor to display information about\n"
14101 "Neighbor on BGP configured interface\n"
14102 "Display information received from a BGP neighbor\n"
14103 "Display the prefixlist filter\n"
14106 afi_t afi
= AFI_IP6
;
14107 safi_t safi
= SAFI_UNICAST
;
14108 char *peerstr
= NULL
;
14113 struct bgp
*bgp
= NULL
;
14114 bool uj
= use_json(argc
, argv
);
14119 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14122 return CMD_WARNING
;
14124 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14125 argv_find(argv
, argc
, "neighbors", &idx
);
14126 peerstr
= argv
[++idx
]->arg
;
14128 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14130 return CMD_WARNING
;
14132 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14133 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14136 vty_out(vty
, "Address Family: %s\n",
14137 get_afi_safi_str(afi
, safi
, false));
14138 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14141 vty_out(vty
, "{}\n");
14143 vty_out(vty
, "No functional output\n");
14146 return CMD_SUCCESS
;
14149 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14150 afi_t afi
, safi_t safi
,
14151 enum bgp_show_type type
, bool use_json
)
14153 uint16_t show_flags
= 0;
14156 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14158 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14160 json_object
*json_no
= NULL
;
14161 json_no
= json_object_new_object();
14162 json_object_string_add(
14163 json_no
, "warning",
14164 "No such neighbor or address family");
14165 vty_out(vty
, "%s\n",
14166 json_object_to_json_string(json_no
));
14167 json_object_free(json_no
);
14169 vty_out(vty
, "%% No such neighbor or address family\n");
14170 return CMD_WARNING
;
14173 /* labeled-unicast routes live in the unicast table */
14174 if (safi
== SAFI_LABELED_UNICAST
)
14175 safi
= SAFI_UNICAST
;
14177 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14178 RPKI_NOT_BEING_USED
);
14181 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14182 show_ip_bgp_flowspec_routes_detailed_cmd
,
14183 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14187 BGP_INSTANCE_HELP_STR
14190 "Detailed information on flowspec entries\n"
14193 afi_t afi
= AFI_IP6
;
14194 safi_t safi
= SAFI_UNICAST
;
14195 struct bgp
*bgp
= NULL
;
14197 bool uj
= use_json(argc
, argv
);
14198 uint16_t show_flags
= BGP_SHOW_OPT_DETAIL
;
14202 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14205 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14208 return CMD_WARNING
;
14210 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14211 show_flags
, RPKI_NOT_BEING_USED
);
14214 DEFUN (show_ip_bgp_neighbor_routes
,
14215 show_ip_bgp_neighbor_routes_cmd
,
14216 "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]",
14220 BGP_INSTANCE_HELP_STR
14222 BGP_SAFI_WITH_LABEL_HELP_STR
14223 "Detailed information on TCP and BGP neighbor connections\n"
14224 "Neighbor to display information about\n"
14225 "Neighbor to display information about\n"
14226 "Neighbor on BGP configured interface\n"
14227 "Display flap statistics of the routes learned from neighbor\n"
14228 "Display the dampened routes received from neighbor\n"
14229 "Display routes learned from neighbor\n"
14232 char *peerstr
= NULL
;
14233 struct bgp
*bgp
= NULL
;
14234 afi_t afi
= AFI_IP6
;
14235 safi_t safi
= SAFI_UNICAST
;
14237 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14239 bool uj
= use_json(argc
, argv
);
14244 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14247 return CMD_WARNING
;
14249 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14250 argv_find(argv
, argc
, "neighbors", &idx
);
14251 peerstr
= argv
[++idx
]->arg
;
14253 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14255 return CMD_WARNING
;
14257 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14258 sh_type
= bgp_show_type_flap_neighbor
;
14259 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14260 sh_type
= bgp_show_type_damp_neighbor
;
14261 else if (argv_find(argv
, argc
, "routes", &idx
))
14262 sh_type
= bgp_show_type_neighbor
;
14264 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14267 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14269 struct bgp_distance
{
14270 /* Distance value for the IP source prefix. */
14273 /* Name of the access-list to be matched. */
14277 DEFUN (show_bgp_afi_vpn_rd_route
,
14278 show_bgp_afi_vpn_rd_route_cmd
,
14279 "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]",
14283 "Address Family modifier\n"
14284 "Display information for a route distinguisher\n"
14285 "Route Distinguisher\n"
14286 "All Route Distinguishers\n"
14287 "Network in the BGP routing table to display\n"
14288 "Network in the BGP routing table to display\n"
14292 struct prefix_rd prd
;
14293 afi_t afi
= AFI_MAX
;
14296 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14297 vty_out(vty
, "%% Malformed Address Family\n");
14298 return CMD_WARNING
;
14301 if (!strcmp(argv
[5]->arg
, "all"))
14302 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14303 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14304 RPKI_NOT_BEING_USED
,
14305 use_json(argc
, argv
));
14307 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14309 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14310 return CMD_WARNING
;
14313 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14314 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14315 use_json(argc
, argv
));
14318 static struct bgp_distance
*bgp_distance_new(void)
14320 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14323 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14325 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14328 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14329 const char *ip_str
, const char *access_list_str
)
14336 struct bgp_dest
*dest
;
14337 struct bgp_distance
*bdistance
;
14339 afi
= bgp_node_afi(vty
);
14340 safi
= bgp_node_safi(vty
);
14342 ret
= str2prefix(ip_str
, &p
);
14344 vty_out(vty
, "Malformed prefix\n");
14345 return CMD_WARNING_CONFIG_FAILED
;
14348 distance
= atoi(distance_str
);
14350 /* Get BGP distance node. */
14351 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14352 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14354 bgp_dest_unlock_node(dest
);
14356 bdistance
= bgp_distance_new();
14357 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14360 /* Set distance value. */
14361 bdistance
->distance
= distance
;
14363 /* Reset access-list configuration. */
14364 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14365 if (access_list_str
)
14366 bdistance
->access_list
=
14367 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14369 return CMD_SUCCESS
;
14372 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14373 const char *ip_str
, const char *access_list_str
)
14380 struct bgp_dest
*dest
;
14381 struct bgp_distance
*bdistance
;
14383 afi
= bgp_node_afi(vty
);
14384 safi
= bgp_node_safi(vty
);
14386 ret
= str2prefix(ip_str
, &p
);
14388 vty_out(vty
, "Malformed prefix\n");
14389 return CMD_WARNING_CONFIG_FAILED
;
14392 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14394 vty_out(vty
, "Can't find specified prefix\n");
14395 return CMD_WARNING_CONFIG_FAILED
;
14398 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14399 distance
= atoi(distance_str
);
14401 if (bdistance
->distance
!= distance
) {
14402 vty_out(vty
, "Distance does not match configured\n");
14403 bgp_dest_unlock_node(dest
);
14404 return CMD_WARNING_CONFIG_FAILED
;
14407 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14408 bgp_distance_free(bdistance
);
14410 bgp_dest_set_bgp_path_info(dest
, NULL
);
14411 bgp_dest_unlock_node(dest
);
14412 bgp_dest_unlock_node(dest
);
14414 return CMD_SUCCESS
;
14417 /* Apply BGP information to distance method. */
14418 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14419 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14421 struct bgp_dest
*dest
;
14422 struct prefix q
= {0};
14424 struct bgp_distance
*bdistance
;
14425 struct access_list
*alist
;
14426 struct bgp_static
*bgp_static
;
14431 peer
= pinfo
->peer
;
14433 if (pinfo
->attr
->distance
)
14434 return pinfo
->attr
->distance
;
14436 /* Check source address.
14437 * Note: for aggregate route, peer can have unspec af type.
14439 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14440 && !sockunion2hostprefix(&peer
->su
, &q
))
14443 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14445 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14446 bgp_dest_unlock_node(dest
);
14448 if (bdistance
->access_list
) {
14449 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14451 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14452 return bdistance
->distance
;
14454 return bdistance
->distance
;
14457 /* Backdoor check. */
14458 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14460 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14461 bgp_dest_unlock_node(dest
);
14463 if (bgp_static
->backdoor
) {
14464 if (bgp
->distance_local
[afi
][safi
])
14465 return bgp
->distance_local
[afi
][safi
];
14467 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14471 if (peer
->sort
== BGP_PEER_EBGP
) {
14472 if (bgp
->distance_ebgp
[afi
][safi
])
14473 return bgp
->distance_ebgp
[afi
][safi
];
14474 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14475 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14476 if (bgp
->distance_ibgp
[afi
][safi
])
14477 return bgp
->distance_ibgp
[afi
][safi
];
14478 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14480 if (bgp
->distance_local
[afi
][safi
])
14481 return bgp
->distance_local
[afi
][safi
];
14482 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14486 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14487 * we should tell ZEBRA update the routes for a specific
14488 * AFI/SAFI to reflect changes in RIB.
14490 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
14492 safi_t update_safi
)
14497 FOREACH_AFI_SAFI (afi
, safi
) {
14498 if (!bgp_fibupd_safi(safi
))
14501 if (afi
!= update_afi
&& safi
!= update_safi
)
14504 if (BGP_DEBUG(zebra
, ZEBRA
))
14506 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14507 __func__
, afi
, safi
);
14508 bgp_zebra_announce_table(bgp
, afi
, safi
);
14512 DEFUN (bgp_distance
,
14514 "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
);
14522 int idx_number
= 2;
14523 int idx_number_2
= 3;
14524 int idx_number_3
= 4;
14525 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
14526 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
14527 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
14531 afi
= bgp_node_afi(vty
);
14532 safi
= bgp_node_safi(vty
);
14534 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
14535 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
14536 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
14537 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
14538 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
14539 bgp
->distance_local
[afi
][safi
] = distance_local
;
14540 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14542 return CMD_SUCCESS
;
14545 DEFUN (no_bgp_distance
,
14546 no_bgp_distance_cmd
,
14547 "no distance bgp [(1-255) (1-255) (1-255)]",
14549 "Define an administrative distance\n"
14551 "Distance for routes external to the AS\n"
14552 "Distance for routes internal to the AS\n"
14553 "Distance for local routes\n")
14555 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14559 afi
= bgp_node_afi(vty
);
14560 safi
= bgp_node_safi(vty
);
14562 if (bgp
->distance_ebgp
[afi
][safi
] != 0
14563 || bgp
->distance_ibgp
[afi
][safi
] != 0
14564 || bgp
->distance_local
[afi
][safi
] != 0) {
14565 bgp
->distance_ebgp
[afi
][safi
] = 0;
14566 bgp
->distance_ibgp
[afi
][safi
] = 0;
14567 bgp
->distance_local
[afi
][safi
] = 0;
14568 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14570 return CMD_SUCCESS
;
14574 DEFUN (bgp_distance_source
,
14575 bgp_distance_source_cmd
,
14576 "distance (1-255) A.B.C.D/M",
14577 "Define an administrative distance\n"
14578 "Administrative distance\n"
14579 "IP source prefix\n")
14581 int idx_number
= 1;
14582 int idx_ipv4_prefixlen
= 2;
14583 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14584 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14585 return CMD_SUCCESS
;
14588 DEFUN (no_bgp_distance_source
,
14589 no_bgp_distance_source_cmd
,
14590 "no distance (1-255) A.B.C.D/M",
14592 "Define an administrative distance\n"
14593 "Administrative distance\n"
14594 "IP source prefix\n")
14596 int idx_number
= 2;
14597 int idx_ipv4_prefixlen
= 3;
14598 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14599 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14600 return CMD_SUCCESS
;
14603 DEFUN (bgp_distance_source_access_list
,
14604 bgp_distance_source_access_list_cmd
,
14605 "distance (1-255) A.B.C.D/M WORD",
14606 "Define an administrative distance\n"
14607 "Administrative distance\n"
14608 "IP source prefix\n"
14609 "Access list name\n")
14611 int idx_number
= 1;
14612 int idx_ipv4_prefixlen
= 2;
14614 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14615 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14616 return CMD_SUCCESS
;
14619 DEFUN (no_bgp_distance_source_access_list
,
14620 no_bgp_distance_source_access_list_cmd
,
14621 "no distance (1-255) A.B.C.D/M WORD",
14623 "Define an administrative distance\n"
14624 "Administrative distance\n"
14625 "IP source prefix\n"
14626 "Access list name\n")
14628 int idx_number
= 2;
14629 int idx_ipv4_prefixlen
= 3;
14631 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14632 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14633 return CMD_SUCCESS
;
14636 DEFUN (ipv6_bgp_distance_source
,
14637 ipv6_bgp_distance_source_cmd
,
14638 "distance (1-255) X:X::X:X/M",
14639 "Define an administrative distance\n"
14640 "Administrative distance\n"
14641 "IP source prefix\n")
14643 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
14644 return CMD_SUCCESS
;
14647 DEFUN (no_ipv6_bgp_distance_source
,
14648 no_ipv6_bgp_distance_source_cmd
,
14649 "no distance (1-255) X:X::X:X/M",
14651 "Define an administrative distance\n"
14652 "Administrative distance\n"
14653 "IP source prefix\n")
14655 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
14656 return CMD_SUCCESS
;
14659 DEFUN (ipv6_bgp_distance_source_access_list
,
14660 ipv6_bgp_distance_source_access_list_cmd
,
14661 "distance (1-255) X:X::X:X/M WORD",
14662 "Define an administrative distance\n"
14663 "Administrative distance\n"
14664 "IP source prefix\n"
14665 "Access list name\n")
14667 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
14668 return CMD_SUCCESS
;
14671 DEFUN (no_ipv6_bgp_distance_source_access_list
,
14672 no_ipv6_bgp_distance_source_access_list_cmd
,
14673 "no distance (1-255) X:X::X:X/M WORD",
14675 "Define an administrative distance\n"
14676 "Administrative distance\n"
14677 "IP source prefix\n"
14678 "Access list name\n")
14680 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
14681 return CMD_SUCCESS
;
14684 DEFUN (bgp_damp_set
,
14686 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
14687 "BGP Specific commands\n"
14688 "Enable route-flap dampening\n"
14689 "Half-life time for the penalty\n"
14690 "Value to start reusing a route\n"
14691 "Value to start suppressing a route\n"
14692 "Maximum duration to suppress a stable route\n")
14694 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14695 int idx_half_life
= 2;
14697 int idx_suppress
= 4;
14698 int idx_max_suppress
= 5;
14699 int half
= DEFAULT_HALF_LIFE
* 60;
14700 int reuse
= DEFAULT_REUSE
;
14701 int suppress
= DEFAULT_SUPPRESS
;
14702 int max
= 4 * half
;
14705 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14706 reuse
= atoi(argv
[idx_reuse
]->arg
);
14707 suppress
= atoi(argv
[idx_suppress
]->arg
);
14708 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
14709 } else if (argc
== 3) {
14710 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14715 * These can't be 0 but our SA doesn't understand the
14716 * way our cli is constructed
14720 if (suppress
< reuse
) {
14722 "Suppress value cannot be less than reuse value \n");
14726 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
14727 reuse
, suppress
, max
);
14730 DEFUN (bgp_damp_unset
,
14731 bgp_damp_unset_cmd
,
14732 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
14734 "BGP Specific commands\n"
14735 "Enable route-flap dampening\n"
14736 "Half-life time for the penalty\n"
14737 "Value to start reusing a route\n"
14738 "Value to start suppressing a route\n"
14739 "Maximum duration to suppress a stable route\n")
14741 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14742 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
14745 /* Display specified route of BGP table. */
14746 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14747 const char *ip_str
, afi_t afi
, safi_t safi
,
14748 struct prefix_rd
*prd
, int prefix_check
)
14751 struct prefix match
;
14752 struct bgp_dest
*dest
;
14753 struct bgp_dest
*rm
;
14754 struct bgp_path_info
*pi
;
14755 struct bgp_path_info
*pi_temp
;
14757 struct bgp_table
*table
;
14759 /* BGP structure lookup. */
14761 bgp
= bgp_lookup_by_name(view_name
);
14763 vty_out(vty
, "%% Can't find BGP instance %s\n",
14765 return CMD_WARNING
;
14768 bgp
= bgp_get_default();
14770 vty_out(vty
, "%% No BGP process is configured\n");
14771 return CMD_WARNING
;
14775 /* Check IP address argument. */
14776 ret
= str2prefix(ip_str
, &match
);
14778 vty_out(vty
, "%% address is malformed\n");
14779 return CMD_WARNING
;
14782 match
.family
= afi2family(afi
);
14784 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14785 || (safi
== SAFI_EVPN
)) {
14786 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
14787 dest
= bgp_route_next(dest
)) {
14788 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14790 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
14792 table
= bgp_dest_get_bgp_table_info(dest
);
14795 rm
= bgp_node_match(table
, &match
);
14799 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
14802 || rm_p
->prefixlen
== match
.prefixlen
) {
14803 pi
= bgp_dest_get_bgp_path_info(rm
);
14805 if (pi
->extra
&& pi
->extra
->damp_info
) {
14806 pi_temp
= pi
->next
;
14807 bgp_damp_info_free(
14808 pi
->extra
->damp_info
,
14816 bgp_dest_unlock_node(rm
);
14819 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
14820 if (dest
!= NULL
) {
14821 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14824 || dest_p
->prefixlen
== match
.prefixlen
) {
14825 pi
= bgp_dest_get_bgp_path_info(dest
);
14827 if (pi
->extra
&& pi
->extra
->damp_info
) {
14828 pi_temp
= pi
->next
;
14829 bgp_damp_info_free(
14830 pi
->extra
->damp_info
,
14838 bgp_dest_unlock_node(dest
);
14842 return CMD_SUCCESS
;
14845 DEFUN (clear_ip_bgp_dampening
,
14846 clear_ip_bgp_dampening_cmd
,
14847 "clear ip bgp dampening",
14851 "Clear route flap dampening information\n")
14853 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
14854 return CMD_SUCCESS
;
14857 DEFUN (clear_ip_bgp_dampening_prefix
,
14858 clear_ip_bgp_dampening_prefix_cmd
,
14859 "clear ip bgp dampening A.B.C.D/M",
14863 "Clear route flap dampening information\n"
14866 int idx_ipv4_prefixlen
= 4;
14867 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
14868 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
14871 DEFUN (clear_ip_bgp_dampening_address
,
14872 clear_ip_bgp_dampening_address_cmd
,
14873 "clear ip bgp dampening A.B.C.D",
14877 "Clear route flap dampening information\n"
14878 "Network to clear damping information\n")
14881 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
14882 SAFI_UNICAST
, NULL
, 0);
14885 DEFUN (clear_ip_bgp_dampening_address_mask
,
14886 clear_ip_bgp_dampening_address_mask_cmd
,
14887 "clear ip bgp dampening A.B.C.D A.B.C.D",
14891 "Clear route flap dampening information\n"
14892 "Network to clear damping information\n"
14896 int idx_ipv4_2
= 5;
14898 char prefix_str
[BUFSIZ
];
14900 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
14901 prefix_str
, sizeof(prefix_str
));
14903 vty_out(vty
, "%% Inconsistent address and mask\n");
14904 return CMD_WARNING
;
14907 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
14911 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
14913 struct vty
*vty
= arg
;
14914 struct peer
*peer
= bucket
->data
;
14915 char buf
[SU_ADDRSTRLEN
];
14917 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
14918 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
14921 DEFUN (show_bgp_listeners
,
14922 show_bgp_listeners_cmd
,
14923 "show bgp listeners",
14926 "Display Listen Sockets and who created them\n")
14928 bgp_dump_listener_info(vty
);
14930 return CMD_SUCCESS
;
14933 DEFUN (show_bgp_peerhash
,
14934 show_bgp_peerhash_cmd
,
14935 "show bgp peerhash",
14938 "Display information about the BGP peerhash\n")
14940 struct list
*instances
= bm
->bgp
;
14941 struct listnode
*node
;
14944 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
14945 vty_out(vty
, "BGP: %s\n", bgp
->name
);
14946 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
14950 return CMD_SUCCESS
;
14953 /* also used for encap safi */
14954 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
14955 afi_t afi
, safi_t safi
)
14957 struct bgp_dest
*pdest
;
14958 struct bgp_dest
*dest
;
14959 struct bgp_table
*table
;
14960 const struct prefix
*p
;
14961 const struct prefix_rd
*prd
;
14962 struct bgp_static
*bgp_static
;
14963 mpls_label_t label
;
14964 char rdbuf
[RD_ADDRSTRLEN
];
14966 /* Network configuration. */
14967 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14968 pdest
= bgp_route_next(pdest
)) {
14969 table
= bgp_dest_get_bgp_table_info(pdest
);
14973 for (dest
= bgp_table_top(table
); dest
;
14974 dest
= bgp_route_next(dest
)) {
14975 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14976 if (bgp_static
== NULL
)
14979 p
= bgp_dest_get_prefix(dest
);
14980 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14983 /* "network" configuration display. */
14984 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14985 label
= decode_label(&bgp_static
->label
);
14987 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
14988 if (safi
== SAFI_MPLS_VPN
)
14989 vty_out(vty
, " label %u", label
);
14991 if (bgp_static
->rmap
.name
)
14992 vty_out(vty
, " route-map %s",
14993 bgp_static
->rmap
.name
);
14995 if (bgp_static
->backdoor
)
14996 vty_out(vty
, " backdoor");
14998 vty_out(vty
, "\n");
15003 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15004 afi_t afi
, safi_t safi
)
15006 struct bgp_dest
*pdest
;
15007 struct bgp_dest
*dest
;
15008 struct bgp_table
*table
;
15009 const struct prefix
*p
;
15010 const struct prefix_rd
*prd
;
15011 struct bgp_static
*bgp_static
;
15012 char buf
[PREFIX_STRLEN
* 2];
15013 char buf2
[SU_ADDRSTRLEN
];
15014 char rdbuf
[RD_ADDRSTRLEN
];
15015 char esi_buf
[ESI_STR_LEN
];
15017 /* Network configuration. */
15018 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15019 pdest
= bgp_route_next(pdest
)) {
15020 table
= bgp_dest_get_bgp_table_info(pdest
);
15024 for (dest
= bgp_table_top(table
); dest
;
15025 dest
= bgp_route_next(dest
)) {
15026 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15027 if (bgp_static
== NULL
)
15030 char *macrouter
= NULL
;
15032 if (bgp_static
->router_mac
)
15033 macrouter
= prefix_mac2str(
15034 bgp_static
->router_mac
, NULL
, 0);
15035 if (bgp_static
->eth_s_id
)
15036 esi_to_str(bgp_static
->eth_s_id
,
15037 esi_buf
, sizeof(esi_buf
));
15038 p
= bgp_dest_get_prefix(dest
);
15039 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15041 /* "network" configuration display. */
15042 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
15043 if (p
->u
.prefix_evpn
.route_type
== 5) {
15044 char local_buf
[PREFIX_STRLEN
];
15045 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15046 struct prefix_evpn
*)p
)
15050 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
15051 local_buf
, PREFIX_STRLEN
);
15052 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15053 p
->u
.prefix_evpn
.prefix_addr
15054 .ip_prefix_length
);
15056 prefix2str(p
, buf
, sizeof(buf
));
15059 if (bgp_static
->gatewayIp
.family
== AF_INET
15060 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15061 inet_ntop(bgp_static
->gatewayIp
.family
,
15062 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15065 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15067 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15068 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15071 XFREE(MTYPE_TMP
, macrouter
);
15076 /* Configuration of static route announcement and aggregate
15078 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15081 struct bgp_dest
*dest
;
15082 const struct prefix
*p
;
15083 struct bgp_static
*bgp_static
;
15084 struct bgp_aggregate
*bgp_aggregate
;
15086 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15087 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15091 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15092 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15096 /* Network configuration. */
15097 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15098 dest
= bgp_route_next(dest
)) {
15099 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15100 if (bgp_static
== NULL
)
15103 p
= bgp_dest_get_prefix(dest
);
15105 vty_out(vty
, " network %pFX", p
);
15107 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15108 vty_out(vty
, " label-index %u",
15109 bgp_static
->label_index
);
15111 if (bgp_static
->rmap
.name
)
15112 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15114 if (bgp_static
->backdoor
)
15115 vty_out(vty
, " backdoor");
15117 vty_out(vty
, "\n");
15120 /* Aggregate-address configuration. */
15121 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15122 dest
= bgp_route_next(dest
)) {
15123 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15124 if (bgp_aggregate
== NULL
)
15127 p
= bgp_dest_get_prefix(dest
);
15129 vty_out(vty
, " aggregate-address %pFX", p
);
15131 if (bgp_aggregate
->as_set
)
15132 vty_out(vty
, " as-set");
15134 if (bgp_aggregate
->summary_only
)
15135 vty_out(vty
, " summary-only");
15137 if (bgp_aggregate
->rmap
.name
)
15138 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15140 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15141 vty_out(vty
, " origin %s",
15142 bgp_origin2str(bgp_aggregate
->origin
));
15144 if (bgp_aggregate
->match_med
)
15145 vty_out(vty
, " matching-MED-only");
15147 if (bgp_aggregate
->suppress_map_name
)
15148 vty_out(vty
, " suppress-map %s",
15149 bgp_aggregate
->suppress_map_name
);
15151 vty_out(vty
, "\n");
15155 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15158 struct bgp_dest
*dest
;
15159 struct bgp_distance
*bdistance
;
15161 /* Distance configuration. */
15162 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15163 && bgp
->distance_local
[afi
][safi
]
15164 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15165 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15166 || bgp
->distance_local
[afi
][safi
]
15167 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15168 vty_out(vty
, " distance bgp %d %d %d\n",
15169 bgp
->distance_ebgp
[afi
][safi
],
15170 bgp
->distance_ibgp
[afi
][safi
],
15171 bgp
->distance_local
[afi
][safi
]);
15174 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15175 dest
= bgp_route_next(dest
)) {
15176 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15177 if (bdistance
!= NULL
)
15178 vty_out(vty
, " distance %d %pBD %s\n",
15179 bdistance
->distance
, dest
,
15180 bdistance
->access_list
? bdistance
->access_list
15185 /* Allocate routing table structure and install commands. */
15186 void bgp_route_init(void)
15191 /* Init BGP distance table. */
15192 FOREACH_AFI_SAFI (afi
, safi
)
15193 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15195 /* IPv4 BGP commands. */
15196 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15197 install_element(BGP_NODE
, &bgp_network_cmd
);
15198 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15200 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15202 /* IPv4 unicast configuration. */
15203 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15204 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15205 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15207 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15209 /* IPv4 multicast configuration. */
15210 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15211 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15212 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15213 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15215 /* IPv4 labeled-unicast configuration. */
15216 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15217 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15219 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15220 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15221 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15222 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15223 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15224 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15225 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15226 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15228 install_element(VIEW_NODE
,
15229 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15230 install_element(VIEW_NODE
,
15231 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15232 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15233 install_element(VIEW_NODE
,
15234 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15235 #ifdef KEEP_OLD_VPN_COMMANDS
15236 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15237 #endif /* KEEP_OLD_VPN_COMMANDS */
15238 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15239 install_element(VIEW_NODE
,
15240 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15242 /* BGP dampening clear commands */
15243 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15244 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15246 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15247 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15250 install_element(ENABLE_NODE
,
15251 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15252 #ifdef KEEP_OLD_VPN_COMMANDS
15253 install_element(ENABLE_NODE
,
15254 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15255 #endif /* KEEP_OLD_VPN_COMMANDS */
15257 /* New config IPv6 BGP commands. */
15258 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15259 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15260 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15262 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15264 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15266 /* IPv6 labeled unicast address family. */
15267 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15268 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15270 install_element(BGP_NODE
, &bgp_distance_cmd
);
15271 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15272 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15273 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15274 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15275 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15276 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15277 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15278 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15279 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15280 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15281 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15282 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15283 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15284 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15285 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15286 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15287 install_element(BGP_IPV4M_NODE
,
15288 &no_bgp_distance_source_access_list_cmd
);
15289 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15290 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15291 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15292 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15293 install_element(BGP_IPV6_NODE
,
15294 &ipv6_bgp_distance_source_access_list_cmd
);
15295 install_element(BGP_IPV6_NODE
,
15296 &no_ipv6_bgp_distance_source_access_list_cmd
);
15297 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15298 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15299 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15300 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15301 install_element(BGP_IPV6M_NODE
,
15302 &ipv6_bgp_distance_source_access_list_cmd
);
15303 install_element(BGP_IPV6M_NODE
,
15304 &no_ipv6_bgp_distance_source_access_list_cmd
);
15306 /* BGP dampening */
15307 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15308 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15309 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15310 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15311 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15312 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15313 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15314 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15315 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15316 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15317 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15318 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15319 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15320 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15322 /* Large Communities */
15323 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15324 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15326 /* show bgp ipv4 flowspec detailed */
15327 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15329 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15330 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15333 void bgp_route_finish(void)
15338 FOREACH_AFI_SAFI (afi
, safi
) {
15339 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15340 bgp_distance_table
[afi
][safi
] = NULL
;