1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "sockunion.h"
39 #include "workqueue.h"
44 #include "lib_errors.h"
46 #include "bgpd/bgpd.h"
47 #include "bgpd/bgp_table.h"
48 #include "bgpd/bgp_route.h"
49 #include "bgpd/bgp_attr.h"
50 #include "bgpd/bgp_debug.h"
51 #include "bgpd/bgp_errors.h"
52 #include "bgpd/bgp_aspath.h"
53 #include "bgpd/bgp_regex.h"
54 #include "bgpd/bgp_community.h"
55 #include "bgpd/bgp_community_alias.h"
56 #include "bgpd/bgp_ecommunity.h"
57 #include "bgpd/bgp_lcommunity.h"
58 #include "bgpd/bgp_clist.h"
59 #include "bgpd/bgp_packet.h"
60 #include "bgpd/bgp_filter.h"
61 #include "bgpd/bgp_fsm.h"
62 #include "bgpd/bgp_mplsvpn.h"
63 #include "bgpd/bgp_nexthop.h"
64 #include "bgpd/bgp_damp.h"
65 #include "bgpd/bgp_advertise.h"
66 #include "bgpd/bgp_zebra.h"
67 #include "bgpd/bgp_vty.h"
68 #include "bgpd/bgp_mpath.h"
69 #include "bgpd/bgp_nht.h"
70 #include "bgpd/bgp_updgrp.h"
71 #include "bgpd/bgp_label.h"
72 #include "bgpd/bgp_addpath.h"
73 #include "bgpd/bgp_mac.h"
74 #include "bgpd/bgp_network.h"
75 #include "bgpd/bgp_trace.h"
76 #include "bgpd/bgp_rpki.h"
79 #include "bgpd/rfapi/rfapi_backend.h"
80 #include "bgpd/rfapi/vnc_import_bgp.h"
81 #include "bgpd/rfapi/vnc_export_bgp.h"
83 #include "bgpd/bgp_encap_types.h"
84 #include "bgpd/bgp_encap_tlv.h"
85 #include "bgpd/bgp_evpn.h"
86 #include "bgpd/bgp_evpn_mh.h"
87 #include "bgpd/bgp_evpn_vty.h"
88 #include "bgpd/bgp_flowspec.h"
89 #include "bgpd/bgp_flowspec_util.h"
90 #include "bgpd/bgp_pbr.h"
92 #ifndef VTYSH_EXTRACT_PL
93 #include "bgpd/bgp_route_clippy.c"
96 DEFINE_HOOK(bgp_snmp_update_stats
,
97 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
100 DEFINE_HOOK(bgp_rpki_prefix_status
,
101 (struct peer
*peer
, struct attr
*attr
,
102 const struct prefix
*prefix
),
103 (peer
, attr
, prefix
));
105 /* Render dest to prefix_rd based on safi */
106 static const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
109 /* Extern from bgp_dump.c */
110 extern const char *bgp_origin_str
[];
111 extern const char *bgp_origin_long_str
[];
114 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
115 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
116 static const struct message bgp_pmsi_tnltype_str
[] = {
117 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
118 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
119 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
120 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
121 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
122 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
123 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
124 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
128 #define VRFID_NONE_STR "-"
129 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
131 DEFINE_HOOK(bgp_process
,
132 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
133 struct peer
*peer
, bool withdraw
),
134 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
136 /** Test if path is suppressed. */
137 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
139 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
142 return listcount(pi
->extra
->aggr_suppressors
) > 0;
145 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
146 safi_t safi
, const struct prefix
*p
,
147 struct prefix_rd
*prd
)
149 struct bgp_dest
*dest
;
150 struct bgp_dest
*pdest
= NULL
;
154 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
155 || (safi
== SAFI_EVPN
)) {
156 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
158 if (!bgp_dest_has_bgp_path_info_data(pdest
))
159 bgp_dest_set_bgp_table_info(
160 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
162 bgp_dest_unlock_node(pdest
);
163 table
= bgp_dest_get_bgp_table_info(pdest
);
166 dest
= bgp_node_get(table
, p
);
168 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
169 || (safi
== SAFI_EVPN
))
175 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
176 safi_t safi
, const struct prefix
*p
,
177 struct prefix_rd
*prd
)
179 struct bgp_dest
*dest
;
180 struct bgp_dest
*pdest
= NULL
;
185 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
186 || (safi
== SAFI_EVPN
)) {
187 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
191 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
192 bgp_dest_unlock_node(pdest
);
196 table
= bgp_dest_get_bgp_table_info(pdest
);
199 dest
= bgp_node_lookup(table
, p
);
204 /* Allocate bgp_path_info_extra */
205 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
207 struct bgp_path_info_extra
*new;
208 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
209 sizeof(struct bgp_path_info_extra
));
210 new->label
[0] = MPLS_INVALID_LABEL
;
212 new->bgp_fs_pbr
= NULL
;
213 new->bgp_fs_iprule
= NULL
;
217 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
219 struct bgp_path_info_extra
*e
;
221 if (!extra
|| !*extra
)
226 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
231 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
234 /* FIXME: since multiple e may have the same e->parent
235 * and e->parent->net is holding a refcount for each
236 * of them, we need to do some fudging here.
238 * WARNING: if bpi->net->lock drops to 0, bpi may be
239 * freed as well (because bpi->net was holding the
240 * last reference to bpi) => write after free!
244 bpi
= bgp_path_info_lock(bpi
);
245 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
246 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
249 bgp_path_info_unlock(bpi
);
251 bgp_path_info_unlock(e
->parent
);
256 bgp_unlock(e
->bgp_orig
);
258 if (e
->aggr_suppressors
)
259 list_delete(&e
->aggr_suppressors
);
262 bgp_evpn_path_mh_info_free(e
->mh_info
);
264 if ((*extra
)->bgp_fs_iprule
)
265 list_delete(&((*extra
)->bgp_fs_iprule
));
266 if ((*extra
)->bgp_fs_pbr
)
267 list_delete(&((*extra
)->bgp_fs_pbr
));
268 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
271 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
272 * allocated if required.
274 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
277 pi
->extra
= bgp_path_info_extra_new();
281 /* Free bgp route information. */
282 static void bgp_path_info_free(struct bgp_path_info
*path
)
284 bgp_attr_unintern(&path
->attr
);
286 bgp_unlink_nexthop(path
);
287 bgp_path_info_extra_free(&path
->extra
);
288 bgp_path_info_mpath_free(&path
->mpath
);
290 bgp_addpath_free_info_data(&path
->tx_addpath
,
291 &path
->net
->tx_addpath
);
293 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
295 XFREE(MTYPE_BGP_ROUTE
, path
);
298 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
304 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
306 assert(path
&& path
->lock
> 0);
309 if (path
->lock
== 0) {
310 bgp_path_info_free(path
);
317 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
318 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
321 struct bgp_path_info
*old_pi
, *nextpi
;
322 bool set_flag
= false;
323 struct bgp
*bgp
= NULL
;
324 struct bgp_table
*table
= NULL
;
328 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
329 * then the route selection is deferred
331 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
334 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
335 if (BGP_DEBUG(update
, UPDATE_OUT
))
337 "Route %pBD is in workqueue and being processed, not deferred.",
343 table
= bgp_dest_table(dest
);
350 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
351 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
352 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
355 /* Route selection is deferred if there is a stale path which
356 * which indicates peer is in restart mode
358 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
359 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
362 /* If the peer is graceful restart capable and peer is
363 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
366 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
367 && BGP_PEER_RESTARTING_MODE(peer
)
369 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
377 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
380 if (set_flag
&& table
) {
381 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
382 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
383 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
384 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
385 if (BGP_DEBUG(update
, UPDATE_OUT
))
386 zlog_debug("DEFER route %pBD, dest %p", dest
,
394 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
396 struct bgp_path_info
*top
;
398 top
= bgp_dest_get_bgp_path_info(dest
);
404 bgp_dest_set_bgp_path_info(dest
, pi
);
406 bgp_path_info_lock(pi
);
407 bgp_dest_lock_node(dest
);
408 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
409 bgp_dest_set_defer_flag(dest
, false);
410 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
413 /* Do the actual removal of info from RIB, for use by bgp_process
414 completion callback *only* */
415 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
418 pi
->next
->prev
= pi
->prev
;
420 pi
->prev
->next
= pi
->next
;
422 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
424 bgp_path_info_mpath_dequeue(pi
);
425 bgp_path_info_unlock(pi
);
426 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
427 bgp_dest_unlock_node(dest
);
430 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
432 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
433 /* set of previous already took care of pcount */
434 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
437 /* undo the effects of a previous call to bgp_path_info_delete; typically
438 called when a route is deleted and then quickly re-added before the
439 deletion has been processed */
440 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
442 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
443 /* unset of previous already took care of pcount */
444 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
447 /* Adjust pcount as required */
448 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
450 struct bgp_table
*table
;
452 assert(dest
&& bgp_dest_table(dest
));
453 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
455 table
= bgp_dest_table(dest
);
457 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
460 if (!BGP_PATH_COUNTABLE(pi
)
461 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
463 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
465 /* slight hack, but more robust against errors. */
466 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
467 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
469 flog_err(EC_LIB_DEVELOPMENT
,
470 "Asked to decrement 0 prefix count for peer");
471 } else if (BGP_PATH_COUNTABLE(pi
)
472 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
473 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
474 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
478 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
479 struct bgp_path_info
*pi2
)
481 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
484 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
485 * This is here primarily to keep prefix-count in check.
487 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
490 SET_FLAG(pi
->flags
, flag
);
492 /* early bath if we know it's not a flag that changes countability state
494 if (!CHECK_FLAG(flag
,
495 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
498 bgp_pcount_adjust(dest
, pi
);
501 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
504 UNSET_FLAG(pi
->flags
, flag
);
506 /* early bath if we know it's not a flag that changes countability state
508 if (!CHECK_FLAG(flag
,
509 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
512 bgp_pcount_adjust(dest
, pi
);
515 /* Get MED value. If MED value is missing and "bgp bestpath
516 missing-as-worst" is specified, treat it as the worst value. */
517 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
519 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
522 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
529 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
532 if (pi
->addpath_rx_id
)
533 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
534 pi
->peer
->host
, pi
->addpath_rx_id
);
536 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
541 * Get the ultimate path info.
543 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
545 struct bgp_path_info
*bpi_ultimate
;
547 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
550 for (bpi_ultimate
= info
;
551 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
552 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
558 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
560 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
561 struct bgp_path_info
*exist
, int *paths_eq
,
562 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
563 char *pfx_buf
, afi_t afi
, safi_t safi
,
564 enum bgp_path_selection_reason
*reason
)
566 const struct prefix
*new_p
;
567 struct attr
*newattr
, *existattr
;
568 bgp_peer_sort_t new_sort
;
569 bgp_peer_sort_t exist_sort
;
575 uint32_t exist_weight
;
576 uint32_t newm
, existm
;
577 struct in_addr new_id
;
578 struct in_addr exist_id
;
581 int internal_as_route
;
584 int igp_metric_ret
= 0;
585 int peer_sort_ret
= -1;
586 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
587 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
589 uint32_t exist_mm_seq
;
596 bool new_origin
, exist_origin
;
597 struct bgp_path_info
*bpi_ultimate
;
603 *reason
= bgp_path_selection_none
;
605 zlog_debug("%s: new is NULL", pfx_buf
);
610 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
616 *reason
= bgp_path_selection_first
;
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf
, bgp
->name_pretty
, new_buf
);
624 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
629 exist_buf
, exist
->flags
);
633 existattr
= exist
->attr
;
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
644 if (newattr
->community
&&
645 community_include(newattr
->community
, COMMUNITY_LLGR_STALE
)) {
648 "%s: %s wins over %s due to LLGR_STALE community",
649 pfx_buf
, new_buf
, exist_buf
);
653 if (existattr
->community
&&
654 community_include(existattr
->community
, COMMUNITY_LLGR_STALE
)) {
657 "%s: %s loses to %s due to LLGR_STALE community",
658 pfx_buf
, new_buf
, exist_buf
);
662 new_p
= bgp_dest_get_prefix(new->net
);
664 /* For EVPN routes, we cannot just go by local vs remote, we have to
665 * look at the MAC mobility sequence number, if present.
667 if ((safi
== SAFI_EVPN
)
668 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
669 /* This is an error condition described in RFC 7432 Section
671 * states that in this scenario "the PE MUST alert the operator"
673 * does not state what other action to take. In order to provide
675 * consistency in this scenario we are going to prefer the path
679 if (newattr
->sticky
!= existattr
->sticky
) {
681 prefix2str(new_p
, pfx_buf
,
683 * PREFIX2STR_BUFFER
);
684 bgp_path_info_path_with_addpath_rx_str(
685 new, new_buf
, sizeof(new_buf
));
686 bgp_path_info_path_with_addpath_rx_str(
687 exist
, exist_buf
, sizeof(exist_buf
));
690 if (newattr
->sticky
&& !existattr
->sticky
) {
691 *reason
= bgp_path_selection_evpn_sticky_mac
;
694 "%s: %s wins over %s due to sticky MAC flag",
695 pfx_buf
, new_buf
, exist_buf
);
699 if (!newattr
->sticky
&& existattr
->sticky
) {
700 *reason
= bgp_path_selection_evpn_sticky_mac
;
703 "%s: %s loses to %s due to sticky MAC flag",
704 pfx_buf
, new_buf
, exist_buf
);
709 new_esi
= bgp_evpn_attr_get_esi(newattr
);
710 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
711 if (bgp_evpn_is_esi_valid(new_esi
) &&
712 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
718 /* If both paths have the same non-zero ES and
719 * one path is local it wins.
720 * PS: Note the local path wins even if the remote
721 * has the higher MM seq. The local path's
722 * MM seq will be fixed up to match the highest
723 * rem seq, subsequently.
726 char esi_buf
[ESI_STR_LEN
];
728 if (bgp_evpn_is_path_local(bgp
, new)) {
729 *reason
= bgp_path_selection_evpn_local_path
;
732 "%s: %s wins over %s as ES %s is same and local",
733 pfx_buf
, new_buf
, exist_buf
,
734 esi_to_str(new_esi
, esi_buf
,
738 if (bgp_evpn_is_path_local(bgp
, exist
)) {
739 *reason
= bgp_path_selection_evpn_local_path
;
742 "%s: %s loses to %s as ES %s is same and local",
743 pfx_buf
, new_buf
, exist_buf
,
744 esi_to_str(new_esi
, esi_buf
,
750 new_mm_seq
= mac_mobility_seqnum(newattr
);
751 exist_mm_seq
= mac_mobility_seqnum(existattr
);
753 if (new_mm_seq
> exist_mm_seq
) {
754 *reason
= bgp_path_selection_evpn_seq
;
757 "%s: %s wins over %s due to MM seq %u > %u",
758 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
763 if (new_mm_seq
< exist_mm_seq
) {
764 *reason
= bgp_path_selection_evpn_seq
;
767 "%s: %s loses to %s due to MM seq %u < %u",
768 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
773 /* if the sequence numbers and ESI are the same and one path
774 * is non-proxy it wins (over proxy)
776 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
777 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
778 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
779 old_proxy
!= new_proxy
) {
781 *reason
= bgp_path_selection_evpn_non_proxy
;
784 "%s: %s wins over %s, same seq/es and non-proxy",
785 pfx_buf
, new_buf
, exist_buf
);
789 *reason
= bgp_path_selection_evpn_non_proxy
;
792 "%s: %s loses to %s, same seq/es and non-proxy",
793 pfx_buf
, new_buf
, exist_buf
);
798 * if sequence numbers are the same path with the lowest IP
801 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
803 *reason
= bgp_path_selection_evpn_lower_ip
;
806 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
807 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
808 &new->attr
->nexthop
);
812 *reason
= bgp_path_selection_evpn_lower_ip
;
815 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
816 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
817 &new->attr
->nexthop
);
822 /* 1. Weight check. */
823 new_weight
= newattr
->weight
;
824 exist_weight
= existattr
->weight
;
826 if (new_weight
> exist_weight
) {
827 *reason
= bgp_path_selection_weight
;
829 zlog_debug("%s: %s wins over %s due to weight %d > %d",
830 pfx_buf
, new_buf
, exist_buf
, new_weight
,
835 if (new_weight
< exist_weight
) {
836 *reason
= bgp_path_selection_weight
;
838 zlog_debug("%s: %s loses to %s due to weight %d < %d",
839 pfx_buf
, new_buf
, exist_buf
, new_weight
,
844 /* 2. Local preference check. */
845 new_pref
= exist_pref
= bgp
->default_local_pref
;
847 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
848 new_pref
= newattr
->local_pref
;
849 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
850 exist_pref
= existattr
->local_pref
;
852 if (new_pref
> exist_pref
) {
853 *reason
= bgp_path_selection_local_pref
;
856 "%s: %s wins over %s due to localpref %d > %d",
857 pfx_buf
, new_buf
, exist_buf
, new_pref
,
862 if (new_pref
< exist_pref
) {
863 *reason
= bgp_path_selection_local_pref
;
866 "%s: %s loses to %s due to localpref %d < %d",
867 pfx_buf
, new_buf
, exist_buf
, new_pref
,
872 /* 3. Local route check. We prefer:
874 * - BGP_ROUTE_AGGREGATE
875 * - BGP_ROUTE_REDISTRIBUTE
877 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
878 new->sub_type
== BGP_ROUTE_IMPORTED
);
879 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
880 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
882 if (new_origin
&& !exist_origin
) {
883 *reason
= bgp_path_selection_local_route
;
886 "%s: %s wins over %s due to preferred BGP_ROUTE type",
887 pfx_buf
, new_buf
, exist_buf
);
891 if (!new_origin
&& exist_origin
) {
892 *reason
= bgp_path_selection_local_route
;
895 "%s: %s loses to %s due to preferred BGP_ROUTE type",
896 pfx_buf
, new_buf
, exist_buf
);
900 /* Here if these are imported routes then get ultimate pi for
903 new = bgp_get_imported_bpi_ultimate(new);
904 exist
= bgp_get_imported_bpi_ultimate(exist
);
906 existattr
= exist
->attr
;
908 /* 4. AS path length check. */
909 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
910 int exist_hops
= aspath_count_hops(existattr
->aspath
);
911 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
913 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
916 aspath_hops
= aspath_count_hops(newattr
->aspath
);
917 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
919 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
920 *reason
= bgp_path_selection_confed_as_path
;
923 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
924 pfx_buf
, new_buf
, exist_buf
,
926 (exist_hops
+ exist_confeds
));
930 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
931 *reason
= bgp_path_selection_confed_as_path
;
934 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
935 pfx_buf
, new_buf
, exist_buf
,
937 (exist_hops
+ exist_confeds
));
941 int newhops
= aspath_count_hops(newattr
->aspath
);
943 if (newhops
< exist_hops
) {
944 *reason
= bgp_path_selection_as_path
;
947 "%s: %s wins over %s due to aspath hopcount %d < %d",
948 pfx_buf
, new_buf
, exist_buf
,
949 newhops
, exist_hops
);
953 if (newhops
> exist_hops
) {
954 *reason
= bgp_path_selection_as_path
;
957 "%s: %s loses to %s due to aspath hopcount %d > %d",
958 pfx_buf
, new_buf
, exist_buf
,
959 newhops
, exist_hops
);
965 /* 5. Origin check. */
966 if (newattr
->origin
< existattr
->origin
) {
967 *reason
= bgp_path_selection_origin
;
969 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
970 pfx_buf
, new_buf
, exist_buf
,
971 bgp_origin_long_str
[newattr
->origin
],
972 bgp_origin_long_str
[existattr
->origin
]);
976 if (newattr
->origin
> existattr
->origin
) {
977 *reason
= bgp_path_selection_origin
;
979 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
980 pfx_buf
, new_buf
, exist_buf
,
981 bgp_origin_long_str
[newattr
->origin
],
982 bgp_origin_long_str
[existattr
->origin
]);
987 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
988 && aspath_count_hops(existattr
->aspath
) == 0);
989 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
990 && aspath_count_confeds(existattr
->aspath
) > 0
991 && aspath_count_hops(newattr
->aspath
) == 0
992 && aspath_count_hops(existattr
->aspath
) == 0);
994 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
995 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
996 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
997 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
998 || internal_as_route
) {
999 new_med
= bgp_med_value(new->attr
, bgp
);
1000 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1002 if (new_med
< exist_med
) {
1003 *reason
= bgp_path_selection_med
;
1006 "%s: %s wins over %s due to MED %d < %d",
1007 pfx_buf
, new_buf
, exist_buf
, new_med
,
1012 if (new_med
> exist_med
) {
1013 *reason
= bgp_path_selection_med
;
1016 "%s: %s loses to %s due to MED %d > %d",
1017 pfx_buf
, new_buf
, exist_buf
, new_med
,
1023 /* 7. Peer type check. */
1024 new_sort
= new->peer
->sort
;
1025 exist_sort
= exist
->peer
->sort
;
1027 if (new_sort
== BGP_PEER_EBGP
1028 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1029 *reason
= bgp_path_selection_peer
;
1032 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1033 pfx_buf
, new_buf
, exist_buf
);
1034 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1039 if (exist_sort
== BGP_PEER_EBGP
1040 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1041 *reason
= bgp_path_selection_peer
;
1044 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1045 pfx_buf
, new_buf
, exist_buf
);
1046 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1051 /* 8. IGP metric check. */
1055 newm
= new->extra
->igpmetric
;
1057 existm
= exist
->extra
->igpmetric
;
1059 if (newm
< existm
) {
1060 if (debug
&& peer_sort_ret
< 0)
1062 "%s: %s wins over %s due to IGP metric %u < %u",
1063 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1067 if (newm
> existm
) {
1068 if (debug
&& peer_sort_ret
< 0)
1070 "%s: %s loses to %s due to IGP metric %u > %u",
1071 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1075 /* 9. Same IGP metric. Compare the cluster list length as
1076 representative of IGP hops metric. Rewrite the metric value
1077 pair (newm, existm) with the cluster list length. Prefer the
1078 path with smaller cluster list length. */
1079 if (newm
== existm
) {
1080 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
1081 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
1082 && (mpath_cfg
== NULL
1084 mpath_cfg
->ibgp_flags
,
1085 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
1086 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1087 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1089 if (newm
< existm
) {
1090 if (debug
&& peer_sort_ret
< 0)
1092 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1093 pfx_buf
, new_buf
, exist_buf
,
1098 if (newm
> existm
) {
1099 if (debug
&& peer_sort_ret
< 0)
1101 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1102 pfx_buf
, new_buf
, exist_buf
,
1109 /* 10. confed-external vs. confed-internal */
1110 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1111 if (new_sort
== BGP_PEER_CONFED
1112 && exist_sort
== BGP_PEER_IBGP
) {
1113 *reason
= bgp_path_selection_confed
;
1116 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1117 pfx_buf
, new_buf
, exist_buf
);
1118 if (!CHECK_FLAG(bgp
->flags
,
1119 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1124 if (exist_sort
== BGP_PEER_CONFED
1125 && new_sort
== BGP_PEER_IBGP
) {
1126 *reason
= bgp_path_selection_confed
;
1129 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1130 pfx_buf
, new_buf
, exist_buf
);
1131 if (!CHECK_FLAG(bgp
->flags
,
1132 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1138 /* 11. Maximum path check. */
1139 if (newm
== existm
) {
1140 /* If one path has a label but the other does not, do not treat
1141 * them as equals for multipath
1143 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1145 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1148 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1149 pfx_buf
, new_buf
, exist_buf
);
1150 } else if (CHECK_FLAG(bgp
->flags
,
1151 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1154 * For the two paths, all comparison steps till IGP
1156 * have succeeded - including AS_PATH hop count. Since
1158 * bestpath as-path multipath-relax' knob is on, we
1160 * an exact match of AS_PATH. Thus, mark the paths are
1162 * That will trigger both these paths to get into the
1170 "%s: %s and %s are equal via multipath-relax",
1171 pfx_buf
, new_buf
, exist_buf
);
1172 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1173 if (aspath_cmp(new->attr
->aspath
,
1174 exist
->attr
->aspath
)) {
1179 "%s: %s and %s are equal via matching aspaths",
1180 pfx_buf
, new_buf
, exist_buf
);
1182 } else if (new->peer
->as
== exist
->peer
->as
) {
1187 "%s: %s and %s are equal via same remote-as",
1188 pfx_buf
, new_buf
, exist_buf
);
1192 * TODO: If unequal cost ibgp multipath is enabled we can
1193 * mark the paths as equal here instead of returning
1196 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1197 * if either step 7 or 10 (peer type checks) yielded a winner,
1198 * that result was returned immediately. Returning from step 10
1199 * ignored the return value computed in steps 8 and 9 (IGP
1200 * metric checks). In order to preserve that behavior, if
1201 * peer_sort_ret is set, return that rather than igp_metric_ret.
1203 ret
= peer_sort_ret
;
1204 if (peer_sort_ret
< 0) {
1205 ret
= igp_metric_ret
;
1209 "%s: %s wins over %s after IGP metric comparison",
1210 pfx_buf
, new_buf
, exist_buf
);
1213 "%s: %s loses to %s after IGP metric comparison",
1214 pfx_buf
, new_buf
, exist_buf
);
1216 *reason
= bgp_path_selection_igp_metric
;
1222 * At this point, the decision whether to set *paths_eq = 1 has been
1223 * completed. If we deferred returning because of bestpath peer-type
1224 * relax configuration, return now.
1226 if (peer_sort_ret
>= 0)
1227 return peer_sort_ret
;
1229 /* 12. If both paths are external, prefer the path that was received
1230 first (the oldest one). This step minimizes route-flap, since a
1231 newer path won't displace an older one, even if it was the
1232 preferred route based on the additional decision criteria below. */
1233 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1234 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1235 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1236 *reason
= bgp_path_selection_older
;
1239 "%s: %s wins over %s due to oldest external",
1240 pfx_buf
, new_buf
, exist_buf
);
1244 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1245 *reason
= bgp_path_selection_older
;
1248 "%s: %s loses to %s due to oldest external",
1249 pfx_buf
, new_buf
, exist_buf
);
1254 /* 13. Router-ID comparision. */
1255 /* If one of the paths is "stale", the corresponding peer router-id will
1256 * be 0 and would always win over the other path. If originator id is
1257 * used for the comparision, it will decide which path is better.
1259 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1260 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1262 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1263 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1264 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1266 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1268 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1269 *reason
= bgp_path_selection_router_id
;
1272 "%s: %s wins over %s due to Router-ID comparison",
1273 pfx_buf
, new_buf
, exist_buf
);
1277 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1278 *reason
= bgp_path_selection_router_id
;
1281 "%s: %s loses to %s due to Router-ID comparison",
1282 pfx_buf
, new_buf
, exist_buf
);
1286 /* 14. Cluster length comparision. */
1287 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1288 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1290 if (new_cluster
< exist_cluster
) {
1291 *reason
= bgp_path_selection_cluster_length
;
1294 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1295 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1300 if (new_cluster
> exist_cluster
) {
1301 *reason
= bgp_path_selection_cluster_length
;
1304 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1305 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1310 /* 15. Neighbor address comparision. */
1311 /* Do this only if neither path is "stale" as stale paths do not have
1312 * valid peer information (as the connection may or may not be up).
1314 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1315 *reason
= bgp_path_selection_stale
;
1318 "%s: %s wins over %s due to latter path being STALE",
1319 pfx_buf
, new_buf
, exist_buf
);
1323 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1324 *reason
= bgp_path_selection_stale
;
1327 "%s: %s loses to %s due to former path being STALE",
1328 pfx_buf
, new_buf
, exist_buf
);
1332 /* locally configured routes to advertise do not have su_remote */
1333 if (new->peer
->su_remote
== NULL
) {
1334 *reason
= bgp_path_selection_local_configured
;
1337 if (exist
->peer
->su_remote
== NULL
) {
1338 *reason
= bgp_path_selection_local_configured
;
1342 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1345 *reason
= bgp_path_selection_neighbor_ip
;
1348 "%s: %s loses to %s due to Neighor IP comparison",
1349 pfx_buf
, new_buf
, exist_buf
);
1354 *reason
= bgp_path_selection_neighbor_ip
;
1357 "%s: %s wins over %s due to Neighor IP comparison",
1358 pfx_buf
, new_buf
, exist_buf
);
1362 *reason
= bgp_path_selection_default
;
1364 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1365 pfx_buf
, new_buf
, exist_buf
);
1371 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1372 struct bgp_path_info
*exist
, int *paths_eq
)
1374 enum bgp_path_selection_reason reason
;
1375 char pfx_buf
[PREFIX2STR_BUFFER
];
1377 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1378 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1381 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1382 * is preferred, or 0 if they are the same (usually will only occur if
1383 * multipath is enabled
1384 * This version is compatible with */
1385 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1386 struct bgp_path_info
*exist
, char *pfx_buf
,
1387 afi_t afi
, safi_t safi
,
1388 enum bgp_path_selection_reason
*reason
)
1392 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1406 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1407 const struct prefix
*p
,
1408 struct attr
*attr
, afi_t afi
,
1411 struct bgp_filter
*filter
;
1412 enum filter_type ret
= FILTER_PERMIT
;
1414 filter
= &peer
->filter
[afi
][safi
];
1416 #define FILTER_EXIST_WARN(F, f, filter) \
1417 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1418 zlog_debug("%s: Could not find configured input %s-list %s!", \
1419 peer->host, #f, F##_IN_NAME(filter));
1421 if (DISTRIBUTE_IN_NAME(filter
)) {
1422 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1424 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1431 if (PREFIX_LIST_IN_NAME(filter
)) {
1432 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1434 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1441 if (FILTER_LIST_IN_NAME(filter
)) {
1442 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1444 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1445 == AS_FILTER_DENY
) {
1452 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1453 char pfxprint
[PREFIX2STR_BUFFER
];
1455 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1456 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1457 ret
== FILTER_PERMIT
? "permit" : "deny");
1461 #undef FILTER_EXIST_WARN
1464 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1465 const struct prefix
*p
,
1466 struct attr
*attr
, afi_t afi
,
1469 struct bgp_filter
*filter
;
1470 enum filter_type ret
= FILTER_PERMIT
;
1472 filter
= &peer
->filter
[afi
][safi
];
1474 #define FILTER_EXIST_WARN(F, f, filter) \
1475 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1476 zlog_debug("%s: Could not find configured output %s-list %s!", \
1477 peer->host, #f, F##_OUT_NAME(filter));
1479 if (DISTRIBUTE_OUT_NAME(filter
)) {
1480 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1482 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1489 if (PREFIX_LIST_OUT_NAME(filter
)) {
1490 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1492 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1499 if (FILTER_LIST_OUT_NAME(filter
)) {
1500 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1502 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1503 == AS_FILTER_DENY
) {
1509 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1510 char pfxprint
[PREFIX2STR_BUFFER
];
1512 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1513 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1514 ret
== FILTER_PERMIT
? "permit" : "deny");
1519 #undef FILTER_EXIST_WARN
1522 /* If community attribute includes no_export then return 1. */
1523 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1525 if (attr
->community
) {
1526 /* NO_ADVERTISE check. */
1527 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1530 /* NO_EXPORT check. */
1531 if (peer
->sort
== BGP_PEER_EBGP
1532 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1535 /* NO_EXPORT_SUBCONFED check. */
1536 if (peer
->sort
== BGP_PEER_EBGP
1537 || peer
->sort
== BGP_PEER_CONFED
)
1538 if (community_include(attr
->community
,
1539 COMMUNITY_NO_EXPORT_SUBCONFED
))
1545 /* Route reflection loop check. */
1546 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1548 struct in_addr cluster_id
;
1549 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1552 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1553 cluster_id
= peer
->bgp
->cluster_id
;
1555 cluster_id
= peer
->bgp
->router_id
;
1557 if (cluster_loop_check(cluster
, cluster_id
))
1563 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1564 struct attr
*attr
, afi_t afi
, safi_t safi
,
1565 const char *rmap_name
, mpls_label_t
*label
,
1566 uint32_t num_labels
, struct bgp_dest
*dest
)
1568 struct bgp_filter
*filter
;
1569 struct bgp_path_info rmap_path
= { 0 };
1570 struct bgp_path_info_extra extra
= { 0 };
1571 route_map_result_t ret
;
1572 struct route_map
*rmap
= NULL
;
1574 filter
= &peer
->filter
[afi
][safi
];
1576 /* Apply default weight value. */
1577 if (peer
->weight
[afi
][safi
])
1578 attr
->weight
= peer
->weight
[afi
][safi
];
1581 rmap
= route_map_lookup_by_name(rmap_name
);
1586 if (ROUTE_MAP_IN_NAME(filter
)) {
1587 rmap
= ROUTE_MAP_IN(filter
);
1594 /* Route map apply. */
1596 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1597 /* Duplicate current value to new strucutre for modification. */
1598 rmap_path
.peer
= peer
;
1599 rmap_path
.attr
= attr
;
1600 rmap_path
.extra
= &extra
;
1601 rmap_path
.net
= dest
;
1603 extra
.num_labels
= num_labels
;
1604 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1605 memcpy(extra
.label
, label
,
1606 num_labels
* sizeof(mpls_label_t
));
1608 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1610 /* Apply BGP route map to the attribute. */
1611 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1613 peer
->rmap_type
= 0;
1615 if (ret
== RMAP_DENYMATCH
)
1621 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1622 struct attr
*attr
, afi_t afi
, safi_t safi
,
1623 const char *rmap_name
)
1625 struct bgp_path_info rmap_path
;
1626 route_map_result_t ret
;
1627 struct route_map
*rmap
= NULL
;
1631 * So if we get to this point and have no rmap_name
1632 * we want to just show the output as it currently
1638 /* Apply default weight value. */
1639 if (peer
->weight
[afi
][safi
])
1640 attr
->weight
= peer
->weight
[afi
][safi
];
1642 rmap
= route_map_lookup_by_name(rmap_name
);
1645 * If we have a route map name and we do not find
1646 * the routemap that means we have an implicit
1652 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1653 /* Route map apply. */
1654 /* Duplicate current value to new strucutre for modification. */
1655 rmap_path
.peer
= peer
;
1656 rmap_path
.attr
= attr
;
1658 rmap_type
= peer
->rmap_type
;
1659 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1661 /* Apply BGP route map to the attribute. */
1662 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1664 peer
->rmap_type
= rmap_type
;
1666 if (ret
== RMAP_DENYMATCH
)
1668 * caller has multiple error paths with bgp_attr_flush()
1675 /* If this is an EBGP peer with remove-private-AS */
1676 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1677 struct peer
*peer
, struct attr
*attr
)
1679 if (peer
->sort
== BGP_PEER_EBGP
1680 && (peer_af_flag_check(peer
, afi
, safi
,
1681 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1682 || peer_af_flag_check(peer
, afi
, safi
,
1683 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1684 || peer_af_flag_check(peer
, afi
, safi
,
1685 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1686 || peer_af_flag_check(peer
, afi
, safi
,
1687 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1688 // Take action on the entire aspath
1689 if (peer_af_flag_check(peer
, afi
, safi
,
1690 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1691 || peer_af_flag_check(peer
, afi
, safi
,
1692 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1693 if (peer_af_flag_check(
1695 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1696 attr
->aspath
= aspath_replace_private_asns(
1697 attr
->aspath
, bgp
->as
, peer
->as
);
1699 // The entire aspath consists of private ASNs so create
1701 else if (aspath_private_as_check(attr
->aspath
))
1702 attr
->aspath
= aspath_empty_get();
1704 // There are some public and some private ASNs, remove
1707 attr
->aspath
= aspath_remove_private_asns(
1708 attr
->aspath
, peer
->as
);
1711 // 'all' was not specified so the entire aspath must be private
1713 // for us to do anything
1714 else if (aspath_private_as_check(attr
->aspath
)) {
1715 if (peer_af_flag_check(
1717 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1718 attr
->aspath
= aspath_replace_private_asns(
1719 attr
->aspath
, bgp
->as
, peer
->as
);
1721 attr
->aspath
= aspath_empty_get();
1726 /* If this is an EBGP peer with as-override */
1727 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1728 struct peer
*peer
, struct attr
*attr
)
1730 if (peer
->sort
== BGP_PEER_EBGP
1731 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1732 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1733 attr
->aspath
= aspath_replace_specific_asn(
1734 attr
->aspath
, peer
->as
, bgp
->as
);
1738 void bgp_attr_add_llgr_community(struct attr
*attr
)
1740 struct community
*old
;
1741 struct community
*new;
1742 struct community
*merge
;
1743 struct community
*llgr
;
1745 old
= attr
->community
;
1746 llgr
= community_str2com("llgr-stale");
1751 merge
= community_merge(community_dup(old
), llgr
);
1753 if (old
->refcnt
== 0)
1754 community_free(&old
);
1756 new = community_uniq_sort(merge
);
1757 community_free(&merge
);
1759 new = community_dup(llgr
);
1762 community_free(&llgr
);
1764 attr
->community
= new;
1765 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1768 void bgp_attr_add_gshut_community(struct attr
*attr
)
1770 struct community
*old
;
1771 struct community
*new;
1772 struct community
*merge
;
1773 struct community
*gshut
;
1775 old
= attr
->community
;
1776 gshut
= community_str2com("graceful-shutdown");
1781 merge
= community_merge(community_dup(old
), gshut
);
1783 if (old
->refcnt
== 0)
1784 community_free(&old
);
1786 new = community_uniq_sort(merge
);
1787 community_free(&merge
);
1789 new = community_dup(gshut
);
1792 community_free(&gshut
);
1793 attr
->community
= new;
1794 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1796 /* When we add the graceful-shutdown community we must also
1797 * lower the local-preference */
1798 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1799 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1803 /* Notify BGP Conditional advertisement scanner process. */
1804 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1806 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1807 afi_t afi
= SUBGRP_AFI(subgrp
);
1808 safi_t safi
= SUBGRP_SAFI(subgrp
);
1809 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1811 if (!ADVERTISE_MAP_NAME(filter
))
1814 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1817 peer
->advmap_table_change
= true;
1821 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1823 if (family
== AF_INET
) {
1824 attr
->nexthop
.s_addr
= INADDR_ANY
;
1825 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1827 if (family
== AF_INET6
)
1828 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1829 if (family
== AF_EVPN
)
1830 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1833 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1834 struct update_subgroup
*subgrp
,
1835 const struct prefix
*p
, struct attr
*attr
,
1836 bool skip_rmap_check
)
1838 struct bgp_filter
*filter
;
1841 struct peer
*onlypeer
;
1843 struct attr
*piattr
;
1844 route_map_result_t ret
;
1849 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1850 bool nh_reset
= false;
1853 if (DISABLE_BGP_ANNOUNCE
)
1856 afi
= SUBGRP_AFI(subgrp
);
1857 safi
= SUBGRP_SAFI(subgrp
);
1858 peer
= SUBGRP_PEER(subgrp
);
1860 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1861 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1864 filter
= &peer
->filter
[afi
][safi
];
1865 bgp
= SUBGRP_INST(subgrp
);
1866 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1869 #ifdef ENABLE_BGP_VNC
1870 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1871 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1872 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1875 * direct and direct_ext type routes originate internally even
1876 * though they can have peer pointers that reference other
1879 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1885 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1886 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1887 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1888 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1890 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1895 /* With addpath we may be asked to TX all kinds of paths so make sure
1897 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1898 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1899 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1903 /* If this is not the bestpath then check to see if there is an enabled
1905 * feature that requires us to advertise it */
1906 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1907 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1912 /* Aggregate-address suppress check. */
1913 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
1917 * If we are doing VRF 2 VRF leaking via the import
1918 * statement, we want to prevent the route going
1919 * off box as that the RT and RD created are localy
1920 * significant and globaly useless.
1922 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1923 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1926 /* If it's labeled safi, make sure the route has a valid label. */
1927 if (safi
== SAFI_LABELED_UNICAST
) {
1928 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1929 if (!bgp_is_valid_label(&label
)) {
1930 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1931 zlog_debug("u%" PRIu64
":s%" PRIu64
1932 " %pFX is filtered - no label (%p)",
1933 subgrp
->update_group
->id
, subgrp
->id
,
1939 /* Do not send back route to sender. */
1940 if (onlypeer
&& from
== onlypeer
) {
1944 /* Do not send the default route in the BGP table if the neighbor is
1945 * configured for default-originate */
1946 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1947 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1948 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1950 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1954 /* Transparency check. */
1955 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1956 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1961 /* If community is not disabled check the no-export and local. */
1962 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1963 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1964 zlog_debug("%s: community filter check fail for %pFX",
1969 /* If the attribute has originator-id and it is same as remote
1971 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1972 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1973 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1975 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1980 /* ORF prefix-list filter check */
1981 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1982 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1983 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1984 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1985 if (peer
->orf_plist
[afi
][safi
]) {
1986 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1988 if (bgp_debug_update(NULL
, p
,
1989 subgrp
->update_group
, 0))
1991 "%s [Update:SEND] %pFX is filtered via ORF",
1997 /* Output filter check. */
1998 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1999 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2000 zlog_debug("%s [Update:SEND] %pFX is filtered",
2005 /* AS path loop check. */
2006 if (onlypeer
&& onlypeer
->as_path_loop_detection
2007 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
2008 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2010 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2011 onlypeer
->host
, onlypeer
->as
);
2015 /* If we're a CONFED we need to loop check the CONFED ID too */
2016 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2017 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
2018 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2020 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
2021 peer
->host
, bgp
->confed_id
);
2026 /* Route-Reflect check. */
2027 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2032 /* IBGP reflection check. */
2033 if (reflect
&& !samepeer_safe
) {
2034 /* A route from a Client peer. */
2035 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2036 PEER_FLAG_REFLECTOR_CLIENT
)) {
2037 /* Reflect to all the Non-Client peers and also to the
2038 Client peers other than the originator. Originator
2040 is already done. So there is noting to do. */
2041 /* no bgp client-to-client reflection check. */
2042 if (CHECK_FLAG(bgp
->flags
,
2043 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2044 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2045 PEER_FLAG_REFLECTOR_CLIENT
))
2048 /* A route from a Non-client peer. Reflect to all other
2050 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2051 PEER_FLAG_REFLECTOR_CLIENT
))
2056 /* For modify attribute, copy it to temporary structure. */
2059 /* If local-preference is not set. */
2060 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2061 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2062 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2063 attr
->local_pref
= bgp
->default_local_pref
;
2066 /* If originator-id is not set and the route is to be reflected,
2067 set the originator id */
2069 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2070 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2071 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2074 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2076 if (peer
->sort
== BGP_PEER_EBGP
2077 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2078 if (from
!= bgp
->peer_self
&& !transparent
2079 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2080 PEER_FLAG_MED_UNCHANGED
))
2082 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2085 /* Since the nexthop attribute can vary per peer, it is not explicitly
2087 * in announce check, only certain flags and length (or number of
2089 * -- for IPv6/MP_REACH) are set here in order to guide the update
2091 * code in setting the nexthop(s) on a per peer basis in
2093 * Typically, the source nexthop in the attribute is preserved but in
2095 * scenarios where we know it will always be overwritten, we reset the
2096 * nexthop to "0" in an attempt to achieve better Update packing. An
2097 * example of this is when a prefix from each of 2 IBGP peers needs to
2099 * announced to an EBGP peer (and they have the same attributes barring
2103 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2105 #define NEXTHOP_IS_V6 \
2106 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2107 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2108 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2109 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2111 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2113 * the peer (group) is configured to receive link-local nexthop
2115 * and it is available in the prefix OR we're not reflecting the route,
2116 * link-local nexthop address is valid and
2117 * the peer (group) to whom we're going to announce is on a shared
2119 * and this is either a self-originated route or the peer is EBGP.
2120 * By checking if nexthop LL address is valid we are sure that
2121 * we do not announce LL address as `::`.
2123 if (NEXTHOP_IS_V6
) {
2124 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2125 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2126 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2127 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2128 || (!reflect
&& !transparent
2129 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2130 && peer
->shared_network
2131 && (from
== bgp
->peer_self
2132 || peer
->sort
== BGP_PEER_EBGP
))) {
2133 attr
->mp_nexthop_len
=
2134 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2137 /* Clear off link-local nexthop in source, whenever it is not
2139 * ensure more prefixes share the same attribute for
2142 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2143 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2144 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2147 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2148 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2150 /* Route map & unsuppress-map apply. */
2151 if (!skip_rmap_check
2152 && (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2153 struct bgp_path_info rmap_path
= {0};
2154 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2155 struct attr dummy_attr
= {0};
2157 /* Fill temp path_info */
2158 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2161 /* don't confuse inbound and outbound setting */
2162 RESET_FLAG(attr
->rmap_change_flags
);
2165 * The route reflector is not allowed to modify the attributes
2166 * of the reflected IBGP routes unless explicitly allowed.
2168 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2169 && !CHECK_FLAG(bgp
->flags
,
2170 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2172 rmap_path
.attr
= &dummy_attr
;
2175 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2177 if (bgp_path_suppressed(pi
))
2178 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2181 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2184 peer
->rmap_type
= 0;
2186 if (ret
== RMAP_DENYMATCH
) {
2187 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2189 "%s [Update:SEND] %pFX is filtered by route-map",
2192 bgp_attr_flush(attr
);
2197 /* RFC 8212 to prevent route leaks.
2198 * This specification intends to improve this situation by requiring the
2199 * explicit configuration of both BGP Import and Export Policies for any
2200 * External BGP (EBGP) session such as customers, peers, or
2201 * confederation boundaries for all enabled address families. Through
2202 * codification of the aforementioned requirement, operators will
2203 * benefit from consistent behavior across different BGP
2206 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2207 if (!bgp_outbound_policy_exists(peer
, filter
))
2210 /* draft-ietf-idr-deprecate-as-set-confed-set
2211 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2212 * Eventually, This document (if approved) updates RFC 4271
2213 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2214 * and obsoletes RFC 6472.
2216 if (peer
->bgp
->reject_as_sets
)
2217 if (aspath_check_as_sets(attr
->aspath
))
2220 /* Codification of AS 0 Processing */
2221 if (aspath_check_as_zero(attr
->aspath
))
2224 if (bgp_in_graceful_shutdown(bgp
)) {
2225 if (peer
->sort
== BGP_PEER_IBGP
2226 || peer
->sort
== BGP_PEER_CONFED
) {
2227 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2228 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2230 bgp_attr_add_gshut_community(attr
);
2234 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2235 * Capability" to a neighbor MUST perform the following upon receiving
2236 * a route from that neighbor with the "LLGR_STALE" community, or upon
2237 * attaching the "LLGR_STALE" community itself per Section 4.2:
2239 * The route SHOULD NOT be advertised to any neighbor from which the
2240 * Long-lived Graceful Restart Capability has not been received.
2242 if (attr
->community
&&
2243 community_include(attr
->community
, COMMUNITY_LLGR_STALE
) &&
2244 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2245 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2248 /* After route-map has been applied, we check to see if the nexthop to
2249 * be carried in the attribute (that is used for the announcement) can
2250 * be cleared off or not. We do this in all cases where we would be
2251 * setting the nexthop to "ourselves". For IPv6, we only need to
2253 * the global nexthop here; the link-local nexthop would have been
2255 * already, and if not, it is required by the update formation code.
2256 * Also see earlier comments in this function.
2259 * If route-map has performed some operation on the nexthop or the peer
2260 * configuration says to pass it unchanged, we cannot reset the nexthop
2261 * here, so only attempt to do it if these aren't true. Note that the
2262 * route-map handler itself might have cleared the nexthop, if for
2264 * it is configured as 'peer-address'.
2266 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2267 piattr
->rmap_change_flags
)
2269 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2270 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2271 /* We can reset the nexthop, if setting (or forcing) it to
2273 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2274 PEER_FLAG_NEXTHOP_SELF
)
2275 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2276 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2278 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2279 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2280 subgroup_announce_reset_nhop(
2281 (peer_cap_enhe(peer
, afi
, safi
)
2287 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2288 /* Can also reset the nexthop if announcing to EBGP, but
2290 * no peer in the subgroup is on a shared subnet.
2291 * Note: 3rd party nexthop currently implemented for
2294 if ((p
->family
== AF_INET
) &&
2295 (!bgp_subgrp_multiaccess_check_v4(
2298 subgroup_announce_reset_nhop(
2299 (peer_cap_enhe(peer
, afi
, safi
)
2306 if ((p
->family
== AF_INET6
) &&
2307 (!bgp_subgrp_multiaccess_check_v6(
2308 piattr
->mp_nexthop_global
,
2310 subgroup_announce_reset_nhop(
2311 (peer_cap_enhe(peer
, afi
, safi
)
2320 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2322 * This flag is used for leaked vpn-vrf routes
2324 int family
= p
->family
;
2326 if (peer_cap_enhe(peer
, afi
, safi
))
2329 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2331 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2332 __func__
, family2str(family
));
2333 subgroup_announce_reset_nhop(family
, attr
);
2338 /* If IPv6/MP and nexthop does not have any override and happens
2340 * be a link-local address, reset it so that we don't pass along
2342 * source's link-local IPv6 address to recipients who may not be
2344 * the same interface.
2346 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2347 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2348 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2354 * When the next hop is set to ourselves, if all multipaths have
2355 * link-bandwidth announce the cumulative bandwidth as that makes
2356 * the most sense. However, don't modify if the link-bandwidth has
2357 * been explicitly set by user policy.
2360 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2361 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2362 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2363 attr
->ecommunity
= ecommunity_replace_linkbw(
2364 bgp
->as
, attr
->ecommunity
, cum_bw
,
2365 CHECK_FLAG(peer
->flags
,
2366 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2371 static int bgp_route_select_timer_expire(struct thread
*thread
)
2373 struct afi_safi_info
*info
;
2378 info
= THREAD_ARG(thread
);
2383 if (BGP_DEBUG(update
, UPDATE_OUT
))
2384 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2387 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2389 XFREE(MTYPE_TMP
, info
);
2391 /* Best path selection */
2392 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2395 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2396 struct bgp_maxpaths_cfg
*mpath_cfg
,
2397 struct bgp_path_info_pair
*result
, afi_t afi
,
2400 struct bgp_path_info
*new_select
;
2401 struct bgp_path_info
*old_select
;
2402 struct bgp_path_info
*pi
;
2403 struct bgp_path_info
*pi1
;
2404 struct bgp_path_info
*pi2
;
2405 struct bgp_path_info
*nextpi
= NULL
;
2406 int paths_eq
, do_mpath
, debug
;
2407 struct list mp_list
;
2408 char pfx_buf
[PREFIX2STR_BUFFER
];
2409 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2411 bgp_mp_list_init(&mp_list
);
2413 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2415 debug
= bgp_debug_bestpath(dest
);
2418 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2420 dest
->reason
= bgp_path_selection_none
;
2421 /* bgp deterministic-med */
2423 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2425 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2426 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2428 bgp_path_info_unset_flag(dest
, pi1
,
2429 BGP_PATH_DMED_SELECTED
);
2431 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2433 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2435 if (BGP_PATH_HOLDDOWN(pi1
))
2437 if (pi1
->peer
!= bgp
->peer_self
)
2438 if (!peer_established(pi1
->peer
))
2443 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2444 if (CHECK_FLAG(pi2
->flags
,
2445 BGP_PATH_DMED_CHECK
))
2447 if (BGP_PATH_HOLDDOWN(pi2
))
2449 if (pi2
->peer
!= bgp
->peer_self
2452 PEER_STATUS_NSF_WAIT
))
2453 if (pi2
->peer
->status
2457 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2459 && !aspath_cmp_left_confed(
2464 if (bgp_path_info_cmp(
2465 bgp
, pi2
, new_select
,
2466 &paths_eq
, mpath_cfg
, debug
,
2469 bgp_path_info_unset_flag(
2471 BGP_PATH_DMED_SELECTED
);
2475 bgp_path_info_set_flag(
2476 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2479 bgp_path_info_set_flag(dest
, new_select
,
2480 BGP_PATH_DMED_CHECK
);
2481 bgp_path_info_set_flag(dest
, new_select
,
2482 BGP_PATH_DMED_SELECTED
);
2485 bgp_path_info_path_with_addpath_rx_str(
2486 new_select
, path_buf
, sizeof(path_buf
));
2488 "%pBD(%s): %s is the bestpath from AS %u",
2489 dest
, bgp
->name_pretty
, path_buf
,
2490 aspath_get_first_as(
2491 new_select
->attr
->aspath
));
2496 /* Check old selected route and new selected route. */
2499 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2500 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2501 enum bgp_path_selection_reason reason
;
2503 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2506 if (BGP_PATH_HOLDDOWN(pi
)) {
2507 /* reap REMOVED routes, if needs be
2508 * selected route must stay for a while longer though
2510 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2511 && (pi
!= old_select
))
2512 bgp_path_info_reap(dest
, pi
);
2515 zlog_debug("%s: pi %p in holddown", __func__
,
2521 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2522 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2523 if (!peer_established(pi
->peer
)) {
2527 "%s: pi %p non self peer %s not estab state",
2528 __func__
, pi
, pi
->peer
->host
);
2533 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2534 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2535 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2537 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2541 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2543 reason
= dest
->reason
;
2544 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2545 debug
, pfx_buf
, afi
, safi
,
2547 if (new_select
== NULL
&&
2548 reason
!= bgp_path_selection_none
)
2549 dest
->reason
= reason
;
2554 /* Now that we know which path is the bestpath see if any of the other
2556 * qualify as multipaths
2560 bgp_path_info_path_with_addpath_rx_str(
2561 new_select
, path_buf
, sizeof(path_buf
));
2563 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2565 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2566 dest
, bgp
->name_pretty
, path_buf
,
2567 old_select
? old_select
->peer
->host
: "NONE");
2570 if (do_mpath
&& new_select
) {
2571 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2572 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2575 bgp_path_info_path_with_addpath_rx_str(
2576 pi
, path_buf
, sizeof(path_buf
));
2578 if (pi
== new_select
) {
2581 "%pBD(%s): %s is the bestpath, add to the multipath list",
2582 dest
, bgp
->name_pretty
,
2584 bgp_mp_list_add(&mp_list
, pi
);
2588 if (BGP_PATH_HOLDDOWN(pi
))
2591 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2592 && !CHECK_FLAG(pi
->peer
->sflags
,
2593 PEER_STATUS_NSF_WAIT
))
2594 if (!peer_established(pi
->peer
))
2597 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2600 "%pBD: %s has the same nexthop as the bestpath, skip it",
2605 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2606 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2612 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2614 bgp_mp_list_add(&mp_list
, pi
);
2619 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2621 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2622 bgp_mp_list_clear(&mp_list
);
2624 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2626 result
->old
= old_select
;
2627 result
->new = new_select
;
2633 * A new route/change in bestpath of an existing route. Evaluate the path
2634 * for advertisement to the subgroup.
2636 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2637 struct bgp_path_info
*selected
,
2638 struct bgp_dest
*dest
,
2639 uint32_t addpath_tx_id
)
2641 const struct prefix
*p
;
2642 struct peer
*onlypeer
;
2649 p
= bgp_dest_get_prefix(dest
);
2650 afi
= SUBGRP_AFI(subgrp
);
2651 safi
= SUBGRP_SAFI(subgrp
);
2652 bgp
= SUBGRP_INST(subgrp
);
2653 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2656 if (BGP_DEBUG(update
, UPDATE_OUT
))
2657 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2659 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2660 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2661 PEER_STATUS_ORF_WAIT_REFRESH
))
2664 memset(&attr
, 0, sizeof(struct attr
));
2665 /* It's initialized in bgp_announce_check() */
2667 /* Announcement to the subgroup. If the route is filtered withdraw it.
2668 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2669 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2672 advertise
= bgp_check_advertise(bgp
, dest
);
2675 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2677 /* Route is selected, if the route is already installed
2678 * in FIB, then it is advertised
2681 if (!bgp_check_withdrawal(bgp
, dest
))
2682 bgp_adj_out_set_subgroup(
2683 dest
, subgrp
, &attr
, selected
);
2685 bgp_adj_out_unset_subgroup(
2686 dest
, subgrp
, 1, addpath_tx_id
);
2689 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2693 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2695 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2700 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2701 * This is called at the end of route processing.
2703 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2705 struct bgp_path_info
*pi
;
2707 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2708 if (BGP_PATH_HOLDDOWN(pi
))
2710 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2711 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2716 * Has the route changed from the RIB's perspective? This is invoked only
2717 * if the route selection returns the same best route as earlier - to
2718 * determine if we need to update zebra or not.
2720 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2722 struct bgp_path_info
*mpinfo
;
2724 /* If this is multipath, check all selected paths for any nexthop
2725 * change or attribute change. Some attribute changes (e.g., community)
2726 * aren't of relevance to the RIB, but we'll update zebra to ensure
2727 * we handle the case of BGP nexthop change. This is the behavior
2728 * when the best path has an attribute change anyway.
2730 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2731 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2732 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2736 * If this is multipath, check all selected paths for any nexthop change
2738 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2739 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2740 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2741 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2745 /* Nothing has changed from the RIB's perspective. */
2749 struct bgp_process_queue
{
2751 STAILQ_HEAD(, bgp_dest
) pqueue
;
2752 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2754 unsigned int queued
;
2757 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2758 safi_t safi
, struct bgp_dest
*dest
,
2759 struct bgp_path_info
*new_select
,
2760 struct bgp_path_info
*old_select
)
2762 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2764 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2767 if (advertise_type5_routes(bgp
, afi
) && new_select
2768 && is_route_injectable_into_evpn(new_select
)) {
2770 /* apply the route-map */
2771 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2772 route_map_result_t ret
;
2773 struct bgp_path_info rmap_path
;
2774 struct bgp_path_info_extra rmap_path_extra
;
2775 struct attr dummy_attr
;
2777 dummy_attr
= *new_select
->attr
;
2779 /* Fill temp path_info */
2780 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2781 new_select
, new_select
->peer
,
2784 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2786 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2789 if (ret
== RMAP_DENYMATCH
) {
2790 bgp_attr_flush(&dummy_attr
);
2791 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2794 bgp_evpn_advertise_type5_route(
2795 bgp
, p
, &dummy_attr
, afi
, safi
);
2797 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2800 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2801 && is_route_injectable_into_evpn(old_select
))
2802 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2806 * Utility to determine whether a particular path_info should use
2807 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2808 * in a path where we basically _know_ this is a BGP-LU route.
2810 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
2812 /* Certain types get imp null; so do paths where the nexthop is
2815 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2816 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2817 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
2819 else if (new_select
->extra
== NULL
||
2820 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
2821 /* TODO -- should be configurable? */
2828 * old_select = The old best path
2829 * new_select = the new best path
2831 * if (!old_select && new_select)
2832 * We are sending new information on.
2834 * if (old_select && new_select) {
2835 * if (new_select != old_select)
2836 * We have a new best path send a change
2838 * We've received a update with new attributes that needs
2842 * if (old_select && !new_select)
2843 * We have no eligible route that we can announce or the rn
2846 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2847 afi_t afi
, safi_t safi
)
2849 struct bgp_path_info
*new_select
;
2850 struct bgp_path_info
*old_select
;
2851 struct bgp_path_info_pair old_and_new
;
2854 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2856 debug
= bgp_debug_bestpath(dest
);
2859 "%s: bgp delete in progress, ignoring event, p=%pBD",
2863 /* Is it end of initial update? (after startup) */
2865 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2866 sizeof(bgp
->update_delay_zebra_resume_time
));
2868 bgp
->main_zebra_update_hold
= 0;
2869 FOREACH_AFI_SAFI (afi
, safi
) {
2870 if (bgp_fibupd_safi(safi
))
2871 bgp_zebra_announce_table(bgp
, afi
, safi
);
2873 bgp
->main_peers_update_hold
= 0;
2875 bgp_start_routeadv(bgp
);
2879 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2881 debug
= bgp_debug_bestpath(dest
);
2883 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__
,
2884 dest
, bgp
->name_pretty
, afi2str(afi
),
2887 /* The best path calculation for the route is deferred if
2888 * BGP_NODE_SELECT_DEFER is set
2890 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2891 if (BGP_DEBUG(update
, UPDATE_OUT
))
2892 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
2896 /* Best path selection. */
2897 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2899 old_select
= old_and_new
.old
;
2900 new_select
= old_and_new
.new;
2902 /* Do we need to allocate or free labels?
2903 * Right now, since we only deal with per-prefix labels, it is not
2904 * necessary to do this upon changes to best path. Exceptions:
2905 * - label index has changed -> recalculate resulting label
2906 * - path_info sub_type changed -> switch to/from implicit-null
2907 * - no valid label (due to removed static label binding) -> get new one
2909 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2912 || bgp_label_index_differs(new_select
, old_select
)
2913 || new_select
->sub_type
!= old_select
->sub_type
2914 || !bgp_is_valid_label(&dest
->local_label
)) {
2915 /* Enforced penultimate hop popping:
2916 * implicit-null for local routes, aggregate
2917 * and redistributed routes
2919 if (bgp_lu_need_imp_null(new_select
)) {
2922 BGP_NODE_REGISTERED_FOR_LABEL
)
2925 BGP_NODE_LABEL_REQUESTED
))
2926 bgp_unregister_for_label(dest
);
2927 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2928 &dest
->local_label
);
2929 bgp_set_valid_label(&dest
->local_label
);
2931 bgp_register_for_label(dest
,
2934 } else if (CHECK_FLAG(dest
->flags
,
2935 BGP_NODE_REGISTERED_FOR_LABEL
)
2936 || CHECK_FLAG(dest
->flags
,
2937 BGP_NODE_LABEL_REQUESTED
)) {
2938 bgp_unregister_for_label(dest
);
2940 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
2941 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
2942 bgp_unregister_for_label(dest
);
2947 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
2948 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
2949 safi2str(safi
), old_select
, new_select
);
2951 /* If best route remains the same and this is not due to user-initiated
2952 * clear, see exactly what needs to be done.
2954 if (old_select
&& old_select
== new_select
2955 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2956 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2957 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2958 if (bgp_zebra_has_route_changed(old_select
)) {
2959 #ifdef ENABLE_BGP_VNC
2960 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2961 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2963 if (bgp_fibupd_safi(safi
)
2964 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2966 if (BGP_SUPPRESS_FIB_ENABLED(bgp
)
2967 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
2968 SET_FLAG(dest
->flags
,
2969 BGP_NODE_FIB_INSTALL_PENDING
);
2971 if (new_select
->type
== ZEBRA_ROUTE_BGP
2972 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2973 || new_select
->sub_type
2974 == BGP_ROUTE_IMPORTED
))
2976 bgp_zebra_announce(dest
, p
, old_select
,
2981 /* If there is a change of interest to peers, reannounce the
2983 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2984 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2985 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2986 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2988 /* unicast routes must also be annouced to
2989 * labeled-unicast update-groups */
2990 if (safi
== SAFI_UNICAST
)
2991 group_announce_route(bgp
, afi
,
2992 SAFI_LABELED_UNICAST
, dest
,
2995 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2996 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
2999 /* advertise/withdraw type-5 routes */
3000 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3001 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3002 bgp_process_evpn_route_injection(
3003 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3005 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3006 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3007 bgp_zebra_clear_route_change_flags(dest
);
3008 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3012 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3014 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3016 /* bestpath has changed; bump version */
3017 if (old_select
|| new_select
) {
3018 bgp_bump_version(dest
);
3020 if (!bgp
->t_rmap_def_originate_eval
) {
3024 update_group_refresh_default_originate_route_map
,
3025 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3026 &bgp
->t_rmap_def_originate_eval
);
3031 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3034 zlog_debug("%s: setting SELECTED flag", __func__
);
3035 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3036 bgp_path_info_unset_flag(dest
, new_select
,
3037 BGP_PATH_ATTR_CHANGED
);
3038 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3039 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3042 #ifdef ENABLE_BGP_VNC
3043 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3044 if (old_select
!= new_select
) {
3046 vnc_import_bgp_exterior_del_route(bgp
, p
,
3048 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3051 vnc_import_bgp_exterior_add_route(bgp
, p
,
3053 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3059 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3061 /* unicast routes must also be annouced to labeled-unicast update-groups
3063 if (safi
== SAFI_UNICAST
)
3064 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3068 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3069 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3071 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3072 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3073 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3074 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3076 if (BGP_SUPPRESS_FIB_ENABLED(bgp
))
3077 SET_FLAG(dest
->flags
,
3078 BGP_NODE_FIB_INSTALL_PENDING
);
3080 /* if this is an evpn imported type-5 prefix,
3081 * we need to withdraw the route first to clear
3082 * the nh neigh and the RMAC entry.
3085 is_route_parent_evpn(old_select
))
3086 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3088 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3090 /* Withdraw the route from the kernel. */
3091 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3092 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3093 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3094 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3096 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3100 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3103 /* Clear any route change flags. */
3104 bgp_zebra_clear_route_change_flags(dest
);
3106 /* Reap old select bgp_path_info, if it has been removed */
3107 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3108 bgp_path_info_reap(dest
, old_select
);
3110 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3114 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3115 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3117 struct bgp_dest
*dest
;
3119 struct afi_safi_info
*thread_info
;
3121 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3122 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3124 thread_info
= THREAD_ARG(t
);
3125 XFREE(MTYPE_TMP
, thread_info
);
3126 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3129 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3130 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3131 get_afi_safi_str(afi
, safi
, false),
3132 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3135 /* Process the route list */
3136 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3137 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0;
3138 dest
= bgp_route_next(dest
)) {
3139 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3142 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3143 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3144 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3146 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
) {
3147 bgp_dest_unlock_node(dest
);
3152 /* Send EOR message when all routes are processed */
3153 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3154 bgp_send_delayed_eor(bgp
);
3155 /* Send route processing complete message to RIB */
3156 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3157 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3161 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3163 thread_info
->afi
= afi
;
3164 thread_info
->safi
= safi
;
3165 thread_info
->bgp
= bgp
;
3167 /* If there are more routes to be processed, start the
3170 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3171 BGP_ROUTE_SELECT_DELAY
,
3172 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3176 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3178 struct bgp_process_queue
*pqnode
= data
;
3179 struct bgp
*bgp
= pqnode
->bgp
;
3180 struct bgp_table
*table
;
3181 struct bgp_dest
*dest
;
3184 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3185 bgp_process_main_one(bgp
, NULL
, 0, 0);
3186 /* should always have dedicated wq call */
3187 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3191 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3192 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3193 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3194 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3195 table
= bgp_dest_table(dest
);
3196 /* note, new DESTs may be added as part of processing */
3197 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3199 bgp_dest_unlock_node(dest
);
3200 bgp_table_unlock(table
);
3206 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3208 struct bgp_process_queue
*pqnode
= data
;
3210 bgp_unlock(pqnode
->bgp
);
3212 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3215 void bgp_process_queue_init(struct bgp
*bgp
)
3217 if (!bgp
->process_queue
) {
3220 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3221 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3224 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3225 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3226 bgp
->process_queue
->spec
.max_retries
= 0;
3227 bgp
->process_queue
->spec
.hold
= 50;
3228 /* Use a higher yield value of 50ms for main queue processing */
3229 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3232 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3234 struct bgp_process_queue
*pqnode
;
3236 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3237 sizeof(struct bgp_process_queue
));
3239 /* unlocked in bgp_processq_del */
3240 pqnode
->bgp
= bgp_lock(bgp
);
3241 STAILQ_INIT(&pqnode
->pqueue
);
3246 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3248 #define ARBITRARY_PROCESS_QLEN 10000
3249 struct work_queue
*wq
= bgp
->process_queue
;
3250 struct bgp_process_queue
*pqnode
;
3251 int pqnode_reuse
= 0;
3253 /* already scheduled for processing? */
3254 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3257 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3260 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3261 if (BGP_DEBUG(update
, UPDATE_OUT
))
3262 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3267 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3268 if (BGP_DEBUG(update
, UPDATE_OUT
))
3270 "Soft reconfigure table in progress for route %p",
3278 /* Add route nodes to an existing work queue item until reaching the
3279 limit only if is from the same BGP view and it's not an EOIU marker
3281 if (work_queue_item_count(wq
)) {
3282 struct work_queue_item
*item
= work_queue_last_item(wq
);
3283 pqnode
= item
->data
;
3285 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3286 || pqnode
->bgp
!= bgp
3287 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3288 pqnode
= bgp_processq_alloc(bgp
);
3292 pqnode
= bgp_processq_alloc(bgp
);
3293 /* all unlocked in bgp_process_wq */
3294 bgp_table_lock(bgp_dest_table(dest
));
3296 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3297 bgp_dest_lock_node(dest
);
3299 /* can't be enqueued twice */
3300 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3301 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3305 work_queue_add(wq
, pqnode
);
3310 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3312 struct bgp_process_queue
*pqnode
;
3314 if (bgp
->process_queue
== NULL
)
3317 pqnode
= bgp_processq_alloc(bgp
);
3319 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3320 work_queue_add(bgp
->process_queue
, pqnode
);
3323 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3327 peer
= THREAD_ARG(thread
);
3328 peer
->t_pmax_restart
= NULL
;
3330 if (bgp_debug_neighbor_events(peer
))
3332 "%s Maximum-prefix restart timer expired, restore peering",
3335 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3336 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3341 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3345 bool filtered
= false;
3346 struct bgp_dest
*dest
;
3347 struct bgp_adj_in
*ain
;
3348 struct attr attr
= {};
3349 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3351 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3352 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3353 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3357 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3361 if (bgp_input_modifier(
3362 peer
, rn_p
, &attr
, afi
, safi
,
3363 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3371 bgp_attr_undup(&attr
, ain
->attr
);
3378 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3382 iana_safi_t pkt_safi
;
3383 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3384 PEER_FLAG_MAX_PREFIX_FORCE
))
3385 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3386 + peer
->pcount
[afi
][safi
]
3387 : peer
->pcount
[afi
][safi
];
3389 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3392 if (pcount
> peer
->pmax
[afi
][safi
]) {
3393 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3394 PEER_STATUS_PREFIX_LIMIT
)
3399 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3400 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3401 peer
->pmax
[afi
][safi
]);
3402 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3404 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3405 PEER_FLAG_MAX_PREFIX_WARNING
))
3408 /* Convert AFI, SAFI to values for packet. */
3409 pkt_afi
= afi_int2iana(afi
);
3410 pkt_safi
= safi_int2iana(safi
);
3414 ndata
[0] = (pkt_afi
>> 8);
3416 ndata
[2] = pkt_safi
;
3417 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3418 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3419 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3420 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3422 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3423 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3424 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3428 /* Dynamic peers will just close their connection. */
3429 if (peer_dynamic_neighbor(peer
))
3432 /* restart timer start */
3433 if (peer
->pmax_restart
[afi
][safi
]) {
3434 peer
->v_pmax_restart
=
3435 peer
->pmax_restart
[afi
][safi
] * 60;
3437 if (bgp_debug_neighbor_events(peer
))
3439 "%s Maximum-prefix restart timer started for %d secs",
3440 peer
->host
, peer
->v_pmax_restart
);
3442 BGP_TIMER_ON(peer
->t_pmax_restart
,
3443 bgp_maximum_prefix_restart_timer
,
3444 peer
->v_pmax_restart
);
3449 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3450 PEER_STATUS_PREFIX_LIMIT
);
3453 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3454 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3455 PEER_STATUS_PREFIX_THRESHOLD
)
3460 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3461 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3462 peer
->pmax
[afi
][safi
]);
3463 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3464 PEER_STATUS_PREFIX_THRESHOLD
);
3466 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3467 PEER_STATUS_PREFIX_THRESHOLD
);
3471 /* Unconditionally remove the route from the RIB, without taking
3472 * damping into consideration (eg, because the session went down)
3474 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3475 struct peer
*peer
, afi_t afi
, safi_t safi
)
3478 struct bgp
*bgp
= NULL
;
3479 bool delete_route
= false;
3481 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3484 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3485 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3487 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3490 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3491 delete_route
= true;
3492 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3493 delete_route
= true;
3495 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3496 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3497 bgp
= pi
->peer
->bgp
;
3498 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3503 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3504 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3507 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3508 struct peer
*peer
, afi_t afi
, safi_t safi
,
3509 struct prefix_rd
*prd
)
3511 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3513 /* apply dampening, if result is suppressed, we'll be retaining
3514 * the bgp_path_info in the RIB for historical reference.
3516 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3517 && peer
->sort
== BGP_PEER_EBGP
)
3518 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3519 == BGP_DAMP_SUPPRESSED
) {
3520 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3525 #ifdef ENABLE_BGP_VNC
3526 if (safi
== SAFI_MPLS_VPN
) {
3527 struct bgp_dest
*pdest
= NULL
;
3528 struct bgp_table
*table
= NULL
;
3530 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3531 (struct prefix
*)prd
);
3532 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3533 table
= bgp_dest_get_bgp_table_info(pdest
);
3535 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3536 peer
->bgp
, prd
, table
, p
, pi
);
3538 bgp_dest_unlock_node(pdest
);
3540 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3541 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3543 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3544 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3549 /* If this is an EVPN route, process for un-import. */
3550 if (safi
== SAFI_EVPN
)
3551 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3553 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3556 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3557 struct peer
*peer
, struct attr
*attr
,
3558 struct bgp_dest
*dest
)
3560 struct bgp_path_info
*new;
3562 /* Make new BGP info. */
3563 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3565 new->instance
= instance
;
3566 new->sub_type
= sub_type
;
3569 new->uptime
= bgp_clock();
3574 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3575 union gw_addr
*gw_ip
)
3577 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(path
->attr
);
3578 union gw_addr path_gw_ip
, *path_gw_ip_remote
;
3584 if (afi
!= AFI_L2VPN
)
3587 path_gw_ip
= eo
->gw_ip
;
3589 if (gw_ip
== NULL
) {
3590 memset(&temp
, 0, sizeof(temp
));
3591 path_gw_ip_remote
= &temp
.ip
;
3593 path_gw_ip_remote
= gw_ip
;
3595 return !!memcmp(&path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
));
3598 /* Check if received nexthop is valid or not. */
3599 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3600 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3601 struct bgp_dest
*dest
)
3604 bool is_bgp_static_route
=
3605 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3609 * Only validated for unicast and multicast currently.
3610 * Also valid for EVPN where the nexthop is an IP address.
3611 * If we are a bgp static route being checked then there is
3612 * no need to check to see if the nexthop is martian as
3613 * that it should be ok.
3615 if (is_bgp_static_route
||
3616 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3619 /* If NEXT_HOP is present, validate it. */
3620 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3621 if (attr
->nexthop
.s_addr
== INADDR_ANY
3622 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3623 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3627 /* If MP_NEXTHOP is present, validate it. */
3628 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3629 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3630 * it is not an IPv6 link-local address.
3632 * If we receive an UPDATE with nexthop length set to 32 bytes
3633 * we shouldn't discard an UPDATE if it's set to (::).
3634 * The link-local (2st) is validated along the code path later.
3636 if (attr
->mp_nexthop_len
) {
3637 switch (attr
->mp_nexthop_len
) {
3638 case BGP_ATTR_NHLEN_IPV4
:
3639 case BGP_ATTR_NHLEN_VPNV4
:
3640 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3642 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3643 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3647 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3648 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3649 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3650 &attr
->mp_nexthop_global
)
3651 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3652 || IN6_IS_ADDR_MULTICAST(
3653 &attr
->mp_nexthop_global
)
3654 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3657 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3658 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3659 || IN6_IS_ADDR_MULTICAST(
3660 &attr
->mp_nexthop_global
)
3661 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3674 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3676 struct community
*old
;
3677 struct community
*new;
3678 struct community
*merge
;
3679 struct community
*no_export
;
3681 old
= attr
->community
;
3682 no_export
= community_str2com("no-export");
3687 merge
= community_merge(community_dup(old
), no_export
);
3690 community_free(&old
);
3692 new = community_uniq_sort(merge
);
3693 community_free(&merge
);
3695 new = community_dup(no_export
);
3698 community_free(&no_export
);
3700 attr
->community
= new;
3701 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
3704 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3705 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3706 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3707 uint32_t num_labels
, int soft_reconfig
,
3708 struct bgp_route_evpn
*evpn
)
3711 int aspath_loop_count
= 0;
3712 struct bgp_dest
*dest
;
3714 struct attr new_attr
;
3715 struct attr
*attr_new
;
3716 struct bgp_path_info
*pi
;
3717 struct bgp_path_info
*new;
3718 struct bgp_path_info_extra
*extra
;
3720 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3722 int do_loop_check
= 1;
3723 int has_valid_label
= 0;
3725 uint8_t pi_type
= 0;
3726 uint8_t pi_sub_type
= 0;
3727 bool force_evpn_import
= false;
3728 safi_t orig_safi
= safi
;
3730 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3731 char pfxprint
[PREFIX2STR_BUFFER
];
3733 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3734 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3738 #ifdef ENABLE_BGP_VNC
3739 int vnc_implicit_withdraw
= 0;
3743 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3744 if (orig_safi
== SAFI_LABELED_UNICAST
)
3745 safi
= SAFI_UNICAST
;
3747 memset(&new_attr
, 0, sizeof(struct attr
));
3748 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3749 new_attr
.label
= MPLS_INVALID_LABEL
;
3752 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3753 /* TODO: Check to see if we can get rid of "is_valid_label" */
3754 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3755 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3757 has_valid_label
= bgp_is_valid_label(label
);
3759 if (has_valid_label
)
3760 assert(label
!= NULL
);
3762 /* Update overlay index of the attribute */
3763 if (afi
== AFI_L2VPN
&& evpn
)
3764 memcpy(&attr
->evpn_overlay
, evpn
,
3765 sizeof(struct bgp_route_evpn
));
3767 /* When peer's soft reconfiguration enabled. Record input packet in
3770 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3771 && peer
!= bgp
->peer_self
)
3772 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3774 /* Check previously received route. */
3775 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3776 if (pi
->peer
== peer
&& pi
->type
== type
3777 && pi
->sub_type
== sub_type
3778 && pi
->addpath_rx_id
== addpath_id
)
3781 /* AS path local-as loop check. */
3782 if (peer
->change_local_as
) {
3783 if (peer
->allowas_in
[afi
][safi
])
3784 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3785 else if (!CHECK_FLAG(peer
->flags
,
3786 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3787 aspath_loop_count
= 1;
3789 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3790 > aspath_loop_count
) {
3791 peer
->stat_pfx_aspath_loop
++;
3792 reason
= "as-path contains our own AS;";
3797 /* If the peer is configured for "allowas-in origin" and the last ASN in
3799 * as-path is our ASN then we do not need to call aspath_loop_check
3801 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3802 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3805 /* AS path loop check. */
3806 if (do_loop_check
) {
3807 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3808 > peer
->allowas_in
[afi
][safi
]
3809 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3810 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3811 > peer
->allowas_in
[afi
][safi
])) {
3812 peer
->stat_pfx_aspath_loop
++;
3813 reason
= "as-path contains our own AS;";
3818 /* Route reflector originator ID check. */
3819 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3820 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3821 peer
->stat_pfx_originator_loop
++;
3822 reason
= "originator is us;";
3826 /* Route reflector cluster ID check. */
3827 if (bgp_cluster_filter(peer
, attr
)) {
3828 peer
->stat_pfx_cluster_loop
++;
3829 reason
= "reflected from the same cluster;";
3833 /* Apply incoming filter. */
3834 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
3835 peer
->stat_pfx_filter
++;
3840 /* RFC 8212 to prevent route leaks.
3841 * This specification intends to improve this situation by requiring the
3842 * explicit configuration of both BGP Import and Export Policies for any
3843 * External BGP (EBGP) session such as customers, peers, or
3844 * confederation boundaries for all enabled address families. Through
3845 * codification of the aforementioned requirement, operators will
3846 * benefit from consistent behavior across different BGP
3849 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3850 if (!bgp_inbound_policy_exists(peer
,
3851 &peer
->filter
[afi
][safi
])) {
3852 reason
= "inbound policy missing";
3856 /* draft-ietf-idr-deprecate-as-set-confed-set
3857 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3858 * Eventually, This document (if approved) updates RFC 4271
3859 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3860 * and obsoletes RFC 6472.
3862 if (peer
->bgp
->reject_as_sets
)
3863 if (aspath_check_as_sets(attr
->aspath
)) {
3865 "as-path contains AS_SET or AS_CONFED_SET type;";
3871 /* Apply incoming route-map.
3872 * NB: new_attr may now contain newly allocated values from route-map
3874 * commands, so we need bgp_attr_flush in the error paths, until we
3876 * the attr (which takes over the memory references) */
3877 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
3880 peer
->stat_pfx_filter
++;
3881 reason
= "route-map;";
3882 bgp_attr_flush(&new_attr
);
3886 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3887 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3888 /* remove from RIB previous entry */
3889 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3892 if (peer
->sort
== BGP_PEER_EBGP
) {
3895 * A BGP speaker receiving an announcement tagged with the
3896 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3897 * NO_EXPORT community as defined in RFC1997, or a
3898 * similar community, to prevent propagation of the
3899 * prefix outside the local AS. The community to prevent
3900 * propagation SHOULD be chosen according to the operator's
3903 if (new_attr
.community
3904 && community_include(new_attr
.community
,
3905 COMMUNITY_BLACKHOLE
))
3906 bgp_attr_add_no_export_community(&new_attr
);
3908 /* If we receive the graceful-shutdown community from an eBGP
3909 * peer we must lower local-preference */
3910 if (new_attr
.community
3911 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3912 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3913 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3915 /* If graceful-shutdown is configured then add the GSHUT
3916 * community to all paths received from eBGP peers */
3917 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3918 bgp_attr_add_gshut_community(&new_attr
);
3923 pi_sub_type
= pi
->sub_type
;
3926 /* next hop check. */
3927 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3928 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3930 peer
->stat_pfx_nh_invalid
++;
3931 reason
= "martian or self next-hop;";
3932 bgp_attr_flush(&new_attr
);
3936 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3937 peer
->stat_pfx_nh_invalid
++;
3938 reason
= "self mac;";
3942 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3944 * Suppress fib is enabled
3945 * BGP_OPT_NO_FIB is not enabled
3946 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3947 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3949 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
3950 && (sub_type
== BGP_ROUTE_NORMAL
)
3951 && (!bgp_option_check(BGP_OPT_NO_FIB
))
3952 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
3953 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
3955 attr_new
= bgp_attr_intern(&new_attr
);
3957 /* If maximum prefix count is configured and current prefix
3960 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3963 /* If the update is implicit withdraw. */
3965 pi
->uptime
= bgp_clock();
3966 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3968 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3970 /* Same attribute comes in. */
3971 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3973 && (!has_valid_label
3974 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3975 num_labels
* sizeof(mpls_label_t
))
3977 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3978 BGP_CONFIG_DAMPENING
)
3979 && peer
->sort
== BGP_PEER_EBGP
3980 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3981 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3982 bgp_debug_rdpfxpath2str(
3983 afi
, safi
, prd
, p
, label
,
3984 num_labels
, addpath_id
? 1 : 0,
3985 addpath_id
, evpn
, pfx_buf
,
3987 zlog_debug("%s rcvd %s", peer
->host
,
3991 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3992 != BGP_DAMP_SUPPRESSED
) {
3993 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3995 bgp_process(bgp
, dest
, afi
, safi
);
3997 } else /* Duplicate - odd */
3999 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4000 if (!peer
->rcvd_attr_printed
) {
4002 "%s rcvd UPDATE w/ attr: %s",
4004 peer
->rcvd_attr_str
);
4005 peer
->rcvd_attr_printed
= 1;
4008 bgp_debug_rdpfxpath2str(
4009 afi
, safi
, prd
, p
, label
,
4010 num_labels
, addpath_id
? 1 : 0,
4011 addpath_id
, evpn
, pfx_buf
,
4014 "%s rcvd %s...duplicate ignored",
4015 peer
->host
, pfx_buf
);
4018 /* graceful restart STALE flag unset. */
4019 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4020 bgp_path_info_unset_flag(
4021 dest
, pi
, BGP_PATH_STALE
);
4022 bgp_dest_set_defer_flag(dest
, false);
4023 bgp_process(bgp
, dest
, afi
, safi
);
4027 bgp_dest_unlock_node(dest
);
4028 bgp_attr_unintern(&attr_new
);
4033 /* Withdraw/Announce before we fully processed the withdraw */
4034 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4035 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4036 bgp_debug_rdpfxpath2str(
4037 afi
, safi
, prd
, p
, label
, num_labels
,
4038 addpath_id
? 1 : 0, addpath_id
, evpn
,
4039 pfx_buf
, sizeof(pfx_buf
));
4041 "%s rcvd %s, flapped quicker than processing",
4042 peer
->host
, pfx_buf
);
4045 bgp_path_info_restore(dest
, pi
);
4048 * If the BGP_PATH_REMOVED flag is set, then EVPN
4049 * routes would have been unimported already when a
4050 * prior BGP withdraw processing happened. Such routes
4051 * need to be imported again, so flag accordingly.
4053 force_evpn_import
= true;
4056 /* Received Logging. */
4057 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4058 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4059 num_labels
, addpath_id
? 1 : 0,
4060 addpath_id
, evpn
, pfx_buf
,
4062 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
4065 /* graceful restart STALE flag unset. */
4066 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4067 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4068 bgp_dest_set_defer_flag(dest
, false);
4071 /* The attribute is changed. */
4072 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4074 /* implicit withdraw, decrement aggregate and pcount here.
4075 * only if update is accepted, they'll increment below.
4077 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4079 /* Update bgp route dampening information. */
4080 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4081 && peer
->sort
== BGP_PEER_EBGP
) {
4082 /* This is implicit withdraw so we should update
4085 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4086 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4088 #ifdef ENABLE_BGP_VNC
4089 if (safi
== SAFI_MPLS_VPN
) {
4090 struct bgp_dest
*pdest
= NULL
;
4091 struct bgp_table
*table
= NULL
;
4093 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4094 (struct prefix
*)prd
);
4095 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4096 table
= bgp_dest_get_bgp_table_info(pdest
);
4098 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4099 bgp
, prd
, table
, p
, pi
);
4101 bgp_dest_unlock_node(pdest
);
4103 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4104 && (safi
== SAFI_UNICAST
)) {
4105 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4107 * Implicit withdraw case.
4109 ++vnc_implicit_withdraw
;
4110 vnc_import_bgp_del_route(bgp
, p
, pi
);
4111 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4116 /* Special handling for EVPN update of an existing route. If the
4117 * extended community attribute has changed, we need to
4119 * the route using its existing extended community. It will be
4120 * subsequently processed for import with the new extended
4123 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4126 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4128 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4131 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
4132 attr_new
->ecommunity
);
4134 if (bgp_debug_update(peer
, p
, NULL
, 1))
4136 "Change in EXT-COMM, existing %s new %s",
4138 pi
->attr
->ecommunity
),
4140 attr_new
->ecommunity
));
4141 if (safi
== SAFI_EVPN
)
4142 bgp_evpn_unimport_route(
4143 bgp
, afi
, safi
, p
, pi
);
4144 else /* SAFI_MPLS_VPN */
4145 vpn_leak_to_vrf_withdraw(bgp
,
4151 /* Update to new attribute. */
4152 bgp_attr_unintern(&pi
->attr
);
4153 pi
->attr
= attr_new
;
4155 /* Update MPLS label */
4156 if (has_valid_label
) {
4157 extra
= bgp_path_info_extra_get(pi
);
4158 if (extra
->label
!= label
) {
4159 memcpy(&extra
->label
, label
,
4160 num_labels
* sizeof(mpls_label_t
));
4161 extra
->num_labels
= num_labels
;
4163 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4164 bgp_set_valid_label(&extra
->label
[0]);
4167 /* Update SRv6 SID */
4168 if (attr
->srv6_l3vpn
) {
4169 extra
= bgp_path_info_extra_get(pi
);
4170 if (sid_diff(&extra
->sid
[0].sid
,
4171 &attr
->srv6_l3vpn
->sid
)) {
4172 sid_copy(&extra
->sid
[0].sid
,
4173 &attr
->srv6_l3vpn
->sid
);
4174 extra
->num_sids
= 1;
4176 extra
->sid
[0].loc_block_len
= 0;
4177 extra
->sid
[0].loc_node_len
= 0;
4178 extra
->sid
[0].func_len
= 0;
4179 extra
->sid
[0].arg_len
= 0;
4181 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4182 extra
->sid
[0].loc_block_len
=
4183 attr
->srv6_l3vpn
->loc_block_len
;
4184 extra
->sid
[0].loc_node_len
=
4185 attr
->srv6_l3vpn
->loc_node_len
;
4186 extra
->sid
[0].func_len
=
4187 attr
->srv6_l3vpn
->func_len
;
4188 extra
->sid
[0].arg_len
=
4189 attr
->srv6_l3vpn
->arg_len
;
4193 * draft-ietf-bess-srv6-services-07
4194 * The part of SRv6 SID may be encoded as MPLS
4195 * Label for the efficient packing.
4197 if (attr
->srv6_l3vpn
->transposition_len
!= 0)
4200 decode_label(label
),
4202 ->transposition_offset
,
4204 ->transposition_len
);
4206 } else if (attr
->srv6_vpn
) {
4207 extra
= bgp_path_info_extra_get(pi
);
4208 if (sid_diff(&extra
->sid
[0].sid
,
4209 &attr
->srv6_vpn
->sid
)) {
4210 sid_copy(&extra
->sid
[0].sid
,
4211 &attr
->srv6_vpn
->sid
);
4212 extra
->num_sids
= 1;
4216 #ifdef ENABLE_BGP_VNC
4217 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4218 && (safi
== SAFI_UNICAST
)) {
4219 if (vnc_implicit_withdraw
) {
4221 * Add back the route with its new attributes
4223 * The route is still selected, until the route
4225 * queued by bgp_process actually runs. We have
4227 * update to the VNC side immediately to avoid
4229 * configuration changes (e.g., route-map
4231 * trigger re-importation of the entire RIB.
4233 vnc_import_bgp_add_route(bgp
, p
, pi
);
4234 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4239 /* Update bgp route dampening information. */
4240 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4241 && peer
->sort
== BGP_PEER_EBGP
) {
4242 /* Now we do normal update dampening. */
4243 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4244 if (ret
== BGP_DAMP_SUPPRESSED
) {
4245 bgp_dest_unlock_node(dest
);
4250 /* Nexthop reachability check - for unicast and
4251 * labeled-unicast.. */
4252 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4253 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4254 || (safi
== SAFI_EVPN
&&
4255 bgp_evpn_is_prefix_nht_supported(p
))) {
4256 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4257 && peer
->ttl
== BGP_DEFAULT_TTL
4258 && !CHECK_FLAG(peer
->flags
,
4259 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4260 && !CHECK_FLAG(bgp
->flags
,
4261 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4266 struct bgp
*bgp_nexthop
= bgp
;
4268 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4269 bgp_nexthop
= pi
->extra
->bgp_orig
;
4271 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4273 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4274 safi
, pi
, NULL
, connected
,
4276 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4277 bgp_path_info_set_flag(dest
, pi
,
4280 if (BGP_DEBUG(nht
, NHT
)) {
4281 zlog_debug("%s(%pI4): NH unresolved",
4283 (in_addr_t
*)&attr_new
->nexthop
);
4285 bgp_path_info_unset_flag(dest
, pi
,
4289 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4291 #ifdef ENABLE_BGP_VNC
4292 if (safi
== SAFI_MPLS_VPN
) {
4293 struct bgp_dest
*pdest
= NULL
;
4294 struct bgp_table
*table
= NULL
;
4296 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4297 (struct prefix
*)prd
);
4298 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4299 table
= bgp_dest_get_bgp_table_info(pdest
);
4301 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4302 bgp
, prd
, table
, p
, pi
);
4304 bgp_dest_unlock_node(pdest
);
4308 /* If this is an EVPN route and some attribute has changed,
4309 * or we are explicitly told to perform a route import, process
4310 * route for import. If the extended community has changed, we
4312 * have done the un-import earlier and the import would result
4314 * route getting injected into appropriate L2 VNIs. If it is
4316 * some other attribute change, the import will result in
4318 * the attributes for the route in the VNI(s).
4320 if (safi
== SAFI_EVPN
&&
4321 (!same_attr
|| force_evpn_import
) &&
4322 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4323 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4325 /* Process change. */
4326 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4328 bgp_process(bgp
, dest
, afi
, safi
);
4329 bgp_dest_unlock_node(dest
);
4331 if (SAFI_UNICAST
== safi
4332 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4333 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4335 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4337 if ((SAFI_MPLS_VPN
== safi
)
4338 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4340 vpn_leak_to_vrf_update(bgp
, pi
);
4343 #ifdef ENABLE_BGP_VNC
4344 if (SAFI_MPLS_VPN
== safi
) {
4345 mpls_label_t label_decoded
= decode_label(label
);
4347 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4348 type
, sub_type
, &label_decoded
);
4350 if (SAFI_ENCAP
== safi
) {
4351 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4352 type
, sub_type
, NULL
);
4357 } // End of implicit withdraw
4359 /* Received Logging. */
4360 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4361 if (!peer
->rcvd_attr_printed
) {
4362 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4363 peer
->rcvd_attr_str
);
4364 peer
->rcvd_attr_printed
= 1;
4367 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4368 addpath_id
? 1 : 0, addpath_id
, evpn
,
4369 pfx_buf
, sizeof(pfx_buf
));
4370 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
4373 /* Make new BGP info. */
4374 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4376 /* Update MPLS label */
4377 if (has_valid_label
) {
4378 extra
= bgp_path_info_extra_get(new);
4379 if (extra
->label
!= label
) {
4380 memcpy(&extra
->label
, label
,
4381 num_labels
* sizeof(mpls_label_t
));
4382 extra
->num_labels
= num_labels
;
4384 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4385 bgp_set_valid_label(&extra
->label
[0]);
4388 /* Update SRv6 SID */
4389 if (safi
== SAFI_MPLS_VPN
) {
4390 extra
= bgp_path_info_extra_get(new);
4391 if (attr
->srv6_l3vpn
) {
4392 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4393 extra
->num_sids
= 1;
4395 extra
->sid
[0].loc_block_len
=
4396 attr
->srv6_l3vpn
->loc_block_len
;
4397 extra
->sid
[0].loc_node_len
=
4398 attr
->srv6_l3vpn
->loc_node_len
;
4399 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4400 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4403 * draft-ietf-bess-srv6-services-07
4404 * The part of SRv6 SID may be encoded as MPLS Label for
4405 * the efficient packing.
4407 if (attr
->srv6_l3vpn
->transposition_len
!= 0)
4409 &extra
->sid
[0].sid
, decode_label(label
),
4410 attr
->srv6_l3vpn
->transposition_offset
,
4411 attr
->srv6_l3vpn
->transposition_len
);
4412 } else if (attr
->srv6_vpn
) {
4413 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4414 extra
->num_sids
= 1;
4418 /* Nexthop reachability check. */
4419 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4420 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4421 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4422 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4423 && peer
->ttl
== BGP_DEFAULT_TTL
4424 && !CHECK_FLAG(peer
->flags
,
4425 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4426 && !CHECK_FLAG(bgp
->flags
,
4427 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4432 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4434 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4436 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4437 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4439 if (BGP_DEBUG(nht
, NHT
)) {
4440 char buf1
[INET6_ADDRSTRLEN
];
4442 (const void *)&attr_new
->nexthop
,
4443 buf1
, INET6_ADDRSTRLEN
);
4444 zlog_debug("%s(%s): NH unresolved", __func__
,
4447 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4450 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4453 new->addpath_rx_id
= addpath_id
;
4455 /* Increment prefix */
4456 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4458 /* Register new BGP information. */
4459 bgp_path_info_add(dest
, new);
4461 /* route_node_get lock */
4462 bgp_dest_unlock_node(dest
);
4464 #ifdef ENABLE_BGP_VNC
4465 if (safi
== SAFI_MPLS_VPN
) {
4466 struct bgp_dest
*pdest
= NULL
;
4467 struct bgp_table
*table
= NULL
;
4469 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4470 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4471 table
= bgp_dest_get_bgp_table_info(pdest
);
4473 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4474 bgp
, prd
, table
, p
, new);
4476 bgp_dest_unlock_node(pdest
);
4480 /* If this is an EVPN route, process for import. */
4481 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4482 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4484 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4486 /* Process change. */
4487 bgp_process(bgp
, dest
, afi
, safi
);
4489 if (SAFI_UNICAST
== safi
4490 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4491 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4492 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4494 if ((SAFI_MPLS_VPN
== safi
)
4495 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4497 vpn_leak_to_vrf_update(bgp
, new);
4499 #ifdef ENABLE_BGP_VNC
4500 if (SAFI_MPLS_VPN
== safi
) {
4501 mpls_label_t label_decoded
= decode_label(label
);
4503 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4504 sub_type
, &label_decoded
);
4506 if (SAFI_ENCAP
== safi
) {
4507 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4514 /* This BGP update is filtered. Log the reason then update BGP
4517 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4519 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4520 if (!peer
->rcvd_attr_printed
) {
4521 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4522 peer
->rcvd_attr_str
);
4523 peer
->rcvd_attr_printed
= 1;
4526 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4527 addpath_id
? 1 : 0, addpath_id
, evpn
,
4528 pfx_buf
, sizeof(pfx_buf
));
4529 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4530 peer
->host
, pfx_buf
, reason
);
4534 /* If this is an EVPN route, un-import it as it is now filtered.
4536 if (safi
== SAFI_EVPN
)
4537 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4539 if (SAFI_UNICAST
== safi
4540 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4541 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4543 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4545 if ((SAFI_MPLS_VPN
== safi
)
4546 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4548 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4551 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4554 bgp_dest_unlock_node(dest
);
4556 #ifdef ENABLE_BGP_VNC
4558 * Filtered update is treated as an implicit withdrawal (see
4560 * a few lines above)
4562 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4563 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4571 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4572 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4573 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4574 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4577 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4578 struct bgp_dest
*dest
;
4579 struct bgp_path_info
*pi
;
4581 #ifdef ENABLE_BGP_VNC
4582 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4583 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4591 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4593 /* If peer is soft reconfiguration enabled. Record input packet for
4594 * further calculation.
4596 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4597 * routes that are filtered. This tanks out Quagga RS pretty badly due
4599 * the iteration over all RS clients.
4600 * Since we need to remove the entry from adj_in anyway, do that first
4602 * if there was no entry, we don't need to do anything more.
4604 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4605 && peer
!= bgp
->peer_self
)
4606 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4607 peer
->stat_pfx_dup_withdraw
++;
4609 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4610 bgp_debug_rdpfxpath2str(
4611 afi
, safi
, prd
, p
, label
, num_labels
,
4612 addpath_id
? 1 : 0, addpath_id
, NULL
,
4613 pfx_buf
, sizeof(pfx_buf
));
4615 "%s withdrawing route %s not in adj-in",
4616 peer
->host
, pfx_buf
);
4618 bgp_dest_unlock_node(dest
);
4622 /* Lookup withdrawn route. */
4623 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4624 if (pi
->peer
== peer
&& pi
->type
== type
4625 && pi
->sub_type
== sub_type
4626 && pi
->addpath_rx_id
== addpath_id
)
4630 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4631 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4632 addpath_id
? 1 : 0, addpath_id
, NULL
,
4633 pfx_buf
, sizeof(pfx_buf
));
4634 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4638 /* Withdraw specified route from routing table. */
4639 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4640 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4641 if (SAFI_UNICAST
== safi
4642 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4643 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4644 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4646 if ((SAFI_MPLS_VPN
== safi
)
4647 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4649 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4651 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4652 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4653 addpath_id
? 1 : 0, addpath_id
, NULL
,
4654 pfx_buf
, sizeof(pfx_buf
));
4655 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4658 /* Unlock bgp_node_get() lock. */
4659 bgp_dest_unlock_node(dest
);
4664 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4667 struct update_subgroup
*subgrp
;
4668 subgrp
= peer_subgroup(peer
, afi
, safi
);
4669 subgroup_default_originate(subgrp
, withdraw
);
4674 * bgp_stop_announce_route_timer
4676 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4678 if (!paf
->t_announce_route
)
4681 thread_cancel(&paf
->t_announce_route
);
4685 * bgp_announce_route_timer_expired
4687 * Callback that is invoked when the route announcement timer for a
4690 static int bgp_announce_route_timer_expired(struct thread
*t
)
4692 struct peer_af
*paf
;
4695 paf
= THREAD_ARG(t
);
4698 if (!peer_established(peer
))
4701 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4704 peer_af_announce_route(paf
, 1);
4706 /* Notify BGP conditional advertisement scanner percess */
4707 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
4713 * bgp_announce_route
4715 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4717 * if force is true we will force an update even if the update
4718 * limiting code is attempted to kick in.
4720 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
4722 struct peer_af
*paf
;
4723 struct update_subgroup
*subgrp
;
4725 paf
= peer_af_find(peer
, afi
, safi
);
4728 subgrp
= PAF_SUBGRP(paf
);
4731 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4732 * or a refresh has already been triggered.
4734 if (!subgrp
|| paf
->t_announce_route
)
4738 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
4741 * Start a timer to stagger/delay the announce. This serves
4742 * two purposes - announcement can potentially be combined for
4743 * multiple peers and the announcement doesn't happen in the
4746 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4747 (subgrp
->peer_count
== 1)
4748 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4749 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4750 &paf
->t_announce_route
);
4754 * Announce routes from all AF tables to a peer.
4756 * This should ONLY be called when there is a need to refresh the
4757 * routes to the peer based on a policy change for this peer alone
4758 * or a route refresh request received from the peer.
4759 * The operation will result in splitting the peer from its existing
4760 * subgroups and putting it in new subgroups.
4762 void bgp_announce_route_all(struct peer
*peer
)
4767 FOREACH_AFI_SAFI (afi
, safi
)
4768 bgp_announce_route(peer
, afi
, safi
, false);
4771 /* Flag or unflag bgp_dest to determine whether it should be treated by
4772 * bgp_soft_reconfig_table_task.
4773 * Flag if flag is true. Unflag if flag is false.
4775 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
4777 struct bgp_dest
*dest
;
4778 struct bgp_adj_in
*ain
;
4783 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4784 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4785 if (ain
->peer
!= NULL
)
4788 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
4789 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4791 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4795 static int bgp_soft_reconfig_table_update(struct peer
*peer
,
4796 struct bgp_dest
*dest
,
4797 struct bgp_adj_in
*ain
, afi_t afi
,
4798 safi_t safi
, struct prefix_rd
*prd
)
4800 struct bgp_path_info
*pi
;
4801 uint32_t num_labels
= 0;
4802 mpls_label_t
*label_pnt
= NULL
;
4803 struct bgp_route_evpn evpn
;
4805 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4806 if (pi
->peer
== peer
)
4809 if (pi
&& pi
->extra
)
4810 num_labels
= pi
->extra
->num_labels
;
4812 label_pnt
= &pi
->extra
->label
[0];
4814 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
4817 memset(&evpn
, 0, sizeof(evpn
));
4819 return bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
4820 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
4821 BGP_ROUTE_NORMAL
, prd
, label_pnt
, num_labels
, 1,
4825 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4826 struct bgp_table
*table
,
4827 struct prefix_rd
*prd
)
4830 struct bgp_dest
*dest
;
4831 struct bgp_adj_in
*ain
;
4834 table
= peer
->bgp
->rib
[afi
][safi
];
4836 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4837 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4838 if (ain
->peer
!= peer
)
4841 ret
= bgp_soft_reconfig_table_update(peer
, dest
, ain
,
4845 bgp_dest_unlock_node(dest
);
4851 /* Do soft reconfig table per bgp table.
4852 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4853 * when BGP_NODE_SOFT_RECONFIG is set,
4854 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4855 * Schedule a new thread to continue the job.
4856 * Without splitting the full job into several part,
4857 * vtysh waits for the job to finish before responding to a BGP command
4859 static int bgp_soft_reconfig_table_task(struct thread
*thread
)
4861 uint32_t iter
, max_iter
;
4863 struct bgp_dest
*dest
;
4864 struct bgp_adj_in
*ain
;
4866 struct bgp_table
*table
;
4867 struct prefix_rd
*prd
;
4868 struct listnode
*node
, *nnode
;
4870 table
= THREAD_ARG(thread
);
4873 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
4874 if (table
->soft_reconfig_init
) {
4875 /* first call of the function with a new srta structure.
4876 * Don't do any treatment this time on nodes
4877 * in order vtysh to respond quickly
4882 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
4883 dest
= bgp_route_next(dest
)) {
4884 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
4887 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4889 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4890 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
4892 if (ain
->peer
!= peer
)
4895 ret
= bgp_soft_reconfig_table_update(
4896 peer
, dest
, ain
, table
->afi
,
4901 bgp_dest_unlock_node(dest
);
4903 table
->soft_reconfig_peers
,
4905 bgp_announce_route(peer
, table
->afi
,
4906 table
->safi
, false);
4908 table
->soft_reconfig_peers
)) {
4910 &table
->soft_reconfig_peers
);
4911 bgp_soft_reconfig_table_flag(
4920 /* we're either starting the initial iteration,
4921 * or we're going to continue an ongoing iteration
4923 if (dest
|| table
->soft_reconfig_init
) {
4924 table
->soft_reconfig_init
= false;
4925 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
4926 table
, 0, &table
->soft_reconfig_thread
);
4929 /* we're done, clean up the background iteration context info and
4930 schedule route annoucement
4932 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
4933 listnode_delete(table
->soft_reconfig_peers
, peer
);
4934 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
4937 list_delete(&table
->soft_reconfig_peers
);
4943 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4945 * - bgp cannot be NULL
4946 * - if table and peer are NULL, cancel all threads within the bgp instance
4947 * - if table is NULL and peer is not,
4948 * remove peer in all threads within the bgp instance
4949 * - if peer is NULL, cancel all threads matching table within the bgp instance
4951 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
4952 const struct bgp_table
*table
,
4953 const struct peer
*peer
)
4956 struct listnode
*node
, *nnode
;
4958 struct bgp_table
*ntable
;
4963 FOREACH_AFI_SAFI (afi
, safi
) {
4964 ntable
= bgp
->rib
[afi
][safi
];
4967 if (table
&& table
!= ntable
)
4970 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
4972 if (peer
&& peer
!= npeer
)
4974 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
4977 if (!ntable
->soft_reconfig_peers
4978 || !list_isempty(ntable
->soft_reconfig_peers
))
4981 list_delete(&ntable
->soft_reconfig_peers
);
4982 bgp_soft_reconfig_table_flag(ntable
, false);
4983 BGP_TIMER_OFF(ntable
->soft_reconfig_thread
);
4987 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4989 struct bgp_dest
*dest
;
4990 struct bgp_table
*table
;
4991 struct listnode
*node
, *nnode
;
4993 struct peer_af
*paf
;
4995 if (!peer_established(peer
))
4998 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4999 && (safi
!= SAFI_EVPN
)) {
5000 table
= peer
->bgp
->rib
[afi
][safi
];
5004 table
->soft_reconfig_init
= true;
5006 if (!table
->soft_reconfig_peers
)
5007 table
->soft_reconfig_peers
= list_new();
5009 /* add peer to the table soft_reconfig_peers if not already
5012 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5018 listnode_add(table
->soft_reconfig_peers
, peer
);
5020 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5021 * on table would start back at the beginning.
5023 bgp_soft_reconfig_table_flag(table
, true);
5025 if (!table
->soft_reconfig_thread
)
5026 thread_add_event(bm
->master
,
5027 bgp_soft_reconfig_table_task
, table
, 0,
5028 &table
->soft_reconfig_thread
);
5029 /* Cancel bgp_announce_route_timer_expired threads.
5030 * bgp_announce_route_timer_expired threads have been scheduled
5031 * to announce routes as soon as the soft_reconfigure process
5033 * In this case, soft_reconfigure is also scheduled by using
5034 * a thread but is planned after the
5035 * bgp_announce_route_timer_expired threads. It means that,
5036 * without cancelling the threads, the route announcement task
5037 * would run before the soft reconfiguration one. That would
5038 * useless and would block vtysh during several seconds. Route
5039 * announcements are rescheduled as soon as the soft_reconfigure
5042 paf
= peer_af_find(peer
, afi
, safi
);
5044 bgp_stop_announce_route_timer(paf
);
5046 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5047 dest
= bgp_route_next(dest
)) {
5048 table
= bgp_dest_get_bgp_table_info(dest
);
5053 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5054 struct prefix_rd prd
;
5056 prd
.family
= AF_UNSPEC
;
5058 memcpy(&prd
.val
, p
->u
.val
, 8);
5060 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5065 struct bgp_clear_node_queue
{
5066 struct bgp_dest
*dest
;
5069 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5071 struct bgp_clear_node_queue
*cnq
= data
;
5072 struct bgp_dest
*dest
= cnq
->dest
;
5073 struct peer
*peer
= wq
->spec
.data
;
5074 struct bgp_path_info
*pi
;
5076 afi_t afi
= bgp_dest_table(dest
)->afi
;
5077 safi_t safi
= bgp_dest_table(dest
)->safi
;
5079 assert(dest
&& peer
);
5082 /* It is possible that we have multiple paths for a prefix from a peer
5083 * if that peer is using AddPath.
5085 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5086 if (pi
->peer
!= peer
)
5089 /* graceful restart STALE flag set. */
5090 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5091 && peer
->nsf
[afi
][safi
])
5092 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5093 PEER_STATUS_ENHANCED_REFRESH
))
5094 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5095 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5096 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5098 /* If this is an EVPN route, process for
5100 if (safi
== SAFI_EVPN
)
5101 bgp_evpn_unimport_route(
5103 bgp_dest_get_prefix(dest
), pi
);
5104 /* Handle withdraw for VRF route-leaking and L3VPN */
5105 if (SAFI_UNICAST
== safi
5106 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5107 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5108 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5111 if (SAFI_MPLS_VPN
== safi
&&
5112 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5113 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5116 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5122 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5124 struct bgp_clear_node_queue
*cnq
= data
;
5125 struct bgp_dest
*dest
= cnq
->dest
;
5126 struct bgp_table
*table
= bgp_dest_table(dest
);
5128 bgp_dest_unlock_node(dest
);
5129 bgp_table_unlock(table
);
5130 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5133 static void bgp_clear_node_complete(struct work_queue
*wq
)
5135 struct peer
*peer
= wq
->spec
.data
;
5137 /* Tickle FSM to start moving again */
5138 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5140 peer_unlock(peer
); /* bgp_clear_route */
5143 static void bgp_clear_node_queue_init(struct peer
*peer
)
5145 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5147 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5148 #undef CLEAR_QUEUE_NAME_LEN
5150 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5151 peer
->clear_node_queue
->spec
.hold
= 10;
5152 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5153 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5154 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5155 peer
->clear_node_queue
->spec
.max_retries
= 0;
5157 /* we only 'lock' this peer reference when the queue is actually active
5159 peer
->clear_node_queue
->spec
.data
= peer
;
5162 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5163 struct bgp_table
*table
)
5165 struct bgp_dest
*dest
;
5166 int force
= peer
->bgp
->process_queue
? 0 : 1;
5169 table
= peer
->bgp
->rib
[afi
][safi
];
5171 /* If still no table => afi/safi isn't configured at all or smth. */
5175 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5176 struct bgp_path_info
*pi
, *next
;
5177 struct bgp_adj_in
*ain
;
5178 struct bgp_adj_in
*ain_next
;
5180 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5181 * queued for every clearing peer, regardless of whether it is
5182 * relevant to the peer at hand.
5184 * Overview: There are 3 different indices which need to be
5185 * scrubbed, potentially, when a peer is removed:
5187 * 1 peer's routes visible via the RIB (ie accepted routes)
5188 * 2 peer's routes visible by the (optional) peer's adj-in index
5189 * 3 other routes visible by the peer's adj-out index
5191 * 3 there is no hurry in scrubbing, once the struct peer is
5192 * removed from bgp->peer, we could just GC such deleted peer's
5193 * adj-outs at our leisure.
5195 * 1 and 2 must be 'scrubbed' in some way, at least made
5196 * invisible via RIB index before peer session is allowed to be
5197 * brought back up. So one needs to know when such a 'search' is
5202 * - there'd be a single global queue or a single RIB walker
5203 * - rather than tracking which route_nodes still need to be
5204 * examined on a peer basis, we'd track which peers still
5207 * Given that our per-peer prefix-counts now should be reliable,
5208 * this may actually be achievable. It doesn't seem to be a huge
5209 * problem at this time,
5211 * It is possible that we have multiple paths for a prefix from
5213 * if that peer is using AddPath.
5217 ain_next
= ain
->next
;
5219 if (ain
->peer
== peer
)
5220 bgp_adj_in_remove(dest
, ain
);
5225 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5227 if (pi
->peer
!= peer
)
5231 bgp_path_info_reap(dest
, pi
);
5233 struct bgp_clear_node_queue
*cnq
;
5235 /* both unlocked in bgp_clear_node_queue_del */
5236 bgp_table_lock(bgp_dest_table(dest
));
5237 bgp_dest_lock_node(dest
);
5239 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5240 sizeof(struct bgp_clear_node_queue
));
5242 work_queue_add(peer
->clear_node_queue
, cnq
);
5250 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5252 struct bgp_dest
*dest
;
5253 struct bgp_table
*table
;
5255 if (peer
->clear_node_queue
== NULL
)
5256 bgp_clear_node_queue_init(peer
);
5258 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5259 * Idle until it receives a Clearing_Completed event. This protects
5260 * against peers which flap faster than we can we clear, which could
5263 * a) race with routes from the new session being installed before
5264 * clear_route_node visits the node (to delete the route of that
5266 * b) resource exhaustion, clear_route_node likely leads to an entry
5267 * on the process_main queue. Fast-flapping could cause that queue
5271 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5272 * the unlock will happen upon work-queue completion; other wise, the
5273 * unlock happens at the end of this function.
5275 if (!peer
->clear_node_queue
->thread
)
5278 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5279 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5281 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5282 dest
= bgp_route_next(dest
)) {
5283 table
= bgp_dest_get_bgp_table_info(dest
);
5287 bgp_clear_route_table(peer
, afi
, safi
, table
);
5290 /* unlock if no nodes got added to the clear-node-queue. */
5291 if (!peer
->clear_node_queue
->thread
)
5295 void bgp_clear_route_all(struct peer
*peer
)
5300 FOREACH_AFI_SAFI (afi
, safi
)
5301 bgp_clear_route(peer
, afi
, safi
);
5303 #ifdef ENABLE_BGP_VNC
5304 rfapiProcessPeerDown(peer
);
5308 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5310 struct bgp_table
*table
;
5311 struct bgp_dest
*dest
;
5312 struct bgp_adj_in
*ain
;
5313 struct bgp_adj_in
*ain_next
;
5315 table
= peer
->bgp
->rib
[afi
][safi
];
5317 /* It is possible that we have multiple paths for a prefix from a peer
5318 * if that peer is using AddPath.
5320 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5324 ain_next
= ain
->next
;
5326 if (ain
->peer
== peer
)
5327 bgp_adj_in_remove(dest
, ain
);
5334 /* If any of the routes from the peer have been marked with the NO_LLGR
5335 * community, either as sent by the peer, or as the result of a configured
5336 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5337 * operation of [RFC4271].
5339 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5341 struct bgp_dest
*dest
;
5342 struct bgp_path_info
*pi
;
5343 struct bgp_table
*table
;
5345 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5346 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5347 dest
= bgp_route_next(dest
)) {
5348 struct bgp_dest
*rm
;
5350 /* look for neighbor in tables */
5351 table
= bgp_dest_get_bgp_table_info(dest
);
5355 for (rm
= bgp_table_top(table
); rm
;
5356 rm
= bgp_route_next(rm
))
5357 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5359 if (pi
->peer
!= peer
)
5362 peer
->af_sflags
[afi
][safi
],
5363 PEER_STATUS_LLGR_WAIT
) &&
5364 pi
->attr
->community
&&
5366 pi
->attr
->community
,
5369 if (!CHECK_FLAG(pi
->flags
,
5374 * If this is VRF leaked route
5375 * process for withdraw.
5378 BGP_ROUTE_IMPORTED
&&
5379 peer
->bgp
->inst_type
==
5380 BGP_INSTANCE_TYPE_DEFAULT
)
5381 vpn_leak_to_vrf_withdraw(
5384 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5389 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5390 dest
= bgp_route_next(dest
))
5391 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5393 if (pi
->peer
!= peer
)
5395 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5396 PEER_STATUS_LLGR_WAIT
) &&
5397 pi
->attr
->community
&&
5398 !community_include(pi
->attr
->community
,
5401 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5403 if (safi
== SAFI_UNICAST
&&
5404 (peer
->bgp
->inst_type
==
5405 BGP_INSTANCE_TYPE_VRF
||
5406 peer
->bgp
->inst_type
==
5407 BGP_INSTANCE_TYPE_DEFAULT
))
5408 vpn_leak_from_vrf_withdraw(
5409 bgp_get_default(), peer
->bgp
,
5412 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5418 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5420 struct bgp_dest
*dest
, *ndest
;
5421 struct bgp_path_info
*pi
;
5422 struct bgp_table
*table
;
5424 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5425 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5426 dest
= bgp_route_next(dest
)) {
5427 table
= bgp_dest_get_bgp_table_info(dest
);
5431 for (ndest
= bgp_table_top(table
); ndest
;
5432 ndest
= bgp_route_next(ndest
)) {
5433 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5435 if (pi
->peer
!= peer
)
5439 peer
->af_sflags
[afi
][safi
],
5440 PEER_STATUS_ENHANCED_REFRESH
))
5441 && !CHECK_FLAG(pi
->flags
,
5445 BGP_PATH_UNUSEABLE
)) {
5446 if (bgp_debug_neighbor_events(
5449 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5453 bgp_dest_get_prefix(
5456 bgp_path_info_set_flag(
5464 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5465 dest
= bgp_route_next(dest
)) {
5466 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5468 if (pi
->peer
!= peer
)
5471 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5472 PEER_STATUS_ENHANCED_REFRESH
))
5473 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5474 && !CHECK_FLAG(pi
->flags
,
5475 BGP_PATH_UNUSEABLE
)) {
5476 if (bgp_debug_neighbor_events(peer
))
5478 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5482 bgp_dest_get_prefix(
5485 bgp_path_info_set_flag(dest
, pi
,
5493 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5495 if (peer
->sort
== BGP_PEER_IBGP
)
5498 if (peer
->sort
== BGP_PEER_EBGP
5499 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5500 || FILTER_LIST_OUT_NAME(filter
)
5501 || DISTRIBUTE_OUT_NAME(filter
)))
5506 bool bgp_inbound_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_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5513 || FILTER_LIST_IN_NAME(filter
)
5514 || DISTRIBUTE_IN_NAME(filter
)))
5519 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5522 struct bgp_dest
*dest
;
5523 struct bgp_path_info
*pi
;
5524 struct bgp_path_info
*next
;
5526 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5527 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5528 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5532 /* Unimport EVPN routes from VRFs */
5533 if (safi
== SAFI_EVPN
)
5534 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5537 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5538 && pi
->type
== ZEBRA_ROUTE_BGP
5539 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5540 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5541 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5543 if (bgp_fibupd_safi(safi
))
5544 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5547 bgp_path_info_reap(dest
, pi
);
5551 /* Delete all kernel routes. */
5552 void bgp_cleanup_routes(struct bgp
*bgp
)
5555 struct bgp_dest
*dest
;
5556 struct bgp_table
*table
;
5558 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5559 if (afi
== AFI_L2VPN
)
5561 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5564 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5566 if (afi
!= AFI_L2VPN
) {
5568 safi
= SAFI_MPLS_VPN
;
5569 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5570 dest
= bgp_route_next(dest
)) {
5571 table
= bgp_dest_get_bgp_table_info(dest
);
5572 if (table
!= NULL
) {
5573 bgp_cleanup_table(bgp
, table
, safi
);
5574 bgp_table_finish(&table
);
5575 bgp_dest_set_bgp_table_info(dest
, NULL
);
5576 bgp_dest_unlock_node(dest
);
5580 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5581 dest
= bgp_route_next(dest
)) {
5582 table
= bgp_dest_get_bgp_table_info(dest
);
5583 if (table
!= NULL
) {
5584 bgp_cleanup_table(bgp
, table
, safi
);
5585 bgp_table_finish(&table
);
5586 bgp_dest_set_bgp_table_info(dest
, NULL
);
5587 bgp_dest_unlock_node(dest
);
5592 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5593 dest
= bgp_route_next(dest
)) {
5594 table
= bgp_dest_get_bgp_table_info(dest
);
5595 if (table
!= NULL
) {
5596 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5597 bgp_table_finish(&table
);
5598 bgp_dest_set_bgp_table_info(dest
, NULL
);
5599 bgp_dest_unlock_node(dest
);
5604 void bgp_reset(void)
5607 bgp_zclient_reset();
5608 access_list_reset();
5609 prefix_list_reset();
5612 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5614 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5615 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5616 PEER_CAP_ADDPATH_AF_TX_RCV
));
5619 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5621 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5622 struct bgp_nlri
*packet
)
5631 int addpath_encoded
;
5632 uint32_t addpath_id
;
5635 lim
= pnt
+ packet
->length
;
5637 safi
= packet
->safi
;
5639 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5641 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5642 syntactic validity. If the field is syntactically incorrect,
5643 then the Error Subcode is set to Invalid Network Field. */
5644 for (; pnt
< lim
; pnt
+= psize
) {
5645 /* Clear prefix structure. */
5646 memset(&p
, 0, sizeof(struct prefix
));
5648 if (addpath_encoded
) {
5650 /* When packet overflow occurs return immediately. */
5651 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5652 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5654 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5655 addpath_id
= ntohl(addpath_id
);
5656 pnt
+= BGP_ADDPATH_ID_LEN
;
5659 /* Fetch prefix length. */
5660 p
.prefixlen
= *pnt
++;
5661 /* afi/safi validity already verified by caller,
5662 * bgp_update_receive */
5663 p
.family
= afi2family(afi
);
5665 /* Prefix length check. */
5666 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5669 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5670 peer
->host
, p
.prefixlen
, packet
->afi
);
5671 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5674 /* Packet size overflow check. */
5675 psize
= PSIZE(p
.prefixlen
);
5677 /* When packet overflow occur return immediately. */
5678 if (pnt
+ psize
> lim
) {
5681 "%s [Error] Update packet error (prefix length %d overflows packet)",
5682 peer
->host
, p
.prefixlen
);
5683 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5686 /* Defensive coding, double-check the psize fits in a struct
5688 if (psize
> (ssize_t
)sizeof(p
.u
)) {
5691 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5692 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
5693 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5696 /* Fetch prefix from NLRI packet. */
5697 memcpy(p
.u
.val
, pnt
, psize
);
5699 /* Check address. */
5700 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5701 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5702 /* From RFC4271 Section 6.3:
5704 * If a prefix in the NLRI field is semantically
5706 * (e.g., an unexpected multicast IP address),
5708 * be logged locally, and the prefix SHOULD be
5713 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5714 peer
->host
, &p
.u
.prefix4
);
5719 /* Check address. */
5720 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5721 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5724 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5725 peer
->host
, &p
.u
.prefix6
);
5729 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5732 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5733 peer
->host
, &p
.u
.prefix6
);
5739 /* Normal process. */
5741 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5742 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5743 NULL
, NULL
, 0, 0, NULL
);
5745 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5746 safi
, ZEBRA_ROUTE_BGP
,
5747 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5750 /* Do not send BGP notification twice when maximum-prefix count
5752 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5753 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5755 /* Address family configuration mismatch. */
5757 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5760 /* Packet length consistency check. */
5764 "%s [Error] Update packet error (prefix length mismatch with total length)",
5766 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5769 return BGP_NLRI_PARSE_OK
;
5772 static struct bgp_static
*bgp_static_new(void)
5774 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5777 static void bgp_static_free(struct bgp_static
*bgp_static
)
5779 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5780 route_map_counter_decrement(bgp_static
->rmap
.map
);
5782 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5783 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5786 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5787 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5789 struct bgp_dest
*dest
;
5790 struct bgp_path_info
*pi
;
5791 struct bgp_path_info
*new;
5792 struct bgp_path_info rmap_path
;
5794 struct attr
*attr_new
;
5795 route_map_result_t ret
;
5796 #ifdef ENABLE_BGP_VNC
5797 int vnc_implicit_withdraw
= 0;
5802 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5804 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5806 attr
.nexthop
= bgp_static
->igpnexthop
;
5807 attr
.med
= bgp_static
->igpmetric
;
5808 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5810 if (bgp_static
->atomic
)
5811 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5813 /* Store label index, if required. */
5814 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5815 attr
.label_index
= bgp_static
->label_index
;
5816 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5819 /* Apply route-map. */
5820 if (bgp_static
->rmap
.name
) {
5821 struct attr attr_tmp
= attr
;
5823 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5824 rmap_path
.peer
= bgp
->peer_self
;
5825 rmap_path
.attr
= &attr_tmp
;
5827 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5829 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5831 bgp
->peer_self
->rmap_type
= 0;
5833 if (ret
== RMAP_DENYMATCH
) {
5834 /* Free uninterned attribute. */
5835 bgp_attr_flush(&attr_tmp
);
5837 /* Unintern original. */
5838 aspath_unintern(&attr
.aspath
);
5839 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5843 if (bgp_in_graceful_shutdown(bgp
))
5844 bgp_attr_add_gshut_community(&attr_tmp
);
5846 attr_new
= bgp_attr_intern(&attr_tmp
);
5849 if (bgp_in_graceful_shutdown(bgp
))
5850 bgp_attr_add_gshut_community(&attr
);
5852 attr_new
= bgp_attr_intern(&attr
);
5855 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5856 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5857 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5861 if (attrhash_cmp(pi
->attr
, attr_new
)
5862 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5863 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5864 bgp_dest_unlock_node(dest
);
5865 bgp_attr_unintern(&attr_new
);
5866 aspath_unintern(&attr
.aspath
);
5869 /* The attribute is changed. */
5870 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5872 /* Rewrite BGP route information. */
5873 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5874 bgp_path_info_restore(dest
, pi
);
5876 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5877 #ifdef ENABLE_BGP_VNC
5878 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5879 && (safi
== SAFI_UNICAST
)) {
5880 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5882 * Implicit withdraw case.
5883 * We have to do this before pi is
5886 ++vnc_implicit_withdraw
;
5887 vnc_import_bgp_del_route(bgp
, p
, pi
);
5888 vnc_import_bgp_exterior_del_route(
5893 bgp_attr_unintern(&pi
->attr
);
5894 pi
->attr
= attr_new
;
5895 pi
->uptime
= bgp_clock();
5896 #ifdef ENABLE_BGP_VNC
5897 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5898 && (safi
== SAFI_UNICAST
)) {
5899 if (vnc_implicit_withdraw
) {
5900 vnc_import_bgp_add_route(bgp
, p
, pi
);
5901 vnc_import_bgp_exterior_add_route(
5907 /* Nexthop reachability check. */
5908 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5909 && (safi
== SAFI_UNICAST
5910 || safi
== SAFI_LABELED_UNICAST
)) {
5912 struct bgp
*bgp_nexthop
= bgp
;
5914 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5915 bgp_nexthop
= pi
->extra
->bgp_orig
;
5917 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5918 afi
, safi
, pi
, NULL
,
5920 bgp_path_info_set_flag(dest
, pi
,
5923 if (BGP_DEBUG(nht
, NHT
)) {
5924 char buf1
[INET6_ADDRSTRLEN
];
5925 inet_ntop(p
->family
,
5929 "%s(%s): Route not in table, not advertising",
5932 bgp_path_info_unset_flag(
5933 dest
, pi
, BGP_PATH_VALID
);
5936 /* Delete the NHT structure if any, if we're
5938 * enabling/disabling import check. We
5939 * deregister the route
5940 * from NHT to avoid overloading NHT and the
5941 * process interaction
5943 bgp_unlink_nexthop(pi
);
5944 bgp_path_info_set_flag(dest
, pi
,
5947 /* Process change. */
5948 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5949 bgp_process(bgp
, dest
, afi
, safi
);
5951 if (SAFI_UNICAST
== safi
5952 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5954 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5955 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5959 bgp_dest_unlock_node(dest
);
5960 aspath_unintern(&attr
.aspath
);
5965 /* Make new BGP info. */
5966 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5968 /* Nexthop reachability check. */
5969 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5970 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5971 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
5973 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5975 if (BGP_DEBUG(nht
, NHT
)) {
5976 char buf1
[INET6_ADDRSTRLEN
];
5977 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5980 "%s(%s): Route not in table, not advertising",
5983 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5986 /* Delete the NHT structure if any, if we're toggling between
5987 * enabling/disabling import check. We deregister the route
5988 * from NHT to avoid overloading NHT and the process interaction
5990 bgp_unlink_nexthop(new);
5992 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5995 /* Aggregate address increment. */
5996 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5998 /* Register new BGP information. */
5999 bgp_path_info_add(dest
, new);
6001 /* route_node_get lock */
6002 bgp_dest_unlock_node(dest
);
6004 /* Process change. */
6005 bgp_process(bgp
, dest
, afi
, safi
);
6007 if (SAFI_UNICAST
== safi
6008 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6009 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6010 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6013 /* Unintern original. */
6014 aspath_unintern(&attr
.aspath
);
6017 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6020 struct bgp_dest
*dest
;
6021 struct bgp_path_info
*pi
;
6023 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6025 /* Check selected route and self inserted route. */
6026 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6027 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6028 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6031 /* Withdraw static BGP route from routing table. */
6033 if (SAFI_UNICAST
== safi
6034 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6035 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6036 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6038 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6039 bgp_unlink_nexthop(pi
);
6040 bgp_path_info_delete(dest
, pi
);
6041 bgp_process(bgp
, dest
, afi
, safi
);
6044 /* Unlock bgp_node_lookup. */
6045 bgp_dest_unlock_node(dest
);
6049 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6051 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6052 afi_t afi
, safi_t safi
,
6053 struct prefix_rd
*prd
)
6055 struct bgp_dest
*dest
;
6056 struct bgp_path_info
*pi
;
6058 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6060 /* Check selected route and self inserted route. */
6061 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6062 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6063 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6066 /* Withdraw static BGP route from routing table. */
6068 #ifdef ENABLE_BGP_VNC
6069 rfapiProcessWithdraw(
6070 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6071 1); /* Kill, since it is an administrative change */
6073 if (SAFI_MPLS_VPN
== safi
6074 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6075 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6077 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6078 bgp_path_info_delete(dest
, pi
);
6079 bgp_process(bgp
, dest
, afi
, safi
);
6082 /* Unlock bgp_node_lookup. */
6083 bgp_dest_unlock_node(dest
);
6086 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6087 struct bgp_static
*bgp_static
, afi_t afi
,
6090 struct bgp_dest
*dest
;
6091 struct bgp_path_info
*new;
6092 struct attr
*attr_new
;
6093 struct attr attr
= {0};
6094 struct bgp_path_info
*pi
;
6095 #ifdef ENABLE_BGP_VNC
6096 mpls_label_t label
= 0;
6098 uint32_t num_labels
= 0;
6103 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6105 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6108 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
6110 attr
.nexthop
= bgp_static
->igpnexthop
;
6111 attr
.med
= bgp_static
->igpmetric
;
6112 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6114 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6115 || (safi
== SAFI_ENCAP
)) {
6116 if (afi
== AFI_IP
) {
6117 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6118 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6121 if (afi
== AFI_L2VPN
) {
6122 if (bgp_static
->gatewayIp
.family
== AF_INET
)
6124 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
6125 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
6126 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
6127 sizeof(struct in6_addr
));
6128 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6129 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6130 struct bgp_encap_type_vxlan bet
;
6131 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
6132 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6133 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6135 if (bgp_static
->router_mac
) {
6136 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6139 /* Apply route-map. */
6140 if (bgp_static
->rmap
.name
) {
6141 struct attr attr_tmp
= attr
;
6142 struct bgp_path_info rmap_path
;
6143 route_map_result_t ret
;
6145 rmap_path
.peer
= bgp
->peer_self
;
6146 rmap_path
.attr
= &attr_tmp
;
6148 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6150 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6152 bgp
->peer_self
->rmap_type
= 0;
6154 if (ret
== RMAP_DENYMATCH
) {
6155 /* Free uninterned attribute. */
6156 bgp_attr_flush(&attr_tmp
);
6158 /* Unintern original. */
6159 aspath_unintern(&attr
.aspath
);
6160 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6165 attr_new
= bgp_attr_intern(&attr_tmp
);
6167 attr_new
= bgp_attr_intern(&attr
);
6170 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6171 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6172 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6176 memset(&add
, 0, sizeof(union gw_addr
));
6177 if (attrhash_cmp(pi
->attr
, attr_new
)
6178 && overlay_index_equal(afi
, pi
, &add
)
6179 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6180 bgp_dest_unlock_node(dest
);
6181 bgp_attr_unintern(&attr_new
);
6182 aspath_unintern(&attr
.aspath
);
6185 /* The attribute is changed. */
6186 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6188 /* Rewrite BGP route information. */
6189 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6190 bgp_path_info_restore(dest
, pi
);
6192 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6193 bgp_attr_unintern(&pi
->attr
);
6194 pi
->attr
= attr_new
;
6195 pi
->uptime
= bgp_clock();
6196 #ifdef ENABLE_BGP_VNC
6198 label
= decode_label(&pi
->extra
->label
[0]);
6201 /* Process change. */
6202 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6203 bgp_process(bgp
, dest
, afi
, safi
);
6205 if (SAFI_MPLS_VPN
== safi
6206 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6207 vpn_leak_to_vrf_update(bgp
, pi
);
6209 #ifdef ENABLE_BGP_VNC
6210 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6211 pi
->attr
, afi
, safi
, pi
->type
,
6212 pi
->sub_type
, &label
);
6214 bgp_dest_unlock_node(dest
);
6215 aspath_unintern(&attr
.aspath
);
6221 /* Make new BGP info. */
6222 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6224 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6225 new->extra
= bgp_path_info_extra_new();
6227 new->extra
->label
[0] = bgp_static
->label
;
6228 new->extra
->num_labels
= num_labels
;
6230 #ifdef ENABLE_BGP_VNC
6231 label
= decode_label(&bgp_static
->label
);
6234 /* Aggregate address increment. */
6235 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6237 /* Register new BGP information. */
6238 bgp_path_info_add(dest
, new);
6239 /* route_node_get lock */
6240 bgp_dest_unlock_node(dest
);
6242 /* Process change. */
6243 bgp_process(bgp
, dest
, afi
, safi
);
6245 if (SAFI_MPLS_VPN
== safi
6246 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6247 vpn_leak_to_vrf_update(bgp
, new);
6249 #ifdef ENABLE_BGP_VNC
6250 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6251 safi
, new->type
, new->sub_type
, &label
);
6254 /* Unintern original. */
6255 aspath_unintern(&attr
.aspath
);
6258 /* Configure static BGP network. When user don't run zebra, static
6259 route should be installed as valid. */
6260 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6261 const char *ip_str
, afi_t afi
, safi_t safi
,
6262 const char *rmap
, int backdoor
, uint32_t label_index
)
6264 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6267 struct bgp_static
*bgp_static
;
6268 struct bgp_dest
*dest
;
6269 uint8_t need_update
= 0;
6271 /* Convert IP prefix string to struct prefix. */
6272 ret
= str2prefix(ip_str
, &p
);
6274 vty_out(vty
, "%% Malformed prefix\n");
6275 return CMD_WARNING_CONFIG_FAILED
;
6277 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6278 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6279 return CMD_WARNING_CONFIG_FAILED
;
6286 /* Set BGP static route configuration. */
6287 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6290 vty_out(vty
, "%% Can't find static route specified\n");
6291 return CMD_WARNING_CONFIG_FAILED
;
6294 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6296 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6297 && (label_index
!= bgp_static
->label_index
)) {
6299 "%% label-index doesn't match static route\n");
6300 bgp_dest_unlock_node(dest
);
6301 return CMD_WARNING_CONFIG_FAILED
;
6304 if ((rmap
&& bgp_static
->rmap
.name
)
6305 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6307 "%% route-map name doesn't match static route\n");
6308 bgp_dest_unlock_node(dest
);
6309 return CMD_WARNING_CONFIG_FAILED
;
6312 /* Update BGP RIB. */
6313 if (!bgp_static
->backdoor
)
6314 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6316 /* Clear configuration. */
6317 bgp_static_free(bgp_static
);
6318 bgp_dest_set_bgp_static_info(dest
, NULL
);
6319 bgp_dest_unlock_node(dest
);
6320 bgp_dest_unlock_node(dest
);
6323 /* Set BGP static route configuration. */
6324 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6325 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6327 /* Configuration change. */
6328 /* Label index cannot be changed. */
6329 if (bgp_static
->label_index
!= label_index
) {
6330 vty_out(vty
, "%% cannot change label-index\n");
6331 return CMD_WARNING_CONFIG_FAILED
;
6334 /* Check previous routes are installed into BGP. */
6335 if (bgp_static
->valid
6336 && bgp_static
->backdoor
!= backdoor
)
6339 bgp_static
->backdoor
= backdoor
;
6342 XFREE(MTYPE_ROUTE_MAP_NAME
,
6343 bgp_static
->rmap
.name
);
6344 route_map_counter_decrement(
6345 bgp_static
->rmap
.map
);
6346 bgp_static
->rmap
.name
=
6347 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6348 bgp_static
->rmap
.map
=
6349 route_map_lookup_by_name(rmap
);
6350 route_map_counter_increment(
6351 bgp_static
->rmap
.map
);
6353 XFREE(MTYPE_ROUTE_MAP_NAME
,
6354 bgp_static
->rmap
.name
);
6355 route_map_counter_decrement(
6356 bgp_static
->rmap
.map
);
6357 bgp_static
->rmap
.map
= NULL
;
6358 bgp_static
->valid
= 0;
6360 bgp_dest_unlock_node(dest
);
6362 /* New configuration. */
6363 bgp_static
= bgp_static_new();
6364 bgp_static
->backdoor
= backdoor
;
6365 bgp_static
->valid
= 0;
6366 bgp_static
->igpmetric
= 0;
6367 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6368 bgp_static
->label_index
= label_index
;
6371 XFREE(MTYPE_ROUTE_MAP_NAME
,
6372 bgp_static
->rmap
.name
);
6373 route_map_counter_decrement(
6374 bgp_static
->rmap
.map
);
6375 bgp_static
->rmap
.name
=
6376 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6377 bgp_static
->rmap
.map
=
6378 route_map_lookup_by_name(rmap
);
6379 route_map_counter_increment(
6380 bgp_static
->rmap
.map
);
6382 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6385 bgp_static
->valid
= 1;
6387 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6389 if (!bgp_static
->backdoor
)
6390 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6396 void bgp_static_add(struct bgp
*bgp
)
6400 struct bgp_dest
*dest
;
6401 struct bgp_dest
*rm
;
6402 struct bgp_table
*table
;
6403 struct bgp_static
*bgp_static
;
6405 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6406 FOREACH_AFI_SAFI (afi
, safi
)
6407 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6408 dest
= bgp_route_next(dest
)) {
6409 if (!bgp_dest_has_bgp_path_info_data(dest
))
6412 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6413 || (safi
== SAFI_EVPN
)) {
6414 table
= bgp_dest_get_bgp_table_info(dest
);
6416 for (rm
= bgp_table_top(table
); rm
;
6417 rm
= bgp_route_next(rm
)) {
6419 bgp_dest_get_bgp_static_info(
6421 bgp_static_update_safi(
6422 bgp
, bgp_dest_get_prefix(rm
),
6423 bgp_static
, afi
, safi
);
6427 bgp
, bgp_dest_get_prefix(dest
),
6428 bgp_dest_get_bgp_static_info(dest
), afi
,
6432 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6435 /* Called from bgp_delete(). Delete all static routes from the BGP
6437 void bgp_static_delete(struct bgp
*bgp
)
6441 struct bgp_dest
*dest
;
6442 struct bgp_dest
*rm
;
6443 struct bgp_table
*table
;
6444 struct bgp_static
*bgp_static
;
6446 FOREACH_AFI_SAFI (afi
, safi
)
6447 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6448 dest
= bgp_route_next(dest
)) {
6449 if (!bgp_dest_has_bgp_path_info_data(dest
))
6452 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6453 || (safi
== SAFI_EVPN
)) {
6454 table
= bgp_dest_get_bgp_table_info(dest
);
6456 for (rm
= bgp_table_top(table
); rm
;
6457 rm
= bgp_route_next(rm
)) {
6459 bgp_dest_get_bgp_static_info(
6464 bgp_static_withdraw_safi(
6465 bgp
, bgp_dest_get_prefix(rm
),
6467 (struct prefix_rd
*)
6468 bgp_dest_get_prefix(
6470 bgp_static_free(bgp_static
);
6471 bgp_dest_set_bgp_static_info(rm
,
6473 bgp_dest_unlock_node(rm
);
6476 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6477 bgp_static_withdraw(bgp
,
6478 bgp_dest_get_prefix(dest
),
6480 bgp_static_free(bgp_static
);
6481 bgp_dest_set_bgp_static_info(dest
, NULL
);
6482 bgp_dest_unlock_node(dest
);
6487 void bgp_static_redo_import_check(struct bgp
*bgp
)
6491 struct bgp_dest
*dest
;
6492 struct bgp_dest
*rm
;
6493 struct bgp_table
*table
;
6494 struct bgp_static
*bgp_static
;
6496 /* Use this flag to force reprocessing of the route */
6497 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6498 FOREACH_AFI_SAFI (afi
, safi
) {
6499 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6500 dest
= bgp_route_next(dest
)) {
6501 if (!bgp_dest_has_bgp_path_info_data(dest
))
6504 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6505 || (safi
== SAFI_EVPN
)) {
6506 table
= bgp_dest_get_bgp_table_info(dest
);
6508 for (rm
= bgp_table_top(table
); rm
;
6509 rm
= bgp_route_next(rm
)) {
6511 bgp_dest_get_bgp_static_info(
6513 bgp_static_update_safi(
6514 bgp
, bgp_dest_get_prefix(rm
),
6515 bgp_static
, afi
, safi
);
6518 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6519 bgp_static_update(bgp
,
6520 bgp_dest_get_prefix(dest
),
6521 bgp_static
, afi
, safi
);
6525 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6528 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6531 struct bgp_table
*table
;
6532 struct bgp_dest
*dest
;
6533 struct bgp_path_info
*pi
;
6535 /* Do not install the aggregate route if BGP is in the
6536 * process of termination.
6538 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6539 || (bgp
->peer_self
== NULL
))
6542 table
= bgp
->rib
[afi
][safi
];
6543 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6544 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6545 if (pi
->peer
== bgp
->peer_self
6546 && ((pi
->type
== ZEBRA_ROUTE_BGP
6547 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6548 || (pi
->type
!= ZEBRA_ROUTE_BGP
6550 == BGP_ROUTE_REDISTRIBUTE
))) {
6551 bgp_aggregate_decrement(
6552 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6554 bgp_unlink_nexthop(pi
);
6555 bgp_path_info_delete(dest
, pi
);
6556 bgp_process(bgp
, dest
, afi
, safi
);
6563 * Purge all networks and redistributed routes from routing table.
6564 * Invoked upon the instance going down.
6566 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6571 FOREACH_AFI_SAFI (afi
, safi
)
6572 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6577 * Currently this is used to set static routes for VPN and ENCAP.
6578 * I think it can probably be factored with bgp_static_set.
6580 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6581 const char *ip_str
, const char *rd_str
,
6582 const char *label_str
, const char *rmap_str
,
6583 int evpn_type
, const char *esi
, const char *gwip
,
6584 const char *ethtag
, const char *routermac
)
6586 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6589 struct prefix_rd prd
;
6590 struct bgp_dest
*pdest
;
6591 struct bgp_dest
*dest
;
6592 struct bgp_table
*table
;
6593 struct bgp_static
*bgp_static
;
6594 mpls_label_t label
= MPLS_INVALID_LABEL
;
6595 struct prefix gw_ip
;
6597 /* validate ip prefix */
6598 ret
= str2prefix(ip_str
, &p
);
6600 vty_out(vty
, "%% Malformed prefix\n");
6601 return CMD_WARNING_CONFIG_FAILED
;
6604 if ((afi
== AFI_L2VPN
)
6605 && (bgp_build_evpn_prefix(evpn_type
,
6606 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6607 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6608 return CMD_WARNING_CONFIG_FAILED
;
6611 ret
= str2prefix_rd(rd_str
, &prd
);
6613 vty_out(vty
, "%% Malformed rd\n");
6614 return CMD_WARNING_CONFIG_FAILED
;
6618 unsigned long label_val
;
6619 label_val
= strtoul(label_str
, NULL
, 10);
6620 encode_label(label_val
, &label
);
6623 if (safi
== SAFI_EVPN
) {
6624 if (esi
&& str2esi(esi
, NULL
) == 0) {
6625 vty_out(vty
, "%% Malformed ESI\n");
6626 return CMD_WARNING_CONFIG_FAILED
;
6628 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6629 vty_out(vty
, "%% Malformed Router MAC\n");
6630 return CMD_WARNING_CONFIG_FAILED
;
6633 memset(&gw_ip
, 0, sizeof(struct prefix
));
6634 ret
= str2prefix(gwip
, &gw_ip
);
6636 vty_out(vty
, "%% Malformed GatewayIp\n");
6637 return CMD_WARNING_CONFIG_FAILED
;
6639 if ((gw_ip
.family
== AF_INET
6640 && is_evpn_prefix_ipaddr_v6(
6641 (struct prefix_evpn
*)&p
))
6642 || (gw_ip
.family
== AF_INET6
6643 && is_evpn_prefix_ipaddr_v4(
6644 (struct prefix_evpn
*)&p
))) {
6646 "%% GatewayIp family differs with IP prefix\n");
6647 return CMD_WARNING_CONFIG_FAILED
;
6651 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6652 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6653 bgp_dest_set_bgp_table_info(pdest
,
6654 bgp_table_init(bgp
, afi
, safi
));
6655 table
= bgp_dest_get_bgp_table_info(pdest
);
6657 dest
= bgp_node_get(table
, &p
);
6659 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6660 vty_out(vty
, "%% Same network configuration exists\n");
6661 bgp_dest_unlock_node(dest
);
6663 /* New configuration. */
6664 bgp_static
= bgp_static_new();
6665 bgp_static
->backdoor
= 0;
6666 bgp_static
->valid
= 0;
6667 bgp_static
->igpmetric
= 0;
6668 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6669 bgp_static
->label
= label
;
6670 bgp_static
->prd
= prd
;
6673 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6674 route_map_counter_decrement(bgp_static
->rmap
.map
);
6675 bgp_static
->rmap
.name
=
6676 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6677 bgp_static
->rmap
.map
=
6678 route_map_lookup_by_name(rmap_str
);
6679 route_map_counter_increment(bgp_static
->rmap
.map
);
6682 if (safi
== SAFI_EVPN
) {
6684 bgp_static
->eth_s_id
=
6687 str2esi(esi
, bgp_static
->eth_s_id
);
6690 bgp_static
->router_mac
=
6691 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
6692 (void)prefix_str2mac(routermac
,
6693 bgp_static
->router_mac
);
6696 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
6698 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6700 bgp_static
->valid
= 1;
6701 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
6707 /* Configure static BGP network. */
6708 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6709 const char *ip_str
, const char *rd_str
,
6710 const char *label_str
, int evpn_type
, const char *esi
,
6711 const char *gwip
, const char *ethtag
)
6713 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6716 struct prefix_rd prd
;
6717 struct bgp_dest
*pdest
;
6718 struct bgp_dest
*dest
;
6719 struct bgp_table
*table
;
6720 struct bgp_static
*bgp_static
;
6721 mpls_label_t label
= MPLS_INVALID_LABEL
;
6723 /* Convert IP prefix string to struct prefix. */
6724 ret
= str2prefix(ip_str
, &p
);
6726 vty_out(vty
, "%% Malformed prefix\n");
6727 return CMD_WARNING_CONFIG_FAILED
;
6730 if ((afi
== AFI_L2VPN
)
6731 && (bgp_build_evpn_prefix(evpn_type
,
6732 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6733 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6734 return CMD_WARNING_CONFIG_FAILED
;
6736 ret
= str2prefix_rd(rd_str
, &prd
);
6738 vty_out(vty
, "%% Malformed rd\n");
6739 return CMD_WARNING_CONFIG_FAILED
;
6743 unsigned long label_val
;
6744 label_val
= strtoul(label_str
, NULL
, 10);
6745 encode_label(label_val
, &label
);
6748 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6749 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6750 bgp_dest_set_bgp_table_info(pdest
,
6751 bgp_table_init(bgp
, afi
, safi
));
6753 bgp_dest_unlock_node(pdest
);
6754 table
= bgp_dest_get_bgp_table_info(pdest
);
6756 dest
= bgp_node_lookup(table
, &p
);
6759 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6761 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6762 bgp_static_free(bgp_static
);
6763 bgp_dest_set_bgp_static_info(dest
, NULL
);
6764 bgp_dest_unlock_node(dest
);
6765 bgp_dest_unlock_node(dest
);
6767 vty_out(vty
, "%% Can't find the route\n");
6772 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6773 const char *rmap_name
)
6775 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6776 struct bgp_rmap
*rmap
;
6778 rmap
= &bgp
->table_map
[afi
][safi
];
6780 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6781 route_map_counter_decrement(rmap
->map
);
6782 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6783 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6784 route_map_counter_increment(rmap
->map
);
6786 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6787 route_map_counter_decrement(rmap
->map
);
6791 if (bgp_fibupd_safi(safi
))
6792 bgp_zebra_announce_table(bgp
, afi
, safi
);
6797 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6798 const char *rmap_name
)
6800 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6801 struct bgp_rmap
*rmap
;
6803 rmap
= &bgp
->table_map
[afi
][safi
];
6804 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6805 route_map_counter_decrement(rmap
->map
);
6808 if (bgp_fibupd_safi(safi
))
6809 bgp_zebra_announce_table(bgp
, afi
, safi
);
6814 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6817 if (bgp
->table_map
[afi
][safi
].name
) {
6818 vty_out(vty
, " table-map %s\n",
6819 bgp
->table_map
[afi
][safi
].name
);
6823 DEFUN (bgp_table_map
,
6826 "BGP table to RIB route download filter\n"
6827 "Name of the route map\n")
6830 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6831 argv
[idx_word
]->arg
);
6833 DEFUN (no_bgp_table_map
,
6834 no_bgp_table_map_cmd
,
6835 "no table-map WORD",
6837 "BGP table to RIB route download filter\n"
6838 "Name of the route map\n")
6841 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6842 argv
[idx_word
]->arg
);
6848 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6849 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6850 backdoor$backdoor}]",
6852 "Specify a network to announce via BGP\n"
6857 "Route-map to modify the attributes\n"
6858 "Name of the route map\n"
6859 "Label index to associate with the prefix\n"
6860 "Label index value\n"
6861 "Specify a BGP backdoor route\n")
6863 char addr_prefix_str
[BUFSIZ
];
6868 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6870 sizeof(addr_prefix_str
));
6872 vty_out(vty
, "%% Inconsistent address and mask\n");
6873 return CMD_WARNING_CONFIG_FAILED
;
6877 return bgp_static_set(
6878 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
6879 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
6880 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6883 DEFPY(ipv6_bgp_network
,
6884 ipv6_bgp_network_cmd
,
6885 "[no] network X:X::X:X/M$prefix \
6886 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6888 "Specify a network to announce via BGP\n"
6890 "Route-map to modify the attributes\n"
6891 "Name of the route map\n"
6892 "Label index to associate with the prefix\n"
6893 "Label index value\n")
6895 return bgp_static_set(
6896 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
6897 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6900 static struct bgp_aggregate
*bgp_aggregate_new(void)
6902 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6905 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6907 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
6908 route_map_counter_decrement(aggregate
->suppress_map
);
6909 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6910 route_map_counter_decrement(aggregate
->rmap
.map
);
6911 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6915 * Helper function to avoid repeated code: prepare variables for a
6916 * `route_map_apply` call.
6918 * \returns `true` on route map match, otherwise `false`.
6920 static bool aggr_suppress_map_test(struct bgp
*bgp
,
6921 struct bgp_aggregate
*aggregate
,
6922 struct bgp_path_info
*pi
)
6924 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
6925 route_map_result_t rmr
= RMAP_DENYMATCH
;
6926 struct bgp_path_info rmap_path
= {};
6927 struct attr attr
= {};
6929 /* No route map entries created, just don't match. */
6930 if (aggregate
->suppress_map
== NULL
)
6933 /* Call route map matching and return result. */
6934 attr
.aspath
= aspath_empty();
6935 rmap_path
.peer
= bgp
->peer_self
;
6936 rmap_path
.attr
= &attr
;
6938 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
6939 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
6940 bgp
->peer_self
->rmap_type
= 0;
6942 bgp_attr_flush(&attr
);
6944 return rmr
== RMAP_PERMITMATCH
;
6947 /** Test whether the aggregation has suppressed this path or not. */
6948 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
6949 struct bgp_path_info
*pi
)
6951 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
6954 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
6958 * Suppress this path and keep the reference.
6960 * \returns `true` if needs processing otherwise `false`.
6962 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
6963 struct bgp_path_info
*pi
)
6965 struct bgp_path_info_extra
*pie
;
6967 /* Path is already suppressed by this aggregation. */
6968 if (aggr_suppress_exists(aggregate
, pi
))
6971 pie
= bgp_path_info_extra_get(pi
);
6973 /* This is the first suppression, allocate memory and list it. */
6974 if (pie
->aggr_suppressors
== NULL
)
6975 pie
->aggr_suppressors
= list_new();
6977 listnode_add(pie
->aggr_suppressors
, aggregate
);
6979 /* Only mark for processing if suppressed. */
6980 if (listcount(pie
->aggr_suppressors
) == 1) {
6981 if (BGP_DEBUG(update
, UPDATE_OUT
))
6982 zlog_debug("aggregate-address suppressing: %pFX",
6983 bgp_dest_get_prefix(pi
->net
));
6985 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6993 * Unsuppress this path and remove the reference.
6995 * \returns `true` if needs processing otherwise `false`.
6997 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
6998 struct bgp_path_info
*pi
)
7000 /* Path wasn't suppressed. */
7001 if (!aggr_suppress_exists(aggregate
, pi
))
7004 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7006 /* Unsuppress and free extra memory if last item. */
7007 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7008 if (BGP_DEBUG(update
, UPDATE_OUT
))
7009 zlog_debug("aggregate-address unsuppressing: %pFX",
7010 bgp_dest_get_prefix(pi
->net
));
7012 list_delete(&pi
->extra
->aggr_suppressors
);
7013 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7020 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7021 struct aspath
*aspath
,
7022 struct community
*comm
,
7023 struct ecommunity
*ecomm
,
7024 struct lcommunity
*lcomm
)
7026 static struct aspath
*ae
= NULL
;
7029 ae
= aspath_empty();
7034 if (origin
!= pi
->attr
->origin
)
7037 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7040 if (!community_cmp(pi
->attr
->community
, comm
))
7043 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
7046 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
7049 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7055 static void bgp_aggregate_install(
7056 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7057 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7058 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7059 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7061 struct bgp_dest
*dest
;
7062 struct bgp_table
*table
;
7063 struct bgp_path_info
*pi
, *orig
, *new;
7066 table
= bgp
->rib
[afi
][safi
];
7068 dest
= bgp_node_get(table
, p
);
7070 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7071 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7072 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7076 * If we have paths with different MEDs, then don't install
7077 * (or uninstall) the aggregate route.
7079 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7080 goto uninstall_aggregate_route
;
7082 if (aggregate
->count
> 0) {
7084 * If the aggregate information has not changed
7085 * no need to re-install it again.
7087 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7088 ecommunity
, lcommunity
)) {
7089 bgp_dest_unlock_node(dest
);
7092 aspath_free(aspath
);
7094 community_free(&community
);
7096 ecommunity_free(&ecommunity
);
7098 lcommunity_free(&lcommunity
);
7104 * Mark the old as unusable
7107 bgp_path_info_delete(dest
, pi
);
7109 attr
= bgp_attr_aggregate_intern(
7110 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7111 aggregate
, atomic_aggregate
, p
);
7114 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7115 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7116 zlog_debug("%s: %pFX null attribute", __func__
,
7121 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7122 bgp
->peer_self
, attr
, dest
);
7124 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7126 bgp_path_info_add(dest
, new);
7127 bgp_process(bgp
, dest
, afi
, safi
);
7129 uninstall_aggregate_route
:
7130 for (pi
= orig
; pi
; pi
= pi
->next
)
7131 if (pi
->peer
== bgp
->peer_self
7132 && pi
->type
== ZEBRA_ROUTE_BGP
7133 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7136 /* Withdraw static BGP route from routing table. */
7138 bgp_path_info_delete(dest
, pi
);
7139 bgp_process(bgp
, dest
, afi
, safi
);
7143 bgp_dest_unlock_node(dest
);
7147 * Check if the current path has different MED than other known paths.
7149 * \returns `true` if the MED matched the others else `false`.
7151 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7152 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7154 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7156 /* This is the first route being analyzed. */
7157 if (!aggregate
->med_initialized
) {
7158 aggregate
->med_initialized
= true;
7159 aggregate
->med_mismatched
= false;
7160 aggregate
->med_matched_value
= cur_med
;
7162 /* Check if routes with different MED showed up. */
7163 if (cur_med
!= aggregate
->med_matched_value
)
7164 aggregate
->med_mismatched
= true;
7167 return !aggregate
->med_mismatched
;
7171 * Initializes and tests all routes in the aggregate address path for MED
7174 * \returns `true` if all MEDs are the same otherwise `false`.
7176 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7177 struct bgp
*bgp
, const struct prefix
*p
,
7178 afi_t afi
, safi_t safi
)
7180 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7181 const struct prefix
*dest_p
;
7182 struct bgp_dest
*dest
, *top
;
7183 struct bgp_path_info
*pi
;
7184 bool med_matched
= true;
7186 aggregate
->med_initialized
= false;
7188 top
= bgp_node_get(table
, p
);
7189 for (dest
= bgp_node_get(table
, p
); dest
;
7190 dest
= bgp_route_next_until(dest
, top
)) {
7191 dest_p
= bgp_dest_get_prefix(dest
);
7192 if (dest_p
->prefixlen
<= p
->prefixlen
)
7195 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7196 if (BGP_PATH_HOLDDOWN(pi
))
7198 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7200 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7201 med_matched
= false;
7208 bgp_dest_unlock_node(top
);
7214 * Toggles the route suppression status for this aggregate address
7217 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7218 struct bgp
*bgp
, const struct prefix
*p
,
7219 afi_t afi
, safi_t safi
, bool suppress
)
7221 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7222 const struct prefix
*dest_p
;
7223 struct bgp_dest
*dest
, *top
;
7224 struct bgp_path_info
*pi
;
7225 bool toggle_suppression
;
7227 /* We've found a different MED we must revert any suppressed routes. */
7228 top
= bgp_node_get(table
, p
);
7229 for (dest
= bgp_node_get(table
, p
); dest
;
7230 dest
= bgp_route_next_until(dest
, top
)) {
7231 dest_p
= bgp_dest_get_prefix(dest
);
7232 if (dest_p
->prefixlen
<= p
->prefixlen
)
7235 toggle_suppression
= false;
7236 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7237 if (BGP_PATH_HOLDDOWN(pi
))
7239 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7242 /* We are toggling suppression back. */
7244 /* Suppress route if not suppressed already. */
7245 if (aggr_suppress_path(aggregate
, pi
))
7246 toggle_suppression
= true;
7250 /* Install route if there is no more suppression. */
7251 if (aggr_unsuppress_path(aggregate
, pi
))
7252 toggle_suppression
= true;
7255 if (toggle_suppression
)
7256 bgp_process(bgp
, dest
, afi
, safi
);
7258 bgp_dest_unlock_node(top
);
7262 * Aggregate address MED matching incremental test: this function is called
7263 * when the initial aggregation occurred and we are only testing a single
7266 * In addition to testing and setting the MED validity it also installs back
7267 * suppressed routes (if summary is configured).
7269 * Must not be called in `bgp_aggregate_route`.
7271 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7272 struct bgp
*bgp
, const struct prefix
*p
,
7273 afi_t afi
, safi_t safi
,
7274 struct bgp_path_info
*pi
, bool is_adding
)
7276 /* MED matching disabled. */
7277 if (!aggregate
->match_med
)
7280 /* Aggregation with different MED, nothing to do. */
7281 if (aggregate
->med_mismatched
)
7285 * Test the current entry:
7287 * is_adding == true: if the new entry doesn't match then we must
7288 * install all suppressed routes.
7290 * is_adding == false: if the entry being removed was the last
7291 * unmatching entry then we can suppress all routes.
7294 if (bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
)
7295 && aggregate
->summary_only
)
7296 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
,
7299 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7301 /* No mismatches, just quit. */
7302 if (!aggregate
->med_mismatched
)
7305 /* Route summarization is disabled. */
7306 if (!aggregate
->summary_only
)
7309 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7312 /* Update an aggregate as routes are added/removed from the BGP table */
7313 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7314 safi_t safi
, struct bgp_aggregate
*aggregate
)
7316 struct bgp_table
*table
;
7317 struct bgp_dest
*top
;
7318 struct bgp_dest
*dest
;
7320 struct aspath
*aspath
= NULL
;
7321 struct community
*community
= NULL
;
7322 struct ecommunity
*ecommunity
= NULL
;
7323 struct lcommunity
*lcommunity
= NULL
;
7324 struct bgp_path_info
*pi
;
7325 unsigned long match
= 0;
7326 uint8_t atomic_aggregate
= 0;
7328 /* If the bgp instance is being deleted or self peer is deleted
7329 * then do not create aggregate route
7331 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7332 || (bgp
->peer_self
== NULL
))
7335 /* Initialize and test routes for MED difference. */
7336 if (aggregate
->match_med
)
7337 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7340 * Reset aggregate count: we might've been called from route map
7341 * update so in that case we must retest all more specific routes.
7343 * \see `bgp_route_map_process_update`.
7345 aggregate
->count
= 0;
7346 aggregate
->incomplete_origin_count
= 0;
7347 aggregate
->incomplete_origin_count
= 0;
7348 aggregate
->egp_origin_count
= 0;
7350 /* ORIGIN attribute: If at least one route among routes that are
7351 aggregated has ORIGIN with the value INCOMPLETE, then the
7352 aggregated route must have the ORIGIN attribute with the value
7353 INCOMPLETE. Otherwise, if at least one route among routes that
7354 are aggregated has ORIGIN with the value EGP, then the aggregated
7355 route must have the origin attribute with the value EGP. In all
7356 other case the value of the ORIGIN attribute of the aggregated
7357 route is INTERNAL. */
7358 origin
= BGP_ORIGIN_IGP
;
7360 table
= bgp
->rib
[afi
][safi
];
7362 top
= bgp_node_get(table
, p
);
7363 for (dest
= bgp_node_get(table
, p
); dest
;
7364 dest
= bgp_route_next_until(dest
, top
)) {
7365 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7367 if (dest_p
->prefixlen
<= p
->prefixlen
)
7370 /* If suppress fib is enabled and route not installed
7371 * in FIB, skip the route
7373 if (!bgp_check_advertise(bgp
, dest
))
7378 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7379 if (BGP_PATH_HOLDDOWN(pi
))
7383 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7384 atomic_aggregate
= 1;
7386 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7390 * summary-only aggregate route suppress
7391 * aggregated route announcements.
7394 * Don't create summaries if MED didn't match
7395 * otherwise neither the specific routes and the
7396 * aggregation will be announced.
7398 if (aggregate
->summary_only
7399 && AGGREGATE_MED_VALID(aggregate
)) {
7400 if (aggr_suppress_path(aggregate
, pi
))
7405 * Suppress more specific routes that match the route
7409 * Don't suppress routes if MED matching is enabled and
7410 * it mismatched otherwise we might end up with no
7411 * routes for this path.
7413 if (aggregate
->suppress_map_name
7414 && AGGREGATE_MED_VALID(aggregate
)
7415 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7416 if (aggr_suppress_path(aggregate
, pi
))
7423 * If at least one route among routes that are
7424 * aggregated has ORIGIN with the value INCOMPLETE,
7425 * then the aggregated route MUST have the ORIGIN
7426 * attribute with the value INCOMPLETE. Otherwise, if
7427 * at least one route among routes that are aggregated
7428 * has ORIGIN with the value EGP, then the aggregated
7429 * route MUST have the ORIGIN attribute with the value
7432 switch (pi
->attr
->origin
) {
7433 case BGP_ORIGIN_INCOMPLETE
:
7434 aggregate
->incomplete_origin_count
++;
7436 case BGP_ORIGIN_EGP
:
7437 aggregate
->egp_origin_count
++;
7445 if (!aggregate
->as_set
)
7449 * as-set aggregate route generate origin, as path,
7450 * and community aggregation.
7452 /* Compute aggregate route's as-path.
7454 bgp_compute_aggregate_aspath_hash(aggregate
,
7457 /* Compute aggregate route's community.
7459 if (pi
->attr
->community
)
7460 bgp_compute_aggregate_community_hash(
7462 pi
->attr
->community
);
7464 /* Compute aggregate route's extended community.
7466 if (pi
->attr
->ecommunity
)
7467 bgp_compute_aggregate_ecommunity_hash(
7469 pi
->attr
->ecommunity
);
7471 /* Compute aggregate route's large community.
7473 if (pi
->attr
->lcommunity
)
7474 bgp_compute_aggregate_lcommunity_hash(
7476 pi
->attr
->lcommunity
);
7479 bgp_process(bgp
, dest
, afi
, safi
);
7481 if (aggregate
->as_set
) {
7482 bgp_compute_aggregate_aspath_val(aggregate
);
7483 bgp_compute_aggregate_community_val(aggregate
);
7484 bgp_compute_aggregate_ecommunity_val(aggregate
);
7485 bgp_compute_aggregate_lcommunity_val(aggregate
);
7489 bgp_dest_unlock_node(top
);
7492 if (aggregate
->incomplete_origin_count
> 0)
7493 origin
= BGP_ORIGIN_INCOMPLETE
;
7494 else if (aggregate
->egp_origin_count
> 0)
7495 origin
= BGP_ORIGIN_EGP
;
7497 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7498 origin
= aggregate
->origin
;
7500 if (aggregate
->as_set
) {
7501 if (aggregate
->aspath
)
7502 /* Retrieve aggregate route's as-path.
7504 aspath
= aspath_dup(aggregate
->aspath
);
7506 if (aggregate
->community
)
7507 /* Retrieve aggregate route's community.
7509 community
= community_dup(aggregate
->community
);
7511 if (aggregate
->ecommunity
)
7512 /* Retrieve aggregate route's ecommunity.
7514 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7516 if (aggregate
->lcommunity
)
7517 /* Retrieve aggregate route's lcommunity.
7519 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7522 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7523 ecommunity
, lcommunity
, atomic_aggregate
,
7527 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7528 safi_t safi
, struct bgp_aggregate
*aggregate
)
7530 struct bgp_table
*table
;
7531 struct bgp_dest
*top
;
7532 struct bgp_dest
*dest
;
7533 struct bgp_path_info
*pi
;
7534 unsigned long match
;
7536 table
= bgp
->rib
[afi
][safi
];
7538 /* If routes exists below this node, generate aggregate routes. */
7539 top
= bgp_node_get(table
, p
);
7540 for (dest
= bgp_node_get(table
, p
); dest
;
7541 dest
= bgp_route_next_until(dest
, top
)) {
7542 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7544 if (dest_p
->prefixlen
<= p
->prefixlen
)
7548 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7549 if (BGP_PATH_HOLDDOWN(pi
))
7552 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7556 * This route is suppressed: attempt to unsuppress it.
7558 * `aggr_unsuppress_path` will fail if this particular
7559 * aggregate route was not the suppressor.
7561 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7562 listcount(pi
->extra
->aggr_suppressors
)) {
7563 if (aggr_unsuppress_path(aggregate
, pi
))
7569 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7570 aggregate
->incomplete_origin_count
--;
7571 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7572 aggregate
->egp_origin_count
--;
7574 if (aggregate
->as_set
) {
7575 /* Remove as-path from aggregate.
7577 bgp_remove_aspath_from_aggregate_hash(
7581 if (pi
->attr
->community
)
7582 /* Remove community from aggregate.
7584 bgp_remove_comm_from_aggregate_hash(
7586 pi
->attr
->community
);
7588 if (pi
->attr
->ecommunity
)
7589 /* Remove ecommunity from aggregate.
7591 bgp_remove_ecomm_from_aggregate_hash(
7593 pi
->attr
->ecommunity
);
7595 if (pi
->attr
->lcommunity
)
7596 /* Remove lcommunity from aggregate.
7598 bgp_remove_lcomm_from_aggregate_hash(
7600 pi
->attr
->lcommunity
);
7604 /* If this node was suppressed, process the change. */
7606 bgp_process(bgp
, dest
, afi
, safi
);
7608 if (aggregate
->as_set
) {
7609 aspath_free(aggregate
->aspath
);
7610 aggregate
->aspath
= NULL
;
7611 if (aggregate
->community
)
7612 community_free(&aggregate
->community
);
7613 if (aggregate
->ecommunity
)
7614 ecommunity_free(&aggregate
->ecommunity
);
7615 if (aggregate
->lcommunity
)
7616 lcommunity_free(&aggregate
->lcommunity
);
7619 bgp_dest_unlock_node(top
);
7622 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7623 const struct prefix
*aggr_p
,
7624 struct bgp_path_info
*pinew
, afi_t afi
,
7626 struct bgp_aggregate
*aggregate
)
7629 struct aspath
*aspath
= NULL
;
7630 uint8_t atomic_aggregate
= 0;
7631 struct community
*community
= NULL
;
7632 struct ecommunity
*ecommunity
= NULL
;
7633 struct lcommunity
*lcommunity
= NULL
;
7635 /* If the bgp instance is being deleted or self peer is deleted
7636 * then do not create aggregate route
7638 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7639 || (bgp
->peer_self
== NULL
))
7642 /* ORIGIN attribute: If at least one route among routes that are
7643 * aggregated has ORIGIN with the value INCOMPLETE, then the
7644 * aggregated route must have the ORIGIN attribute with the value
7645 * INCOMPLETE. Otherwise, if at least one route among routes that
7646 * are aggregated has ORIGIN with the value EGP, then the aggregated
7647 * route must have the origin attribute with the value EGP. In all
7648 * other case the value of the ORIGIN attribute of the aggregated
7649 * route is INTERNAL.
7651 origin
= BGP_ORIGIN_IGP
;
7656 * This must be called before `summary` check to avoid
7657 * "suppressing" twice.
7659 if (aggregate
->match_med
)
7660 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7663 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7664 aggr_suppress_path(aggregate
, pinew
);
7666 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7667 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7668 aggr_suppress_path(aggregate
, pinew
);
7670 switch (pinew
->attr
->origin
) {
7671 case BGP_ORIGIN_INCOMPLETE
:
7672 aggregate
->incomplete_origin_count
++;
7674 case BGP_ORIGIN_EGP
:
7675 aggregate
->egp_origin_count
++;
7683 if (aggregate
->incomplete_origin_count
> 0)
7684 origin
= BGP_ORIGIN_INCOMPLETE
;
7685 else if (aggregate
->egp_origin_count
> 0)
7686 origin
= BGP_ORIGIN_EGP
;
7688 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7689 origin
= aggregate
->origin
;
7691 if (aggregate
->as_set
) {
7692 /* Compute aggregate route's as-path.
7694 bgp_compute_aggregate_aspath(aggregate
,
7695 pinew
->attr
->aspath
);
7697 /* Compute aggregate route's community.
7699 if (pinew
->attr
->community
)
7700 bgp_compute_aggregate_community(
7702 pinew
->attr
->community
);
7704 /* Compute aggregate route's extended community.
7706 if (pinew
->attr
->ecommunity
)
7707 bgp_compute_aggregate_ecommunity(
7709 pinew
->attr
->ecommunity
);
7711 /* Compute aggregate route's large community.
7713 if (pinew
->attr
->lcommunity
)
7714 bgp_compute_aggregate_lcommunity(
7716 pinew
->attr
->lcommunity
);
7718 /* Retrieve aggregate route's as-path.
7720 if (aggregate
->aspath
)
7721 aspath
= aspath_dup(aggregate
->aspath
);
7723 /* Retrieve aggregate route's community.
7725 if (aggregate
->community
)
7726 community
= community_dup(aggregate
->community
);
7728 /* Retrieve aggregate route's ecommunity.
7730 if (aggregate
->ecommunity
)
7731 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7733 /* Retrieve aggregate route's lcommunity.
7735 if (aggregate
->lcommunity
)
7736 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7739 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7740 aspath
, community
, ecommunity
,
7741 lcommunity
, atomic_aggregate
, aggregate
);
7744 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7746 struct bgp_path_info
*pi
,
7747 struct bgp_aggregate
*aggregate
,
7748 const struct prefix
*aggr_p
)
7751 struct aspath
*aspath
= NULL
;
7752 uint8_t atomic_aggregate
= 0;
7753 struct community
*community
= NULL
;
7754 struct ecommunity
*ecommunity
= NULL
;
7755 struct lcommunity
*lcommunity
= NULL
;
7756 unsigned long match
= 0;
7758 /* If the bgp instance is being deleted or self peer is deleted
7759 * then do not create aggregate route
7761 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7762 || (bgp
->peer_self
== NULL
))
7765 if (BGP_PATH_HOLDDOWN(pi
))
7768 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7771 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7772 if (aggr_unsuppress_path(aggregate
, pi
))
7775 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7776 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7777 if (aggr_unsuppress_path(aggregate
, pi
))
7781 * This must be called after `summary`, `suppress-map` check to avoid
7782 * "unsuppressing" twice.
7784 if (aggregate
->match_med
)
7785 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
,
7788 if (aggregate
->count
> 0)
7791 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7792 aggregate
->incomplete_origin_count
--;
7793 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7794 aggregate
->egp_origin_count
--;
7796 if (aggregate
->as_set
) {
7797 /* Remove as-path from aggregate.
7799 bgp_remove_aspath_from_aggregate(aggregate
,
7802 if (pi
->attr
->community
)
7803 /* Remove community from aggregate.
7805 bgp_remove_community_from_aggregate(
7807 pi
->attr
->community
);
7809 if (pi
->attr
->ecommunity
)
7810 /* Remove ecommunity from aggregate.
7812 bgp_remove_ecommunity_from_aggregate(
7814 pi
->attr
->ecommunity
);
7816 if (pi
->attr
->lcommunity
)
7817 /* Remove lcommunity from aggregate.
7819 bgp_remove_lcommunity_from_aggregate(
7821 pi
->attr
->lcommunity
);
7824 /* If this node was suppressed, process the change. */
7826 bgp_process(bgp
, pi
->net
, afi
, safi
);
7828 origin
= BGP_ORIGIN_IGP
;
7829 if (aggregate
->incomplete_origin_count
> 0)
7830 origin
= BGP_ORIGIN_INCOMPLETE
;
7831 else if (aggregate
->egp_origin_count
> 0)
7832 origin
= BGP_ORIGIN_EGP
;
7834 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7835 origin
= aggregate
->origin
;
7837 if (aggregate
->as_set
) {
7838 /* Retrieve aggregate route's as-path.
7840 if (aggregate
->aspath
)
7841 aspath
= aspath_dup(aggregate
->aspath
);
7843 /* Retrieve aggregate route's community.
7845 if (aggregate
->community
)
7846 community
= community_dup(aggregate
->community
);
7848 /* Retrieve aggregate route's ecommunity.
7850 if (aggregate
->ecommunity
)
7851 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7853 /* Retrieve aggregate route's lcommunity.
7855 if (aggregate
->lcommunity
)
7856 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7859 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7860 aspath
, community
, ecommunity
,
7861 lcommunity
, atomic_aggregate
, aggregate
);
7864 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
7865 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
7867 struct bgp_dest
*child
;
7868 struct bgp_dest
*dest
;
7869 struct bgp_aggregate
*aggregate
;
7870 struct bgp_table
*table
;
7872 table
= bgp
->aggregate
[afi
][safi
];
7874 /* No aggregates configured. */
7875 if (bgp_table_top_nolock(table
) == NULL
)
7878 if (p
->prefixlen
== 0)
7881 if (BGP_PATH_HOLDDOWN(pi
))
7884 /* If suppress fib is enabled and route not installed
7885 * in FIB, do not update the aggregate route
7887 if (!bgp_check_advertise(bgp
, pi
->net
))
7890 child
= bgp_node_get(table
, p
);
7892 /* Aggregate address configuration check. */
7893 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7894 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7896 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7897 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7898 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
7902 bgp_dest_unlock_node(child
);
7905 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
7906 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
7908 struct bgp_dest
*child
;
7909 struct bgp_dest
*dest
;
7910 struct bgp_aggregate
*aggregate
;
7911 struct bgp_table
*table
;
7913 table
= bgp
->aggregate
[afi
][safi
];
7915 /* No aggregates configured. */
7916 if (bgp_table_top_nolock(table
) == NULL
)
7919 if (p
->prefixlen
== 0)
7922 child
= bgp_node_get(table
, p
);
7924 /* Aggregate address configuration check. */
7925 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7926 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7928 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7929 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7930 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
7934 bgp_dest_unlock_node(child
);
7937 /* Aggregate route attribute. */
7938 #define AGGREGATE_SUMMARY_ONLY 1
7939 #define AGGREGATE_AS_SET 1
7940 #define AGGREGATE_AS_UNSET 0
7942 static const char *bgp_origin2str(uint8_t origin
)
7945 case BGP_ORIGIN_IGP
:
7947 case BGP_ORIGIN_EGP
:
7949 case BGP_ORIGIN_INCOMPLETE
:
7950 return "incomplete";
7955 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
7958 case RPKI_NOT_BEING_USED
:
7968 assert(!"We should never get here this is a dev escape");
7972 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
7973 afi_t afi
, safi_t safi
)
7975 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7978 struct bgp_dest
*dest
;
7979 struct bgp_aggregate
*aggregate
;
7981 /* Convert string to prefix structure. */
7982 ret
= str2prefix(prefix_str
, &p
);
7984 vty_out(vty
, "Malformed prefix\n");
7985 return CMD_WARNING_CONFIG_FAILED
;
7989 /* Old configuration check. */
7990 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
7993 "%% There is no aggregate-address configuration.\n");
7994 return CMD_WARNING_CONFIG_FAILED
;
7997 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7998 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
7999 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8000 NULL
, NULL
, 0, aggregate
);
8002 /* Unlock aggregate address configuration. */
8003 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8005 if (aggregate
->community
)
8006 community_free(&aggregate
->community
);
8008 if (aggregate
->community_hash
) {
8009 /* Delete all communities in the hash.
8011 hash_clean(aggregate
->community_hash
,
8012 bgp_aggr_community_remove
);
8013 /* Free up the community_hash.
8015 hash_free(aggregate
->community_hash
);
8018 if (aggregate
->ecommunity
)
8019 ecommunity_free(&aggregate
->ecommunity
);
8021 if (aggregate
->ecommunity_hash
) {
8022 /* Delete all ecommunities in the hash.
8024 hash_clean(aggregate
->ecommunity_hash
,
8025 bgp_aggr_ecommunity_remove
);
8026 /* Free up the ecommunity_hash.
8028 hash_free(aggregate
->ecommunity_hash
);
8031 if (aggregate
->lcommunity
)
8032 lcommunity_free(&aggregate
->lcommunity
);
8034 if (aggregate
->lcommunity_hash
) {
8035 /* Delete all lcommunities in the hash.
8037 hash_clean(aggregate
->lcommunity_hash
,
8038 bgp_aggr_lcommunity_remove
);
8039 /* Free up the lcommunity_hash.
8041 hash_free(aggregate
->lcommunity_hash
);
8044 if (aggregate
->aspath
)
8045 aspath_free(aggregate
->aspath
);
8047 if (aggregate
->aspath_hash
) {
8048 /* Delete all as-paths in the hash.
8050 hash_clean(aggregate
->aspath_hash
,
8051 bgp_aggr_aspath_remove
);
8052 /* Free up the aspath_hash.
8054 hash_free(aggregate
->aspath_hash
);
8057 bgp_aggregate_free(aggregate
);
8058 bgp_dest_unlock_node(dest
);
8059 bgp_dest_unlock_node(dest
);
8064 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8065 safi_t safi
, const char *rmap
,
8066 uint8_t summary_only
, uint8_t as_set
,
8067 uint8_t origin
, bool match_med
,
8068 const char *suppress_map
)
8070 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8073 struct bgp_dest
*dest
;
8074 struct bgp_aggregate
*aggregate
;
8075 uint8_t as_set_new
= as_set
;
8077 if (suppress_map
&& summary_only
) {
8079 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8080 return CMD_WARNING_CONFIG_FAILED
;
8083 /* Convert string to prefix structure. */
8084 ret
= str2prefix(prefix_str
, &p
);
8086 vty_out(vty
, "Malformed prefix\n");
8087 return CMD_WARNING_CONFIG_FAILED
;
8091 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8092 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8093 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8095 return CMD_WARNING_CONFIG_FAILED
;
8098 /* Old configuration check. */
8099 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8100 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8103 vty_out(vty
, "There is already same aggregate network.\n");
8104 /* try to remove the old entry */
8105 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8107 vty_out(vty
, "Error deleting aggregate.\n");
8108 bgp_dest_unlock_node(dest
);
8109 return CMD_WARNING_CONFIG_FAILED
;
8113 /* Make aggregate address structure. */
8114 aggregate
= bgp_aggregate_new();
8115 aggregate
->summary_only
= summary_only
;
8116 aggregate
->match_med
= match_med
;
8118 /* Network operators MUST NOT locally generate any new
8119 * announcements containing AS_SET or AS_CONFED_SET. If they have
8120 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8121 * SHOULD withdraw those routes and re-announce routes for the
8122 * aggregate or component prefixes (i.e., the more-specific routes
8123 * subsumed by the previously aggregated route) without AS_SET
8124 * or AS_CONFED_SET in the updates.
8126 if (bgp
->reject_as_sets
) {
8127 if (as_set
== AGGREGATE_AS_SET
) {
8128 as_set_new
= AGGREGATE_AS_UNSET
;
8130 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8133 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8137 aggregate
->as_set
= as_set_new
;
8138 aggregate
->safi
= safi
;
8139 /* Override ORIGIN attribute if defined.
8140 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8141 * to IGP which is not what rfc4271 says.
8142 * This enables the same behavior, optionally.
8144 aggregate
->origin
= origin
;
8147 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8148 route_map_counter_decrement(aggregate
->rmap
.map
);
8149 aggregate
->rmap
.name
=
8150 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8151 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8152 route_map_counter_increment(aggregate
->rmap
.map
);
8156 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8157 route_map_counter_decrement(aggregate
->suppress_map
);
8159 aggregate
->suppress_map_name
=
8160 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8161 aggregate
->suppress_map
=
8162 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8163 route_map_counter_increment(aggregate
->suppress_map
);
8166 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8168 /* Aggregate address insert into BGP routing table. */
8169 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8174 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8175 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8177 "|summary-only$summary_only"
8178 "|route-map WORD$rmap_name"
8179 "|origin <egp|igp|incomplete>$origin_s"
8180 "|matching-MED-only$match_med"
8181 "|suppress-map WORD$suppress_map"
8184 "Configure BGP aggregate entries\n"
8185 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
8186 "Generate AS set path information\n"
8187 "Filter more specific routes from updates\n"
8188 "Apply route map to aggregate network\n"
8193 "Unknown heritage\n"
8194 "Only aggregate routes with matching MED\n"
8195 "Suppress the selected more specific routes\n"
8196 "Route map with the route selectors\n")
8198 const char *prefix_s
= NULL
;
8199 safi_t safi
= bgp_node_safi(vty
);
8200 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8201 int as_set
= AGGREGATE_AS_UNSET
;
8202 char prefix_buf
[PREFIX2STR_BUFFER
];
8205 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8208 vty_out(vty
, "%% Inconsistent address and mask\n");
8209 return CMD_WARNING_CONFIG_FAILED
;
8211 prefix_s
= prefix_buf
;
8213 prefix_s
= prefix_str
;
8216 if (strcmp(origin_s
, "egp") == 0)
8217 origin
= BGP_ORIGIN_EGP
;
8218 else if (strcmp(origin_s
, "igp") == 0)
8219 origin
= BGP_ORIGIN_IGP
;
8220 else if (strcmp(origin_s
, "incomplete") == 0)
8221 origin
= BGP_ORIGIN_INCOMPLETE
;
8225 as_set
= AGGREGATE_AS_SET
;
8227 /* Handle configuration removal, otherwise installation. */
8229 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8231 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8232 summary_only
!= NULL
, as_set
, origin
,
8233 match_med
!= NULL
, suppress_map
);
8236 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8237 "[no] aggregate-address X:X::X:X/M$prefix [{"
8239 "|summary-only$summary_only"
8240 "|route-map WORD$rmap_name"
8241 "|origin <egp|igp|incomplete>$origin_s"
8242 "|matching-MED-only$match_med"
8243 "|suppress-map WORD$suppress_map"
8246 "Configure BGP aggregate entries\n"
8247 "Aggregate prefix\n"
8248 "Generate AS set path information\n"
8249 "Filter more specific routes from updates\n"
8250 "Apply route map to aggregate network\n"
8255 "Unknown heritage\n"
8256 "Only aggregate routes with matching MED\n"
8257 "Suppress the selected more specific routes\n"
8258 "Route map with the route selectors\n")
8260 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8261 int as_set
= AGGREGATE_AS_UNSET
;
8264 if (strcmp(origin_s
, "egp") == 0)
8265 origin
= BGP_ORIGIN_EGP
;
8266 else if (strcmp(origin_s
, "igp") == 0)
8267 origin
= BGP_ORIGIN_IGP
;
8268 else if (strcmp(origin_s
, "incomplete") == 0)
8269 origin
= BGP_ORIGIN_INCOMPLETE
;
8273 as_set
= AGGREGATE_AS_SET
;
8275 /* Handle configuration removal, otherwise installation. */
8277 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8280 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8281 rmap_name
, summary_only
!= NULL
, as_set
,
8282 origin
, match_med
!= NULL
, suppress_map
);
8285 /* Redistribute route treatment. */
8286 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8287 const union g_addr
*nexthop
, ifindex_t ifindex
,
8288 enum nexthop_types_t nhtype
, uint8_t distance
,
8289 enum blackhole_type bhtype
, uint32_t metric
,
8290 uint8_t type
, unsigned short instance
,
8293 struct bgp_path_info
*new;
8294 struct bgp_path_info
*bpi
;
8295 struct bgp_path_info rmap_path
;
8296 struct bgp_dest
*bn
;
8298 struct attr
*new_attr
;
8300 route_map_result_t ret
;
8301 struct bgp_redist
*red
;
8303 /* Make default attribute. */
8304 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
8306 * This must not be NULL to satisfy Coverity SA
8308 assert(attr
.aspath
);
8311 case NEXTHOP_TYPE_IFINDEX
:
8313 case NEXTHOP_TYPE_IPV4
:
8314 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8315 attr
.nexthop
= nexthop
->ipv4
;
8317 case NEXTHOP_TYPE_IPV6
:
8318 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8319 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8320 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8322 case NEXTHOP_TYPE_BLACKHOLE
:
8323 switch (p
->family
) {
8325 attr
.nexthop
.s_addr
= INADDR_ANY
;
8328 memset(&attr
.mp_nexthop_global
, 0,
8329 sizeof(attr
.mp_nexthop_global
));
8330 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8333 attr
.bh_type
= bhtype
;
8336 attr
.nh_type
= nhtype
;
8337 attr
.nh_ifindex
= ifindex
;
8340 attr
.distance
= distance
;
8341 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8344 afi
= family2afi(p
->family
);
8346 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8348 struct attr attr_new
;
8350 /* Copy attribute for modification. */
8353 if (red
->redist_metric_flag
)
8354 attr_new
.med
= red
->redist_metric
;
8356 /* Apply route-map. */
8357 if (red
->rmap
.name
) {
8358 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
8359 rmap_path
.peer
= bgp
->peer_self
;
8360 rmap_path
.attr
= &attr_new
;
8362 SET_FLAG(bgp
->peer_self
->rmap_type
,
8363 PEER_RMAP_TYPE_REDISTRIBUTE
);
8365 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8367 bgp
->peer_self
->rmap_type
= 0;
8369 if (ret
== RMAP_DENYMATCH
) {
8370 /* Free uninterned attribute. */
8371 bgp_attr_flush(&attr_new
);
8373 /* Unintern original. */
8374 aspath_unintern(&attr
.aspath
);
8375 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8380 if (bgp_in_graceful_shutdown(bgp
))
8381 bgp_attr_add_gshut_community(&attr_new
);
8383 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8384 SAFI_UNICAST
, p
, NULL
);
8386 new_attr
= bgp_attr_intern(&attr_new
);
8388 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8389 if (bpi
->peer
== bgp
->peer_self
8390 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8394 /* Ensure the (source route) type is updated. */
8396 if (attrhash_cmp(bpi
->attr
, new_attr
)
8397 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8398 bgp_attr_unintern(&new_attr
);
8399 aspath_unintern(&attr
.aspath
);
8400 bgp_dest_unlock_node(bn
);
8403 /* The attribute is changed. */
8404 bgp_path_info_set_flag(bn
, bpi
,
8405 BGP_PATH_ATTR_CHANGED
);
8407 /* Rewrite BGP route information. */
8408 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8409 bgp_path_info_restore(bn
, bpi
);
8411 bgp_aggregate_decrement(
8412 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8413 bgp_attr_unintern(&bpi
->attr
);
8414 bpi
->attr
= new_attr
;
8415 bpi
->uptime
= bgp_clock();
8417 /* Process change. */
8418 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8420 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8421 bgp_dest_unlock_node(bn
);
8422 aspath_unintern(&attr
.aspath
);
8424 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8426 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8428 vpn_leak_from_vrf_update(
8429 bgp_get_default(), bgp
, bpi
);
8435 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8436 bgp
->peer_self
, new_attr
, bn
);
8437 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8439 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8440 bgp_path_info_add(bn
, new);
8441 bgp_dest_unlock_node(bn
);
8442 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8443 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8445 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8446 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8448 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8452 /* Unintern original. */
8453 aspath_unintern(&attr
.aspath
);
8456 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8457 unsigned short instance
)
8460 struct bgp_dest
*dest
;
8461 struct bgp_path_info
*pi
;
8462 struct bgp_redist
*red
;
8464 afi
= family2afi(p
->family
);
8466 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8468 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8469 SAFI_UNICAST
, p
, NULL
);
8471 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8472 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8476 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8477 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8479 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8482 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8483 bgp_path_info_delete(dest
, pi
);
8484 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8486 bgp_dest_unlock_node(dest
);
8490 /* Withdraw specified route type's route. */
8491 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8492 unsigned short instance
)
8494 struct bgp_dest
*dest
;
8495 struct bgp_path_info
*pi
;
8496 struct bgp_table
*table
;
8498 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8500 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8501 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8502 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8503 && pi
->instance
== instance
)
8507 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8508 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8510 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8513 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8514 pi
, afi
, SAFI_UNICAST
);
8515 bgp_path_info_delete(dest
, pi
);
8516 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8521 /* Static function to display route. */
8522 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8523 struct vty
*vty
, json_object
*json
, bool wide
)
8528 if (p
->family
== AF_INET
) {
8530 len
= vty_out(vty
, "%pFX", p
);
8532 json_object_string_add(json
, "prefix",
8533 inet_ntop(p
->family
,
8536 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8537 json_object_string_addf(json
, "network", "%pFX", p
);
8538 json_object_int_add(json
, "version", dest
->version
);
8540 } else if (p
->family
== AF_ETHERNET
) {
8541 len
= vty_out(vty
, "%pFX", p
);
8542 } else if (p
->family
== AF_EVPN
) {
8544 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8546 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8547 } else if (p
->family
== AF_FLOWSPEC
) {
8548 route_vty_out_flowspec(vty
, p
, NULL
,
8550 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8551 NLRI_STRING_FORMAT_MIN
, json
);
8554 len
= vty_out(vty
, "%pFX", p
);
8556 json_object_string_add(json
, "prefix",
8557 inet_ntop(p
->family
,
8560 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8561 json_object_string_addf(json
, "network", "%pFX", p
);
8562 json_object_int_add(json
, "version", dest
->version
);
8567 len
= wide
? (45 - len
) : (17 - len
);
8569 vty_out(vty
, "\n%*s", 20, " ");
8571 vty_out(vty
, "%*s", len
, " ");
8575 enum bgp_display_type
{
8579 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8582 case bgp_path_selection_none
:
8583 return "Nothing to Select";
8584 case bgp_path_selection_first
:
8585 return "First path received";
8586 case bgp_path_selection_evpn_sticky_mac
:
8587 return "EVPN Sticky Mac";
8588 case bgp_path_selection_evpn_seq
:
8589 return "EVPN sequence number";
8590 case bgp_path_selection_evpn_lower_ip
:
8591 return "EVPN lower IP";
8592 case bgp_path_selection_evpn_local_path
:
8593 return "EVPN local ES path";
8594 case bgp_path_selection_evpn_non_proxy
:
8595 return "EVPN non proxy";
8596 case bgp_path_selection_weight
:
8598 case bgp_path_selection_local_pref
:
8599 return "Local Pref";
8600 case bgp_path_selection_local_route
:
8601 return "Local Route";
8602 case bgp_path_selection_confed_as_path
:
8603 return "Confederation based AS Path";
8604 case bgp_path_selection_as_path
:
8606 case bgp_path_selection_origin
:
8608 case bgp_path_selection_med
:
8610 case bgp_path_selection_peer
:
8612 case bgp_path_selection_confed
:
8613 return "Confed Peer Type";
8614 case bgp_path_selection_igp_metric
:
8615 return "IGP Metric";
8616 case bgp_path_selection_older
:
8617 return "Older Path";
8618 case bgp_path_selection_router_id
:
8620 case bgp_path_selection_cluster_length
:
8621 return "Cluster length";
8622 case bgp_path_selection_stale
:
8623 return "Path Staleness";
8624 case bgp_path_selection_local_configured
:
8625 return "Locally configured route";
8626 case bgp_path_selection_neighbor_ip
:
8627 return "Neighbor IP";
8628 case bgp_path_selection_default
:
8629 return "Nothing left to compare";
8631 return "Invalid (internal error)";
8634 /* Print the short form route status for a bgp_path_info */
8635 static void route_vty_short_status_out(struct vty
*vty
,
8636 struct bgp_path_info
*path
,
8637 const struct prefix
*p
,
8638 json_object
*json_path
)
8640 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8644 /* Route status display. */
8645 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8646 json_object_boolean_true_add(json_path
, "removed");
8648 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8649 json_object_boolean_true_add(json_path
, "stale");
8651 if (path
->extra
&& bgp_path_suppressed(path
))
8652 json_object_boolean_true_add(json_path
, "suppressed");
8654 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8655 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8656 json_object_boolean_true_add(json_path
, "valid");
8659 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8660 json_object_boolean_true_add(json_path
, "history");
8662 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8663 json_object_boolean_true_add(json_path
, "damped");
8665 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8666 json_object_boolean_true_add(json_path
, "bestpath");
8667 json_object_string_add(json_path
, "selectionReason",
8668 bgp_path_selection_reason2str(
8669 path
->net
->reason
));
8672 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8673 json_object_boolean_true_add(json_path
, "multipath");
8675 /* Internal route. */
8676 if ((path
->peer
->as
)
8677 && (path
->peer
->as
== path
->peer
->local_as
))
8678 json_object_string_add(json_path
, "pathFrom",
8681 json_object_string_add(json_path
, "pathFrom",
8687 /* RPKI validation state */
8689 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
8691 if (rpki_state
== RPKI_VALID
)
8693 else if (rpki_state
== RPKI_INVALID
)
8695 else if (rpki_state
== RPKI_NOTFOUND
)
8698 /* Route status display. */
8699 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8701 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8703 else if (bgp_path_suppressed(path
))
8705 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8706 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8712 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8714 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8716 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8718 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8723 /* Internal route. */
8724 if (path
->peer
&& (path
->peer
->as
)
8725 && (path
->peer
->as
== path
->peer
->local_as
))
8731 static char *bgp_nexthop_hostname(struct peer
*peer
,
8732 struct bgp_nexthop_cache
*bnc
)
8735 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8736 return peer
->hostname
;
8740 /* called from terminal list command */
8741 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8742 struct bgp_path_info
*path
, int display
, safi_t safi
,
8743 json_object
*json_paths
, bool wide
)
8746 struct attr
*attr
= path
->attr
;
8747 json_object
*json_path
= NULL
;
8748 json_object
*json_nexthops
= NULL
;
8749 json_object
*json_nexthop_global
= NULL
;
8750 json_object
*json_nexthop_ll
= NULL
;
8751 json_object
*json_ext_community
= NULL
;
8752 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8754 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8755 bool nexthop_othervrf
= false;
8756 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8757 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8758 char *nexthop_hostname
=
8759 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8760 char esi_buf
[ESI_STR_LEN
];
8763 json_path
= json_object_new_object();
8765 /* short status lead text */
8766 route_vty_short_status_out(vty
, path
, p
, json_path
);
8769 /* print prefix and mask */
8771 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8773 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8775 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8779 * If vrf id of nexthop is different from that of prefix,
8780 * set up printable string to append
8782 if (path
->extra
&& path
->extra
->bgp_orig
) {
8783 const char *self
= "";
8788 nexthop_othervrf
= true;
8789 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8791 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8792 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8793 "@%s%s", VRFID_NONE_STR
, self
);
8795 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8796 path
->extra
->bgp_orig
->vrf_id
, self
);
8798 if (path
->extra
->bgp_orig
->inst_type
8799 != BGP_INSTANCE_TYPE_DEFAULT
)
8801 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8803 const char *self
= "";
8808 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8812 * For ENCAP and EVPN routes, nexthop address family is not
8813 * neccessarily the same as the prefix address family.
8814 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8815 * EVPN routes are also exchanged with a MP nexthop. Currently,
8817 * is only IPv4, the value will be present in either
8819 * attr->mp_nexthop_global_in
8821 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
8824 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8828 snprintf(nexthop
, sizeof(nexthop
), "%s",
8829 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
8833 snprintf(nexthop
, sizeof(nexthop
), "%s",
8834 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
8838 snprintf(nexthop
, sizeof(nexthop
), "?");
8843 json_nexthop_global
= json_object_new_object();
8845 json_object_string_add(json_nexthop_global
, "ip",
8848 if (path
->peer
->hostname
)
8849 json_object_string_add(json_nexthop_global
,
8851 path
->peer
->hostname
);
8853 json_object_string_add(json_nexthop_global
, "afi",
8854 (af
== AF_INET
) ? "ipv4"
8856 json_object_boolean_true_add(json_nexthop_global
,
8859 if (nexthop_hostname
)
8860 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
8861 nexthop_hostname
, vrf_id_str
);
8863 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
8865 len
= wide
? (41 - len
) : (16 - len
);
8867 vty_out(vty
, "\n%*s", 36, " ");
8869 vty_out(vty
, "%*s", len
, " ");
8871 } else if (safi
== SAFI_EVPN
) {
8873 json_nexthop_global
= json_object_new_object();
8875 json_object_string_addf(json_nexthop_global
, "ip",
8876 "%pI4", &attr
->nexthop
);
8878 if (path
->peer
->hostname
)
8879 json_object_string_add(json_nexthop_global
,
8881 path
->peer
->hostname
);
8883 json_object_string_add(json_nexthop_global
, "afi",
8885 json_object_boolean_true_add(json_nexthop_global
,
8888 if (nexthop_hostname
)
8889 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8890 nexthop_hostname
, vrf_id_str
);
8892 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8895 len
= wide
? (41 - len
) : (16 - len
);
8897 vty_out(vty
, "\n%*s", 36, " ");
8899 vty_out(vty
, "%*s", len
, " ");
8901 } else if (safi
== SAFI_FLOWSPEC
) {
8902 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
8904 json_nexthop_global
= json_object_new_object();
8906 json_object_string_add(json_nexthop_global
,
8908 json_object_string_addf(json_nexthop_global
,
8912 if (path
->peer
->hostname
)
8913 json_object_string_add(
8914 json_nexthop_global
, "hostname",
8915 path
->peer
->hostname
);
8917 json_object_boolean_true_add(
8918 json_nexthop_global
,
8921 if (nexthop_hostname
)
8922 len
= vty_out(vty
, "%pI4(%s)%s",
8927 len
= vty_out(vty
, "%pI4%s",
8931 len
= wide
? (41 - len
) : (16 - len
);
8933 vty_out(vty
, "\n%*s", 36, " ");
8935 vty_out(vty
, "%*s", len
, " ");
8938 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8940 json_nexthop_global
= json_object_new_object();
8942 json_object_string_addf(json_nexthop_global
, "ip",
8943 "%pI4", &attr
->nexthop
);
8945 if (path
->peer
->hostname
)
8946 json_object_string_add(json_nexthop_global
,
8948 path
->peer
->hostname
);
8950 json_object_string_add(json_nexthop_global
, "afi",
8952 json_object_boolean_true_add(json_nexthop_global
,
8955 if (nexthop_hostname
)
8956 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8957 nexthop_hostname
, vrf_id_str
);
8959 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8962 len
= wide
? (41 - len
) : (16 - len
);
8964 vty_out(vty
, "\n%*s", 36, " ");
8966 vty_out(vty
, "%*s", len
, " ");
8971 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8973 json_nexthop_global
= json_object_new_object();
8974 json_object_string_addf(json_nexthop_global
, "ip",
8976 &attr
->mp_nexthop_global
);
8978 if (path
->peer
->hostname
)
8979 json_object_string_add(json_nexthop_global
,
8981 path
->peer
->hostname
);
8983 json_object_string_add(json_nexthop_global
, "afi",
8985 json_object_string_add(json_nexthop_global
, "scope",
8988 /* We display both LL & GL if both have been
8990 if ((attr
->mp_nexthop_len
8991 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8992 || (path
->peer
->conf_if
)) {
8993 json_nexthop_ll
= json_object_new_object();
8994 json_object_string_addf(
8995 json_nexthop_ll
, "ip", "%pI6",
8996 &attr
->mp_nexthop_local
);
8998 if (path
->peer
->hostname
)
8999 json_object_string_add(
9000 json_nexthop_ll
, "hostname",
9001 path
->peer
->hostname
);
9003 json_object_string_add(json_nexthop_ll
, "afi",
9005 json_object_string_add(json_nexthop_ll
, "scope",
9008 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9009 &attr
->mp_nexthop_local
)
9011 && !attr
->mp_nexthop_prefer_global
)
9012 json_object_boolean_true_add(
9013 json_nexthop_ll
, "used");
9015 json_object_boolean_true_add(
9016 json_nexthop_global
, "used");
9018 json_object_boolean_true_add(
9019 json_nexthop_global
, "used");
9021 /* Display LL if LL/Global both in table unless
9022 * prefer-global is set */
9023 if (((attr
->mp_nexthop_len
9024 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9025 && !attr
->mp_nexthop_prefer_global
)
9026 || (path
->peer
->conf_if
)) {
9027 if (path
->peer
->conf_if
) {
9028 len
= vty_out(vty
, "%s",
9029 path
->peer
->conf_if
);
9030 /* len of IPv6 addr + max len of def
9032 len
= wide
? (41 - len
) : (16 - len
);
9035 vty_out(vty
, "\n%*s", 36, " ");
9037 vty_out(vty
, "%*s", len
, " ");
9039 if (nexthop_hostname
)
9042 &attr
->mp_nexthop_local
,
9048 &attr
->mp_nexthop_local
,
9051 len
= wide
? (41 - len
) : (16 - len
);
9054 vty_out(vty
, "\n%*s", 36, " ");
9056 vty_out(vty
, "%*s", len
, " ");
9059 if (nexthop_hostname
)
9060 len
= vty_out(vty
, "%pI6(%s)%s",
9061 &attr
->mp_nexthop_global
,
9065 len
= vty_out(vty
, "%pI6%s",
9066 &attr
->mp_nexthop_global
,
9069 len
= wide
? (41 - len
) : (16 - len
);
9072 vty_out(vty
, "\n%*s", 36, " ");
9074 vty_out(vty
, "%*s", len
, " ");
9080 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9082 json_object_int_add(json_path
, "metric", attr
->med
);
9084 vty_out(vty
, "%7u", attr
->med
);
9086 vty_out(vty
, "%10u", attr
->med
);
9087 else if (!json_paths
) {
9089 vty_out(vty
, "%*s", 7, " ");
9091 vty_out(vty
, "%*s", 10, " ");
9095 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9097 json_object_int_add(json_path
, "locPrf",
9100 vty_out(vty
, "%7u", attr
->local_pref
);
9101 else if (!json_paths
)
9105 json_object_int_add(json_path
, "weight", attr
->weight
);
9107 vty_out(vty
, "%7u ", attr
->weight
);
9111 json_object_string_add(
9112 json_path
, "peerId",
9113 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
9119 json_object_string_add(json_path
, "path",
9122 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9127 json_object_string_add(json_path
, "origin",
9128 bgp_origin_long_str
[attr
->origin
]);
9130 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9133 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9134 json_object_string_add(json_path
, "esi",
9135 esi_to_str(&attr
->esi
,
9136 esi_buf
, sizeof(esi_buf
)));
9138 if (safi
== SAFI_EVPN
&&
9139 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9140 json_ext_community
= json_object_new_object();
9141 json_object_string_add(json_ext_community
,
9143 attr
->ecommunity
->str
);
9144 json_object_object_add(json_path
,
9145 "extendedCommunity",
9146 json_ext_community
);
9150 json_object_boolean_true_add(json_path
,
9151 "announceNexthopSelf");
9152 if (nexthop_othervrf
) {
9153 json_object_string_add(json_path
, "nhVrfName",
9156 json_object_int_add(json_path
, "nhVrfId",
9157 ((nexthop_vrfid
== VRF_UNKNOWN
)
9159 : (int)nexthop_vrfid
));
9164 if (json_nexthop_global
|| json_nexthop_ll
) {
9165 json_nexthops
= json_object_new_array();
9167 if (json_nexthop_global
)
9168 json_object_array_add(json_nexthops
,
9169 json_nexthop_global
);
9171 if (json_nexthop_ll
)
9172 json_object_array_add(json_nexthops
,
9175 json_object_object_add(json_path
, "nexthops",
9179 json_object_array_add(json_paths
, json_path
);
9183 if (safi
== SAFI_EVPN
) {
9184 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9185 /* XXX - add these params to the json out */
9186 vty_out(vty
, "%*s", 20, " ");
9187 vty_out(vty
, "ESI:%s",
9188 esi_to_str(&attr
->esi
, esi_buf
,
9194 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9195 vty_out(vty
, "%*s", 20, " ");
9196 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
9200 #ifdef ENABLE_BGP_VNC
9201 /* prints an additional line, indented, with VNC info, if
9203 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9204 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9209 /* called from terminal list command */
9210 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9211 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9212 bool use_json
, json_object
*json_ar
, bool wide
)
9214 json_object
*json_status
= NULL
;
9215 json_object
*json_net
= NULL
;
9219 /* Route status display. */
9221 json_status
= json_object_new_object();
9222 json_net
= json_object_new_object();
9229 /* print prefix and mask */
9231 if (safi
== SAFI_EVPN
)
9232 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9233 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9234 json_object_string_add(
9235 json_net
, "addrPrefix",
9236 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9238 json_object_int_add(json_net
, "prefixLen",
9240 json_object_string_addf(json_net
, "network", "%pFX", p
);
9243 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9245 /* Print attribute */
9248 if (p
->family
== AF_INET
9249 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9250 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9251 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9252 json_object_string_addf(
9253 json_net
, "nextHop", "%pI4",
9254 &attr
->mp_nexthop_global_in
);
9256 json_object_string_addf(
9257 json_net
, "nextHop", "%pI4",
9259 } else if (p
->family
== AF_INET6
9260 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9261 json_object_string_addf(
9262 json_net
, "nextHopGlobal", "%pI6",
9263 &attr
->mp_nexthop_global
);
9264 } else if (p
->family
== AF_EVPN
9265 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9266 json_object_string_addf(
9267 json_net
, "nextHop", "%pI4",
9268 &attr
->mp_nexthop_global_in
);
9272 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9273 json_object_int_add(json_net
, "metric",
9276 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9277 json_object_int_add(json_net
, "locPrf",
9280 json_object_int_add(json_net
, "weight", attr
->weight
);
9284 json_object_string_add(json_net
, "path",
9288 json_object_string_add(json_net
, "bgpOriginCode",
9289 bgp_origin_str
[attr
->origin
]);
9291 if (p
->family
== AF_INET
9292 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9293 || safi
== SAFI_EVPN
9294 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9295 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9296 || safi
== SAFI_EVPN
)
9297 vty_out(vty
, "%-16pI4",
9298 &attr
->mp_nexthop_global_in
);
9300 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9302 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9303 } else if (p
->family
== AF_INET6
9304 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9310 &attr
->mp_nexthop_global
, buf
,
9312 len
= wide
? (41 - len
) : (16 - len
);
9314 vty_out(vty
, "\n%*s", 36, " ");
9316 vty_out(vty
, "%*s", len
, " ");
9319 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9321 vty_out(vty
, "%7u", attr
->med
);
9323 vty_out(vty
, "%10u", attr
->med
);
9329 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9330 vty_out(vty
, "%7u", attr
->local_pref
);
9334 vty_out(vty
, "%7u ", attr
->weight
);
9338 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9341 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9345 json_object_boolean_true_add(json_status
, "*");
9346 json_object_boolean_true_add(json_status
, ">");
9347 json_object_object_add(json_net
, "appliedStatusSymbols",
9350 prefix2str(p
, buff
, PREFIX_STRLEN
);
9351 json_object_object_add(json_ar
, buff
, json_net
);
9356 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9357 struct bgp_path_info
*path
, int display
, safi_t safi
,
9360 json_object
*json_out
= NULL
;
9362 mpls_label_t label
= MPLS_INVALID_LABEL
;
9368 json_out
= json_object_new_object();
9370 /* short status lead text */
9371 route_vty_short_status_out(vty
, path
, p
, json_out
);
9373 /* print prefix and mask */
9376 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9378 vty_out(vty
, "%*s", 17, " ");
9381 /* Print attribute */
9383 if (((p
->family
== AF_INET
)
9384 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9385 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9386 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9387 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9388 || safi
== SAFI_EVPN
) {
9390 json_object_string_addf(
9391 json_out
, "mpNexthopGlobalIn", "%pI4",
9392 &attr
->mp_nexthop_global_in
);
9394 vty_out(vty
, "%-16pI4",
9395 &attr
->mp_nexthop_global_in
);
9398 json_object_string_addf(json_out
, "nexthop",
9399 "%pI4", &attr
->nexthop
);
9401 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9403 } else if (((p
->family
== AF_INET6
)
9404 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9405 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9406 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9409 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9411 json_object_string_addf(
9412 json_out
, "mpNexthopGlobalIn", "%pI6",
9413 &attr
->mp_nexthop_global
);
9417 &attr
->mp_nexthop_global
,
9418 buf_a
, sizeof(buf_a
)));
9419 } else if (attr
->mp_nexthop_len
9420 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9421 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9422 &attr
->mp_nexthop_global
,
9423 &attr
->mp_nexthop_local
);
9425 json_object_string_add(json_out
,
9426 "mpNexthopGlobalLocal",
9429 vty_out(vty
, "%s", buf_a
);
9433 label
= decode_label(&path
->extra
->label
[0]);
9435 if (bgp_is_valid_label(&label
)) {
9437 json_object_int_add(json_out
, "notag", label
);
9438 json_object_array_add(json
, json_out
);
9440 vty_out(vty
, "notag/%d", label
);
9447 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9448 struct bgp_path_info
*path
, int display
,
9449 json_object
*json_paths
)
9452 char buf
[BUFSIZ
] = {0};
9453 json_object
*json_path
= NULL
;
9454 json_object
*json_nexthop
= NULL
;
9455 json_object
*json_overlay
= NULL
;
9461 json_path
= json_object_new_object();
9462 json_overlay
= json_object_new_object();
9463 json_nexthop
= json_object_new_object();
9466 /* short status lead text */
9467 route_vty_short_status_out(vty
, path
, p
, json_path
);
9469 /* print prefix and mask */
9471 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9473 vty_out(vty
, "%*s", 17, " ");
9475 /* Print attribute */
9478 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9482 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
9484 vty_out(vty
, "%-16s", buf
);
9486 json_object_string_add(json_nexthop
, "ip", buf
);
9488 json_object_string_add(json_nexthop
, "afi", "ipv4");
9490 json_object_object_add(json_path
, "nexthop",
9495 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
9496 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
9498 vty_out(vty
, "%s(%s)", buf
, buf1
);
9500 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
9502 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
9505 json_object_string_add(json_nexthop
, "afi", "ipv6");
9507 json_object_object_add(json_path
, "nexthop",
9515 json_object_string_add(json_nexthop
, "Error",
9516 "Unsupported address-family");
9520 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9522 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
))
9523 inet_ntop(AF_INET
, &eo
->gw_ip
.ipv4
, buf
, BUFSIZ
);
9524 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
))
9525 inet_ntop(AF_INET6
, &eo
->gw_ip
.ipv6
, buf
, BUFSIZ
);
9528 vty_out(vty
, "/%s", buf
);
9530 json_object_string_add(json_overlay
, "gw", buf
);
9532 if (attr
->ecommunity
) {
9534 struct ecommunity_val
*routermac
= ecommunity_lookup(
9535 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
9536 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9539 mac
= ecom_mac2str((char *)routermac
->val
);
9542 vty_out(vty
, "/%s", mac
);
9544 json_object_string_add(json_overlay
, "rmac",
9547 XFREE(MTYPE_TMP
, mac
);
9554 json_object_object_add(json_path
, "overlay", json_overlay
);
9556 json_object_array_add(json_paths
, json_path
);
9560 /* dampening route */
9561 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9562 struct bgp_path_info
*path
, int display
,
9563 afi_t afi
, safi_t safi
, bool use_json
,
9564 json_object
*json_paths
)
9566 struct attr
*attr
= path
->attr
;
9568 char timebuf
[BGP_UPTIME_LEN
];
9569 json_object
*json_path
= NULL
;
9572 json_path
= json_object_new_object();
9574 /* short status lead text */
9575 route_vty_short_status_out(vty
, path
, p
, json_path
);
9577 /* print prefix and mask */
9580 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9582 vty_out(vty
, "%*s", 17, " ");
9584 len
= vty_out(vty
, "%s", path
->peer
->host
);
9588 vty_out(vty
, "\n%*s", 34, " ");
9590 vty_out(vty
, "%*s", len
, " ");
9593 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9594 BGP_UPTIME_LEN
, afi
, safi
,
9598 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9600 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9604 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9605 safi
, use_json
, json_path
);
9608 json_object_string_add(json_path
, "asPath",
9611 json_object_string_add(json_path
, "origin",
9612 bgp_origin_str
[attr
->origin
]);
9613 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9615 json_object_array_add(json_paths
, json_path
);
9620 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9621 struct bgp_path_info
*path
, int display
,
9622 afi_t afi
, safi_t safi
, bool use_json
,
9623 json_object
*json_paths
)
9625 struct attr
*attr
= path
->attr
;
9626 struct bgp_damp_info
*bdi
;
9627 char timebuf
[BGP_UPTIME_LEN
];
9629 json_object
*json_path
= NULL
;
9635 json_path
= json_object_new_object();
9637 bdi
= path
->extra
->damp_info
;
9639 /* short status lead text */
9640 route_vty_short_status_out(vty
, path
, p
, json_path
);
9644 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9646 vty_out(vty
, "%*s", 17, " ");
9648 len
= vty_out(vty
, "%s", path
->peer
->host
);
9651 vty_out(vty
, "\n%*s", 33, " ");
9653 vty_out(vty
, "%*s", len
, " ");
9655 len
= vty_out(vty
, "%d", bdi
->flap
);
9660 vty_out(vty
, "%*s", len
, " ");
9662 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9663 BGP_UPTIME_LEN
, 0, NULL
));
9665 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9666 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9668 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9669 BGP_UPTIME_LEN
, afi
,
9670 safi
, use_json
, NULL
));
9672 vty_out(vty
, "%*s ", 8, " ");
9675 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9677 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9681 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9682 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
9684 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9687 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9688 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9689 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9690 BGP_UPTIME_LEN
, afi
, safi
,
9691 use_json
, json_path
);
9694 json_object_string_add(json_path
, "asPath",
9697 json_object_string_add(json_path
, "origin",
9698 bgp_origin_str
[attr
->origin
]);
9700 json_object_array_add(json_paths
, json_path
);
9704 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9705 int *first
, const char *header
,
9706 json_object
*json_adv_to
)
9708 char buf1
[INET6_ADDRSTRLEN
];
9709 json_object
*json_peer
= NULL
;
9712 /* 'advertised-to' is a dictionary of peers we have advertised
9714 * prefix too. The key is the peer's IP or swpX, the value is
9716 * hostname if we know it and "" if not.
9718 json_peer
= json_object_new_object();
9721 json_object_string_add(json_peer
, "hostname",
9725 json_object_object_add(json_adv_to
, peer
->conf_if
,
9728 json_object_object_add(
9730 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
9734 vty_out(vty
, "%s", header
);
9739 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9741 vty_out(vty
, " %s(%s)", peer
->hostname
,
9744 vty_out(vty
, " %s(%s)", peer
->hostname
,
9745 sockunion2str(&peer
->su
, buf1
,
9749 vty_out(vty
, " %s", peer
->conf_if
);
9752 sockunion2str(&peer
->su
, buf1
,
9758 static void route_vty_out_tx_ids(struct vty
*vty
,
9759 struct bgp_addpath_info_data
*d
)
9763 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9764 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9765 d
->addpath_tx_id
[i
],
9766 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9770 static void route_vty_out_detail_es_info(struct vty
*vty
,
9771 struct bgp_path_info
*pi
,
9773 json_object
*json_path
)
9775 char esi_buf
[ESI_STR_LEN
];
9776 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9777 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9778 ATTR_ES_PEER_ROUTER
);
9779 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9780 ATTR_ES_PEER_ACTIVE
);
9781 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9782 ATTR_ES_PEER_PROXY
);
9783 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9785 json_object
*json_es_info
= NULL
;
9787 json_object_string_add(
9790 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9791 json_es_info
= json_object_new_object();
9793 json_object_boolean_true_add(
9794 json_es_info
, "localEs");
9796 json_object_boolean_true_add(
9797 json_es_info
, "peerActive");
9799 json_object_boolean_true_add(
9800 json_es_info
, "peerProxy");
9802 json_object_boolean_true_add(
9803 json_es_info
, "peerRouter");
9804 if (attr
->mm_sync_seqnum
)
9805 json_object_int_add(
9806 json_es_info
, "peerSeq",
9807 attr
->mm_sync_seqnum
);
9808 json_object_object_add(
9809 json_path
, "es_info",
9813 if (bgp_evpn_attr_is_sync(attr
))
9815 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9817 es_local
? "local-es":"",
9818 peer_proxy
? "proxy " : "",
9819 peer_active
? "active ":"",
9820 peer_router
? "router ":"",
9821 attr
->mm_sync_seqnum
);
9823 vty_out(vty
, " ESI %s %s\n",
9825 es_local
? "local-es":"");
9829 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
9830 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
9831 enum rpki_states rpki_curr_state
,
9832 json_object
*json_paths
)
9834 char buf
[INET6_ADDRSTRLEN
];
9836 struct attr
*attr
= path
->attr
;
9837 int sockunion_vty_out(struct vty
*, union sockunion
*);
9839 json_object
*json_bestpath
= NULL
;
9840 json_object
*json_cluster_list
= NULL
;
9841 json_object
*json_cluster_list_list
= NULL
;
9842 json_object
*json_ext_community
= NULL
;
9843 json_object
*json_last_update
= NULL
;
9844 json_object
*json_pmsi
= NULL
;
9845 json_object
*json_nexthop_global
= NULL
;
9846 json_object
*json_nexthop_ll
= NULL
;
9847 json_object
*json_nexthops
= NULL
;
9848 json_object
*json_path
= NULL
;
9849 json_object
*json_peer
= NULL
;
9850 json_object
*json_string
= NULL
;
9851 json_object
*json_adv_to
= NULL
;
9853 struct listnode
*node
, *nnode
;
9855 int addpath_capable
;
9857 unsigned int first_as
;
9859 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9861 char *nexthop_hostname
=
9862 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9865 json_path
= json_object_new_object();
9866 json_peer
= json_object_new_object();
9867 json_nexthop_global
= json_object_new_object();
9870 if (safi
== SAFI_EVPN
) {
9872 vty_out(vty
, " Route %pRN", bn
);
9879 if (path
->extra
&& path
->extra
->num_labels
) {
9880 bgp_evpn_label2str(path
->extra
->label
,
9881 path
->extra
->num_labels
, tag_buf
,
9884 if (safi
== SAFI_EVPN
) {
9886 if (tag_buf
[0] != '\0')
9887 vty_out(vty
, " VNI %s", tag_buf
);
9890 json_object_string_add(json_path
, "VNI",
9895 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9896 struct bgp_path_info
*parent_ri
;
9897 struct bgp_dest
*dest
, *pdest
;
9899 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9900 dest
= parent_ri
->net
;
9901 if (dest
&& dest
->pdest
) {
9902 pdest
= dest
->pdest
;
9904 (struct prefix_rd
*)bgp_dest_get_prefix(
9906 buf1
, sizeof(buf1
));
9907 if (is_pi_family_evpn(parent_ri
)) {
9909 " Imported from %s:%pFX, VNI %s",
9911 (struct prefix_evpn
*)
9912 bgp_dest_get_prefix(
9915 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
9916 vty_out(vty
, ", L3NHG %s",
9918 & ATTR_ES_L3_NHG_ACTIVE
)
9925 " Imported from %s:%pFX\n",
9927 (struct prefix_evpn
*)
9928 bgp_dest_get_prefix(
9934 if (safi
== SAFI_EVPN
9935 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
9936 char gwip_buf
[INET6_ADDRSTRLEN
];
9938 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)&bn
->p
))
9939 inet_ntop(AF_INET
, &attr
->evpn_overlay
.gw_ip
.ipv4
,
9940 gwip_buf
, sizeof(gwip_buf
));
9942 inet_ntop(AF_INET6
, &attr
->evpn_overlay
.gw_ip
.ipv6
,
9943 gwip_buf
, sizeof(gwip_buf
));
9946 json_object_string_add(json_path
, "gatewayIP",
9949 vty_out(vty
, " Gateway IP %s", gwip_buf
);
9952 if (safi
== SAFI_EVPN
)
9955 /* Line1 display AS-path, Aggregator */
9958 if (!attr
->aspath
->json
)
9959 aspath_str_update(attr
->aspath
, true);
9960 json_object_lock(attr
->aspath
->json
);
9961 json_object_object_add(json_path
, "aspath",
9962 attr
->aspath
->json
);
9964 if (attr
->aspath
->segments
)
9965 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9967 vty_out(vty
, " Local");
9971 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9973 json_object_boolean_true_add(json_path
, "removed");
9975 vty_out(vty
, ", (removed)");
9978 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9980 json_object_boolean_true_add(json_path
, "stale");
9982 vty_out(vty
, ", (stale)");
9985 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
9987 json_object_int_add(json_path
, "aggregatorAs",
9988 attr
->aggregator_as
);
9989 json_object_string_addf(json_path
, "aggregatorId",
9990 "%pI4", &attr
->aggregator_addr
);
9992 vty_out(vty
, ", (aggregated by %u %pI4)",
9993 attr
->aggregator_as
, &attr
->aggregator_addr
);
9997 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9998 PEER_FLAG_REFLECTOR_CLIENT
)) {
10000 json_object_boolean_true_add(json_path
,
10001 "rxedFromRrClient");
10003 vty_out(vty
, ", (Received from a RR-client)");
10006 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10007 PEER_FLAG_RSERVER_CLIENT
)) {
10009 json_object_boolean_true_add(json_path
,
10010 "rxedFromRsClient");
10012 vty_out(vty
, ", (Received from a RS-client)");
10015 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10017 json_object_boolean_true_add(json_path
,
10018 "dampeningHistoryEntry");
10020 vty_out(vty
, ", (history entry)");
10021 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10023 json_object_boolean_true_add(json_path
,
10024 "dampeningSuppressed");
10026 vty_out(vty
, ", (suppressed due to dampening)");
10030 vty_out(vty
, "\n");
10032 /* Line2 display Next-hop, Neighbor, Router-id */
10033 /* Display the nexthop */
10034 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
10036 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
10037 || bn_p
->family
== AF_EVPN
)
10038 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
10039 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
10040 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10041 || safi
== SAFI_EVPN
) {
10043 json_object_string_addf(
10044 json_nexthop_global
, "ip", "%pI4",
10045 &attr
->mp_nexthop_global_in
);
10047 if (path
->peer
->hostname
)
10048 json_object_string_add(
10049 json_nexthop_global
, "hostname",
10050 path
->peer
->hostname
);
10052 if (nexthop_hostname
)
10053 vty_out(vty
, " %pI4(%s)",
10054 &attr
->mp_nexthop_global_in
,
10057 vty_out(vty
, " %pI4",
10058 &attr
->mp_nexthop_global_in
);
10062 json_object_string_addf(json_nexthop_global
,
10066 if (path
->peer
->hostname
)
10067 json_object_string_add(
10068 json_nexthop_global
, "hostname",
10069 path
->peer
->hostname
);
10071 if (nexthop_hostname
)
10072 vty_out(vty
, " %pI4(%s)",
10076 vty_out(vty
, " %pI4",
10082 json_object_string_add(json_nexthop_global
, "afi",
10086 json_object_string_addf(json_nexthop_global
, "ip",
10088 &attr
->mp_nexthop_global
);
10090 if (path
->peer
->hostname
)
10091 json_object_string_add(json_nexthop_global
,
10093 path
->peer
->hostname
);
10095 json_object_string_add(json_nexthop_global
, "afi",
10097 json_object_string_add(json_nexthop_global
, "scope",
10100 if (nexthop_hostname
)
10101 vty_out(vty
, " %pI6(%s)",
10102 &attr
->mp_nexthop_global
,
10105 vty_out(vty
, " %pI6",
10106 &attr
->mp_nexthop_global
);
10110 /* Display the IGP cost or 'inaccessible' */
10111 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10113 json_object_boolean_false_add(json_nexthop_global
,
10116 vty_out(vty
, " (inaccessible)");
10118 if (path
->extra
&& path
->extra
->igpmetric
) {
10120 json_object_int_add(json_nexthop_global
,
10122 path
->extra
->igpmetric
);
10124 vty_out(vty
, " (metric %u)",
10125 path
->extra
->igpmetric
);
10128 /* IGP cost is 0, display this only for json */
10131 json_object_int_add(json_nexthop_global
,
10136 json_object_boolean_true_add(json_nexthop_global
,
10140 /* Display peer "from" output */
10141 /* This path was originated locally */
10142 if (path
->peer
== bgp
->peer_self
) {
10144 if (safi
== SAFI_EVPN
10145 || (bn_p
->family
== AF_INET
10146 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
10148 json_object_string_add(json_peer
, "peerId",
10151 vty_out(vty
, " from 0.0.0.0 ");
10154 json_object_string_add(json_peer
, "peerId",
10157 vty_out(vty
, " from :: ");
10161 json_object_string_addf(json_peer
, "routerId", "%pI4",
10164 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10167 /* We RXed this path from one of our peers */
10171 json_object_string_add(json_peer
, "peerId",
10172 sockunion2str(&path
->peer
->su
,
10175 json_object_string_addf(json_peer
, "routerId", "%pI4",
10176 &path
->peer
->remote_id
);
10178 if (path
->peer
->hostname
)
10179 json_object_string_add(json_peer
, "hostname",
10180 path
->peer
->hostname
);
10182 if (path
->peer
->domainname
)
10183 json_object_string_add(json_peer
, "domainname",
10184 path
->peer
->domainname
);
10186 if (path
->peer
->conf_if
)
10187 json_object_string_add(json_peer
, "interface",
10188 path
->peer
->conf_if
);
10190 if (path
->peer
->conf_if
) {
10191 if (path
->peer
->hostname
10192 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10193 BGP_FLAG_SHOW_HOSTNAME
))
10194 vty_out(vty
, " from %s(%s)",
10195 path
->peer
->hostname
,
10196 path
->peer
->conf_if
);
10198 vty_out(vty
, " from %s",
10199 path
->peer
->conf_if
);
10201 if (path
->peer
->hostname
10202 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10203 BGP_FLAG_SHOW_HOSTNAME
))
10204 vty_out(vty
, " from %s(%s)",
10205 path
->peer
->hostname
,
10208 vty_out(vty
, " from %s",
10209 sockunion2str(&path
->peer
->su
,
10214 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10215 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10217 vty_out(vty
, " (%s)",
10219 &path
->peer
->remote_id
, buf1
,
10225 * Note when vrfid of nexthop is different from that of prefix
10227 if (path
->extra
&& path
->extra
->bgp_orig
) {
10228 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10233 if (path
->extra
->bgp_orig
->inst_type
10234 == BGP_INSTANCE_TYPE_DEFAULT
)
10235 vn
= VRF_DEFAULT_NAME
;
10237 vn
= path
->extra
->bgp_orig
->name
;
10239 json_object_string_add(json_path
, "nhVrfName", vn
);
10241 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10242 json_object_int_add(json_path
, "nhVrfId", -1);
10244 json_object_int_add(json_path
, "nhVrfId",
10245 (int)nexthop_vrfid
);
10248 if (nexthop_vrfid
== VRF_UNKNOWN
)
10249 vty_out(vty
, " vrf ?");
10253 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10254 vty_out(vty
, " vrf %s(%u)",
10255 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10260 if (nexthop_self
) {
10262 json_object_boolean_true_add(json_path
,
10263 "announceNexthopSelf");
10265 vty_out(vty
, " announce-nh-self");
10270 vty_out(vty
, "\n");
10272 /* display the link-local nexthop */
10273 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10275 json_nexthop_ll
= json_object_new_object();
10276 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10277 &attr
->mp_nexthop_local
);
10279 if (path
->peer
->hostname
)
10280 json_object_string_add(json_nexthop_ll
,
10282 path
->peer
->hostname
);
10284 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10285 json_object_string_add(json_nexthop_ll
, "scope",
10288 json_object_boolean_true_add(json_nexthop_ll
,
10291 if (!attr
->mp_nexthop_prefer_global
)
10292 json_object_boolean_true_add(json_nexthop_ll
,
10295 json_object_boolean_true_add(
10296 json_nexthop_global
, "used");
10298 vty_out(vty
, " (%s) %s\n",
10299 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10300 buf
, INET6_ADDRSTRLEN
),
10301 attr
->mp_nexthop_prefer_global
10302 ? "(prefer-global)"
10306 /* If we do not have a link-local nexthop then we must flag the
10307 global as "used" */
10310 json_object_boolean_true_add(json_nexthop_global
,
10314 if (safi
== SAFI_EVPN
&&
10315 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10316 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10319 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10320 * Int/Ext/Local, Atomic, best */
10322 json_object_string_add(json_path
, "origin",
10323 bgp_origin_long_str
[attr
->origin
]);
10325 vty_out(vty
, " Origin %s",
10326 bgp_origin_long_str
[attr
->origin
]);
10328 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10330 json_object_int_add(json_path
, "metric", attr
->med
);
10332 vty_out(vty
, ", metric %u", attr
->med
);
10335 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10337 json_object_int_add(json_path
, "locPrf",
10340 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10343 if (attr
->weight
!= 0) {
10345 json_object_int_add(json_path
, "weight", attr
->weight
);
10347 vty_out(vty
, ", weight %u", attr
->weight
);
10350 if (attr
->tag
!= 0) {
10352 json_object_int_add(json_path
, "tag", attr
->tag
);
10354 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10357 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10359 json_object_boolean_false_add(json_path
, "valid");
10361 vty_out(vty
, ", invalid");
10362 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10364 json_object_boolean_true_add(json_path
, "valid");
10366 vty_out(vty
, ", valid");
10370 json_object_int_add(json_path
, "version", bn
->version
);
10372 if (path
->peer
!= bgp
->peer_self
) {
10373 if (path
->peer
->as
== path
->peer
->local_as
) {
10374 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10376 json_object_string_add(
10378 "confed-internal");
10380 vty_out(vty
, ", confed-internal");
10383 json_object_string_add(
10384 json_peer
, "type", "internal");
10386 vty_out(vty
, ", internal");
10389 if (bgp_confederation_peers_check(bgp
,
10392 json_object_string_add(
10394 "confed-external");
10396 vty_out(vty
, ", confed-external");
10399 json_object_string_add(
10400 json_peer
, "type", "external");
10402 vty_out(vty
, ", external");
10405 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10407 json_object_boolean_true_add(json_path
, "aggregated");
10408 json_object_boolean_true_add(json_path
, "local");
10410 vty_out(vty
, ", aggregated, local");
10412 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10414 json_object_boolean_true_add(json_path
, "sourced");
10416 vty_out(vty
, ", sourced");
10419 json_object_boolean_true_add(json_path
, "sourced");
10420 json_object_boolean_true_add(json_path
, "local");
10422 vty_out(vty
, ", sourced, local");
10426 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10428 json_object_boolean_true_add(json_path
,
10429 "atomicAggregate");
10431 vty_out(vty
, ", atomic-aggregate");
10434 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10435 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10436 && bgp_path_info_mpath_count(path
))) {
10438 json_object_boolean_true_add(json_path
, "multipath");
10440 vty_out(vty
, ", multipath");
10443 // Mark the bestpath(s)
10444 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10445 first_as
= aspath_get_first_as(attr
->aspath
);
10448 if (!json_bestpath
)
10449 json_bestpath
= json_object_new_object();
10450 json_object_int_add(json_bestpath
, "bestpathFromAs",
10454 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10456 vty_out(vty
, ", bestpath-from-AS Local");
10460 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10462 if (!json_bestpath
)
10463 json_bestpath
= json_object_new_object();
10464 json_object_boolean_true_add(json_bestpath
, "overall");
10465 json_object_string_add(
10466 json_bestpath
, "selectionReason",
10467 bgp_path_selection_reason2str(bn
->reason
));
10469 vty_out(vty
, ", best");
10470 vty_out(vty
, " (%s)",
10471 bgp_path_selection_reason2str(bn
->reason
));
10475 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10477 json_object_string_add(
10478 json_path
, "rpkiValidationState",
10479 bgp_rpki_validation2str(rpki_curr_state
));
10481 vty_out(vty
, ", rpki validation-state: %s",
10482 bgp_rpki_validation2str(rpki_curr_state
));
10486 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10489 vty_out(vty
, "\n");
10491 /* Line 4 display Community */
10492 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10494 if (!attr
->community
->json
)
10495 community_str(attr
->community
, true);
10496 json_object_lock(attr
->community
->json
);
10497 json_object_object_add(json_path
, "community",
10498 attr
->community
->json
);
10500 vty_out(vty
, " Community: %s\n",
10501 attr
->community
->str
);
10505 /* Line 5 display Extended-community */
10506 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10508 json_ext_community
= json_object_new_object();
10509 json_object_string_add(json_ext_community
, "string",
10510 attr
->ecommunity
->str
);
10511 json_object_object_add(json_path
, "extendedCommunity",
10512 json_ext_community
);
10514 vty_out(vty
, " Extended Community: %s\n",
10515 attr
->ecommunity
->str
);
10519 /* Line 6 display Large community */
10520 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10522 if (!attr
->lcommunity
->json
)
10523 lcommunity_str(attr
->lcommunity
, true);
10524 json_object_lock(attr
->lcommunity
->json
);
10525 json_object_object_add(json_path
, "largeCommunity",
10526 attr
->lcommunity
->json
);
10528 vty_out(vty
, " Large Community: %s\n",
10529 attr
->lcommunity
->str
);
10533 /* Line 7 display Originator, Cluster-id */
10534 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10535 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10536 char buf
[BUFSIZ
] = {0};
10538 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10540 json_object_string_addf(json_path
,
10541 "originatorId", "%pI4",
10542 &attr
->originator_id
);
10544 vty_out(vty
, " Originator: %pI4",
10545 &attr
->originator_id
);
10548 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10549 struct cluster_list
*cluster
=
10550 bgp_attr_get_cluster(attr
);
10554 json_cluster_list
= json_object_new_object();
10555 json_cluster_list_list
=
10556 json_object_new_array();
10558 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10559 json_string
= json_object_new_string(
10562 buf
, sizeof(buf
)));
10563 json_object_array_add(
10564 json_cluster_list_list
,
10569 * struct cluster_list does not have
10570 * "str" variable like aspath and community
10571 * do. Add this someday if someone asks
10573 * json_object_string_add(json_cluster_list,
10574 * "string", cluster->str);
10576 json_object_object_add(json_cluster_list
,
10578 json_cluster_list_list
);
10579 json_object_object_add(json_path
, "clusterList",
10580 json_cluster_list
);
10582 vty_out(vty
, ", Cluster list: ");
10584 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10585 vty_out(vty
, "%pI4 ",
10586 &cluster
->list
[i
]);
10592 vty_out(vty
, "\n");
10595 if (path
->extra
&& path
->extra
->damp_info
)
10596 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10599 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10600 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10601 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
10604 json_object_int_add(json_path
, "remoteLabel", label
);
10606 vty_out(vty
, " Remote label: %d\n", label
);
10610 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10611 inet_ntop(AF_INET6
, &path
->extra
->sid
[0].sid
, buf
, sizeof(buf
));
10613 json_object_string_add(json_path
, "remoteSid", buf
);
10615 vty_out(vty
, " Remote SID: %s\n", buf
);
10619 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10621 json_object_int_add(json_path
, "labelIndex",
10622 attr
->label_index
);
10624 vty_out(vty
, " Label Index: %d\n",
10625 attr
->label_index
);
10628 /* Line 8 display Addpath IDs */
10629 if (path
->addpath_rx_id
10630 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10632 json_object_int_add(json_path
, "addpathRxId",
10633 path
->addpath_rx_id
);
10635 /* Keep backwards compatibility with the old API
10636 * by putting TX All's ID in the old field
10638 json_object_int_add(
10639 json_path
, "addpathTxId",
10641 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10643 /* ... but create a specific field for each
10646 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10647 json_object_int_add(
10649 bgp_addpath_names(i
)->id_json_name
,
10650 path
->tx_addpath
.addpath_tx_id
[i
]);
10653 vty_out(vty
, " AddPath ID: RX %u, ",
10654 path
->addpath_rx_id
);
10656 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10660 /* If we used addpath to TX a non-bestpath we need to display
10661 * "Advertised to" on a path-by-path basis
10663 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10666 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10668 bgp_addpath_encode_tx(peer
, afi
, safi
);
10669 has_adj
= bgp_adj_out_lookup(
10671 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10672 &path
->tx_addpath
));
10674 if ((addpath_capable
&& has_adj
)
10675 || (!addpath_capable
&& has_adj
10676 && CHECK_FLAG(path
->flags
,
10677 BGP_PATH_SELECTED
))) {
10678 if (json_path
&& !json_adv_to
)
10679 json_adv_to
= json_object_new_object();
10681 route_vty_out_advertised_to(
10683 " Advertised to:", json_adv_to
);
10689 json_object_object_add(
10690 json_path
, "advertisedTo", json_adv_to
);
10694 vty_out(vty
, "\n");
10699 /* Line 9 display Uptime */
10700 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
10702 json_last_update
= json_object_new_object();
10703 json_object_int_add(json_last_update
, "epoch", tbuf
);
10704 json_object_string_add(json_last_update
, "string",
10706 json_object_object_add(json_path
, "lastUpdate",
10709 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10711 /* Line 10 display PMSI tunnel attribute, if present */
10712 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10713 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10714 bgp_attr_get_pmsi_tnl_type(attr
),
10715 PMSI_TNLTYPE_STR_DEFAULT
);
10718 json_pmsi
= json_object_new_object();
10719 json_object_string_add(json_pmsi
, "tunnelType", str
);
10720 json_object_int_add(json_pmsi
, "label",
10721 label2vni(&attr
->label
));
10722 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10724 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10725 str
, label2vni(&attr
->label
));
10728 if (path
->peer
->t_gr_restart
&&
10729 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10730 unsigned long gr_remaining
=
10731 thread_timer_remain_second(path
->peer
->t_gr_restart
);
10734 json_object_int_add(json_path
,
10735 "gracefulRestartSecondsRemaining",
10739 " Time until Graceful Restart stale route deleted: %lu\n",
10743 if (path
->peer
->t_llgr_stale
[afi
][safi
] && attr
->community
&&
10744 community_include(attr
->community
, COMMUNITY_LLGR_STALE
)) {
10745 unsigned long llgr_remaining
= thread_timer_remain_second(
10746 path
->peer
->t_llgr_stale
[afi
][safi
]);
10749 json_object_int_add(json_path
, "llgrSecondsRemaining",
10753 " Time until Long-lived stale route deleted: %lu\n",
10757 /* Output some debug about internal state of the dest flags */
10759 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10760 json_object_boolean_true_add(json_path
, "processScheduled");
10761 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10762 json_object_boolean_true_add(json_path
, "userCleared");
10763 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10764 json_object_boolean_true_add(json_path
, "labelChanged");
10765 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10766 json_object_boolean_true_add(json_path
, "registeredForLabel");
10767 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10768 json_object_boolean_true_add(json_path
, "selectDefered");
10769 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10770 json_object_boolean_true_add(json_path
, "fibInstalled");
10771 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10772 json_object_boolean_true_add(json_path
, "fibPending");
10774 if (json_nexthop_global
|| json_nexthop_ll
) {
10775 json_nexthops
= json_object_new_array();
10777 if (json_nexthop_global
)
10778 json_object_array_add(json_nexthops
,
10779 json_nexthop_global
);
10781 if (json_nexthop_ll
)
10782 json_object_array_add(json_nexthops
,
10785 json_object_object_add(json_path
, "nexthops",
10789 json_object_object_add(json_path
, "peer", json_peer
);
10790 json_object_array_add(json_paths
, json_path
);
10794 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10795 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10796 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10798 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10799 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10801 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10802 const char *comstr
, int exact
, afi_t afi
,
10803 safi_t safi
, uint16_t show_flags
);
10805 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10806 struct bgp_table
*table
, enum bgp_show_type type
,
10807 void *output_arg
, const char *rd
, int is_last
,
10808 unsigned long *output_cum
, unsigned long *total_cum
,
10809 unsigned long *json_header_depth
, uint16_t show_flags
,
10810 enum rpki_states rpki_target_state
)
10812 struct bgp_path_info
*pi
;
10813 struct bgp_dest
*dest
;
10814 bool header
= true;
10815 bool json_detail_header
= false;
10817 unsigned long output_count
= 0;
10818 unsigned long total_count
= 0;
10820 json_object
*json_paths
= NULL
;
10822 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10823 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
10824 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10826 if (output_cum
&& *output_cum
!= 0)
10829 if (use_json
&& !*json_header_depth
) {
10831 *json_header_depth
= 1;
10833 vty_out(vty
, "{\n");
10834 *json_header_depth
= 2;
10838 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10839 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10840 " \"localAS\": %u,\n \"routes\": { ",
10841 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
10842 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
10845 table
->version
, &bgp
->router_id
,
10846 bgp
->default_local_pref
, bgp
->as
);
10848 vty_out(vty
, " \"routeDistinguishers\" : {");
10849 ++*json_header_depth
;
10853 if (use_json
&& rd
) {
10854 vty_out(vty
, " \"%s\" : { ", rd
);
10857 /* Check for 'json detail', where we need header output once per dest */
10858 if (use_json
&& CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
) &&
10859 type
!= bgp_show_type_dampend_paths
&&
10860 type
!= bgp_show_type_damp_neighbor
&&
10861 type
!= bgp_show_type_flap_statistics
&&
10862 type
!= bgp_show_type_flap_neighbor
)
10863 json_detail_header
= true;
10865 /* Start processing of routes. */
10866 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
10867 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10868 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
10869 bool json_detail
= json_detail_header
;
10871 pi
= bgp_dest_get_bgp_path_info(dest
);
10877 json_paths
= json_object_new_array();
10881 for (; pi
; pi
= pi
->next
) {
10884 if (type
== bgp_show_type_prefix_version
) {
10886 strtoul(output_arg
, NULL
, 10);
10887 if (dest
->version
< version
)
10891 if (type
== bgp_show_type_community_alias
) {
10892 char *alias
= output_arg
;
10893 char **communities
;
10895 bool found
= false;
10897 if (pi
->attr
->community
) {
10898 frrstr_split(pi
->attr
->community
->str
,
10899 " ", &communities
, &num
);
10900 for (int i
= 0; i
< num
; i
++) {
10901 const char *com2alias
=
10902 bgp_community2alias(
10905 && strcmp(alias
, com2alias
)
10911 XFREE(MTYPE_TMP
, communities
);
10914 if (!found
&& pi
->attr
->lcommunity
) {
10915 frrstr_split(pi
->attr
->lcommunity
->str
,
10916 " ", &communities
, &num
);
10917 for (int i
= 0; i
< num
; i
++) {
10918 const char *com2alias
=
10919 bgp_community2alias(
10922 && strcmp(alias
, com2alias
)
10928 XFREE(MTYPE_TMP
, communities
);
10935 if (type
== bgp_show_type_rpki
) {
10936 if (dest_p
->family
== AF_INET
10937 || dest_p
->family
== AF_INET6
)
10938 rpki_curr_state
= hook_call(
10939 bgp_rpki_prefix_status
,
10940 pi
->peer
, pi
->attr
, dest_p
);
10941 if (rpki_target_state
!= RPKI_NOT_BEING_USED
10942 && rpki_curr_state
!= rpki_target_state
)
10946 if (type
== bgp_show_type_flap_statistics
10947 || type
== bgp_show_type_flap_neighbor
10948 || type
== bgp_show_type_dampend_paths
10949 || type
== bgp_show_type_damp_neighbor
) {
10950 if (!(pi
->extra
&& pi
->extra
->damp_info
))
10953 if (type
== bgp_show_type_regexp
) {
10954 regex_t
*regex
= output_arg
;
10956 if (bgp_regexec(regex
, pi
->attr
->aspath
)
10960 if (type
== bgp_show_type_prefix_list
) {
10961 struct prefix_list
*plist
= output_arg
;
10963 if (prefix_list_apply(plist
, dest_p
)
10967 if (type
== bgp_show_type_filter_list
) {
10968 struct as_list
*as_list
= output_arg
;
10970 if (as_list_apply(as_list
, pi
->attr
->aspath
)
10971 != AS_FILTER_PERMIT
)
10974 if (type
== bgp_show_type_route_map
) {
10975 struct route_map
*rmap
= output_arg
;
10976 struct bgp_path_info path
;
10977 struct attr dummy_attr
;
10978 route_map_result_t ret
;
10980 dummy_attr
= *pi
->attr
;
10982 path
.peer
= pi
->peer
;
10983 path
.attr
= &dummy_attr
;
10985 ret
= route_map_apply(rmap
, dest_p
, &path
);
10986 bgp_attr_flush(&dummy_attr
);
10987 if (ret
== RMAP_DENYMATCH
)
10990 if (type
== bgp_show_type_neighbor
10991 || type
== bgp_show_type_flap_neighbor
10992 || type
== bgp_show_type_damp_neighbor
) {
10993 union sockunion
*su
= output_arg
;
10995 if (pi
->peer
== NULL
10996 || pi
->peer
->su_remote
== NULL
10997 || !sockunion_same(pi
->peer
->su_remote
, su
))
11000 if (type
== bgp_show_type_cidr_only
) {
11001 uint32_t destination
;
11003 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11004 if (IN_CLASSC(destination
)
11005 && dest_p
->prefixlen
== 24)
11007 if (IN_CLASSB(destination
)
11008 && dest_p
->prefixlen
== 16)
11010 if (IN_CLASSA(destination
)
11011 && dest_p
->prefixlen
== 8)
11014 if (type
== bgp_show_type_prefix_longer
) {
11016 if (!prefix_match(p
, dest_p
))
11019 if (type
== bgp_show_type_community_all
) {
11020 if (!pi
->attr
->community
)
11023 if (type
== bgp_show_type_community
) {
11024 struct community
*com
= output_arg
;
11026 if (!pi
->attr
->community
11027 || !community_match(pi
->attr
->community
,
11031 if (type
== bgp_show_type_community_exact
) {
11032 struct community
*com
= output_arg
;
11034 if (!pi
->attr
->community
11035 || !community_cmp(pi
->attr
->community
, com
))
11038 if (type
== bgp_show_type_community_list
) {
11039 struct community_list
*list
= output_arg
;
11041 if (!community_list_match(pi
->attr
->community
,
11045 if (type
== bgp_show_type_community_list_exact
) {
11046 struct community_list
*list
= output_arg
;
11048 if (!community_list_exact_match(
11049 pi
->attr
->community
, list
))
11052 if (type
== bgp_show_type_lcommunity
) {
11053 struct lcommunity
*lcom
= output_arg
;
11055 if (!pi
->attr
->lcommunity
11056 || !lcommunity_match(pi
->attr
->lcommunity
,
11061 if (type
== bgp_show_type_lcommunity_exact
) {
11062 struct lcommunity
*lcom
= output_arg
;
11064 if (!pi
->attr
->lcommunity
11065 || !lcommunity_cmp(pi
->attr
->lcommunity
,
11069 if (type
== bgp_show_type_lcommunity_list
) {
11070 struct community_list
*list
= output_arg
;
11072 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
11077 == bgp_show_type_lcommunity_list_exact
) {
11078 struct community_list
*list
= output_arg
;
11080 if (!lcommunity_list_exact_match(
11081 pi
->attr
->lcommunity
, list
))
11084 if (type
== bgp_show_type_lcommunity_all
) {
11085 if (!pi
->attr
->lcommunity
)
11088 if (type
== bgp_show_type_dampend_paths
11089 || type
== bgp_show_type_damp_neighbor
) {
11090 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11091 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11095 if (!use_json
&& header
) {
11097 "BGP table version is %" PRIu64
11098 ", local router ID is %pI4, vrf id ",
11099 table
->version
, &bgp
->router_id
);
11100 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11101 vty_out(vty
, "%s", VRFID_NONE_STR
);
11103 vty_out(vty
, "%u", bgp
->vrf_id
);
11104 vty_out(vty
, "\n");
11105 vty_out(vty
, "Default local pref %u, ",
11106 bgp
->default_local_pref
);
11107 vty_out(vty
, "local AS %u\n", bgp
->as
);
11108 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11109 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11110 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11111 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11112 if (type
== bgp_show_type_dampend_paths
11113 || type
== bgp_show_type_damp_neighbor
)
11114 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11115 else if (type
== bgp_show_type_flap_statistics
11116 || type
== bgp_show_type_flap_neighbor
)
11117 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11119 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11120 : BGP_SHOW_HEADER
));
11123 } else if (json_detail
&& json_paths
!= NULL
) {
11124 const struct prefix_rd
*prd
;
11125 json_object
*jtemp
;
11127 /* Use common detail header, for most types;
11128 * need a json 'object'.
11131 jtemp
= json_object_new_object();
11132 prd
= bgp_rd_from_dest(dest
, safi
);
11134 route_vty_out_detail_header(
11135 vty
, bgp
, dest
, prd
, table
->afi
,
11138 json_object_array_add(json_paths
, jtemp
);
11140 json_detail
= false;
11143 if (rd
!= NULL
&& !display
&& !output_count
) {
11146 "Route Distinguisher: %s\n",
11149 if (type
== bgp_show_type_dampend_paths
11150 || type
== bgp_show_type_damp_neighbor
)
11151 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11152 AFI_IP
, safi
, use_json
,
11154 else if (type
== bgp_show_type_flap_statistics
11155 || type
== bgp_show_type_flap_neighbor
)
11156 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11157 AFI_IP
, safi
, use_json
,
11160 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
11161 route_vty_out_detail(
11162 vty
, bgp
, dest
, pi
,
11163 family2afi(dest_p
->family
),
11164 safi
, RPKI_NOT_BEING_USED
,
11167 route_vty_out(vty
, dest_p
, pi
, display
,
11168 safi
, json_paths
, wide
);
11178 /* encode prefix */
11179 if (dest_p
->family
== AF_FLOWSPEC
) {
11180 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11183 bgp_fs_nlri_get_string(
11185 dest_p
->u
.prefix_flowspec
.ptr
,
11186 dest_p
->u
.prefix_flowspec
.prefixlen
,
11187 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11188 family2afi(dest_p
->u
11189 .prefix_flowspec
.family
));
11191 vty_out(vty
, "\"%s/%d\": ", retstr
,
11192 dest_p
->u
.prefix_flowspec
11195 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11196 dest_p
->u
.prefix_flowspec
11200 vty_out(vty
, "\"%pFX\": ", dest_p
);
11202 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11205 json_object_to_json_string_ext(
11206 json_paths
, JSON_C_TO_STRING_PRETTY
));
11207 json_object_free(json_paths
);
11211 json_object_free(json_paths
);
11215 output_count
+= *output_cum
;
11216 *output_cum
= output_count
;
11219 total_count
+= *total_cum
;
11220 *total_cum
= total_count
;
11224 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11228 for (i
= 0; i
< *json_header_depth
; ++i
)
11229 vty_out(vty
, " } ");
11231 vty_out(vty
, "\n");
11235 /* No route is displayed */
11236 if (output_count
== 0) {
11237 if (type
== bgp_show_type_normal
)
11239 "No BGP prefixes displayed, %ld exist\n",
11243 "\nDisplayed %ld routes and %ld total paths\n",
11244 output_count
, total_count
);
11248 return CMD_SUCCESS
;
11251 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11252 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11253 enum bgp_show_type type
, void *output_arg
, bool use_json
)
11255 struct bgp_dest
*dest
, *next
;
11256 unsigned long output_cum
= 0;
11257 unsigned long total_cum
= 0;
11258 unsigned long json_header_depth
= 0;
11259 struct bgp_table
*itable
;
11261 uint16_t show_flags
= 0;
11263 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11266 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11268 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11269 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11271 next
= bgp_route_next(dest
);
11272 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11275 itable
= bgp_dest_get_bgp_table_info(dest
);
11276 if (itable
!= NULL
) {
11277 struct prefix_rd prd
;
11278 char rd
[RD_ADDRSTRLEN
];
11280 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11281 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11282 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11283 rd
, next
== NULL
, &output_cum
,
11284 &total_cum
, &json_header_depth
,
11285 show_flags
, RPKI_NOT_BEING_USED
);
11291 if (output_cum
== 0)
11292 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11296 "\nDisplayed %ld routes and %ld total paths\n",
11297 output_cum
, total_cum
);
11299 return CMD_SUCCESS
;
11302 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11303 enum bgp_show_type type
, void *output_arg
,
11304 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11306 struct bgp_table
*table
;
11307 unsigned long json_header_depth
= 0;
11308 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11311 bgp
= bgp_get_default();
11316 vty_out(vty
, "No BGP process is configured\n");
11318 vty_out(vty
, "{}\n");
11319 return CMD_WARNING
;
11322 /* Labeled-unicast routes live in the unicast table. */
11323 if (safi
== SAFI_LABELED_UNICAST
)
11324 safi
= SAFI_UNICAST
;
11326 table
= bgp
->rib
[afi
][safi
];
11327 /* use MPLS and ENCAP specific shows until they are merged */
11328 if (safi
== SAFI_MPLS_VPN
) {
11329 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11330 output_arg
, use_json
);
11333 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11334 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11335 output_arg
, use_json
,
11339 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11340 NULL
, NULL
, &json_header_depth
, show_flags
,
11341 rpki_target_state
);
11344 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11345 safi_t safi
, uint16_t show_flags
)
11347 struct listnode
*node
, *nnode
;
11350 bool route_output
= false;
11351 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11354 vty_out(vty
, "{\n");
11356 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11357 route_output
= true;
11360 vty_out(vty
, ",\n");
11364 vty_out(vty
, "\"%s\":",
11365 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11369 vty_out(vty
, "\nInstance %s:\n",
11370 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11374 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11375 show_flags
, RPKI_NOT_BEING_USED
);
11379 vty_out(vty
, "}\n");
11380 else if (!route_output
)
11381 vty_out(vty
, "%% BGP instance not found\n");
11384 /* Header of detailed BGP route information */
11385 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11386 struct bgp_dest
*dest
,
11387 const struct prefix_rd
*prd
,
11388 afi_t afi
, safi_t safi
, json_object
*json
)
11390 struct bgp_path_info
*pi
;
11391 const struct prefix
*p
;
11393 struct listnode
*node
, *nnode
;
11394 char buf1
[RD_ADDRSTRLEN
];
11398 int accept_own
= 0;
11399 int route_filter_translated_v4
= 0;
11400 int route_filter_v4
= 0;
11401 int route_filter_translated_v6
= 0;
11402 int route_filter_v6
= 0;
11403 int llgr_stale
= 0;
11405 int accept_own_nexthop
= 0;
11408 int no_advertise
= 0;
11412 int has_valid_label
= 0;
11413 mpls_label_t label
= 0;
11414 json_object
*json_adv_to
= NULL
;
11416 p
= bgp_dest_get_prefix(dest
);
11417 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
11419 if (has_valid_label
)
11420 label
= label_pton(&dest
->local_label
);
11422 if (safi
== SAFI_EVPN
) {
11425 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11426 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11428 prd
? ":" : "", (struct prefix_evpn
*)p
);
11430 json_object_string_add(json
, "rd",
11431 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11433 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11438 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11440 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11441 ? prefix_rd2str(prd
, buf1
,
11444 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11448 json_object_string_addf(json
, "prefix", "%pFX", p
);
11449 json_object_int_add(json
, "version", dest
->version
);
11454 if (has_valid_label
) {
11456 json_object_int_add(json
, "localLabel", label
);
11458 vty_out(vty
, "Local label: %d\n", label
);
11462 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11463 vty_out(vty
, "not allocated\n");
11465 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11467 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11469 if (bgp_path_suppressed(pi
))
11472 if (pi
->attr
->community
== NULL
)
11475 no_advertise
+= community_include(
11476 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
11477 no_export
+= community_include(pi
->attr
->community
,
11478 COMMUNITY_NO_EXPORT
);
11479 local_as
+= community_include(pi
->attr
->community
,
11480 COMMUNITY_LOCAL_AS
);
11481 accept_own
+= community_include(pi
->attr
->community
,
11482 COMMUNITY_ACCEPT_OWN
);
11483 route_filter_translated_v4
+= community_include(
11484 pi
->attr
->community
,
11485 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11486 route_filter_translated_v6
+= community_include(
11487 pi
->attr
->community
,
11488 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11489 route_filter_v4
+= community_include(
11490 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
11491 route_filter_v6
+= community_include(
11492 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
11493 llgr_stale
+= community_include(pi
->attr
->community
,
11494 COMMUNITY_LLGR_STALE
);
11495 no_llgr
+= community_include(pi
->attr
->community
,
11496 COMMUNITY_NO_LLGR
);
11497 accept_own_nexthop
+=
11498 community_include(pi
->attr
->community
,
11499 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11500 blackhole
+= community_include(pi
->attr
->community
,
11501 COMMUNITY_BLACKHOLE
);
11502 no_peer
+= community_include(pi
->attr
->community
,
11503 COMMUNITY_NO_PEER
);
11508 vty_out(vty
, "Paths: (%d available", count
);
11510 vty_out(vty
, ", best #%d", best
);
11511 if (safi
== SAFI_UNICAST
) {
11512 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11513 vty_out(vty
, ", table %s",
11516 vty_out(vty
, ", vrf %s",
11520 vty_out(vty
, ", no best path");
11524 ", accept own local route exported and imported in different VRF");
11525 else if (route_filter_translated_v4
)
11527 ", mark translated RTs for VPNv4 route filtering");
11528 else if (route_filter_v4
)
11530 ", attach RT as-is for VPNv4 route filtering");
11531 else if (route_filter_translated_v6
)
11533 ", mark translated RTs for VPNv6 route filtering");
11534 else if (route_filter_v6
)
11536 ", attach RT as-is for VPNv6 route filtering");
11537 else if (llgr_stale
)
11539 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11542 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11543 else if (accept_own_nexthop
)
11545 ", accept local nexthop");
11546 else if (blackhole
)
11547 vty_out(vty
, ", inform peer to blackhole prefix");
11548 else if (no_export
)
11549 vty_out(vty
, ", not advertised to EBGP peer");
11550 else if (no_advertise
)
11551 vty_out(vty
, ", not advertised to any peer");
11553 vty_out(vty
, ", not advertised outside local AS");
11556 ", inform EBGP peer not to advertise to their EBGP peers");
11560 ", Advertisements suppressed by an aggregate.");
11561 vty_out(vty
, ")\n");
11564 /* If we are not using addpath then we can display Advertised to and
11566 * show what peers we advertised the bestpath to. If we are using
11568 * though then we must display Advertised to on a path-by-path basis. */
11569 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11570 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11571 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11572 if (json
&& !json_adv_to
)
11573 json_adv_to
= json_object_new_object();
11575 route_vty_out_advertised_to(
11577 " Advertised to non peer-group peers:\n ",
11584 json_object_object_add(json
, "advertisedTo",
11589 vty_out(vty
, " Not advertised to any peer");
11590 vty_out(vty
, "\n");
11595 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
11596 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11597 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11598 json_object
*json
, enum bgp_path_type pathtype
,
11599 int *display
, enum rpki_states rpki_target_state
)
11601 struct bgp_path_info
*pi
;
11603 char rdbuf
[RD_ADDRSTRLEN
];
11604 json_object
*json_header
= NULL
;
11605 json_object
*json_paths
= NULL
;
11606 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
11608 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11609 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11611 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
11612 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
11613 pi
->peer
, pi
->attr
, p
);
11615 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11616 && rpki_curr_state
!= rpki_target_state
)
11619 if (json
&& !json_paths
) {
11620 /* Instantiate json_paths only if path is valid */
11621 json_paths
= json_object_new_array();
11623 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11624 json_header
= json_object_new_object();
11626 json_header
= json
;
11630 route_vty_out_detail_header(
11631 vty
, bgp
, bgp_node
, pfx_rd
,
11632 AFI_IP
, safi
, json_header
);
11637 if (pathtype
== BGP_PATH_SHOW_ALL
11638 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11639 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11640 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11641 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11642 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11643 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
11644 safi
, rpki_curr_state
, json_paths
);
11647 if (json
&& json_paths
) {
11648 json_object_object_add(json_header
, "paths", json_paths
);
11651 json_object_object_add(json
, rdbuf
, json_header
);
11656 * Return rd based on safi
11658 static const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
11662 case SAFI_MPLS_VPN
:
11665 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
11672 /* Display specified route of BGP table. */
11673 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11674 struct bgp_table
*rib
, const char *ip_str
,
11675 afi_t afi
, safi_t safi
,
11676 enum rpki_states rpki_target_state
,
11677 struct prefix_rd
*prd
, int prefix_check
,
11678 enum bgp_path_type pathtype
, bool use_json
)
11682 struct prefix match
;
11683 struct bgp_dest
*dest
;
11684 struct bgp_dest
*rm
;
11685 struct bgp_table
*table
;
11686 json_object
*json
= NULL
;
11687 json_object
*json_paths
= NULL
;
11689 /* Check IP address argument. */
11690 ret
= str2prefix(ip_str
, &match
);
11692 vty_out(vty
, "address is malformed\n");
11693 return CMD_WARNING
;
11696 match
.family
= afi2family(afi
);
11699 json
= json_object_new_object();
11701 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11702 for (dest
= bgp_table_top(rib
); dest
;
11703 dest
= bgp_route_next(dest
)) {
11704 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11706 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11708 table
= bgp_dest_get_bgp_table_info(dest
);
11712 rm
= bgp_node_match(table
, &match
);
11716 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11718 && rm_p
->prefixlen
!= match
.prefixlen
) {
11719 bgp_dest_unlock_node(rm
);
11723 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11724 bgp
, afi
, safi
, json
, pathtype
,
11725 &display
, rpki_target_state
);
11727 bgp_dest_unlock_node(rm
);
11729 } else if (safi
== SAFI_EVPN
) {
11730 struct bgp_dest
*longest_pfx
;
11731 bool is_exact_pfxlen_match
= false;
11733 for (dest
= bgp_table_top(rib
); dest
;
11734 dest
= bgp_route_next(dest
)) {
11735 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11737 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11739 table
= bgp_dest_get_bgp_table_info(dest
);
11743 longest_pfx
= NULL
;
11744 is_exact_pfxlen_match
= false;
11746 * Search through all the prefixes for a match. The
11747 * pfx's are enumerated in ascending order of pfxlens.
11748 * So, the last pfx match is the longest match. Set
11749 * is_exact_pfxlen_match when we get exact pfxlen match
11751 for (rm
= bgp_table_top(table
); rm
;
11752 rm
= bgp_route_next(rm
)) {
11753 const struct prefix
*rm_p
=
11754 bgp_dest_get_prefix(rm
);
11756 * Get prefixlen of the ip-prefix within type5
11759 if (evpn_type5_prefix_match(rm_p
, &match
)
11763 bgp_evpn_get_type5_prefixlen(
11765 if (type5_pfxlen
== match
.prefixlen
) {
11766 is_exact_pfxlen_match
= true;
11767 bgp_dest_unlock_node(rm
);
11776 if (prefix_check
&& !is_exact_pfxlen_match
)
11780 bgp_dest_lock_node(rm
);
11782 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11783 bgp
, afi
, safi
, json
, pathtype
,
11784 &display
, rpki_target_state
);
11786 bgp_dest_unlock_node(rm
);
11788 } else if (safi
== SAFI_FLOWSPEC
) {
11790 json_paths
= json_object_new_array();
11792 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11793 &match
, prefix_check
,
11799 json_object_object_add(json
, "paths",
11802 json_object_free(json_paths
);
11805 dest
= bgp_node_match(rib
, &match
);
11806 if (dest
!= NULL
) {
11807 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11809 || dest_p
->prefixlen
== match
.prefixlen
) {
11810 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
11811 safi
, json
, pathtype
,
11812 &display
, rpki_target_state
);
11815 bgp_dest_unlock_node(dest
);
11820 vty_json(vty
, json
);
11823 vty_out(vty
, "%% Network not in table\n");
11824 return CMD_WARNING
;
11828 return CMD_SUCCESS
;
11831 /* Display specified route of Main RIB */
11832 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
11833 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
11834 int prefix_check
, enum bgp_path_type pathtype
,
11835 enum rpki_states rpki_target_state
, bool use_json
)
11838 bgp
= bgp_get_default();
11841 vty_out(vty
, "No BGP process is configured\n");
11843 vty_out(vty
, "{}\n");
11844 return CMD_WARNING
;
11848 /* labeled-unicast routes live in the unicast table */
11849 if (safi
== SAFI_LABELED_UNICAST
)
11850 safi
= SAFI_UNICAST
;
11852 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
11853 afi
, safi
, rpki_target_state
, prd
,
11854 prefix_check
, pathtype
, use_json
);
11857 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
11858 struct cmd_token
**argv
, bool exact
, afi_t afi
,
11859 safi_t safi
, bool uj
)
11861 struct lcommunity
*lcom
;
11866 uint16_t show_flags
= 0;
11870 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11872 b
= buffer_new(1024);
11873 for (i
= 0; i
< argc
; i
++) {
11875 buffer_putc(b
, ' ');
11877 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
11879 buffer_putstr(b
, argv
[i
]->arg
);
11883 buffer_putc(b
, '\0');
11885 str
= buffer_getstr(b
);
11888 lcom
= lcommunity_str2com(str
);
11889 XFREE(MTYPE_TMP
, str
);
11891 vty_out(vty
, "%% Large-community malformed\n");
11892 return CMD_WARNING
;
11895 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11896 (exact
? bgp_show_type_lcommunity_exact
11897 : bgp_show_type_lcommunity
),
11898 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
11900 lcommunity_free(&lcom
);
11904 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
11905 const char *lcom
, bool exact
, afi_t afi
,
11906 safi_t safi
, bool uj
)
11908 struct community_list
*list
;
11909 uint16_t show_flags
= 0;
11912 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11915 list
= community_list_lookup(bgp_clist
, lcom
, 0,
11916 LARGE_COMMUNITY_LIST_MASTER
);
11917 if (list
== NULL
) {
11918 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
11920 return CMD_WARNING
;
11923 return bgp_show(vty
, bgp
, afi
, safi
,
11924 (exact
? bgp_show_type_lcommunity_list_exact
11925 : bgp_show_type_lcommunity_list
),
11926 list
, show_flags
, RPKI_NOT_BEING_USED
);
11929 DEFUN (show_ip_bgp_large_community_list
,
11930 show_ip_bgp_large_community_list_cmd
,
11931 "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]",
11935 BGP_INSTANCE_HELP_STR
11937 BGP_SAFI_WITH_LABEL_HELP_STR
11938 "Display routes matching the large-community-list\n"
11939 "large-community-list number\n"
11940 "large-community-list name\n"
11941 "Exact match of the large-communities\n"
11944 afi_t afi
= AFI_IP6
;
11945 safi_t safi
= SAFI_UNICAST
;
11947 bool exact_match
= 0;
11948 struct bgp
*bgp
= NULL
;
11949 bool uj
= use_json(argc
, argv
);
11954 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11957 return CMD_WARNING
;
11959 argv_find(argv
, argc
, "large-community-list", &idx
);
11961 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11963 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11966 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
11967 exact_match
, afi
, safi
, uj
);
11969 DEFUN (show_ip_bgp_large_community
,
11970 show_ip_bgp_large_community_cmd
,
11971 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11975 BGP_INSTANCE_HELP_STR
11977 BGP_SAFI_WITH_LABEL_HELP_STR
11978 "Display routes matching the large-communities\n"
11979 "List of large-community numbers\n"
11980 "Exact match of the large-communities\n"
11983 afi_t afi
= AFI_IP6
;
11984 safi_t safi
= SAFI_UNICAST
;
11986 bool exact_match
= 0;
11987 struct bgp
*bgp
= NULL
;
11988 bool uj
= use_json(argc
, argv
);
11989 uint16_t show_flags
= 0;
11993 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11996 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11999 return CMD_WARNING
;
12001 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12002 if (argv_find(argv
, argc
, "exact-match", &idx
))
12004 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12005 exact_match
, afi
, safi
, uj
);
12007 return bgp_show(vty
, bgp
, afi
, safi
,
12008 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12009 RPKI_NOT_BEING_USED
);
12012 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12013 safi_t safi
, struct json_object
*json_array
);
12014 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12015 safi_t safi
, struct json_object
*json
);
12018 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12019 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12020 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12021 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12023 bool uj
= use_json(argc
, argv
);
12024 struct bgp
*bgp
= NULL
;
12025 safi_t safi
= SAFI_UNICAST
;
12026 afi_t afi
= AFI_IP6
;
12028 struct json_object
*json_all
= NULL
;
12029 struct json_object
*json_afi_safi
= NULL
;
12031 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12034 return CMD_WARNING
;
12037 json_all
= json_object_new_object();
12039 FOREACH_AFI_SAFI (afi
, safi
) {
12041 * So limit output to those afi/safi pairs that
12042 * actually have something interesting in them
12044 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12049 json_afi_safi
= json_object_new_array();
12050 json_object_object_add(
12052 get_afi_safi_str(afi
, safi
, true),
12055 json_afi_safi
= NULL
;
12058 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12063 json_object_to_json_string_ext(
12064 json_all
, JSON_C_TO_STRING_PRETTY
));
12065 json_object_free(json_all
);
12068 return CMD_SUCCESS
;
12071 /* BGP route print out function without JSON */
12072 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12073 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12074 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12078 BGP_INSTANCE_HELP_STR
12081 "BGP RIB advertisement statistics\n"
12084 afi_t afi
= AFI_IP6
;
12085 safi_t safi
= SAFI_UNICAST
;
12086 struct bgp
*bgp
= NULL
;
12088 bool uj
= use_json(argc
, argv
);
12089 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12091 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12094 return CMD_WARNING
;
12097 json_afi_safi
= json_object_new_array();
12099 json_afi_safi
= NULL
;
12101 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12104 json
= json_object_new_object();
12105 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12107 vty_out(vty
, "%s", json_object_to_json_string_ext(
12108 json
, JSON_C_TO_STRING_PRETTY
));
12109 json_object_free(json
);
12114 /* BGP route print out function without JSON */
12115 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12116 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12117 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12119 statistics [json]",
12120 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12121 BGP_SAFI_WITH_LABEL_HELP_STR
12122 "BGP RIB advertisement statistics\n" JSON_STR
)
12124 afi_t afi
= AFI_IP6
;
12125 safi_t safi
= SAFI_UNICAST
;
12126 struct bgp
*bgp
= NULL
;
12128 bool uj
= use_json(argc
, argv
);
12129 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12131 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12134 return CMD_WARNING
;
12137 json_afi_safi
= json_object_new_array();
12139 json_afi_safi
= NULL
;
12141 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12144 json
= json_object_new_object();
12145 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12148 json_object_to_json_string_ext(
12149 json
, JSON_C_TO_STRING_PRETTY
));
12150 json_object_free(json
);
12155 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12156 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12157 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12158 "]] [all$all] dampening parameters [json]",
12159 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12160 BGP_SAFI_WITH_LABEL_HELP_STR
12161 "Display the entries for all address families\n"
12162 "Display detailed information about dampening\n"
12163 "Display detail of configured dampening parameters\n"
12166 afi_t afi
= AFI_IP6
;
12167 safi_t safi
= SAFI_UNICAST
;
12168 struct bgp
*bgp
= NULL
;
12170 uint16_t show_flags
= 0;
12171 bool uj
= use_json(argc
, argv
);
12175 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12178 /* [<ipv4|ipv6> [all]] */
12180 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12181 if (argv_find(argv
, argc
, "ipv4", &idx
))
12182 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12184 if (argv_find(argv
, argc
, "ipv6", &idx
))
12185 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12188 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12191 return CMD_WARNING
;
12193 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12196 /* BGP route print out function */
12197 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12198 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12199 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12203 |dampening <flap-statistics|dampened-paths>\
12204 |community [AA:NN|local-AS|no-advertise|no-export\
12205 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12206 |accept-own|accept-own-nexthop|route-filter-v6\
12207 |route-filter-v4|route-filter-translated-v6\
12208 |route-filter-translated-v4] [exact-match]\
12209 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12210 |filter-list AS_PATH_FILTER_NAME\
12213 |rpki <invalid|valid|notfound>\
12214 |version (1-4294967295)\
12216 |A.B.C.D/M longer-prefixes\
12217 |X:X::X:X/M longer-prefixes\
12218 ] [json$uj [detail$detail] | wide$wide]",
12219 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12220 BGP_SAFI_WITH_LABEL_HELP_STR
12221 "Display the entries for all address families\n"
12222 "Display only routes with non-natural netmasks\n"
12223 "Display detailed information about dampening\n"
12224 "Display flap statistics of routes\n"
12225 "Display paths suppressed due to dampening\n"
12226 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12227 "Do not send outside local AS (well-known community)\n"
12228 "Do not advertise to any peer (well-known community)\n"
12229 "Do not export to next AS (well-known community)\n"
12230 "Graceful shutdown (well-known community)\n"
12231 "Do not export to any peer (well-known community)\n"
12232 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12233 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12234 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12235 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12236 "Should accept VPN route with local nexthop (well-known community)\n"
12237 "RT VPNv6 route filtering (well-known community)\n"
12238 "RT VPNv4 route filtering (well-known community)\n"
12239 "RT translated VPNv6 route filtering (well-known community)\n"
12240 "RT translated VPNv4 route filtering (well-known community)\n"
12241 "Exact match of the communities\n"
12242 "Community-list number\n"
12243 "Community-list name\n"
12244 "Display routes matching the community-list\n"
12245 "Exact match of the communities\n"
12246 "Display routes conforming to the filter-list\n"
12247 "Regular expression access list name\n"
12248 "Display routes conforming to the prefix-list\n"
12249 "Prefix-list name\n"
12250 "Display routes matching the route-map\n"
12251 "A route-map to match on\n"
12252 "RPKI route types\n"
12253 "A valid path as determined by rpki\n"
12254 "A invalid path as determined by rpki\n"
12255 "A path that has no rpki data\n"
12256 "Display prefixes with matching version numbers\n"
12257 "Version number and above\n"
12258 "Display prefixes with matching BGP community alias\n"
12259 "BGP community alias\n"
12261 "Display route and more specific routes\n"
12263 "Display route and more specific routes\n"
12265 "Display detailed version of JSON output\n"
12266 "Increase table width for longer prefixes\n")
12268 afi_t afi
= AFI_IP6
;
12269 safi_t safi
= SAFI_UNICAST
;
12270 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12271 void *output_arg
= NULL
;
12272 struct bgp
*bgp
= NULL
;
12274 int exact_match
= 0;
12275 char *community
= NULL
;
12277 uint16_t show_flags
= 0;
12278 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12282 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12286 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12288 /* [<ipv4|ipv6> [all]] */
12290 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12292 if (argv_find(argv
, argc
, "ipv4", &idx
))
12293 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12295 if (argv_find(argv
, argc
, "ipv6", &idx
))
12296 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12300 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12302 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12305 return CMD_WARNING
;
12307 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12308 sh_type
= bgp_show_type_cidr_only
;
12310 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12311 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12312 sh_type
= bgp_show_type_dampend_paths
;
12313 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12314 sh_type
= bgp_show_type_flap_statistics
;
12317 if (argv_find(argv
, argc
, "community", &idx
)) {
12318 char *maybecomm
= NULL
;
12320 if (idx
+ 1 < argc
) {
12321 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12322 maybecomm
= argv
[idx
+ 1]->arg
;
12324 maybecomm
= argv
[idx
+ 1]->text
;
12327 if (maybecomm
&& !strmatch(maybecomm
, "json")
12328 && !strmatch(maybecomm
, "exact-match"))
12329 community
= maybecomm
;
12331 if (argv_find(argv
, argc
, "exact-match", &idx
))
12335 sh_type
= bgp_show_type_community_all
;
12338 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12339 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12340 struct community_list
*list
;
12342 if (argv_find(argv
, argc
, "exact-match", &idx
))
12345 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12346 COMMUNITY_LIST_MASTER
);
12347 if (list
== NULL
) {
12349 "%% %s is not a valid community-list name\n",
12350 clist_number_or_name
);
12351 return CMD_WARNING
;
12355 sh_type
= bgp_show_type_community_list_exact
;
12357 sh_type
= bgp_show_type_community_list
;
12361 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12362 const char *filter
= argv
[++idx
]->arg
;
12363 struct as_list
*as_list
;
12365 as_list
= as_list_lookup(filter
);
12366 if (as_list
== NULL
) {
12368 "%% %s is not a valid AS-path access-list name\n",
12370 return CMD_WARNING
;
12373 sh_type
= bgp_show_type_filter_list
;
12374 output_arg
= as_list
;
12377 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12378 const char *prefix_list_str
= argv
[++idx
]->arg
;
12379 struct prefix_list
*plist
;
12381 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12382 if (plist
== NULL
) {
12383 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
12385 return CMD_WARNING
;
12388 sh_type
= bgp_show_type_prefix_list
;
12389 output_arg
= plist
;
12392 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12393 const char *rmap_str
= argv
[++idx
]->arg
;
12394 struct route_map
*rmap
;
12396 rmap
= route_map_lookup_by_name(rmap_str
);
12398 vty_out(vty
, "%% %s is not a valid route-map name\n",
12400 return CMD_WARNING
;
12403 sh_type
= bgp_show_type_route_map
;
12407 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12408 sh_type
= bgp_show_type_rpki
;
12409 if (argv_find(argv
, argc
, "valid", &idx
))
12410 rpki_target_state
= RPKI_VALID
;
12411 else if (argv_find(argv
, argc
, "invalid", &idx
))
12412 rpki_target_state
= RPKI_INVALID
;
12415 /* Display prefixes with matching version numbers */
12416 if (argv_find(argv
, argc
, "version", &idx
)) {
12417 sh_type
= bgp_show_type_prefix_version
;
12418 output_arg
= argv
[idx
+ 1]->arg
;
12421 /* Display prefixes with matching BGP community alias */
12422 if (argv_find(argv
, argc
, "alias", &idx
)) {
12423 sh_type
= bgp_show_type_community_alias
;
12424 output_arg
= argv
[idx
+ 1]->arg
;
12427 /* prefix-longer */
12428 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12429 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12430 const char *prefix_str
= argv
[idx
]->arg
;
12433 if (!str2prefix(prefix_str
, &p
)) {
12434 vty_out(vty
, "%% Malformed Prefix\n");
12435 return CMD_WARNING
;
12438 sh_type
= bgp_show_type_prefix_longer
;
12443 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12445 return bgp_show_community(vty
, bgp
, community
,
12446 exact_match
, afi
, safi
,
12449 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12450 output_arg
, show_flags
,
12451 rpki_target_state
);
12453 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12457 vty_out(vty
, "{\n");
12459 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12460 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12461 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12464 FOREACH_SAFI (safi
) {
12465 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12472 vty_out(vty
, ",\n");
12473 vty_out(vty
, "\"%s\":{\n",
12474 get_afi_safi_str(afi
, safi
,
12478 "\nFor address family: %s\n",
12479 get_afi_safi_str(afi
, safi
,
12483 bgp_show_community(vty
, bgp
, community
,
12487 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12488 output_arg
, show_flags
,
12489 rpki_target_state
);
12491 vty_out(vty
, "}\n");
12494 /* show <ip> bgp all: for each AFI and SAFI*/
12495 FOREACH_AFI_SAFI (afi
, safi
) {
12496 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12503 vty_out(vty
, ",\n");
12505 vty_out(vty
, "\"%s\":{\n",
12506 get_afi_safi_str(afi
, safi
,
12510 "\nFor address family: %s\n",
12511 get_afi_safi_str(afi
, safi
,
12515 bgp_show_community(vty
, bgp
, community
,
12519 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12520 output_arg
, show_flags
,
12521 rpki_target_state
);
12523 vty_out(vty
, "}\n");
12527 vty_out(vty
, "}\n");
12529 return CMD_SUCCESS
;
12532 DEFUN (show_ip_bgp_route
,
12533 show_ip_bgp_route_cmd
,
12534 "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]",
12538 BGP_INSTANCE_HELP_STR
12540 BGP_SAFI_WITH_LABEL_HELP_STR
12541 "Network in the BGP routing table to display\n"
12543 "Network in the BGP routing table to display\n"
12545 "Display only the bestpath\n"
12546 "Display only multipaths\n"
12547 "Display only paths that match the specified rpki state\n"
12548 "A valid path as determined by rpki\n"
12549 "A invalid path as determined by rpki\n"
12550 "A path that has no rpki data\n"
12553 int prefix_check
= 0;
12555 afi_t afi
= AFI_IP6
;
12556 safi_t safi
= SAFI_UNICAST
;
12557 char *prefix
= NULL
;
12558 struct bgp
*bgp
= NULL
;
12559 enum bgp_path_type path_type
;
12560 bool uj
= use_json(argc
, argv
);
12564 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12567 return CMD_WARNING
;
12571 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12572 return CMD_WARNING
;
12575 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12576 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12577 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12579 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12580 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12583 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12584 && afi
!= AFI_IP6
) {
12586 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12587 return CMD_WARNING
;
12589 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12590 && afi
!= AFI_IP
) {
12592 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12593 return CMD_WARNING
;
12596 prefix
= argv
[idx
]->arg
;
12598 /* [<bestpath|multipath>] */
12599 if (argv_find(argv
, argc
, "bestpath", &idx
))
12600 path_type
= BGP_PATH_SHOW_BESTPATH
;
12601 else if (argv_find(argv
, argc
, "multipath", &idx
))
12602 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12604 path_type
= BGP_PATH_SHOW_ALL
;
12606 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12607 path_type
, RPKI_NOT_BEING_USED
, uj
);
12610 DEFUN (show_ip_bgp_regexp
,
12611 show_ip_bgp_regexp_cmd
,
12612 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12616 BGP_INSTANCE_HELP_STR
12618 BGP_SAFI_WITH_LABEL_HELP_STR
12619 "Display routes matching the AS path regular expression\n"
12620 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12623 afi_t afi
= AFI_IP6
;
12624 safi_t safi
= SAFI_UNICAST
;
12625 struct bgp
*bgp
= NULL
;
12626 bool uj
= use_json(argc
, argv
);
12627 char *regstr
= NULL
;
12630 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12633 return CMD_WARNING
;
12635 // get index of regex
12636 if (argv_find(argv
, argc
, "REGEX", &idx
))
12637 regstr
= argv
[idx
]->arg
;
12640 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12641 bgp_show_type_regexp
, uj
);
12644 DEFPY (show_ip_bgp_instance_all
,
12645 show_ip_bgp_instance_all_cmd
,
12646 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12650 BGP_INSTANCE_ALL_HELP_STR
12652 BGP_SAFI_WITH_LABEL_HELP_STR
12654 "Increase table width for longer prefixes\n")
12656 afi_t afi
= AFI_IP6
;
12657 safi_t safi
= SAFI_UNICAST
;
12658 struct bgp
*bgp
= NULL
;
12660 uint16_t show_flags
= 0;
12664 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12668 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12670 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12673 return CMD_WARNING
;
12675 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12676 return CMD_SUCCESS
;
12679 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12680 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12685 uint16_t show_flags
= 0;
12688 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12690 if (!config_bgp_aspath_validate(regstr
)) {
12691 vty_out(vty
, "Invalid character in REGEX %s\n",
12693 return CMD_WARNING_CONFIG_FAILED
;
12696 regex
= bgp_regcomp(regstr
);
12698 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12699 return CMD_WARNING
;
12702 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
12703 RPKI_NOT_BEING_USED
);
12704 bgp_regex_free(regex
);
12708 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12709 const char *comstr
, int exact
, afi_t afi
,
12710 safi_t safi
, uint16_t show_flags
)
12712 struct community
*com
;
12715 com
= community_str2com(comstr
);
12717 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12718 return CMD_WARNING
;
12721 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12722 (exact
? bgp_show_type_community_exact
12723 : bgp_show_type_community
),
12724 com
, show_flags
, RPKI_NOT_BEING_USED
);
12725 community_free(&com
);
12731 BGP_STATS_MAXBITLEN
= 0,
12733 BGP_STATS_PREFIXES
,
12735 BGP_STATS_UNAGGREGATEABLE
,
12736 BGP_STATS_MAX_AGGREGATEABLE
,
12737 BGP_STATS_AGGREGATES
,
12739 BGP_STATS_ASPATH_COUNT
,
12740 BGP_STATS_ASPATH_MAXHOPS
,
12741 BGP_STATS_ASPATH_TOTHOPS
,
12742 BGP_STATS_ASPATH_MAXSIZE
,
12743 BGP_STATS_ASPATH_TOTSIZE
,
12744 BGP_STATS_ASN_HIGHEST
,
12748 #define TABLE_STATS_IDX_VTY 0
12749 #define TABLE_STATS_IDX_JSON 1
12751 static const char *table_stats_strs
[][2] = {
12752 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12753 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12754 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12755 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12756 "unaggregateablePrefixes"},
12757 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12758 "maximumAggregateablePrefixes"},
12759 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12760 "bgpAggregateAdvertisements"},
12761 [BGP_STATS_SPACE
] = {"Address space advertised",
12762 "addressSpaceAdvertised"},
12763 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12764 "advertisementsWithPaths"},
12765 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12767 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12769 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12770 "averageAsPathLengthHops"},
12771 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12772 "averageAsPathSizeBytes"},
12773 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12774 [BGP_STATS_MAX
] = {NULL
, NULL
}
12777 struct bgp_table_stats
{
12778 struct bgp_table
*table
;
12779 unsigned long long counts
[BGP_STATS_MAX
];
12780 double total_space
;
12783 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
12784 struct bgp_table_stats
*ts
, unsigned int space
)
12786 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
12787 struct bgp_path_info
*pi
;
12788 const struct prefix
*rn_p
;
12790 if (!bgp_dest_has_bgp_path_info_data(dest
))
12793 rn_p
= bgp_dest_get_prefix(dest
);
12794 ts
->counts
[BGP_STATS_PREFIXES
]++;
12795 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
12797 /* check if the prefix is included by any other announcements */
12798 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
12799 pdest
= bgp_dest_parent_nolock(pdest
);
12801 if (pdest
== NULL
|| pdest
== top
) {
12802 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
12803 /* announced address space */
12805 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
12806 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
12807 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
12810 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
12811 ts
->counts
[BGP_STATS_RIB
]++;
12813 if (CHECK_FLAG(pi
->attr
->flag
,
12814 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
12815 ts
->counts
[BGP_STATS_AGGREGATES
]++;
12817 /* as-path stats */
12818 if (pi
->attr
->aspath
) {
12819 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
12820 unsigned int size
= aspath_size(pi
->attr
->aspath
);
12821 as_t highest
= aspath_highest(pi
->attr
->aspath
);
12823 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
12825 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
12826 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
12828 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
12829 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
12831 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
12832 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
12833 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
12834 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
12839 static int bgp_table_stats_walker(struct thread
*t
)
12841 struct bgp_dest
*dest
, *ndest
;
12842 struct bgp_dest
*top
;
12843 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
12844 unsigned int space
= 0;
12846 if (!(top
= bgp_table_top(ts
->table
)))
12849 switch (ts
->table
->afi
) {
12851 space
= IPV4_MAX_BITLEN
;
12854 space
= IPV6_MAX_BITLEN
;
12857 space
= EVPN_ROUTE_PREFIXLEN
;
12863 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
12865 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
12866 if (ts
->table
->safi
== SAFI_MPLS_VPN
12867 || ts
->table
->safi
== SAFI_ENCAP
12868 || ts
->table
->safi
== SAFI_EVPN
) {
12869 struct bgp_table
*table
;
12871 table
= bgp_dest_get_bgp_table_info(dest
);
12875 top
= bgp_table_top(table
);
12876 for (ndest
= bgp_table_top(table
); ndest
;
12877 ndest
= bgp_route_next(ndest
))
12878 bgp_table_stats_rn(ndest
, top
, ts
, space
);
12880 bgp_table_stats_rn(dest
, top
, ts
, space
);
12887 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
12888 struct json_object
*json_array
)
12890 struct listnode
*node
, *nnode
;
12893 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
12894 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12897 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12898 safi_t safi
, struct json_object
*json_array
)
12900 struct bgp_table_stats ts
;
12902 int ret
= CMD_SUCCESS
;
12904 struct json_object
*json
= NULL
;
12907 json
= json_object_new_object();
12909 if (!bgp
->rib
[afi
][safi
]) {
12910 char warning_msg
[50];
12912 snprintf(warning_msg
, sizeof(warning_msg
),
12913 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
12917 vty_out(vty
, "%s\n", warning_msg
);
12919 json_object_string_add(json
, "warning", warning_msg
);
12922 goto end_table_stats
;
12926 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
12927 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
12929 json_object_string_add(json
, "instance", bgp
->name_pretty
);
12931 /* labeled-unicast routes live in the unicast table */
12932 if (safi
== SAFI_LABELED_UNICAST
)
12933 safi
= SAFI_UNICAST
;
12935 memset(&ts
, 0, sizeof(ts
));
12936 ts
.table
= bgp
->rib
[afi
][safi
];
12937 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
12939 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
12940 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
12941 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
12945 case BGP_STATS_ASPATH_TOTHOPS
:
12946 case BGP_STATS_ASPATH_TOTSIZE
:
12949 temp_buf
, sizeof(temp_buf
), "%12.2f",
12951 ? (float)ts
.counts
[i
]
12953 [BGP_STATS_ASPATH_COUNT
]
12955 vty_out(vty
, "%-30s: %s",
12956 table_stats_strs
[i
]
12957 [TABLE_STATS_IDX_VTY
],
12960 json_object_double_add(
12962 table_stats_strs
[i
]
12963 [TABLE_STATS_IDX_JSON
],
12965 ? (double)ts
.counts
[i
]
12966 / (double)ts
.counts
12967 [BGP_STATS_ASPATH_COUNT
]
12971 case BGP_STATS_TOTPLEN
:
12974 temp_buf
, sizeof(temp_buf
), "%12.2f",
12976 ? (float)ts
.counts
[i
]
12978 [BGP_STATS_PREFIXES
]
12980 vty_out(vty
, "%-30s: %s",
12981 table_stats_strs
[i
]
12982 [TABLE_STATS_IDX_VTY
],
12985 json_object_double_add(
12987 table_stats_strs
[i
]
12988 [TABLE_STATS_IDX_JSON
],
12990 ? (double)ts
.counts
[i
]
12991 / (double)ts
.counts
12992 [BGP_STATS_PREFIXES
]
12996 case BGP_STATS_SPACE
:
12998 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13000 vty_out(vty
, "%-30s: %s\n",
13001 table_stats_strs
[i
]
13002 [TABLE_STATS_IDX_VTY
],
13005 json_object_double_add(
13007 table_stats_strs
[i
]
13008 [TABLE_STATS_IDX_JSON
],
13009 (double)ts
.total_space
);
13011 if (afi
== AFI_IP6
) {
13013 snprintf(temp_buf
, sizeof(temp_buf
),
13016 * pow(2.0, -128 + 32));
13017 vty_out(vty
, "%30s: %s\n",
13018 "/32 equivalent %s\n",
13021 json_object_double_add(
13022 json
, "/32equivalent",
13023 (double)(ts
.total_space
13028 snprintf(temp_buf
, sizeof(temp_buf
),
13031 * pow(2.0, -128 + 48));
13032 vty_out(vty
, "%30s: %s\n",
13033 "/48 equivalent %s\n",
13036 json_object_double_add(
13037 json
, "/48equivalent",
13038 (double)(ts
.total_space
13044 snprintf(temp_buf
, sizeof(temp_buf
),
13046 ts
.total_space
* 100.
13048 vty_out(vty
, "%30s: %s\n",
13049 "% announced ", temp_buf
);
13051 json_object_double_add(
13052 json
, "%announced",
13053 (double)(ts
.total_space
* 100.
13057 snprintf(temp_buf
, sizeof(temp_buf
),
13060 * pow(2.0, -32 + 8));
13061 vty_out(vty
, "%30s: %s\n",
13062 "/8 equivalent ", temp_buf
);
13064 json_object_double_add(
13065 json
, "/8equivalent",
13066 (double)(ts
.total_space
13067 * pow(2.0, -32 + 8)));
13070 snprintf(temp_buf
, sizeof(temp_buf
),
13073 * pow(2.0, -32 + 24));
13074 vty_out(vty
, "%30s: %s\n",
13075 "/24 equivalent ", temp_buf
);
13077 json_object_double_add(
13078 json
, "/24equivalent",
13079 (double)(ts
.total_space
13080 * pow(2.0, -32 + 24)));
13086 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13088 vty_out(vty
, "%-30s: %s",
13089 table_stats_strs
[i
]
13090 [TABLE_STATS_IDX_VTY
],
13093 json_object_int_add(
13095 table_stats_strs
[i
]
13096 [TABLE_STATS_IDX_JSON
],
13101 vty_out(vty
, "\n");
13105 json_object_array_add(json_array
, json
);
13109 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13110 safi_t safi
, struct json_object
*json_array
)
13113 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13114 return CMD_SUCCESS
;
13117 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13129 PCOUNT_BPATH_SELECTED
,
13130 PCOUNT_PFCNT
, /* the figure we display to users */
13134 static const char *const pcount_strs
[] = {
13135 [PCOUNT_ADJ_IN
] = "Adj-in",
13136 [PCOUNT_DAMPED
] = "Damped",
13137 [PCOUNT_REMOVED
] = "Removed",
13138 [PCOUNT_HISTORY
] = "History",
13139 [PCOUNT_STALE
] = "Stale",
13140 [PCOUNT_VALID
] = "Valid",
13141 [PCOUNT_ALL
] = "All RIB",
13142 [PCOUNT_COUNTED
] = "PfxCt counted",
13143 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13144 [PCOUNT_PFCNT
] = "Useable",
13145 [PCOUNT_MAX
] = NULL
,
13148 struct peer_pcounts
{
13149 unsigned int count
[PCOUNT_MAX
];
13150 const struct peer
*peer
;
13151 const struct bgp_table
*table
;
13155 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13157 const struct bgp_adj_in
*ain
;
13158 const struct bgp_path_info
*pi
;
13159 const struct peer
*peer
= pc
->peer
;
13161 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13162 if (ain
->peer
== peer
)
13163 pc
->count
[PCOUNT_ADJ_IN
]++;
13165 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13167 if (pi
->peer
!= peer
)
13170 pc
->count
[PCOUNT_ALL
]++;
13172 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13173 pc
->count
[PCOUNT_DAMPED
]++;
13174 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13175 pc
->count
[PCOUNT_HISTORY
]++;
13176 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13177 pc
->count
[PCOUNT_REMOVED
]++;
13178 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13179 pc
->count
[PCOUNT_STALE
]++;
13180 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13181 pc
->count
[PCOUNT_VALID
]++;
13182 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13183 pc
->count
[PCOUNT_PFCNT
]++;
13184 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13185 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13187 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13188 pc
->count
[PCOUNT_COUNTED
]++;
13189 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13191 EC_LIB_DEVELOPMENT
,
13192 "Attempting to count but flags say it is unusable");
13194 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13196 EC_LIB_DEVELOPMENT
,
13197 "Not counted but flags say we should");
13202 static int bgp_peer_count_walker(struct thread
*t
)
13204 struct bgp_dest
*rn
, *rm
;
13205 const struct bgp_table
*table
;
13206 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13208 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13209 || pc
->safi
== SAFI_EVPN
) {
13210 /* Special handling for 2-level routing tables. */
13211 for (rn
= bgp_table_top(pc
->table
); rn
;
13212 rn
= bgp_route_next(rn
)) {
13213 table
= bgp_dest_get_bgp_table_info(rn
);
13215 for (rm
= bgp_table_top(table
); rm
;
13216 rm
= bgp_route_next(rm
))
13217 bgp_peer_count_proc(rm
, pc
);
13220 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13221 bgp_peer_count_proc(rn
, pc
);
13226 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13227 safi_t safi
, bool use_json
)
13229 struct peer_pcounts pcounts
= {.peer
= peer
};
13231 json_object
*json
= NULL
;
13232 json_object
*json_loop
= NULL
;
13235 json
= json_object_new_object();
13236 json_loop
= json_object_new_object();
13239 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13240 || !peer
->bgp
->rib
[afi
][safi
]) {
13242 json_object_string_add(
13244 "No such neighbor or address family");
13245 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13246 json_object_free(json
);
13247 json_object_free(json_loop
);
13249 vty_out(vty
, "%% No such neighbor or address family\n");
13251 return CMD_WARNING
;
13254 memset(&pcounts
, 0, sizeof(pcounts
));
13255 pcounts
.peer
= peer
;
13256 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13257 pcounts
.safi
= safi
;
13259 /* in-place call via thread subsystem so as to record execution time
13260 * stats for the thread-walk (i.e. ensure this can't be blamed on
13261 * on just vty_read()).
13263 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13266 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13267 json_object_string_add(json
, "multiProtocol",
13268 get_afi_safi_str(afi
, safi
, true));
13269 json_object_int_add(json
, "pfxCounter",
13270 peer
->pcount
[afi
][safi
]);
13272 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13273 json_object_int_add(json_loop
, pcount_strs
[i
],
13276 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13278 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13279 json_object_string_add(json
, "pfxctDriftFor",
13281 json_object_string_add(
13282 json
, "recommended",
13283 "Please report this bug, with the above command output");
13285 vty_json(vty
, json
);
13289 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13290 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13291 peer
->hostname
, peer
->host
,
13292 get_afi_safi_str(afi
, safi
, false));
13294 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13295 get_afi_safi_str(afi
, safi
, false));
13298 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13299 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13301 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13302 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13305 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13306 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13308 "Please report this bug, with the above command output\n");
13312 return CMD_SUCCESS
;
13315 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13316 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13317 "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]",
13321 BGP_INSTANCE_HELP_STR
13324 "Detailed information on TCP and BGP neighbor connections\n"
13325 "Neighbor to display information about\n"
13326 "Neighbor to display information about\n"
13327 "Neighbor on BGP configured interface\n"
13328 "Display detailed prefix count information\n"
13331 afi_t afi
= AFI_IP6
;
13332 safi_t safi
= SAFI_UNICAST
;
13335 struct bgp
*bgp
= NULL
;
13336 bool uj
= use_json(argc
, argv
);
13341 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13344 return CMD_WARNING
;
13346 argv_find(argv
, argc
, "neighbors", &idx
);
13347 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13349 return CMD_WARNING
;
13351 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13354 #ifdef KEEP_OLD_VPN_COMMANDS
13355 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13356 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13357 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13362 "Display information about all VPNv4 NLRIs\n"
13363 "Detailed information on TCP and BGP neighbor connections\n"
13364 "Neighbor to display information about\n"
13365 "Neighbor to display information about\n"
13366 "Neighbor on BGP configured interface\n"
13367 "Display detailed prefix count information\n"
13372 bool uj
= use_json(argc
, argv
);
13374 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13376 return CMD_WARNING
;
13378 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13381 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13382 show_ip_bgp_vpn_all_route_prefix_cmd
,
13383 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13388 "Display information about all VPNv4 NLRIs\n"
13389 "Network in the BGP routing table to display\n"
13390 "Network in the BGP routing table to display\n"
13394 char *network
= NULL
;
13395 struct bgp
*bgp
= bgp_get_default();
13397 vty_out(vty
, "Can't find default instance\n");
13398 return CMD_WARNING
;
13401 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13402 network
= argv
[idx
]->arg
;
13403 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13404 network
= argv
[idx
]->arg
;
13406 vty_out(vty
, "Unable to figure out Network\n");
13407 return CMD_WARNING
;
13410 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13411 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13412 use_json(argc
, argv
));
13414 #endif /* KEEP_OLD_VPN_COMMANDS */
13416 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13417 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13418 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13423 "Network in the BGP routing table to display\n"
13424 "Network in the BGP routing table to display\n"
13425 "Network in the BGP routing table to display\n"
13426 "Network in the BGP routing table to display\n"
13430 char *network
= NULL
;
13431 int prefix_check
= 0;
13433 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13434 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13435 network
= argv
[idx
]->arg
;
13436 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13437 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13438 network
= argv
[idx
]->arg
;
13441 vty_out(vty
, "Unable to figure out Network\n");
13442 return CMD_WARNING
;
13444 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13445 prefix_check
, BGP_PATH_SHOW_ALL
,
13446 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13449 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
13450 struct bgp_table
*table
, int *header1
,
13451 int *header2
, json_object
*json
,
13452 json_object
*json_scode
,
13453 json_object
*json_ocode
, bool wide
)
13455 uint64_t version
= table
? table
->version
: 0;
13459 json_object_int_add(json
, "bgpTableVersion", version
);
13460 json_object_string_addf(json
, "bgpLocalRouterId",
13461 "%pI4", &bgp
->router_id
);
13462 json_object_int_add(json
, "defaultLocPrf",
13463 bgp
->default_local_pref
);
13464 json_object_int_add(json
, "localAS", bgp
->as
);
13465 json_object_object_add(json
, "bgpStatusCodes",
13467 json_object_object_add(json
, "bgpOriginCodes",
13471 "BGP table version is %" PRIu64
13472 ", local router ID is %pI4, vrf id ",
13473 version
, &bgp
->router_id
);
13474 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13475 vty_out(vty
, "%s", VRFID_NONE_STR
);
13477 vty_out(vty
, "%u", bgp
->vrf_id
);
13478 vty_out(vty
, "\n");
13479 vty_out(vty
, "Default local pref %u, ",
13480 bgp
->default_local_pref
);
13481 vty_out(vty
, "local AS %u\n", bgp
->as
);
13482 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13483 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13484 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13485 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13491 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13492 : BGP_SHOW_HEADER
));
13498 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13499 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13500 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13501 json_object
*json_scode
, json_object
*json_ocode
,
13502 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13503 unsigned long *output_count
, unsigned long *filtered_count
)
13505 struct bgp_adj_in
*ain
;
13506 struct bgp_adj_out
*adj
;
13507 struct bgp_dest
*dest
;
13511 struct update_subgroup
*subgrp
;
13512 struct peer_af
*paf
;
13513 bool route_filtered
;
13514 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13515 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13516 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13517 || (safi
== SAFI_EVPN
))
13523 subgrp
= peer_subgroup(peer
, afi
, safi
);
13525 if (type
== bgp_show_adj_route_advertised
&& subgrp
13526 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13528 json_object_int_add(json
, "bgpTableVersion",
13530 json_object_string_addf(json
, "bgpLocalRouterId",
13531 "%pI4", &bgp
->router_id
);
13532 json_object_int_add(json
, "defaultLocPrf",
13533 bgp
->default_local_pref
);
13534 json_object_int_add(json
, "localAS", bgp
->as
);
13535 json_object_object_add(json
, "bgpStatusCodes",
13537 json_object_object_add(json
, "bgpOriginCodes",
13539 json_object_string_add(
13540 json
, "bgpOriginatingDefaultNetwork",
13541 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13544 "BGP table version is %" PRIu64
13545 ", local router ID is %pI4, vrf id ",
13546 table
->version
, &bgp
->router_id
);
13547 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13548 vty_out(vty
, "%s", VRFID_NONE_STR
);
13550 vty_out(vty
, "%u", bgp
->vrf_id
);
13551 vty_out(vty
, "\n");
13552 vty_out(vty
, "Default local pref %u, ",
13553 bgp
->default_local_pref
);
13554 vty_out(vty
, "local AS %u\n", bgp
->as
);
13555 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13556 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13557 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13558 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13560 vty_out(vty
, "Originating default network %s\n\n",
13561 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13566 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13567 if (type
== bgp_show_adj_route_received
13568 || type
== bgp_show_adj_route_filtered
) {
13569 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13570 if (ain
->peer
!= peer
)
13573 show_adj_route_header(vty
, bgp
, table
, header1
,
13574 header2
, json
, json_scode
,
13577 if ((safi
== SAFI_MPLS_VPN
)
13578 || (safi
== SAFI_ENCAP
)
13579 || (safi
== SAFI_EVPN
)) {
13581 json_object_string_add(
13582 json_ar
, "rd", rd_str
);
13583 else if (show_rd
&& rd_str
) {
13585 "Route Distinguisher: %s\n",
13592 route_filtered
= false;
13594 /* Filter prefix using distribute list,
13595 * filter list or prefix list
13597 const struct prefix
*rn_p
=
13598 bgp_dest_get_prefix(dest
);
13599 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13602 route_filtered
= true;
13604 /* Filter prefix using route-map */
13605 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13606 safi
, rmap_name
, NULL
,
13609 if (type
== bgp_show_adj_route_filtered
&&
13610 !route_filtered
&& ret
!= RMAP_DENY
) {
13611 bgp_attr_undup(&attr
, ain
->attr
);
13615 if (type
== bgp_show_adj_route_received
13616 && (route_filtered
|| ret
== RMAP_DENY
))
13617 (*filtered_count
)++;
13619 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
13620 use_json
, json_ar
, wide
);
13621 bgp_attr_undup(&attr
, ain
->attr
);
13624 } else if (type
== bgp_show_adj_route_advertised
) {
13625 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13626 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13627 if (paf
->peer
!= peer
|| !adj
->attr
)
13630 show_adj_route_header(vty
, bgp
, table
,
13635 const struct prefix
*rn_p
=
13636 bgp_dest_get_prefix(dest
);
13639 ret
= bgp_output_modifier(
13640 peer
, rn_p
, &attr
, afi
, safi
,
13643 if (ret
!= RMAP_DENY
) {
13644 if ((safi
== SAFI_MPLS_VPN
)
13645 || (safi
== SAFI_ENCAP
)
13646 || (safi
== SAFI_EVPN
)) {
13648 json_object_string_add(
13655 "Route Distinguisher: %s\n",
13661 vty
, dest
, rn_p
, &attr
,
13662 safi
, use_json
, json_ar
,
13666 (*filtered_count
)++;
13669 bgp_attr_undup(&attr
, adj
->attr
);
13671 } else if (type
== bgp_show_adj_route_bestpath
) {
13672 struct bgp_path_info
*pi
;
13674 show_adj_route_header(vty
, bgp
, table
, header1
, header2
,
13675 json
, json_scode
, json_ocode
,
13678 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13680 if (pi
->peer
!= peer
)
13683 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13686 route_vty_out_tmp(vty
, dest
,
13687 bgp_dest_get_prefix(dest
),
13688 pi
->attr
, safi
, use_json
,
13696 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13697 safi_t safi
, enum bgp_show_adj_route_type type
,
13698 const char *rmap_name
, uint16_t show_flags
)
13701 struct bgp_table
*table
;
13702 json_object
*json
= NULL
;
13703 json_object
*json_scode
= NULL
;
13704 json_object
*json_ocode
= NULL
;
13705 json_object
*json_ar
= NULL
;
13706 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13708 /* Init BGP headers here so they're only displayed once
13709 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13715 * Initialize variables for each RD
13716 * All prefixes under an RD is aggregated within "json_routes"
13718 char rd_str
[BUFSIZ
] = {0};
13719 json_object
*json_routes
= NULL
;
13722 /* For 2-tier tables, prefix counts need to be
13723 * maintained across multiple runs of show_adj_route()
13725 unsigned long output_count_per_rd
;
13726 unsigned long filtered_count_per_rd
;
13727 unsigned long output_count
= 0;
13728 unsigned long filtered_count
= 0;
13731 json
= json_object_new_object();
13732 json_ar
= json_object_new_object();
13733 json_scode
= json_object_new_object();
13734 json_ocode
= json_object_new_object();
13736 json_object_string_add(json_scode
, "suppressed", "s");
13737 json_object_string_add(json_scode
, "damped", "d");
13738 json_object_string_add(json_scode
, "history", "h");
13739 json_object_string_add(json_scode
, "valid", "*");
13740 json_object_string_add(json_scode
, "best", ">");
13741 json_object_string_add(json_scode
, "multipath", "=");
13742 json_object_string_add(json_scode
, "internal", "i");
13743 json_object_string_add(json_scode
, "ribFailure", "r");
13744 json_object_string_add(json_scode
, "stale", "S");
13745 json_object_string_add(json_scode
, "removed", "R");
13747 json_object_string_add(json_ocode
, "igp", "i");
13748 json_object_string_add(json_ocode
, "egp", "e");
13749 json_object_string_add(json_ocode
, "incomplete", "?");
13752 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13754 json_object_string_add(
13756 "No such neighbor or address family");
13757 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13758 json_object_free(json
);
13759 json_object_free(json_ar
);
13760 json_object_free(json_scode
);
13761 json_object_free(json_ocode
);
13763 vty_out(vty
, "%% No such neighbor or address family\n");
13765 return CMD_WARNING
;
13768 if ((type
== bgp_show_adj_route_received
13769 || type
== bgp_show_adj_route_filtered
)
13770 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
13771 PEER_FLAG_SOFT_RECONFIG
)) {
13773 json_object_string_add(
13775 "Inbound soft reconfiguration not enabled");
13776 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13777 json_object_free(json
);
13778 json_object_free(json_ar
);
13779 json_object_free(json_scode
);
13780 json_object_free(json_ocode
);
13783 "%% Inbound soft reconfiguration not enabled\n");
13785 return CMD_WARNING
;
13790 /* labeled-unicast routes live in the unicast table */
13791 if (safi
== SAFI_LABELED_UNICAST
)
13792 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
13794 table
= bgp
->rib
[afi
][safi
];
13796 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13797 || (safi
== SAFI_EVPN
)) {
13799 struct bgp_dest
*dest
;
13801 for (dest
= bgp_table_top(table
); dest
;
13802 dest
= bgp_route_next(dest
)) {
13803 table
= bgp_dest_get_bgp_table_info(dest
);
13807 output_count_per_rd
= 0;
13808 filtered_count_per_rd
= 0;
13811 json_routes
= json_object_new_object();
13813 const struct prefix_rd
*prd
;
13814 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13817 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
13819 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
13820 rmap_name
, json
, json_routes
, json_scode
,
13821 json_ocode
, show_flags
, &header1
,
13822 &header2
, rd_str
, &output_count_per_rd
,
13823 &filtered_count_per_rd
);
13825 /* Don't include an empty RD in the output! */
13826 if (json_routes
&& (output_count_per_rd
> 0))
13827 json_object_object_add(json_ar
, rd_str
,
13830 output_count
+= output_count_per_rd
;
13831 filtered_count
+= filtered_count_per_rd
;
13834 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
13835 json
, json_ar
, json_scode
, json_ocode
,
13836 show_flags
, &header1
, &header2
, rd_str
,
13837 &output_count
, &filtered_count
);
13840 if (type
== bgp_show_adj_route_advertised
)
13841 json_object_object_add(json
, "advertisedRoutes",
13844 json_object_object_add(json
, "receivedRoutes", json_ar
);
13845 json_object_int_add(json
, "totalPrefixCounter", output_count
);
13846 json_object_int_add(json
, "filteredPrefixCounter",
13850 * These fields only give up ownership to `json` when `header1`
13851 * is used (set to zero). See code in `show_adj_route` and
13852 * `show_adj_route_header`.
13854 if (header1
== 1) {
13855 json_object_free(json_scode
);
13856 json_object_free(json_ocode
);
13859 vty_json(vty
, json
);
13860 } else if (output_count
> 0) {
13861 if (filtered_count
> 0)
13863 "\nTotal number of prefixes %ld (%ld filtered)\n",
13864 output_count
, filtered_count
);
13866 vty_out(vty
, "\nTotal number of prefixes %ld\n",
13870 return CMD_SUCCESS
;
13873 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
13874 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
13875 "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]",
13879 BGP_INSTANCE_HELP_STR
13881 BGP_SAFI_WITH_LABEL_HELP_STR
13882 "Detailed information on TCP and BGP neighbor connections\n"
13883 "Neighbor to display information about\n"
13884 "Neighbor to display information about\n"
13885 "Neighbor on BGP configured interface\n"
13886 "Display the routes selected by best path\n"
13888 "Increase table width for longer prefixes\n")
13890 afi_t afi
= AFI_IP6
;
13891 safi_t safi
= SAFI_UNICAST
;
13892 char *rmap_name
= NULL
;
13893 char *peerstr
= NULL
;
13894 struct bgp
*bgp
= NULL
;
13896 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
13898 uint16_t show_flags
= 0;
13901 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13904 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13906 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13910 return CMD_WARNING
;
13912 argv_find(argv
, argc
, "neighbors", &idx
);
13913 peerstr
= argv
[++idx
]->arg
;
13915 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13917 return CMD_WARNING
;
13919 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13923 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
13924 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
13925 "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]",
13929 BGP_INSTANCE_HELP_STR
13931 BGP_SAFI_WITH_LABEL_HELP_STR
13932 "Display the entries for all address families\n"
13933 "Detailed information on TCP and BGP neighbor connections\n"
13934 "Neighbor to display information about\n"
13935 "Neighbor to display information about\n"
13936 "Neighbor on BGP configured interface\n"
13937 "Display the routes advertised to a BGP neighbor\n"
13938 "Display the received routes from neighbor\n"
13939 "Display the filtered routes received from neighbor\n"
13940 "Route-map to modify the attributes\n"
13941 "Name of the route map\n"
13943 "Increase table width for longer prefixes\n")
13945 afi_t afi
= AFI_IP6
;
13946 safi_t safi
= SAFI_UNICAST
;
13947 char *rmap_name
= NULL
;
13948 char *peerstr
= NULL
;
13949 struct bgp
*bgp
= NULL
;
13951 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
13954 uint16_t show_flags
= 0;
13958 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13962 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
13963 if (argv_find(argv
, argc
, "ipv4", &idx
))
13964 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
13966 if (argv_find(argv
, argc
, "ipv6", &idx
))
13967 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
13971 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13973 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13976 return CMD_WARNING
;
13978 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13979 argv_find(argv
, argc
, "neighbors", &idx
);
13980 peerstr
= argv
[++idx
]->arg
;
13982 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13984 return CMD_WARNING
;
13986 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
13987 type
= bgp_show_adj_route_advertised
;
13988 else if (argv_find(argv
, argc
, "received-routes", &idx
))
13989 type
= bgp_show_adj_route_received
;
13990 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
13991 type
= bgp_show_adj_route_filtered
;
13993 if (argv_find(argv
, argc
, "route-map", &idx
))
13994 rmap_name
= argv
[++idx
]->arg
;
13997 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14000 vty_out(vty
, "{\n");
14002 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14003 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14004 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14006 FOREACH_SAFI (safi
) {
14007 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
14014 vty_out(vty
, ",\n");
14015 vty_out(vty
, "\"%s\":",
14016 get_afi_safi_str(afi
, safi
, true));
14018 vty_out(vty
, "\nFor address family: %s\n",
14019 get_afi_safi_str(afi
, safi
, false));
14021 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14025 FOREACH_AFI_SAFI (afi
, safi
) {
14026 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
14033 vty_out(vty
, ",\n");
14034 vty_out(vty
, "\"%s\":",
14035 get_afi_safi_str(afi
, safi
, true));
14037 vty_out(vty
, "\nFor address family: %s\n",
14038 get_afi_safi_str(afi
, safi
, false));
14040 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14045 vty_out(vty
, "}\n");
14047 return CMD_SUCCESS
;
14050 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14051 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14052 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14056 BGP_INSTANCE_HELP_STR
14059 "Address Family modifier\n"
14060 "Detailed information on TCP and BGP neighbor connections\n"
14061 "Neighbor to display information about\n"
14062 "Neighbor to display information about\n"
14063 "Neighbor on BGP configured interface\n"
14064 "Display information received from a BGP neighbor\n"
14065 "Display the prefixlist filter\n"
14068 afi_t afi
= AFI_IP6
;
14069 safi_t safi
= SAFI_UNICAST
;
14070 char *peerstr
= NULL
;
14075 struct bgp
*bgp
= NULL
;
14076 bool uj
= use_json(argc
, argv
);
14081 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14084 return CMD_WARNING
;
14086 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14087 argv_find(argv
, argc
, "neighbors", &idx
);
14088 peerstr
= argv
[++idx
]->arg
;
14090 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14092 return CMD_WARNING
;
14094 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14095 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14098 vty_out(vty
, "Address Family: %s\n",
14099 get_afi_safi_str(afi
, safi
, false));
14100 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14103 vty_out(vty
, "{}\n");
14105 vty_out(vty
, "No functional output\n");
14108 return CMD_SUCCESS
;
14111 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14112 afi_t afi
, safi_t safi
,
14113 enum bgp_show_type type
, bool use_json
)
14115 uint16_t show_flags
= 0;
14118 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14120 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14122 json_object
*json_no
= NULL
;
14123 json_no
= json_object_new_object();
14124 json_object_string_add(
14125 json_no
, "warning",
14126 "No such neighbor or address family");
14127 vty_out(vty
, "%s\n",
14128 json_object_to_json_string(json_no
));
14129 json_object_free(json_no
);
14131 vty_out(vty
, "%% No such neighbor or address family\n");
14132 return CMD_WARNING
;
14135 /* labeled-unicast routes live in the unicast table */
14136 if (safi
== SAFI_LABELED_UNICAST
)
14137 safi
= SAFI_UNICAST
;
14139 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14140 RPKI_NOT_BEING_USED
);
14143 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14144 show_ip_bgp_flowspec_routes_detailed_cmd
,
14145 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14149 BGP_INSTANCE_HELP_STR
14152 "Detailed information on flowspec entries\n"
14155 afi_t afi
= AFI_IP6
;
14156 safi_t safi
= SAFI_UNICAST
;
14157 struct bgp
*bgp
= NULL
;
14159 bool uj
= use_json(argc
, argv
);
14160 uint16_t show_flags
= 0;
14164 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14167 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14170 return CMD_WARNING
;
14172 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14173 show_flags
, RPKI_NOT_BEING_USED
);
14176 DEFUN (show_ip_bgp_neighbor_routes
,
14177 show_ip_bgp_neighbor_routes_cmd
,
14178 "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]",
14182 BGP_INSTANCE_HELP_STR
14184 BGP_SAFI_WITH_LABEL_HELP_STR
14185 "Detailed information on TCP and BGP neighbor connections\n"
14186 "Neighbor to display information about\n"
14187 "Neighbor to display information about\n"
14188 "Neighbor on BGP configured interface\n"
14189 "Display flap statistics of the routes learned from neighbor\n"
14190 "Display the dampened routes received from neighbor\n"
14191 "Display routes learned from neighbor\n"
14194 char *peerstr
= NULL
;
14195 struct bgp
*bgp
= NULL
;
14196 afi_t afi
= AFI_IP6
;
14197 safi_t safi
= SAFI_UNICAST
;
14199 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14201 bool uj
= use_json(argc
, argv
);
14206 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14209 return CMD_WARNING
;
14211 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14212 argv_find(argv
, argc
, "neighbors", &idx
);
14213 peerstr
= argv
[++idx
]->arg
;
14215 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14217 return CMD_WARNING
;
14219 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14220 sh_type
= bgp_show_type_flap_neighbor
;
14221 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14222 sh_type
= bgp_show_type_damp_neighbor
;
14223 else if (argv_find(argv
, argc
, "routes", &idx
))
14224 sh_type
= bgp_show_type_neighbor
;
14226 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14229 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14231 struct bgp_distance
{
14232 /* Distance value for the IP source prefix. */
14235 /* Name of the access-list to be matched. */
14239 DEFUN (show_bgp_afi_vpn_rd_route
,
14240 show_bgp_afi_vpn_rd_route_cmd
,
14241 "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]",
14245 "Address Family modifier\n"
14246 "Display information for a route distinguisher\n"
14247 "Route Distinguisher\n"
14248 "All Route Distinguishers\n"
14249 "Network in the BGP routing table to display\n"
14250 "Network in the BGP routing table to display\n"
14254 struct prefix_rd prd
;
14255 afi_t afi
= AFI_MAX
;
14258 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14259 vty_out(vty
, "%% Malformed Address Family\n");
14260 return CMD_WARNING
;
14263 if (!strcmp(argv
[5]->arg
, "all"))
14264 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14265 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14266 RPKI_NOT_BEING_USED
,
14267 use_json(argc
, argv
));
14269 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14271 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14272 return CMD_WARNING
;
14275 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14276 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14277 use_json(argc
, argv
));
14280 static struct bgp_distance
*bgp_distance_new(void)
14282 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14285 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14287 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14290 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14291 const char *ip_str
, const char *access_list_str
)
14298 struct bgp_dest
*dest
;
14299 struct bgp_distance
*bdistance
;
14301 afi
= bgp_node_afi(vty
);
14302 safi
= bgp_node_safi(vty
);
14304 ret
= str2prefix(ip_str
, &p
);
14306 vty_out(vty
, "Malformed prefix\n");
14307 return CMD_WARNING_CONFIG_FAILED
;
14310 distance
= atoi(distance_str
);
14312 /* Get BGP distance node. */
14313 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14314 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14316 bgp_dest_unlock_node(dest
);
14318 bdistance
= bgp_distance_new();
14319 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14322 /* Set distance value. */
14323 bdistance
->distance
= distance
;
14325 /* Reset access-list configuration. */
14326 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14327 if (access_list_str
)
14328 bdistance
->access_list
=
14329 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14331 return CMD_SUCCESS
;
14334 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14335 const char *ip_str
, const char *access_list_str
)
14342 struct bgp_dest
*dest
;
14343 struct bgp_distance
*bdistance
;
14345 afi
= bgp_node_afi(vty
);
14346 safi
= bgp_node_safi(vty
);
14348 ret
= str2prefix(ip_str
, &p
);
14350 vty_out(vty
, "Malformed prefix\n");
14351 return CMD_WARNING_CONFIG_FAILED
;
14354 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14356 vty_out(vty
, "Can't find specified prefix\n");
14357 return CMD_WARNING_CONFIG_FAILED
;
14360 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14361 distance
= atoi(distance_str
);
14363 if (bdistance
->distance
!= distance
) {
14364 vty_out(vty
, "Distance does not match configured\n");
14365 bgp_dest_unlock_node(dest
);
14366 return CMD_WARNING_CONFIG_FAILED
;
14369 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14370 bgp_distance_free(bdistance
);
14372 bgp_dest_set_bgp_path_info(dest
, NULL
);
14373 bgp_dest_unlock_node(dest
);
14374 bgp_dest_unlock_node(dest
);
14376 return CMD_SUCCESS
;
14379 /* Apply BGP information to distance method. */
14380 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14381 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14383 struct bgp_dest
*dest
;
14384 struct prefix q
= {0};
14386 struct bgp_distance
*bdistance
;
14387 struct access_list
*alist
;
14388 struct bgp_static
*bgp_static
;
14393 peer
= pinfo
->peer
;
14395 if (pinfo
->attr
->distance
)
14396 return pinfo
->attr
->distance
;
14398 /* Check source address.
14399 * Note: for aggregate route, peer can have unspec af type.
14401 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14402 && !sockunion2hostprefix(&peer
->su
, &q
))
14405 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14407 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14408 bgp_dest_unlock_node(dest
);
14410 if (bdistance
->access_list
) {
14411 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14413 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14414 return bdistance
->distance
;
14416 return bdistance
->distance
;
14419 /* Backdoor check. */
14420 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14422 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14423 bgp_dest_unlock_node(dest
);
14425 if (bgp_static
->backdoor
) {
14426 if (bgp
->distance_local
[afi
][safi
])
14427 return bgp
->distance_local
[afi
][safi
];
14429 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14433 if (peer
->sort
== BGP_PEER_EBGP
) {
14434 if (bgp
->distance_ebgp
[afi
][safi
])
14435 return bgp
->distance_ebgp
[afi
][safi
];
14436 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14437 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14438 if (bgp
->distance_ibgp
[afi
][safi
])
14439 return bgp
->distance_ibgp
[afi
][safi
];
14440 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14442 if (bgp
->distance_local
[afi
][safi
])
14443 return bgp
->distance_local
[afi
][safi
];
14444 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14448 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14449 * we should tell ZEBRA update the routes for a specific
14450 * AFI/SAFI to reflect changes in RIB.
14452 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
14454 safi_t update_safi
)
14459 FOREACH_AFI_SAFI (afi
, safi
) {
14460 if (!bgp_fibupd_safi(safi
))
14463 if (afi
!= update_afi
&& safi
!= update_safi
)
14466 if (BGP_DEBUG(zebra
, ZEBRA
))
14468 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14469 __func__
, afi
, safi
);
14470 bgp_zebra_announce_table(bgp
, afi
, safi
);
14474 DEFUN (bgp_distance
,
14476 "distance bgp (1-255) (1-255) (1-255)",
14477 "Define an administrative distance\n"
14479 "Distance for routes external to the AS\n"
14480 "Distance for routes internal to the AS\n"
14481 "Distance for local routes\n")
14483 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14484 int idx_number
= 2;
14485 int idx_number_2
= 3;
14486 int idx_number_3
= 4;
14487 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
14488 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
14489 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
14493 afi
= bgp_node_afi(vty
);
14494 safi
= bgp_node_safi(vty
);
14496 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
14497 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
14498 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
14499 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
14500 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
14501 bgp
->distance_local
[afi
][safi
] = distance_local
;
14502 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14504 return CMD_SUCCESS
;
14507 DEFUN (no_bgp_distance
,
14508 no_bgp_distance_cmd
,
14509 "no distance bgp [(1-255) (1-255) (1-255)]",
14511 "Define an administrative distance\n"
14513 "Distance for routes external to the AS\n"
14514 "Distance for routes internal to the AS\n"
14515 "Distance for local routes\n")
14517 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14521 afi
= bgp_node_afi(vty
);
14522 safi
= bgp_node_safi(vty
);
14524 if (bgp
->distance_ebgp
[afi
][safi
] != 0
14525 || bgp
->distance_ibgp
[afi
][safi
] != 0
14526 || bgp
->distance_local
[afi
][safi
] != 0) {
14527 bgp
->distance_ebgp
[afi
][safi
] = 0;
14528 bgp
->distance_ibgp
[afi
][safi
] = 0;
14529 bgp
->distance_local
[afi
][safi
] = 0;
14530 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14532 return CMD_SUCCESS
;
14536 DEFUN (bgp_distance_source
,
14537 bgp_distance_source_cmd
,
14538 "distance (1-255) A.B.C.D/M",
14539 "Define an administrative distance\n"
14540 "Administrative distance\n"
14541 "IP source prefix\n")
14543 int idx_number
= 1;
14544 int idx_ipv4_prefixlen
= 2;
14545 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14546 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14547 return CMD_SUCCESS
;
14550 DEFUN (no_bgp_distance_source
,
14551 no_bgp_distance_source_cmd
,
14552 "no distance (1-255) A.B.C.D/M",
14554 "Define an administrative distance\n"
14555 "Administrative distance\n"
14556 "IP source prefix\n")
14558 int idx_number
= 2;
14559 int idx_ipv4_prefixlen
= 3;
14560 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14561 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14562 return CMD_SUCCESS
;
14565 DEFUN (bgp_distance_source_access_list
,
14566 bgp_distance_source_access_list_cmd
,
14567 "distance (1-255) A.B.C.D/M WORD",
14568 "Define an administrative distance\n"
14569 "Administrative distance\n"
14570 "IP source prefix\n"
14571 "Access list name\n")
14573 int idx_number
= 1;
14574 int idx_ipv4_prefixlen
= 2;
14576 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14577 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14578 return CMD_SUCCESS
;
14581 DEFUN (no_bgp_distance_source_access_list
,
14582 no_bgp_distance_source_access_list_cmd
,
14583 "no distance (1-255) A.B.C.D/M WORD",
14585 "Define an administrative distance\n"
14586 "Administrative distance\n"
14587 "IP source prefix\n"
14588 "Access list name\n")
14590 int idx_number
= 2;
14591 int idx_ipv4_prefixlen
= 3;
14593 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14594 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14595 return CMD_SUCCESS
;
14598 DEFUN (ipv6_bgp_distance_source
,
14599 ipv6_bgp_distance_source_cmd
,
14600 "distance (1-255) X:X::X:X/M",
14601 "Define an administrative distance\n"
14602 "Administrative distance\n"
14603 "IP source prefix\n")
14605 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
14606 return CMD_SUCCESS
;
14609 DEFUN (no_ipv6_bgp_distance_source
,
14610 no_ipv6_bgp_distance_source_cmd
,
14611 "no distance (1-255) X:X::X:X/M",
14613 "Define an administrative distance\n"
14614 "Administrative distance\n"
14615 "IP source prefix\n")
14617 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
14618 return CMD_SUCCESS
;
14621 DEFUN (ipv6_bgp_distance_source_access_list
,
14622 ipv6_bgp_distance_source_access_list_cmd
,
14623 "distance (1-255) X:X::X:X/M WORD",
14624 "Define an administrative distance\n"
14625 "Administrative distance\n"
14626 "IP source prefix\n"
14627 "Access list name\n")
14629 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
14630 return CMD_SUCCESS
;
14633 DEFUN (no_ipv6_bgp_distance_source_access_list
,
14634 no_ipv6_bgp_distance_source_access_list_cmd
,
14635 "no distance (1-255) X:X::X:X/M WORD",
14637 "Define an administrative distance\n"
14638 "Administrative distance\n"
14639 "IP source prefix\n"
14640 "Access list name\n")
14642 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
14643 return CMD_SUCCESS
;
14646 DEFUN (bgp_damp_set
,
14648 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
14649 "BGP Specific commands\n"
14650 "Enable route-flap dampening\n"
14651 "Half-life time for the penalty\n"
14652 "Value to start reusing a route\n"
14653 "Value to start suppressing a route\n"
14654 "Maximum duration to suppress a stable route\n")
14656 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14657 int idx_half_life
= 2;
14659 int idx_suppress
= 4;
14660 int idx_max_suppress
= 5;
14661 int half
= DEFAULT_HALF_LIFE
* 60;
14662 int reuse
= DEFAULT_REUSE
;
14663 int suppress
= DEFAULT_SUPPRESS
;
14664 int max
= 4 * half
;
14667 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14668 reuse
= atoi(argv
[idx_reuse
]->arg
);
14669 suppress
= atoi(argv
[idx_suppress
]->arg
);
14670 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
14671 } else if (argc
== 3) {
14672 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14677 * These can't be 0 but our SA doesn't understand the
14678 * way our cli is constructed
14682 if (suppress
< reuse
) {
14684 "Suppress value cannot be less than reuse value \n");
14688 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
14689 reuse
, suppress
, max
);
14692 DEFUN (bgp_damp_unset
,
14693 bgp_damp_unset_cmd
,
14694 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
14696 "BGP Specific commands\n"
14697 "Enable route-flap dampening\n"
14698 "Half-life time for the penalty\n"
14699 "Value to start reusing a route\n"
14700 "Value to start suppressing a route\n"
14701 "Maximum duration to suppress a stable route\n")
14703 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14704 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
14707 /* Display specified route of BGP table. */
14708 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14709 const char *ip_str
, afi_t afi
, safi_t safi
,
14710 struct prefix_rd
*prd
, int prefix_check
)
14713 struct prefix match
;
14714 struct bgp_dest
*dest
;
14715 struct bgp_dest
*rm
;
14716 struct bgp_path_info
*pi
;
14717 struct bgp_path_info
*pi_temp
;
14719 struct bgp_table
*table
;
14721 /* BGP structure lookup. */
14723 bgp
= bgp_lookup_by_name(view_name
);
14725 vty_out(vty
, "%% Can't find BGP instance %s\n",
14727 return CMD_WARNING
;
14730 bgp
= bgp_get_default();
14732 vty_out(vty
, "%% No BGP process is configured\n");
14733 return CMD_WARNING
;
14737 /* Check IP address argument. */
14738 ret
= str2prefix(ip_str
, &match
);
14740 vty_out(vty
, "%% address is malformed\n");
14741 return CMD_WARNING
;
14744 match
.family
= afi2family(afi
);
14746 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14747 || (safi
== SAFI_EVPN
)) {
14748 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
14749 dest
= bgp_route_next(dest
)) {
14750 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14752 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
14754 table
= bgp_dest_get_bgp_table_info(dest
);
14757 rm
= bgp_node_match(table
, &match
);
14761 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
14764 || rm_p
->prefixlen
== match
.prefixlen
) {
14765 pi
= bgp_dest_get_bgp_path_info(rm
);
14767 if (pi
->extra
&& pi
->extra
->damp_info
) {
14768 pi_temp
= pi
->next
;
14769 bgp_damp_info_free(
14770 pi
->extra
->damp_info
,
14778 bgp_dest_unlock_node(rm
);
14781 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
14782 if (dest
!= NULL
) {
14783 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14786 || dest_p
->prefixlen
== match
.prefixlen
) {
14787 pi
= bgp_dest_get_bgp_path_info(dest
);
14789 if (pi
->extra
&& pi
->extra
->damp_info
) {
14790 pi_temp
= pi
->next
;
14791 bgp_damp_info_free(
14792 pi
->extra
->damp_info
,
14800 bgp_dest_unlock_node(dest
);
14804 return CMD_SUCCESS
;
14807 DEFUN (clear_ip_bgp_dampening
,
14808 clear_ip_bgp_dampening_cmd
,
14809 "clear ip bgp dampening",
14813 "Clear route flap dampening information\n")
14815 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
14816 return CMD_SUCCESS
;
14819 DEFUN (clear_ip_bgp_dampening_prefix
,
14820 clear_ip_bgp_dampening_prefix_cmd
,
14821 "clear ip bgp dampening A.B.C.D/M",
14825 "Clear route flap dampening information\n"
14828 int idx_ipv4_prefixlen
= 4;
14829 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
14830 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
14833 DEFUN (clear_ip_bgp_dampening_address
,
14834 clear_ip_bgp_dampening_address_cmd
,
14835 "clear ip bgp dampening A.B.C.D",
14839 "Clear route flap dampening information\n"
14840 "Network to clear damping information\n")
14843 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
14844 SAFI_UNICAST
, NULL
, 0);
14847 DEFUN (clear_ip_bgp_dampening_address_mask
,
14848 clear_ip_bgp_dampening_address_mask_cmd
,
14849 "clear ip bgp dampening A.B.C.D A.B.C.D",
14853 "Clear route flap dampening information\n"
14854 "Network to clear damping information\n"
14858 int idx_ipv4_2
= 5;
14860 char prefix_str
[BUFSIZ
];
14862 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
14863 prefix_str
, sizeof(prefix_str
));
14865 vty_out(vty
, "%% Inconsistent address and mask\n");
14866 return CMD_WARNING
;
14869 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
14873 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
14875 struct vty
*vty
= arg
;
14876 struct peer
*peer
= bucket
->data
;
14877 char buf
[SU_ADDRSTRLEN
];
14879 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
14880 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
14883 DEFUN (show_bgp_listeners
,
14884 show_bgp_listeners_cmd
,
14885 "show bgp listeners",
14888 "Display Listen Sockets and who created them\n")
14890 bgp_dump_listener_info(vty
);
14892 return CMD_SUCCESS
;
14895 DEFUN (show_bgp_peerhash
,
14896 show_bgp_peerhash_cmd
,
14897 "show bgp peerhash",
14900 "Display information about the BGP peerhash\n")
14902 struct list
*instances
= bm
->bgp
;
14903 struct listnode
*node
;
14906 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
14907 vty_out(vty
, "BGP: %s\n", bgp
->name
);
14908 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
14912 return CMD_SUCCESS
;
14915 /* also used for encap safi */
14916 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
14917 afi_t afi
, safi_t safi
)
14919 struct bgp_dest
*pdest
;
14920 struct bgp_dest
*dest
;
14921 struct bgp_table
*table
;
14922 const struct prefix
*p
;
14923 const struct prefix_rd
*prd
;
14924 struct bgp_static
*bgp_static
;
14925 mpls_label_t label
;
14926 char rdbuf
[RD_ADDRSTRLEN
];
14928 /* Network configuration. */
14929 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14930 pdest
= bgp_route_next(pdest
)) {
14931 table
= bgp_dest_get_bgp_table_info(pdest
);
14935 for (dest
= bgp_table_top(table
); dest
;
14936 dest
= bgp_route_next(dest
)) {
14937 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14938 if (bgp_static
== NULL
)
14941 p
= bgp_dest_get_prefix(dest
);
14942 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14945 /* "network" configuration display. */
14946 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14947 label
= decode_label(&bgp_static
->label
);
14949 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
14950 if (safi
== SAFI_MPLS_VPN
)
14951 vty_out(vty
, " label %u", label
);
14953 if (bgp_static
->rmap
.name
)
14954 vty_out(vty
, " route-map %s",
14955 bgp_static
->rmap
.name
);
14957 if (bgp_static
->backdoor
)
14958 vty_out(vty
, " backdoor");
14960 vty_out(vty
, "\n");
14965 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
14966 afi_t afi
, safi_t safi
)
14968 struct bgp_dest
*pdest
;
14969 struct bgp_dest
*dest
;
14970 struct bgp_table
*table
;
14971 const struct prefix
*p
;
14972 const struct prefix_rd
*prd
;
14973 struct bgp_static
*bgp_static
;
14974 char buf
[PREFIX_STRLEN
* 2];
14975 char buf2
[SU_ADDRSTRLEN
];
14976 char rdbuf
[RD_ADDRSTRLEN
];
14977 char esi_buf
[ESI_BYTES
];
14979 /* Network configuration. */
14980 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14981 pdest
= bgp_route_next(pdest
)) {
14982 table
= bgp_dest_get_bgp_table_info(pdest
);
14986 for (dest
= bgp_table_top(table
); dest
;
14987 dest
= bgp_route_next(dest
)) {
14988 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14989 if (bgp_static
== NULL
)
14992 char *macrouter
= NULL
;
14994 if (bgp_static
->router_mac
)
14995 macrouter
= prefix_mac2str(
14996 bgp_static
->router_mac
, NULL
, 0);
14997 if (bgp_static
->eth_s_id
)
14998 esi_to_str(bgp_static
->eth_s_id
,
14999 esi_buf
, sizeof(esi_buf
));
15000 p
= bgp_dest_get_prefix(dest
);
15001 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15003 /* "network" configuration display. */
15004 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
15005 if (p
->u
.prefix_evpn
.route_type
== 5) {
15006 char local_buf
[PREFIX_STRLEN
];
15007 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15008 struct prefix_evpn
*)p
)
15012 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
15013 local_buf
, PREFIX_STRLEN
);
15014 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15015 p
->u
.prefix_evpn
.prefix_addr
15016 .ip_prefix_length
);
15018 prefix2str(p
, buf
, sizeof(buf
));
15021 if (bgp_static
->gatewayIp
.family
== AF_INET
15022 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15023 inet_ntop(bgp_static
->gatewayIp
.family
,
15024 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15027 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15029 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15030 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15033 XFREE(MTYPE_TMP
, macrouter
);
15038 /* Configuration of static route announcement and aggregate
15040 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15043 struct bgp_dest
*dest
;
15044 const struct prefix
*p
;
15045 struct bgp_static
*bgp_static
;
15046 struct bgp_aggregate
*bgp_aggregate
;
15048 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15049 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15053 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15054 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15058 /* Network configuration. */
15059 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15060 dest
= bgp_route_next(dest
)) {
15061 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15062 if (bgp_static
== NULL
)
15065 p
= bgp_dest_get_prefix(dest
);
15067 vty_out(vty
, " network %pFX", p
);
15069 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15070 vty_out(vty
, " label-index %u",
15071 bgp_static
->label_index
);
15073 if (bgp_static
->rmap
.name
)
15074 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15076 if (bgp_static
->backdoor
)
15077 vty_out(vty
, " backdoor");
15079 vty_out(vty
, "\n");
15082 /* Aggregate-address configuration. */
15083 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15084 dest
= bgp_route_next(dest
)) {
15085 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15086 if (bgp_aggregate
== NULL
)
15089 p
= bgp_dest_get_prefix(dest
);
15091 vty_out(vty
, " aggregate-address %pFX", p
);
15093 if (bgp_aggregate
->as_set
)
15094 vty_out(vty
, " as-set");
15096 if (bgp_aggregate
->summary_only
)
15097 vty_out(vty
, " summary-only");
15099 if (bgp_aggregate
->rmap
.name
)
15100 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15102 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15103 vty_out(vty
, " origin %s",
15104 bgp_origin2str(bgp_aggregate
->origin
));
15106 if (bgp_aggregate
->match_med
)
15107 vty_out(vty
, " matching-MED-only");
15109 if (bgp_aggregate
->suppress_map_name
)
15110 vty_out(vty
, " suppress-map %s",
15111 bgp_aggregate
->suppress_map_name
);
15113 vty_out(vty
, "\n");
15117 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15120 struct bgp_dest
*dest
;
15121 struct bgp_distance
*bdistance
;
15123 /* Distance configuration. */
15124 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15125 && bgp
->distance_local
[afi
][safi
]
15126 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15127 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15128 || bgp
->distance_local
[afi
][safi
]
15129 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15130 vty_out(vty
, " distance bgp %d %d %d\n",
15131 bgp
->distance_ebgp
[afi
][safi
],
15132 bgp
->distance_ibgp
[afi
][safi
],
15133 bgp
->distance_local
[afi
][safi
]);
15136 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15137 dest
= bgp_route_next(dest
)) {
15138 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15139 if (bdistance
!= NULL
)
15140 vty_out(vty
, " distance %d %pBD %s\n",
15141 bdistance
->distance
, dest
,
15142 bdistance
->access_list
? bdistance
->access_list
15147 /* Allocate routing table structure and install commands. */
15148 void bgp_route_init(void)
15153 /* Init BGP distance table. */
15154 FOREACH_AFI_SAFI (afi
, safi
)
15155 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15157 /* IPv4 BGP commands. */
15158 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15159 install_element(BGP_NODE
, &bgp_network_cmd
);
15160 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15162 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15164 /* IPv4 unicast configuration. */
15165 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15166 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15167 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15169 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15171 /* IPv4 multicast configuration. */
15172 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15173 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15174 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15175 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15177 /* IPv4 labeled-unicast configuration. */
15178 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15179 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15181 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15182 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15183 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15184 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15185 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15186 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15187 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15188 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15190 install_element(VIEW_NODE
,
15191 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15192 install_element(VIEW_NODE
,
15193 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15194 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15195 install_element(VIEW_NODE
,
15196 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15197 #ifdef KEEP_OLD_VPN_COMMANDS
15198 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15199 #endif /* KEEP_OLD_VPN_COMMANDS */
15200 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15201 install_element(VIEW_NODE
,
15202 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15204 /* BGP dampening clear commands */
15205 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15206 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15208 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15209 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15212 install_element(ENABLE_NODE
,
15213 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15214 #ifdef KEEP_OLD_VPN_COMMANDS
15215 install_element(ENABLE_NODE
,
15216 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15217 #endif /* KEEP_OLD_VPN_COMMANDS */
15219 /* New config IPv6 BGP commands. */
15220 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15221 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15222 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15224 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15226 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15228 /* IPv6 labeled unicast address family. */
15229 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15230 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15232 install_element(BGP_NODE
, &bgp_distance_cmd
);
15233 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15234 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15235 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15236 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15237 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15238 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15239 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15240 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15241 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15242 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15243 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15244 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15245 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15246 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15247 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15248 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15249 install_element(BGP_IPV4M_NODE
,
15250 &no_bgp_distance_source_access_list_cmd
);
15251 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15252 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15253 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15254 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15255 install_element(BGP_IPV6_NODE
,
15256 &ipv6_bgp_distance_source_access_list_cmd
);
15257 install_element(BGP_IPV6_NODE
,
15258 &no_ipv6_bgp_distance_source_access_list_cmd
);
15259 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15260 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15261 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15262 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15263 install_element(BGP_IPV6M_NODE
,
15264 &ipv6_bgp_distance_source_access_list_cmd
);
15265 install_element(BGP_IPV6M_NODE
,
15266 &no_ipv6_bgp_distance_source_access_list_cmd
);
15268 /* BGP dampening */
15269 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15270 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15271 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15272 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15273 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15274 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15275 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15276 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15277 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15278 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15279 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15280 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15281 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15282 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15284 /* Large Communities */
15285 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15286 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15288 /* show bgp ipv4 flowspec detailed */
15289 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15291 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15292 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15295 void bgp_route_finish(void)
15300 FOREACH_AFI_SAFI (afi
, safi
) {
15301 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15302 bgp_distance_table
[afi
][safi
] = NULL
;