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"
91 #include "northbound.h"
92 #include "northbound_cli.h"
93 #include "bgpd/bgp_nb.h"
95 #ifndef VTYSH_EXTRACT_PL
96 #include "bgpd/bgp_route_clippy.c"
99 DEFINE_HOOK(bgp_snmp_update_stats
,
100 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
103 DEFINE_HOOK(bgp_rpki_prefix_status
,
104 (struct peer
*peer
, struct attr
*attr
,
105 const struct prefix
*prefix
),
106 (peer
, attr
, prefix
));
108 /* Extern from bgp_dump.c */
109 extern const char *bgp_origin_str
[];
110 extern const char *bgp_origin_long_str
[];
113 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
114 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
115 static const struct message bgp_pmsi_tnltype_str
[] = {
116 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
117 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
118 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
119 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
120 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
121 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
122 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
123 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
127 #define VRFID_NONE_STR "-"
129 DEFINE_HOOK(bgp_process
,
130 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
131 struct peer
*peer
, bool withdraw
),
132 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
134 /** Test if path is suppressed. */
135 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
137 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
140 return listcount(pi
->extra
->aggr_suppressors
) > 0;
143 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
144 safi_t safi
, const struct prefix
*p
,
145 struct prefix_rd
*prd
)
147 struct bgp_dest
*dest
;
148 struct bgp_dest
*pdest
= NULL
;
152 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
153 || (safi
== SAFI_EVPN
)) {
154 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
156 if (!bgp_dest_has_bgp_path_info_data(pdest
))
157 bgp_dest_set_bgp_table_info(
158 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
160 bgp_dest_unlock_node(pdest
);
161 table
= bgp_dest_get_bgp_table_info(pdest
);
164 dest
= bgp_node_get(table
, p
);
166 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
167 || (safi
== SAFI_EVPN
))
173 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
174 safi_t safi
, const struct prefix
*p
,
175 struct prefix_rd
*prd
)
177 struct bgp_dest
*dest
;
178 struct bgp_dest
*pdest
= NULL
;
183 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
184 || (safi
== SAFI_EVPN
)) {
185 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
189 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
190 bgp_dest_unlock_node(pdest
);
194 table
= bgp_dest_get_bgp_table_info(pdest
);
197 dest
= bgp_node_lookup(table
, p
);
202 /* Allocate bgp_path_info_extra */
203 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
205 struct bgp_path_info_extra
*new;
206 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
207 sizeof(struct bgp_path_info_extra
));
208 new->label
[0] = MPLS_INVALID_LABEL
;
210 new->bgp_fs_pbr
= NULL
;
211 new->bgp_fs_iprule
= NULL
;
215 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
217 struct bgp_path_info_extra
*e
;
219 if (!extra
|| !*extra
)
226 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
229 /* FIXME: since multiple e may have the same e->parent
230 * and e->parent->net is holding a refcount for each
231 * of them, we need to do some fudging here.
233 * WARNING: if bpi->net->lock drops to 0, bpi may be
234 * freed as well (because bpi->net was holding the
235 * last reference to bpi) => write after free!
239 bpi
= bgp_path_info_lock(bpi
);
240 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
241 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
244 bgp_path_info_unlock(bpi
);
246 bgp_path_info_unlock(e
->parent
);
251 bgp_unlock(e
->bgp_orig
);
253 if (e
->aggr_suppressors
)
254 list_delete(&e
->aggr_suppressors
);
257 bgp_evpn_path_mh_info_free(e
->mh_info
);
259 if ((*extra
)->bgp_fs_iprule
)
260 list_delete(&((*extra
)->bgp_fs_iprule
));
261 if ((*extra
)->bgp_fs_pbr
)
262 list_delete(&((*extra
)->bgp_fs_pbr
));
263 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
266 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
267 * allocated if required.
269 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
272 pi
->extra
= bgp_path_info_extra_new();
276 /* Free bgp route information. */
277 static void bgp_path_info_free(struct bgp_path_info
*path
)
279 bgp_attr_unintern(&path
->attr
);
281 bgp_unlink_nexthop(path
);
282 bgp_path_info_extra_free(&path
->extra
);
283 bgp_path_info_mpath_free(&path
->mpath
);
285 bgp_addpath_free_info_data(&path
->tx_addpath
,
286 &path
->net
->tx_addpath
);
288 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
290 XFREE(MTYPE_BGP_ROUTE
, path
);
293 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
299 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
301 assert(path
&& path
->lock
> 0);
304 if (path
->lock
== 0) {
306 zlog_debug ("%s: unlocked and freeing", __func__
);
307 zlog_backtrace (LOG_DEBUG
);
309 bgp_path_info_free(path
);
316 zlog_debug ("%s: unlocked to 1", __func__
);
317 zlog_backtrace (LOG_DEBUG
);
324 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
325 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
328 struct bgp_path_info
*old_pi
, *nextpi
;
329 bool set_flag
= false;
330 struct bgp
*bgp
= NULL
;
331 struct bgp_table
*table
= NULL
;
335 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
336 * then the route selection is deferred
338 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
341 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
342 if (BGP_DEBUG(update
, UPDATE_OUT
))
344 "Route %pBD is in workqueue and being processed, not deferred.",
350 table
= bgp_dest_table(dest
);
357 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
358 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
359 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
362 /* Route selection is deferred if there is a stale path which
363 * which indicates peer is in restart mode
365 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
366 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
369 /* If the peer is graceful restart capable and peer is
370 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
373 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
374 && BGP_PEER_RESTARTING_MODE(peer
)
376 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
384 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
387 if (set_flag
&& table
) {
388 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
389 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
390 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
391 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
392 if (BGP_DEBUG(update
, UPDATE_OUT
))
393 zlog_debug("DEFER route %pBD, dest %p", dest
,
401 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
403 struct bgp_path_info
*top
;
405 top
= bgp_dest_get_bgp_path_info(dest
);
411 bgp_dest_set_bgp_path_info(dest
, pi
);
413 bgp_path_info_lock(pi
);
414 bgp_dest_lock_node(dest
);
415 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
416 bgp_dest_set_defer_flag(dest
, false);
417 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
420 /* Do the actual removal of info from RIB, for use by bgp_process
421 completion callback *only* */
422 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
425 pi
->next
->prev
= pi
->prev
;
427 pi
->prev
->next
= pi
->next
;
429 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
431 bgp_path_info_mpath_dequeue(pi
);
432 bgp_path_info_unlock(pi
);
433 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
434 bgp_dest_unlock_node(dest
);
437 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
439 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
440 /* set of previous already took care of pcount */
441 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
444 /* undo the effects of a previous call to bgp_path_info_delete; typically
445 called when a route is deleted and then quickly re-added before the
446 deletion has been processed */
447 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
449 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
450 /* unset of previous already took care of pcount */
451 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
454 /* Adjust pcount as required */
455 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
457 struct bgp_table
*table
;
459 assert(dest
&& bgp_dest_table(dest
));
460 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
462 table
= bgp_dest_table(dest
);
464 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
467 if (!BGP_PATH_COUNTABLE(pi
)
468 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
470 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
472 /* slight hack, but more robust against errors. */
473 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
474 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
476 flog_err(EC_LIB_DEVELOPMENT
,
477 "Asked to decrement 0 prefix count for peer");
478 } else if (BGP_PATH_COUNTABLE(pi
)
479 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
480 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
481 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
485 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
486 struct bgp_path_info
*pi2
)
488 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
491 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
492 * This is here primarily to keep prefix-count in check.
494 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
497 SET_FLAG(pi
->flags
, flag
);
499 /* early bath if we know it's not a flag that changes countability state
501 if (!CHECK_FLAG(flag
,
502 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
505 bgp_pcount_adjust(dest
, pi
);
508 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
511 UNSET_FLAG(pi
->flags
, flag
);
513 /* early bath if we know it's not a flag that changes countability state
515 if (!CHECK_FLAG(flag
,
516 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
519 bgp_pcount_adjust(dest
, pi
);
522 /* Get MED value. If MED value is missing and "bgp bestpath
523 missing-as-worst" is specified, treat it as the worst value. */
524 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
526 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
529 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
536 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
539 if (pi
->addpath_rx_id
)
540 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
541 pi
->peer
->host
, pi
->addpath_rx_id
);
543 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
546 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
548 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
549 struct bgp_path_info
*exist
, int *paths_eq
,
550 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
551 char *pfx_buf
, afi_t afi
, safi_t safi
,
552 enum bgp_path_selection_reason
*reason
)
554 const struct prefix
*new_p
;
555 struct attr
*newattr
, *existattr
;
556 bgp_peer_sort_t new_sort
;
557 bgp_peer_sort_t exist_sort
;
563 uint32_t exist_weight
;
564 uint32_t newm
, existm
;
565 struct in_addr new_id
;
566 struct in_addr exist_id
;
569 int internal_as_route
;
572 int igp_metric_ret
= 0;
573 int peer_sort_ret
= -1;
574 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
575 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
577 uint32_t exist_mm_seq
;
584 bool new_origin
, exist_origin
;
590 *reason
= bgp_path_selection_none
;
592 zlog_debug("%s: new is NULL", pfx_buf
);
597 bgp_path_info_path_with_addpath_rx_str(new, new_buf
,
601 *reason
= bgp_path_selection_first
;
603 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
609 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
,
611 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
612 pfx_buf
, new_buf
, new->flags
, exist_buf
,
617 existattr
= exist
->attr
;
619 new_p
= bgp_dest_get_prefix(new->net
);
621 /* For EVPN routes, we cannot just go by local vs remote, we have to
622 * look at the MAC mobility sequence number, if present.
624 if ((safi
== SAFI_EVPN
)
625 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
626 /* This is an error condition described in RFC 7432 Section
628 * states that in this scenario "the PE MUST alert the operator"
630 * does not state what other action to take. In order to provide
632 * consistency in this scenario we are going to prefer the path
636 if (newattr
->sticky
!= existattr
->sticky
) {
638 prefix2str(new_p
, pfx_buf
,
640 * PREFIX2STR_BUFFER
);
641 bgp_path_info_path_with_addpath_rx_str(
642 new, new_buf
, sizeof(new_buf
));
643 bgp_path_info_path_with_addpath_rx_str(
644 exist
, exist_buf
, sizeof(exist_buf
));
647 if (newattr
->sticky
&& !existattr
->sticky
) {
648 *reason
= bgp_path_selection_evpn_sticky_mac
;
651 "%s: %s wins over %s due to sticky MAC flag",
652 pfx_buf
, new_buf
, exist_buf
);
656 if (!newattr
->sticky
&& existattr
->sticky
) {
657 *reason
= bgp_path_selection_evpn_sticky_mac
;
660 "%s: %s loses to %s due to sticky MAC flag",
661 pfx_buf
, new_buf
, exist_buf
);
666 new_esi
= bgp_evpn_attr_get_esi(newattr
);
667 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
668 if (bgp_evpn_is_esi_valid(new_esi
) &&
669 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
675 /* If both paths have the same non-zero ES and
676 * one path is local it wins.
677 * PS: Note the local path wins even if the remote
678 * has the higher MM seq. The local path's
679 * MM seq will be fixed up to match the highest
680 * rem seq, subsequently.
683 char esi_buf
[ESI_STR_LEN
];
685 if (bgp_evpn_is_path_local(bgp
, new)) {
686 *reason
= bgp_path_selection_evpn_local_path
;
689 "%s: %s wins over %s as ES %s is same and local",
690 pfx_buf
, new_buf
, exist_buf
,
691 esi_to_str(new_esi
, esi_buf
,
695 if (bgp_evpn_is_path_local(bgp
, exist
)) {
696 *reason
= bgp_path_selection_evpn_local_path
;
699 "%s: %s loses to %s as ES %s is same and local",
700 pfx_buf
, new_buf
, exist_buf
,
701 esi_to_str(new_esi
, esi_buf
,
707 new_mm_seq
= mac_mobility_seqnum(newattr
);
708 exist_mm_seq
= mac_mobility_seqnum(existattr
);
710 if (new_mm_seq
> exist_mm_seq
) {
711 *reason
= bgp_path_selection_evpn_seq
;
714 "%s: %s wins over %s due to MM seq %u > %u",
715 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
720 if (new_mm_seq
< exist_mm_seq
) {
721 *reason
= bgp_path_selection_evpn_seq
;
724 "%s: %s loses to %s due to MM seq %u < %u",
725 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
730 /* if the sequence numbers and ESI are the same and one path
731 * is non-proxy it wins (over proxy)
733 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
734 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
735 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
736 old_proxy
!= new_proxy
) {
738 *reason
= bgp_path_selection_evpn_non_proxy
;
741 "%s: %s wins over %s, same seq/es and non-proxy",
742 pfx_buf
, new_buf
, exist_buf
);
746 *reason
= bgp_path_selection_evpn_non_proxy
;
749 "%s: %s loses to %s, same seq/es and non-proxy",
750 pfx_buf
, new_buf
, exist_buf
);
755 * if sequence numbers are the same path with the lowest IP
758 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
760 *reason
= bgp_path_selection_evpn_lower_ip
;
763 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
764 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
765 &new->attr
->nexthop
);
769 *reason
= bgp_path_selection_evpn_lower_ip
;
772 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
773 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
774 &new->attr
->nexthop
);
779 /* 1. Weight check. */
780 new_weight
= newattr
->weight
;
781 exist_weight
= existattr
->weight
;
783 if (new_weight
> exist_weight
) {
784 *reason
= bgp_path_selection_weight
;
786 zlog_debug("%s: %s wins over %s due to weight %d > %d",
787 pfx_buf
, new_buf
, exist_buf
, new_weight
,
792 if (new_weight
< exist_weight
) {
793 *reason
= bgp_path_selection_weight
;
795 zlog_debug("%s: %s loses to %s due to weight %d < %d",
796 pfx_buf
, new_buf
, exist_buf
, new_weight
,
801 /* 2. Local preference check. */
802 new_pref
= exist_pref
= bgp
->default_local_pref
;
804 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
805 new_pref
= newattr
->local_pref
;
806 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
807 exist_pref
= existattr
->local_pref
;
809 if (new_pref
> exist_pref
) {
810 *reason
= bgp_path_selection_local_pref
;
813 "%s: %s wins over %s due to localpref %d > %d",
814 pfx_buf
, new_buf
, exist_buf
, new_pref
,
819 if (new_pref
< exist_pref
) {
820 *reason
= bgp_path_selection_local_pref
;
823 "%s: %s loses to %s due to localpref %d < %d",
824 pfx_buf
, new_buf
, exist_buf
, new_pref
,
829 /* 3. Local route check. We prefer:
831 * - BGP_ROUTE_AGGREGATE
832 * - BGP_ROUTE_REDISTRIBUTE
834 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
835 new->sub_type
== BGP_ROUTE_IMPORTED
);
836 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
837 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
839 if (new_origin
&& !exist_origin
) {
840 *reason
= bgp_path_selection_local_route
;
843 "%s: %s wins over %s due to preferred BGP_ROUTE type",
844 pfx_buf
, new_buf
, exist_buf
);
848 if (!new_origin
&& exist_origin
) {
849 *reason
= bgp_path_selection_local_route
;
852 "%s: %s loses to %s due to preferred BGP_ROUTE type",
853 pfx_buf
, new_buf
, exist_buf
);
857 /* 4. AS path length check. */
858 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
859 int exist_hops
= aspath_count_hops(existattr
->aspath
);
860 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
862 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
865 aspath_hops
= aspath_count_hops(newattr
->aspath
);
866 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
868 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
869 *reason
= bgp_path_selection_confed_as_path
;
872 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
873 pfx_buf
, new_buf
, exist_buf
,
875 (exist_hops
+ exist_confeds
));
879 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
880 *reason
= bgp_path_selection_confed_as_path
;
883 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
884 pfx_buf
, new_buf
, exist_buf
,
886 (exist_hops
+ exist_confeds
));
890 int newhops
= aspath_count_hops(newattr
->aspath
);
892 if (newhops
< exist_hops
) {
893 *reason
= bgp_path_selection_as_path
;
896 "%s: %s wins over %s due to aspath hopcount %d < %d",
897 pfx_buf
, new_buf
, exist_buf
,
898 newhops
, exist_hops
);
902 if (newhops
> exist_hops
) {
903 *reason
= bgp_path_selection_as_path
;
906 "%s: %s loses to %s due to aspath hopcount %d > %d",
907 pfx_buf
, new_buf
, exist_buf
,
908 newhops
, exist_hops
);
914 /* 5. Origin check. */
915 if (newattr
->origin
< existattr
->origin
) {
916 *reason
= bgp_path_selection_origin
;
918 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
919 pfx_buf
, new_buf
, exist_buf
,
920 bgp_origin_long_str
[newattr
->origin
],
921 bgp_origin_long_str
[existattr
->origin
]);
925 if (newattr
->origin
> existattr
->origin
) {
926 *reason
= bgp_path_selection_origin
;
928 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
929 pfx_buf
, new_buf
, exist_buf
,
930 bgp_origin_long_str
[newattr
->origin
],
931 bgp_origin_long_str
[existattr
->origin
]);
936 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
937 && aspath_count_hops(existattr
->aspath
) == 0);
938 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
939 && aspath_count_confeds(existattr
->aspath
) > 0
940 && aspath_count_hops(newattr
->aspath
) == 0
941 && aspath_count_hops(existattr
->aspath
) == 0);
943 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
944 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
945 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
946 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
947 || internal_as_route
) {
948 new_med
= bgp_med_value(new->attr
, bgp
);
949 exist_med
= bgp_med_value(exist
->attr
, bgp
);
951 if (new_med
< exist_med
) {
952 *reason
= bgp_path_selection_med
;
955 "%s: %s wins over %s due to MED %d < %d",
956 pfx_buf
, new_buf
, exist_buf
, new_med
,
961 if (new_med
> exist_med
) {
962 *reason
= bgp_path_selection_med
;
965 "%s: %s loses to %s due to MED %d > %d",
966 pfx_buf
, new_buf
, exist_buf
, new_med
,
972 /* 7. Peer type check. */
973 new_sort
= new->peer
->sort
;
974 exist_sort
= exist
->peer
->sort
;
976 if (new_sort
== BGP_PEER_EBGP
977 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
978 *reason
= bgp_path_selection_peer
;
981 "%s: %s wins over %s due to eBGP peer > iBGP peer",
982 pfx_buf
, new_buf
, exist_buf
);
983 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
988 if (exist_sort
== BGP_PEER_EBGP
989 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
990 *reason
= bgp_path_selection_peer
;
993 "%s: %s loses to %s due to iBGP peer < eBGP peer",
994 pfx_buf
, new_buf
, exist_buf
);
995 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1000 /* 8. IGP metric check. */
1004 newm
= new->extra
->igpmetric
;
1006 existm
= exist
->extra
->igpmetric
;
1008 if (newm
< existm
) {
1009 if (debug
&& peer_sort_ret
< 0)
1011 "%s: %s wins over %s due to IGP metric %u < %u",
1012 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1016 if (newm
> existm
) {
1017 if (debug
&& peer_sort_ret
< 0)
1019 "%s: %s loses to %s due to IGP metric %u > %u",
1020 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1024 /* 9. Same IGP metric. Compare the cluster list length as
1025 representative of IGP hops metric. Rewrite the metric value
1026 pair (newm, existm) with the cluster list length. Prefer the
1027 path with smaller cluster list length. */
1028 if (newm
== existm
) {
1029 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
1030 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
1031 && (mpath_cfg
== NULL
1033 mpath_cfg
->ibgp_flags
,
1034 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
1035 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1036 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1038 if (newm
< existm
) {
1039 if (debug
&& peer_sort_ret
< 0)
1041 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1042 pfx_buf
, new_buf
, exist_buf
,
1047 if (newm
> existm
) {
1048 if (debug
&& peer_sort_ret
< 0)
1050 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1051 pfx_buf
, new_buf
, exist_buf
,
1058 /* 10. confed-external vs. confed-internal */
1059 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1060 if (new_sort
== BGP_PEER_CONFED
1061 && exist_sort
== BGP_PEER_IBGP
) {
1062 *reason
= bgp_path_selection_confed
;
1065 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1066 pfx_buf
, new_buf
, exist_buf
);
1067 if (!CHECK_FLAG(bgp
->flags
,
1068 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1073 if (exist_sort
== BGP_PEER_CONFED
1074 && new_sort
== BGP_PEER_IBGP
) {
1075 *reason
= bgp_path_selection_confed
;
1078 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1079 pfx_buf
, new_buf
, exist_buf
);
1080 if (!CHECK_FLAG(bgp
->flags
,
1081 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1087 /* 11. Maximum path check. */
1088 if (newm
== existm
) {
1089 /* If one path has a label but the other does not, do not treat
1090 * them as equals for multipath
1092 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1094 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1097 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1098 pfx_buf
, new_buf
, exist_buf
);
1099 } else if (CHECK_FLAG(bgp
->flags
,
1100 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1103 * For the two paths, all comparison steps till IGP
1105 * have succeeded - including AS_PATH hop count. Since
1107 * bestpath as-path multipath-relax' knob is on, we
1109 * an exact match of AS_PATH. Thus, mark the paths are
1111 * That will trigger both these paths to get into the
1119 "%s: %s and %s are equal via multipath-relax",
1120 pfx_buf
, new_buf
, exist_buf
);
1121 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1122 if (aspath_cmp(new->attr
->aspath
,
1123 exist
->attr
->aspath
)) {
1128 "%s: %s and %s are equal via matching aspaths",
1129 pfx_buf
, new_buf
, exist_buf
);
1131 } else if (new->peer
->as
== exist
->peer
->as
) {
1136 "%s: %s and %s are equal via same remote-as",
1137 pfx_buf
, new_buf
, exist_buf
);
1141 * TODO: If unequal cost ibgp multipath is enabled we can
1142 * mark the paths as equal here instead of returning
1145 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1146 * if either step 7 or 10 (peer type checks) yielded a winner,
1147 * that result was returned immediately. Returning from step 10
1148 * ignored the return value computed in steps 8 and 9 (IGP
1149 * metric checks). In order to preserve that behavior, if
1150 * peer_sort_ret is set, return that rather than igp_metric_ret.
1152 ret
= peer_sort_ret
;
1153 if (peer_sort_ret
< 0) {
1154 ret
= igp_metric_ret
;
1158 "%s: %s wins over %s after IGP metric comparison",
1159 pfx_buf
, new_buf
, exist_buf
);
1162 "%s: %s loses to %s after IGP metric comparison",
1163 pfx_buf
, new_buf
, exist_buf
);
1165 *reason
= bgp_path_selection_igp_metric
;
1171 * At this point, the decision whether to set *paths_eq = 1 has been
1172 * completed. If we deferred returning because of bestpath peer-type
1173 * relax configuration, return now.
1175 if (peer_sort_ret
>= 0)
1176 return peer_sort_ret
;
1178 /* 12. If both paths are external, prefer the path that was received
1179 first (the oldest one). This step minimizes route-flap, since a
1180 newer path won't displace an older one, even if it was the
1181 preferred route based on the additional decision criteria below. */
1182 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1183 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1184 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1185 *reason
= bgp_path_selection_older
;
1188 "%s: %s wins over %s due to oldest external",
1189 pfx_buf
, new_buf
, exist_buf
);
1193 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1194 *reason
= bgp_path_selection_older
;
1197 "%s: %s loses to %s due to oldest external",
1198 pfx_buf
, new_buf
, exist_buf
);
1203 /* 13. Router-ID comparision. */
1204 /* If one of the paths is "stale", the corresponding peer router-id will
1205 * be 0 and would always win over the other path. If originator id is
1206 * used for the comparision, it will decide which path is better.
1208 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1209 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1211 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1212 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1213 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1215 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1217 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1218 *reason
= bgp_path_selection_router_id
;
1221 "%s: %s wins over %s due to Router-ID comparison",
1222 pfx_buf
, new_buf
, exist_buf
);
1226 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1227 *reason
= bgp_path_selection_router_id
;
1230 "%s: %s loses to %s due to Router-ID comparison",
1231 pfx_buf
, new_buf
, exist_buf
);
1235 /* 14. Cluster length comparision. */
1236 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1237 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1239 if (new_cluster
< exist_cluster
) {
1240 *reason
= bgp_path_selection_cluster_length
;
1243 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1244 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1249 if (new_cluster
> exist_cluster
) {
1250 *reason
= bgp_path_selection_cluster_length
;
1253 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1254 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1259 /* 15. Neighbor address comparision. */
1260 /* Do this only if neither path is "stale" as stale paths do not have
1261 * valid peer information (as the connection may or may not be up).
1263 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1264 *reason
= bgp_path_selection_stale
;
1267 "%s: %s wins over %s due to latter path being STALE",
1268 pfx_buf
, new_buf
, exist_buf
);
1272 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1273 *reason
= bgp_path_selection_stale
;
1276 "%s: %s loses to %s due to former path being STALE",
1277 pfx_buf
, new_buf
, exist_buf
);
1281 /* locally configured routes to advertise do not have su_remote */
1282 if (new->peer
->su_remote
== NULL
) {
1283 *reason
= bgp_path_selection_local_configured
;
1286 if (exist
->peer
->su_remote
== NULL
) {
1287 *reason
= bgp_path_selection_local_configured
;
1291 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1294 *reason
= bgp_path_selection_neighbor_ip
;
1297 "%s: %s loses to %s due to Neighor IP comparison",
1298 pfx_buf
, new_buf
, exist_buf
);
1303 *reason
= bgp_path_selection_neighbor_ip
;
1306 "%s: %s wins over %s due to Neighor IP comparison",
1307 pfx_buf
, new_buf
, exist_buf
);
1311 *reason
= bgp_path_selection_default
;
1313 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1314 pfx_buf
, new_buf
, exist_buf
);
1320 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1321 struct bgp_path_info
*exist
, int *paths_eq
)
1323 enum bgp_path_selection_reason reason
;
1324 char pfx_buf
[PREFIX2STR_BUFFER
];
1326 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1327 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1330 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1331 * is preferred, or 0 if they are the same (usually will only occur if
1332 * multipath is enabled
1333 * This version is compatible with */
1334 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1335 struct bgp_path_info
*exist
, char *pfx_buf
,
1336 afi_t afi
, safi_t safi
,
1337 enum bgp_path_selection_reason
*reason
)
1341 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1355 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1356 const struct prefix
*p
,
1357 struct attr
*attr
, afi_t afi
,
1360 struct bgp_filter
*filter
;
1361 enum filter_type ret
= FILTER_PERMIT
;
1363 filter
= &peer
->filter
[afi
][safi
];
1365 #define FILTER_EXIST_WARN(F, f, filter) \
1366 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1367 zlog_debug("%s: Could not find configured input %s-list %s!", \
1368 peer->host, #f, F##_IN_NAME(filter));
1370 if (DISTRIBUTE_IN_NAME(filter
)) {
1371 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1373 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1380 if (PREFIX_LIST_IN_NAME(filter
)) {
1381 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1383 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1390 if (FILTER_LIST_IN_NAME(filter
)) {
1391 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1393 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1394 == AS_FILTER_DENY
) {
1401 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1402 char pfxprint
[PREFIX2STR_BUFFER
];
1404 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1405 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1406 ret
== FILTER_PERMIT
? "permit" : "deny");
1410 #undef FILTER_EXIST_WARN
1413 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1414 const struct prefix
*p
,
1415 struct attr
*attr
, afi_t afi
,
1418 struct bgp_filter
*filter
;
1419 enum filter_type ret
= FILTER_PERMIT
;
1421 filter
= &peer
->filter
[afi
][safi
];
1423 #define FILTER_EXIST_WARN(F, f, filter) \
1424 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1425 zlog_debug("%s: Could not find configured output %s-list %s!", \
1426 peer->host, #f, F##_OUT_NAME(filter));
1428 if (DISTRIBUTE_OUT_NAME(filter
)) {
1429 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1431 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1438 if (PREFIX_LIST_OUT_NAME(filter
)) {
1439 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1441 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1448 if (FILTER_LIST_OUT_NAME(filter
)) {
1449 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1451 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1452 == AS_FILTER_DENY
) {
1458 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1459 char pfxprint
[PREFIX2STR_BUFFER
];
1461 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1462 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1463 ret
== FILTER_PERMIT
? "permit" : "deny");
1468 #undef FILTER_EXIST_WARN
1471 /* If community attribute includes no_export then return 1. */
1472 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1474 if (attr
->community
) {
1475 /* NO_ADVERTISE check. */
1476 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1479 /* NO_EXPORT check. */
1480 if (peer
->sort
== BGP_PEER_EBGP
1481 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1484 /* NO_EXPORT_SUBCONFED check. */
1485 if (peer
->sort
== BGP_PEER_EBGP
1486 || peer
->sort
== BGP_PEER_CONFED
)
1487 if (community_include(attr
->community
,
1488 COMMUNITY_NO_EXPORT_SUBCONFED
))
1494 /* Route reflection loop check. */
1495 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1497 struct in_addr cluster_id
;
1498 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1501 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1502 cluster_id
= peer
->bgp
->cluster_id
;
1504 cluster_id
= peer
->bgp
->router_id
;
1506 if (cluster_loop_check(cluster
, cluster_id
))
1512 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1513 struct attr
*attr
, afi_t afi
, safi_t safi
,
1514 const char *rmap_name
, mpls_label_t
*label
,
1515 uint32_t num_labels
, struct bgp_dest
*dest
)
1517 struct bgp_filter
*filter
;
1518 struct bgp_path_info rmap_path
= { 0 };
1519 struct bgp_path_info_extra extra
= { 0 };
1520 route_map_result_t ret
;
1521 struct route_map
*rmap
= NULL
;
1523 filter
= &peer
->filter
[afi
][safi
];
1525 /* Apply default weight value. */
1526 if (peer
->weight
[afi
][safi
])
1527 attr
->weight
= peer
->weight
[afi
][safi
];
1530 rmap
= route_map_lookup_by_name(rmap_name
);
1535 if (ROUTE_MAP_IN_NAME(filter
)) {
1536 rmap
= ROUTE_MAP_IN(filter
);
1543 /* Route map apply. */
1545 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1546 /* Duplicate current value to new strucutre for modification. */
1547 rmap_path
.peer
= peer
;
1548 rmap_path
.attr
= attr
;
1549 rmap_path
.extra
= &extra
;
1550 rmap_path
.net
= dest
;
1552 extra
.num_labels
= num_labels
;
1553 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1554 memcpy(extra
.label
, label
,
1555 num_labels
* sizeof(mpls_label_t
));
1557 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1559 /* Apply BGP route map to the attribute. */
1560 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1562 peer
->rmap_type
= 0;
1564 if (ret
== RMAP_DENYMATCH
)
1570 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1571 struct attr
*attr
, afi_t afi
, safi_t safi
,
1572 const char *rmap_name
)
1574 struct bgp_path_info rmap_path
;
1575 route_map_result_t ret
;
1576 struct route_map
*rmap
= NULL
;
1580 * So if we get to this point and have no rmap_name
1581 * we want to just show the output as it currently
1587 /* Apply default weight value. */
1588 if (peer
->weight
[afi
][safi
])
1589 attr
->weight
= peer
->weight
[afi
][safi
];
1591 rmap
= route_map_lookup_by_name(rmap_name
);
1594 * If we have a route map name and we do not find
1595 * the routemap that means we have an implicit
1601 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1602 /* Route map apply. */
1603 /* Duplicate current value to new strucutre for modification. */
1604 rmap_path
.peer
= peer
;
1605 rmap_path
.attr
= attr
;
1607 rmap_type
= peer
->rmap_type
;
1608 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1610 /* Apply BGP route map to the attribute. */
1611 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1613 peer
->rmap_type
= rmap_type
;
1615 if (ret
== RMAP_DENYMATCH
)
1617 * caller has multiple error paths with bgp_attr_flush()
1624 /* If this is an EBGP peer with remove-private-AS */
1625 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1626 struct peer
*peer
, struct attr
*attr
)
1628 if (peer
->sort
== BGP_PEER_EBGP
1629 && (peer_af_flag_check(peer
, afi
, safi
,
1630 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1631 || peer_af_flag_check(peer
, afi
, safi
,
1632 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1633 || peer_af_flag_check(peer
, afi
, safi
,
1634 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1635 || peer_af_flag_check(peer
, afi
, safi
,
1636 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1637 // Take action on the entire aspath
1638 if (peer_af_flag_check(peer
, afi
, safi
,
1639 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1640 || peer_af_flag_check(peer
, afi
, safi
,
1641 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1642 if (peer_af_flag_check(
1644 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1645 attr
->aspath
= aspath_replace_private_asns(
1646 attr
->aspath
, bgp
->as
, peer
->as
);
1648 // The entire aspath consists of private ASNs so create
1650 else if (aspath_private_as_check(attr
->aspath
))
1651 attr
->aspath
= aspath_empty_get();
1653 // There are some public and some private ASNs, remove
1656 attr
->aspath
= aspath_remove_private_asns(
1657 attr
->aspath
, peer
->as
);
1660 // 'all' was not specified so the entire aspath must be private
1662 // for us to do anything
1663 else if (aspath_private_as_check(attr
->aspath
)) {
1664 if (peer_af_flag_check(
1666 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1667 attr
->aspath
= aspath_replace_private_asns(
1668 attr
->aspath
, bgp
->as
, peer
->as
);
1670 attr
->aspath
= aspath_empty_get();
1675 /* If this is an EBGP peer with as-override */
1676 static void bgp_peer_as_override(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
, PEER_FLAG_AS_OVERRIDE
)) {
1681 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1682 attr
->aspath
= aspath_replace_specific_asn(
1683 attr
->aspath
, peer
->as
, bgp
->as
);
1687 void bgp_attr_add_gshut_community(struct attr
*attr
)
1689 struct community
*old
;
1690 struct community
*new;
1691 struct community
*merge
;
1692 struct community
*gshut
;
1694 old
= attr
->community
;
1695 gshut
= community_str2com("graceful-shutdown");
1700 merge
= community_merge(community_dup(old
), gshut
);
1702 if (old
->refcnt
== 0)
1703 community_free(&old
);
1705 new = community_uniq_sort(merge
);
1706 community_free(&merge
);
1708 new = community_dup(gshut
);
1711 community_free(&gshut
);
1712 attr
->community
= new;
1713 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1715 /* When we add the graceful-shutdown community we must also
1716 * lower the local-preference */
1717 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1718 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1722 /* Notify BGP Conditional advertisement scanner process. */
1723 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1725 struct peer
*temp_peer
;
1726 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1727 struct listnode
*temp_node
, *temp_nnode
= NULL
;
1728 afi_t afi
= SUBGRP_AFI(subgrp
);
1729 safi_t safi
= SUBGRP_SAFI(subgrp
);
1730 struct bgp
*bgp
= SUBGRP_INST(subgrp
);
1731 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1733 if (!ADVERTISE_MAP_NAME(filter
))
1736 for (ALL_LIST_ELEMENTS(bgp
->peer
, temp_node
, temp_nnode
, temp_peer
)) {
1737 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1740 if (peer
!= temp_peer
)
1743 temp_peer
->advmap_table_change
= true;
1749 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1751 if (family
== AF_INET
) {
1752 attr
->nexthop
.s_addr
= INADDR_ANY
;
1753 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1755 if (family
== AF_INET6
)
1756 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1757 if (family
== AF_EVPN
)
1758 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1761 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1762 struct update_subgroup
*subgrp
,
1763 const struct prefix
*p
, struct attr
*attr
,
1764 bool skip_rmap_check
)
1766 struct bgp_filter
*filter
;
1769 struct peer
*onlypeer
;
1771 struct attr
*piattr
;
1772 route_map_result_t ret
;
1777 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1778 bool nh_reset
= false;
1781 if (DISABLE_BGP_ANNOUNCE
)
1784 afi
= SUBGRP_AFI(subgrp
);
1785 safi
= SUBGRP_SAFI(subgrp
);
1786 peer
= SUBGRP_PEER(subgrp
);
1788 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1789 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1792 filter
= &peer
->filter
[afi
][safi
];
1793 bgp
= SUBGRP_INST(subgrp
);
1794 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1797 #ifdef ENABLE_BGP_VNC
1798 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1799 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1800 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1803 * direct and direct_ext type routes originate internally even
1804 * though they can have peer pointers that reference other
1807 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1813 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1814 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1815 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1816 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1818 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1823 /* With addpath we may be asked to TX all kinds of paths so make sure
1825 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1826 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1827 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1831 /* If this is not the bestpath then check to see if there is an enabled
1833 * feature that requires us to advertise it */
1834 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1835 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1840 /* Aggregate-address suppress check. */
1841 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
1845 * If we are doing VRF 2 VRF leaking via the import
1846 * statement, we want to prevent the route going
1847 * off box as that the RT and RD created are localy
1848 * significant and globaly useless.
1850 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1851 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1854 /* If it's labeled safi, make sure the route has a valid label. */
1855 if (safi
== SAFI_LABELED_UNICAST
) {
1856 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1857 if (!bgp_is_valid_label(&label
)) {
1858 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1859 zlog_debug("u%" PRIu64
":s%" PRIu64
1860 " %pFX is filtered - no label (%p)",
1861 subgrp
->update_group
->id
, subgrp
->id
,
1867 /* Do not send back route to sender. */
1868 if (onlypeer
&& from
== onlypeer
) {
1872 /* Do not send the default route in the BGP table if the neighbor is
1873 * configured for default-originate */
1874 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1875 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1876 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1878 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1882 /* Transparency check. */
1883 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1884 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1889 /* If community is not disabled check the no-export and local. */
1890 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1891 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1892 zlog_debug("%s: community filter check fail for %pFX",
1897 /* If the attribute has originator-id and it is same as remote
1899 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1900 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1901 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1903 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1908 /* ORF prefix-list filter check */
1909 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1910 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1911 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1912 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1913 if (peer
->orf_plist
[afi
][safi
]) {
1914 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1916 if (bgp_debug_update(NULL
, p
,
1917 subgrp
->update_group
, 0))
1919 "%s [Update:SEND] %pFX is filtered via ORF",
1925 /* Output filter check. */
1926 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1927 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1928 zlog_debug("%s [Update:SEND] %pFX is filtered",
1933 /* AS path loop check. */
1934 if (onlypeer
&& onlypeer
->as_path_loop_detection
1935 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1936 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1938 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1939 onlypeer
->host
, onlypeer
->as
);
1943 /* If we're a CONFED we need to loop check the CONFED ID too */
1944 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1945 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1946 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1948 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1949 peer
->host
, bgp
->confed_id
);
1954 /* Route-Reflect check. */
1955 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1960 /* IBGP reflection check. */
1961 if (reflect
&& !samepeer_safe
) {
1962 /* A route from a Client peer. */
1963 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1964 PEER_FLAG_REFLECTOR_CLIENT
)) {
1965 /* Reflect to all the Non-Client peers and also to the
1966 Client peers other than the originator. Originator
1968 is already done. So there is noting to do. */
1969 /* no bgp client-to-client reflection check. */
1970 if (CHECK_FLAG(bgp
->flags
,
1971 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1972 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1973 PEER_FLAG_REFLECTOR_CLIENT
))
1976 /* A route from a Non-client peer. Reflect to all other
1978 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1979 PEER_FLAG_REFLECTOR_CLIENT
))
1984 /* For modify attribute, copy it to temporary structure. */
1987 /* If local-preference is not set. */
1988 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1989 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1990 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1991 attr
->local_pref
= bgp
->default_local_pref
;
1994 /* If originator-id is not set and the route is to be reflected,
1995 set the originator id */
1997 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1998 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1999 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2002 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2004 if (peer
->sort
== BGP_PEER_EBGP
2005 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2006 if (from
!= bgp
->peer_self
&& !transparent
2007 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2008 PEER_FLAG_MED_UNCHANGED
))
2010 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2013 /* Since the nexthop attribute can vary per peer, it is not explicitly
2015 * in announce check, only certain flags and length (or number of
2017 * -- for IPv6/MP_REACH) are set here in order to guide the update
2019 * code in setting the nexthop(s) on a per peer basis in
2021 * Typically, the source nexthop in the attribute is preserved but in
2023 * scenarios where we know it will always be overwritten, we reset the
2024 * nexthop to "0" in an attempt to achieve better Update packing. An
2025 * example of this is when a prefix from each of 2 IBGP peers needs to
2027 * announced to an EBGP peer (and they have the same attributes barring
2031 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2033 #define NEXTHOP_IS_V6 \
2034 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2035 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2036 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2037 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2039 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2041 * the peer (group) is configured to receive link-local nexthop
2043 * and it is available in the prefix OR we're not reflecting the route,
2044 * link-local nexthop address is valid and
2045 * the peer (group) to whom we're going to announce is on a shared
2047 * and this is either a self-originated route or the peer is EBGP.
2048 * By checking if nexthop LL address is valid we are sure that
2049 * we do not announce LL address as `::`.
2051 if (NEXTHOP_IS_V6
) {
2052 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2053 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2054 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2055 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2057 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2058 && peer
->shared_network
2059 && (from
== bgp
->peer_self
2060 || peer
->sort
== BGP_PEER_EBGP
))) {
2061 attr
->mp_nexthop_len
=
2062 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2065 /* Clear off link-local nexthop in source, whenever it is not
2067 * ensure more prefixes share the same attribute for
2070 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2071 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2072 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2075 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2076 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2078 /* Route map & unsuppress-map apply. */
2079 if (!skip_rmap_check
2080 && (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2081 struct bgp_path_info rmap_path
= {0};
2082 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2083 struct attr dummy_attr
= {0};
2085 /* Fill temp path_info */
2086 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2089 /* don't confuse inbound and outbound setting */
2090 RESET_FLAG(attr
->rmap_change_flags
);
2093 * The route reflector is not allowed to modify the attributes
2094 * of the reflected IBGP routes unless explicitly allowed.
2096 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2097 && !CHECK_FLAG(bgp
->flags
,
2098 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2100 rmap_path
.attr
= &dummy_attr
;
2103 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2105 if (bgp_path_suppressed(pi
))
2106 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2109 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2112 peer
->rmap_type
= 0;
2114 if (ret
== RMAP_DENYMATCH
) {
2115 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2117 "%s [Update:SEND] %pFX is filtered by route-map",
2120 bgp_attr_flush(attr
);
2125 /* RFC 8212 to prevent route leaks.
2126 * This specification intends to improve this situation by requiring the
2127 * explicit configuration of both BGP Import and Export Policies for any
2128 * External BGP (EBGP) session such as customers, peers, or
2129 * confederation boundaries for all enabled address families. Through
2130 * codification of the aforementioned requirement, operators will
2131 * benefit from consistent behavior across different BGP
2134 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2135 if (!bgp_outbound_policy_exists(peer
, filter
))
2138 /* draft-ietf-idr-deprecate-as-set-confed-set
2139 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2140 * Eventually, This document (if approved) updates RFC 4271
2141 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2142 * and obsoletes RFC 6472.
2144 if (peer
->bgp
->reject_as_sets
)
2145 if (aspath_check_as_sets(attr
->aspath
))
2148 /* Codification of AS 0 Processing */
2149 if (aspath_check_as_zero(attr
->aspath
))
2152 if (bgp_in_graceful_shutdown(bgp
)) {
2153 if (peer
->sort
== BGP_PEER_IBGP
2154 || peer
->sort
== BGP_PEER_CONFED
) {
2155 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2156 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2158 bgp_attr_add_gshut_community(attr
);
2162 /* After route-map has been applied, we check to see if the nexthop to
2163 * be carried in the attribute (that is used for the announcement) can
2164 * be cleared off or not. We do this in all cases where we would be
2165 * setting the nexthop to "ourselves". For IPv6, we only need to
2167 * the global nexthop here; the link-local nexthop would have been
2169 * already, and if not, it is required by the update formation code.
2170 * Also see earlier comments in this function.
2173 * If route-map has performed some operation on the nexthop or the peer
2174 * configuration says to pass it unchanged, we cannot reset the nexthop
2175 * here, so only attempt to do it if these aren't true. Note that the
2176 * route-map handler itself might have cleared the nexthop, if for
2178 * it is configured as 'peer-address'.
2180 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2181 piattr
->rmap_change_flags
)
2183 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2184 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2185 /* We can reset the nexthop, if setting (or forcing) it to
2187 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2188 PEER_FLAG_NEXTHOP_SELF
)
2189 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2190 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2192 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2193 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2194 subgroup_announce_reset_nhop(
2195 (peer_cap_enhe(peer
, afi
, safi
)
2201 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2202 /* Can also reset the nexthop if announcing to EBGP, but
2204 * no peer in the subgroup is on a shared subnet.
2205 * Note: 3rd party nexthop currently implemented for
2208 if ((p
->family
== AF_INET
) &&
2209 (!bgp_subgrp_multiaccess_check_v4(
2212 subgroup_announce_reset_nhop(
2213 (peer_cap_enhe(peer
, afi
, safi
)
2220 if ((p
->family
== AF_INET6
) &&
2221 (!bgp_subgrp_multiaccess_check_v6(
2222 piattr
->mp_nexthop_global
,
2224 subgroup_announce_reset_nhop(
2225 (peer_cap_enhe(peer
, afi
, safi
)
2234 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2236 * This flag is used for leaked vpn-vrf routes
2238 int family
= p
->family
;
2240 if (peer_cap_enhe(peer
, afi
, safi
))
2243 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2245 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2246 __func__
, family2str(family
));
2247 subgroup_announce_reset_nhop(family
, attr
);
2252 /* If IPv6/MP and nexthop does not have any override and happens
2254 * be a link-local address, reset it so that we don't pass along
2256 * source's link-local IPv6 address to recipients who may not be
2258 * the same interface.
2260 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2261 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2262 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2268 * When the next hop is set to ourselves, if all multipaths have
2269 * link-bandwidth announce the cumulative bandwidth as that makes
2270 * the most sense. However, don't modify if the link-bandwidth has
2271 * been explicitly set by user policy.
2274 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2275 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2276 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2277 attr
->ecommunity
= ecommunity_replace_linkbw(
2278 bgp
->as
, attr
->ecommunity
, cum_bw
);
2283 static int bgp_route_select_timer_expire(struct thread
*thread
)
2285 struct afi_safi_info
*info
;
2290 info
= THREAD_ARG(thread
);
2295 if (BGP_DEBUG(update
, UPDATE_OUT
))
2296 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2299 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2301 XFREE(MTYPE_TMP
, info
);
2303 /* Best path selection */
2304 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2307 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2308 struct bgp_maxpaths_cfg
*mpath_cfg
,
2309 struct bgp_path_info_pair
*result
, afi_t afi
,
2312 struct bgp_path_info
*new_select
;
2313 struct bgp_path_info
*old_select
;
2314 struct bgp_path_info
*pi
;
2315 struct bgp_path_info
*pi1
;
2316 struct bgp_path_info
*pi2
;
2317 struct bgp_path_info
*nextpi
= NULL
;
2318 int paths_eq
, do_mpath
, debug
;
2319 struct list mp_list
;
2320 char pfx_buf
[PREFIX2STR_BUFFER
];
2321 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2323 bgp_mp_list_init(&mp_list
);
2325 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2327 debug
= bgp_debug_bestpath(dest
);
2330 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2332 dest
->reason
= bgp_path_selection_none
;
2333 /* bgp deterministic-med */
2335 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2337 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2338 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2340 bgp_path_info_unset_flag(dest
, pi1
,
2341 BGP_PATH_DMED_SELECTED
);
2343 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2345 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2347 if (BGP_PATH_HOLDDOWN(pi1
))
2349 if (pi1
->peer
!= bgp
->peer_self
)
2350 if (!peer_established(pi1
->peer
))
2355 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2356 if (CHECK_FLAG(pi2
->flags
,
2357 BGP_PATH_DMED_CHECK
))
2359 if (BGP_PATH_HOLDDOWN(pi2
))
2361 if (pi2
->peer
!= bgp
->peer_self
2364 PEER_STATUS_NSF_WAIT
))
2365 if (pi2
->peer
->status
2369 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2371 && !aspath_cmp_left_confed(
2376 if (bgp_path_info_cmp(
2377 bgp
, pi2
, new_select
,
2378 &paths_eq
, mpath_cfg
, debug
,
2381 bgp_path_info_unset_flag(
2383 BGP_PATH_DMED_SELECTED
);
2387 bgp_path_info_set_flag(
2388 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2391 bgp_path_info_set_flag(dest
, new_select
,
2392 BGP_PATH_DMED_CHECK
);
2393 bgp_path_info_set_flag(dest
, new_select
,
2394 BGP_PATH_DMED_SELECTED
);
2397 bgp_path_info_path_with_addpath_rx_str(
2398 new_select
, path_buf
, sizeof(path_buf
));
2400 "%pBD: %s is the bestpath from AS %u",
2402 aspath_get_first_as(
2403 new_select
->attr
->aspath
));
2408 /* Check old selected route and new selected route. */
2411 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2412 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2413 enum bgp_path_selection_reason reason
;
2415 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2418 if (BGP_PATH_HOLDDOWN(pi
)) {
2419 /* reap REMOVED routes, if needs be
2420 * selected route must stay for a while longer though
2422 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2423 && (pi
!= old_select
))
2424 bgp_path_info_reap(dest
, pi
);
2427 zlog_debug("%s: pi %p in holddown", __func__
,
2433 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2434 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2435 if (!peer_established(pi
->peer
)) {
2439 "%s: pi %p non self peer %s not estab state",
2440 __func__
, pi
, pi
->peer
->host
);
2445 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2446 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2447 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2449 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2453 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2455 reason
= dest
->reason
;
2456 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2457 debug
, pfx_buf
, afi
, safi
,
2459 if (new_select
== NULL
&&
2460 reason
!= bgp_path_selection_none
)
2461 dest
->reason
= reason
;
2466 /* Now that we know which path is the bestpath see if any of the other
2468 * qualify as multipaths
2472 bgp_path_info_path_with_addpath_rx_str(
2473 new_select
, path_buf
, sizeof(path_buf
));
2475 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2477 "%pBD: After path selection, newbest is %s oldbest was %s",
2479 old_select
? old_select
->peer
->host
: "NONE");
2482 if (do_mpath
&& new_select
) {
2483 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2484 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2487 bgp_path_info_path_with_addpath_rx_str(
2488 pi
, path_buf
, sizeof(path_buf
));
2490 if (pi
== new_select
) {
2493 "%pBD: %s is the bestpath, add to the multipath list",
2495 bgp_mp_list_add(&mp_list
, pi
);
2499 if (BGP_PATH_HOLDDOWN(pi
))
2502 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2503 && !CHECK_FLAG(pi
->peer
->sflags
,
2504 PEER_STATUS_NSF_WAIT
))
2505 if (!peer_established(pi
->peer
))
2508 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2511 "%pBD: %s has the same nexthop as the bestpath, skip it",
2516 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2517 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2523 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2525 bgp_mp_list_add(&mp_list
, pi
);
2530 bgp_path_info_mpath_update(dest
, new_select
, old_select
, &mp_list
,
2532 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2533 bgp_mp_list_clear(&mp_list
);
2535 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2537 result
->old
= old_select
;
2538 result
->new = new_select
;
2544 * A new route/change in bestpath of an existing route. Evaluate the path
2545 * for advertisement to the subgroup.
2547 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2548 struct bgp_path_info
*selected
,
2549 struct bgp_dest
*dest
,
2550 uint32_t addpath_tx_id
)
2552 const struct prefix
*p
;
2553 struct peer
*onlypeer
;
2560 p
= bgp_dest_get_prefix(dest
);
2561 afi
= SUBGRP_AFI(subgrp
);
2562 safi
= SUBGRP_SAFI(subgrp
);
2563 bgp
= SUBGRP_INST(subgrp
);
2564 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2567 if (BGP_DEBUG(update
, UPDATE_OUT
))
2568 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2570 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2571 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2572 PEER_STATUS_ORF_WAIT_REFRESH
))
2575 memset(&attr
, 0, sizeof(struct attr
));
2576 /* It's initialized in bgp_announce_check() */
2578 /* Announcement to the subgroup. If the route is filtered withdraw it.
2579 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2580 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2583 advertise
= bgp_check_advertise(bgp
, dest
);
2586 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2588 /* Route is selected, if the route is already installed
2589 * in FIB, then it is advertised
2592 bgp_adj_out_set_subgroup(dest
, subgrp
, &attr
,
2595 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2599 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2601 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2606 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2607 * This is called at the end of route processing.
2609 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2611 struct bgp_path_info
*pi
;
2613 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2614 if (BGP_PATH_HOLDDOWN(pi
))
2616 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2617 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2622 * Has the route changed from the RIB's perspective? This is invoked only
2623 * if the route selection returns the same best route as earlier - to
2624 * determine if we need to update zebra or not.
2626 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2628 struct bgp_path_info
*mpinfo
;
2630 /* If this is multipath, check all selected paths for any nexthop
2631 * change or attribute change. Some attribute changes (e.g., community)
2632 * aren't of relevance to the RIB, but we'll update zebra to ensure
2633 * we handle the case of BGP nexthop change. This is the behavior
2634 * when the best path has an attribute change anyway.
2636 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2637 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2638 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2642 * If this is multipath, check all selected paths for any nexthop change
2644 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2645 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2646 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2647 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2651 /* Nothing has changed from the RIB's perspective. */
2655 struct bgp_process_queue
{
2657 STAILQ_HEAD(, bgp_dest
) pqueue
;
2658 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2660 unsigned int queued
;
2663 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2664 safi_t safi
, struct bgp_dest
*dest
,
2665 struct bgp_path_info
*new_select
,
2666 struct bgp_path_info
*old_select
)
2668 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2670 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2673 if (advertise_type5_routes(bgp
, afi
) && new_select
2674 && is_route_injectable_into_evpn(new_select
)) {
2676 /* apply the route-map */
2677 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2678 route_map_result_t ret
;
2679 struct bgp_path_info rmap_path
;
2680 struct bgp_path_info_extra rmap_path_extra
;
2681 struct attr dummy_attr
;
2683 dummy_attr
= *new_select
->attr
;
2685 /* Fill temp path_info */
2686 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2687 new_select
, new_select
->peer
,
2690 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2692 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2695 if (ret
== RMAP_DENYMATCH
) {
2696 bgp_attr_flush(&dummy_attr
);
2697 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2700 bgp_evpn_advertise_type5_route(
2701 bgp
, p
, &dummy_attr
, afi
, safi
);
2703 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2706 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2707 && is_route_injectable_into_evpn(old_select
))
2708 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2712 * old_select = The old best path
2713 * new_select = the new best path
2715 * if (!old_select && new_select)
2716 * We are sending new information on.
2718 * if (old_select && new_select) {
2719 * if (new_select != old_select)
2720 * We have a new best path send a change
2722 * We've received a update with new attributes that needs
2726 * if (old_select && !new_select)
2727 * We have no eligible route that we can announce or the rn
2730 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2731 afi_t afi
, safi_t safi
)
2733 struct bgp_path_info
*new_select
;
2734 struct bgp_path_info
*old_select
;
2735 struct bgp_path_info_pair old_and_new
;
2738 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2740 debug
= bgp_debug_bestpath(dest
);
2743 "%s: bgp delete in progress, ignoring event, p=%pBD",
2747 /* Is it end of initial update? (after startup) */
2749 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2750 sizeof(bgp
->update_delay_zebra_resume_time
));
2752 bgp
->main_zebra_update_hold
= 0;
2753 FOREACH_AFI_SAFI (afi
, safi
) {
2754 if (bgp_fibupd_safi(safi
))
2755 bgp_zebra_announce_table(bgp
, afi
, safi
);
2757 bgp
->main_peers_update_hold
= 0;
2759 bgp_start_routeadv(bgp
);
2763 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2765 debug
= bgp_debug_bestpath(dest
);
2767 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__
, dest
,
2768 afi2str(afi
), safi2str(safi
));
2770 /* The best path calculation for the route is deferred if
2771 * BGP_NODE_SELECT_DEFER is set
2773 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2774 if (BGP_DEBUG(update
, UPDATE_OUT
))
2775 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
2779 /* Best path selection. */
2780 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2782 old_select
= old_and_new
.old
;
2783 new_select
= old_and_new
.new;
2785 /* Do we need to allocate or free labels?
2786 * Right now, since we only deal with per-prefix labels, it is not
2787 * necessary to do this upon changes to best path. Exceptions:
2788 * - label index has changed -> recalculate resulting label
2789 * - path_info sub_type changed -> switch to/from implicit-null
2790 * - no valid label (due to removed static label binding) -> get new one
2792 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2795 || bgp_label_index_differs(new_select
, old_select
)
2796 || new_select
->sub_type
!= old_select
->sub_type
2797 || !bgp_is_valid_label(&dest
->local_label
)) {
2798 /* Enforced penultimate hop popping:
2799 * implicit-null for local routes, aggregate
2800 * and redistributed routes
2802 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2803 || new_select
->sub_type
2804 == BGP_ROUTE_AGGREGATE
2805 || new_select
->sub_type
2806 == BGP_ROUTE_REDISTRIBUTE
) {
2809 BGP_NODE_REGISTERED_FOR_LABEL
)
2812 BGP_NODE_LABEL_REQUESTED
))
2813 bgp_unregister_for_label(dest
);
2814 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2815 &dest
->local_label
);
2816 bgp_set_valid_label(&dest
->local_label
);
2818 bgp_register_for_label(dest
,
2821 } else if (CHECK_FLAG(dest
->flags
,
2822 BGP_NODE_REGISTERED_FOR_LABEL
)
2823 || CHECK_FLAG(dest
->flags
,
2824 BGP_NODE_LABEL_REQUESTED
)) {
2825 bgp_unregister_for_label(dest
);
2827 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
2828 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
2829 bgp_unregister_for_label(dest
);
2834 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
2835 __func__
, dest
, afi2str(afi
), safi2str(safi
),
2836 old_select
, new_select
);
2838 /* If best route remains the same and this is not due to user-initiated
2839 * clear, see exactly what needs to be done.
2841 if (old_select
&& old_select
== new_select
2842 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2843 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2844 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2845 if (bgp_zebra_has_route_changed(old_select
)) {
2846 #ifdef ENABLE_BGP_VNC
2847 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2848 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2850 if (bgp_fibupd_safi(safi
)
2851 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2853 if (new_select
->type
== ZEBRA_ROUTE_BGP
2854 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2855 || new_select
->sub_type
2856 == BGP_ROUTE_IMPORTED
))
2858 bgp_zebra_announce(dest
, p
, old_select
,
2863 /* If there is a change of interest to peers, reannounce the
2865 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2866 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2867 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2868 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2870 /* unicast routes must also be annouced to
2871 * labeled-unicast update-groups */
2872 if (safi
== SAFI_UNICAST
)
2873 group_announce_route(bgp
, afi
,
2874 SAFI_LABELED_UNICAST
, dest
,
2877 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2878 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
2881 /* advertise/withdraw type-5 routes */
2882 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2883 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
2884 bgp_process_evpn_route_injection(
2885 bgp
, afi
, safi
, dest
, old_select
, old_select
);
2887 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2888 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2889 bgp_zebra_clear_route_change_flags(dest
);
2890 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2894 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2896 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
2898 /* bestpath has changed; bump version */
2899 if (old_select
|| new_select
) {
2900 bgp_bump_version(dest
);
2902 if (!bgp
->t_rmap_def_originate_eval
) {
2906 update_group_refresh_default_originate_route_map
,
2907 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2908 &bgp
->t_rmap_def_originate_eval
);
2913 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
2916 zlog_debug("%s: setting SELECTED flag", __func__
);
2917 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
2918 bgp_path_info_unset_flag(dest
, new_select
,
2919 BGP_PATH_ATTR_CHANGED
);
2920 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2921 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2924 #ifdef ENABLE_BGP_VNC
2925 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2926 if (old_select
!= new_select
) {
2928 vnc_import_bgp_exterior_del_route(bgp
, p
,
2930 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2933 vnc_import_bgp_exterior_add_route(bgp
, p
,
2935 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2941 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2943 /* unicast routes must also be annouced to labeled-unicast update-groups
2945 if (safi
== SAFI_UNICAST
)
2946 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
2950 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2951 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2952 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2953 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2954 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2955 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2957 /* if this is an evpn imported type-5 prefix,
2958 * we need to withdraw the route first to clear
2959 * the nh neigh and the RMAC entry.
2962 is_route_parent_evpn(old_select
))
2963 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2965 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
2967 /* Withdraw the route from the kernel. */
2968 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2969 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2970 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2971 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2973 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2977 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
2980 /* Clear any route change flags. */
2981 bgp_zebra_clear_route_change_flags(dest
);
2983 /* Reap old select bgp_path_info, if it has been removed */
2984 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2985 bgp_path_info_reap(dest
, old_select
);
2987 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2991 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2992 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2994 struct bgp_dest
*dest
;
2996 struct afi_safi_info
*thread_info
;
2998 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
2999 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3001 thread_info
= THREAD_ARG(t
);
3002 XFREE(MTYPE_TMP
, thread_info
);
3003 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3006 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3007 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3008 get_afi_safi_str(afi
, safi
, false),
3009 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3012 /* Process the route list */
3013 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3014 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0;
3015 dest
= bgp_route_next(dest
)) {
3016 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3019 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3020 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3021 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3023 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
) {
3024 bgp_dest_unlock_node(dest
);
3029 /* Send EOR message when all routes are processed */
3030 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3031 bgp_send_delayed_eor(bgp
);
3032 /* Send route processing complete message to RIB */
3033 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3034 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3038 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3040 thread_info
->afi
= afi
;
3041 thread_info
->safi
= safi
;
3042 thread_info
->bgp
= bgp
;
3044 /* If there are more routes to be processed, start the
3047 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3048 BGP_ROUTE_SELECT_DELAY
,
3049 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3053 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3055 struct bgp_process_queue
*pqnode
= data
;
3056 struct bgp
*bgp
= pqnode
->bgp
;
3057 struct bgp_table
*table
;
3058 struct bgp_dest
*dest
;
3061 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3062 bgp_process_main_one(bgp
, NULL
, 0, 0);
3063 /* should always have dedicated wq call */
3064 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3068 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3069 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3070 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3071 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3072 table
= bgp_dest_table(dest
);
3073 /* note, new DESTs may be added as part of processing */
3074 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3076 bgp_dest_unlock_node(dest
);
3077 bgp_table_unlock(table
);
3083 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3085 struct bgp_process_queue
*pqnode
= data
;
3087 bgp_unlock(pqnode
->bgp
);
3089 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3092 void bgp_process_queue_init(struct bgp
*bgp
)
3094 if (!bgp
->process_queue
) {
3097 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3098 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3101 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3102 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3103 bgp
->process_queue
->spec
.max_retries
= 0;
3104 bgp
->process_queue
->spec
.hold
= 50;
3105 /* Use a higher yield value of 50ms for main queue processing */
3106 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3109 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3111 struct bgp_process_queue
*pqnode
;
3113 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3114 sizeof(struct bgp_process_queue
));
3116 /* unlocked in bgp_processq_del */
3117 pqnode
->bgp
= bgp_lock(bgp
);
3118 STAILQ_INIT(&pqnode
->pqueue
);
3123 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3125 #define ARBITRARY_PROCESS_QLEN 10000
3126 struct work_queue
*wq
= bgp
->process_queue
;
3127 struct bgp_process_queue
*pqnode
;
3128 int pqnode_reuse
= 0;
3130 /* already scheduled for processing? */
3131 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3134 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3137 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3138 if (BGP_DEBUG(update
, UPDATE_OUT
))
3139 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3147 /* Add route nodes to an existing work queue item until reaching the
3148 limit only if is from the same BGP view and it's not an EOIU marker
3150 if (work_queue_item_count(wq
)) {
3151 struct work_queue_item
*item
= work_queue_last_item(wq
);
3152 pqnode
= item
->data
;
3154 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3155 || pqnode
->bgp
!= bgp
3156 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3157 pqnode
= bgp_processq_alloc(bgp
);
3161 pqnode
= bgp_processq_alloc(bgp
);
3162 /* all unlocked in bgp_process_wq */
3163 bgp_table_lock(bgp_dest_table(dest
));
3165 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3166 bgp_dest_lock_node(dest
);
3168 /* can't be enqueued twice */
3169 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3170 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3174 work_queue_add(wq
, pqnode
);
3179 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3181 struct bgp_process_queue
*pqnode
;
3183 if (bgp
->process_queue
== NULL
)
3186 pqnode
= bgp_processq_alloc(bgp
);
3188 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3189 work_queue_add(bgp
->process_queue
, pqnode
);
3192 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3196 peer
= THREAD_ARG(thread
);
3197 peer
->t_pmax_restart
= NULL
;
3199 if (bgp_debug_neighbor_events(peer
))
3201 "%s Maximum-prefix restart timer expired, restore peering",
3204 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3205 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3210 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3214 bool filtered
= false;
3215 struct bgp_dest
*dest
;
3216 struct bgp_adj_in
*ain
;
3217 struct attr attr
= {};
3218 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3220 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3221 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3222 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3226 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3230 if (bgp_input_modifier(
3231 peer
, rn_p
, &attr
, afi
, safi
,
3232 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3240 bgp_attr_undup(&attr
, ain
->attr
);
3247 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3251 iana_safi_t pkt_safi
;
3252 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3253 PEER_FLAG_MAX_PREFIX_FORCE
))
3254 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3255 + peer
->pcount
[afi
][safi
]
3256 : peer
->pcount
[afi
][safi
];
3258 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3261 if (pcount
> peer
->pmax
[afi
][safi
]) {
3262 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3263 PEER_STATUS_PREFIX_LIMIT
)
3268 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3269 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3270 peer
->pmax
[afi
][safi
]);
3271 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3273 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3274 PEER_FLAG_MAX_PREFIX_WARNING
))
3277 /* Convert AFI, SAFI to values for packet. */
3278 pkt_afi
= afi_int2iana(afi
);
3279 pkt_safi
= safi_int2iana(safi
);
3283 ndata
[0] = (pkt_afi
>> 8);
3285 ndata
[2] = pkt_safi
;
3286 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3287 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3288 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3289 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3291 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3292 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3293 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3297 /* Dynamic peers will just close their connection. */
3298 if (peer_dynamic_neighbor(peer
))
3301 /* restart timer start */
3302 if (peer
->pmax_restart
[afi
][safi
]) {
3303 peer
->v_pmax_restart
=
3304 peer
->pmax_restart
[afi
][safi
] * 60;
3306 if (bgp_debug_neighbor_events(peer
))
3308 "%s Maximum-prefix restart timer started for %d secs",
3309 peer
->host
, peer
->v_pmax_restart
);
3311 BGP_TIMER_ON(peer
->t_pmax_restart
,
3312 bgp_maximum_prefix_restart_timer
,
3313 peer
->v_pmax_restart
);
3318 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3319 PEER_STATUS_PREFIX_LIMIT
);
3322 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3323 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3324 PEER_STATUS_PREFIX_THRESHOLD
)
3329 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3330 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3331 peer
->pmax
[afi
][safi
]);
3332 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3333 PEER_STATUS_PREFIX_THRESHOLD
);
3335 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3336 PEER_STATUS_PREFIX_THRESHOLD
);
3340 /* Unconditionally remove the route from the RIB, without taking
3341 * damping into consideration (eg, because the session went down)
3343 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3344 struct peer
*peer
, afi_t afi
, safi_t safi
)
3347 struct bgp
*bgp
= NULL
;
3348 bool delete_route
= false;
3350 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3353 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3354 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3356 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3359 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3360 delete_route
= true;
3361 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3362 delete_route
= true;
3364 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3365 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3366 bgp
= pi
->peer
->bgp
;
3367 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3372 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3373 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3376 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3377 struct peer
*peer
, afi_t afi
, safi_t safi
,
3378 struct prefix_rd
*prd
)
3380 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3382 /* apply dampening, if result is suppressed, we'll be retaining
3383 * the bgp_path_info in the RIB for historical reference.
3385 if (peer
->sort
== BGP_PEER_EBGP
) {
3386 if (get_active_bdc_from_pi(pi
, afi
, safi
)) {
3387 if (bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0)
3388 == BGP_DAMP_SUPPRESSED
) {
3389 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3396 #ifdef ENABLE_BGP_VNC
3397 if (safi
== SAFI_MPLS_VPN
) {
3398 struct bgp_dest
*pdest
= NULL
;
3399 struct bgp_table
*table
= NULL
;
3401 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3402 (struct prefix
*)prd
);
3403 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3404 table
= bgp_dest_get_bgp_table_info(pdest
);
3406 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3407 peer
->bgp
, prd
, table
, p
, pi
);
3409 bgp_dest_unlock_node(pdest
);
3411 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3412 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3414 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3415 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3420 /* If this is an EVPN route, process for un-import. */
3421 if (safi
== SAFI_EVPN
)
3422 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3424 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3427 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3428 struct peer
*peer
, struct attr
*attr
,
3429 struct bgp_dest
*dest
)
3431 struct bgp_path_info
*new;
3433 /* Make new BGP info. */
3434 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3436 new->instance
= instance
;
3437 new->sub_type
= sub_type
;
3440 new->uptime
= bgp_clock();
3445 static void overlay_index_update(struct attr
*attr
,
3446 union gw_addr
*gw_ip
)
3450 if (gw_ip
== NULL
) {
3451 struct bgp_route_evpn eo
;
3453 memset(&eo
, 0, sizeof(eo
));
3454 bgp_attr_set_evpn_overlay(attr
, &eo
);
3456 struct bgp_route_evpn eo
= {.gw_ip
= *gw_ip
};
3458 bgp_attr_set_evpn_overlay(attr
, &eo
);
3462 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3463 union gw_addr
*gw_ip
)
3465 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(path
->attr
);
3466 union gw_addr path_gw_ip
, *path_gw_ip_remote
;
3472 if (afi
!= AFI_L2VPN
)
3475 path_gw_ip
= eo
->gw_ip
;
3477 if (gw_ip
== NULL
) {
3478 memset(&temp
, 0, sizeof(temp
));
3479 path_gw_ip_remote
= &temp
.ip
;
3481 path_gw_ip_remote
= gw_ip
;
3483 return !!memcmp(&path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
));
3486 /* Check if received nexthop is valid or not. */
3487 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3488 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3489 struct bgp_dest
*dest
)
3492 bool is_bgp_static_route
=
3493 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3497 * Only validated for unicast and multicast currently.
3498 * Also valid for EVPN where the nexthop is an IP address.
3499 * If we are a bgp static route being checked then there is
3500 * no need to check to see if the nexthop is martian as
3501 * that it should be ok.
3503 if (is_bgp_static_route
||
3504 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3507 /* If NEXT_HOP is present, validate it. */
3508 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3509 if (attr
->nexthop
.s_addr
== INADDR_ANY
3510 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3511 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3515 /* If MP_NEXTHOP is present, validate it. */
3516 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3517 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3518 * it is not an IPv6 link-local address.
3520 * If we receive an UPDATE with nexthop length set to 32 bytes
3521 * we shouldn't discard an UPDATE if it's set to (::).
3522 * The link-local (2st) is validated along the code path later.
3524 if (attr
->mp_nexthop_len
) {
3525 switch (attr
->mp_nexthop_len
) {
3526 case BGP_ATTR_NHLEN_IPV4
:
3527 case BGP_ATTR_NHLEN_VPNV4
:
3528 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3530 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3531 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3535 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3536 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3537 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3538 &attr
->mp_nexthop_global
)
3539 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3540 || IN6_IS_ADDR_MULTICAST(
3541 &attr
->mp_nexthop_global
)
3542 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3545 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3546 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3547 || IN6_IS_ADDR_MULTICAST(
3548 &attr
->mp_nexthop_global
)
3549 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3562 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3564 struct community
*old
;
3565 struct community
*new;
3566 struct community
*merge
;
3567 struct community
*no_export
;
3569 old
= attr
->community
;
3570 no_export
= community_str2com("no-export");
3575 merge
= community_merge(community_dup(old
), no_export
);
3578 community_free(&old
);
3580 new = community_uniq_sort(merge
);
3581 community_free(&merge
);
3583 new = community_dup(no_export
);
3586 community_free(&no_export
);
3588 attr
->community
= new;
3589 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
3592 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3593 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3594 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3595 uint32_t num_labels
, int soft_reconfig
,
3596 struct bgp_route_evpn
*evpn
)
3599 int aspath_loop_count
= 0;
3600 struct bgp_dest
*dest
;
3602 struct attr new_attr
;
3603 struct attr
*attr_new
;
3604 struct bgp_path_info
*pi
;
3605 struct bgp_path_info
*new;
3606 struct bgp_path_info_extra
*extra
;
3608 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3610 int do_loop_check
= 1;
3611 int has_valid_label
= 0;
3613 uint8_t pi_type
= 0;
3614 uint8_t pi_sub_type
= 0;
3616 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3617 char pfxprint
[PREFIX2STR_BUFFER
];
3619 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3620 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3624 #ifdef ENABLE_BGP_VNC
3625 int vnc_implicit_withdraw
= 0;
3629 memset(&new_attr
, 0, sizeof(struct attr
));
3630 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3631 new_attr
.label
= MPLS_INVALID_LABEL
;
3634 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3635 /* TODO: Check to see if we can get rid of "is_valid_label" */
3636 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3637 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3639 has_valid_label
= bgp_is_valid_label(label
);
3641 if (has_valid_label
)
3642 assert(label
!= NULL
);
3644 /* When peer's soft reconfiguration enabled. Record input packet in
3647 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3648 && peer
!= bgp
->peer_self
)
3649 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3651 /* Check previously received route. */
3652 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3653 if (pi
->peer
== peer
&& pi
->type
== type
3654 && pi
->sub_type
== sub_type
3655 && pi
->addpath_rx_id
== addpath_id
)
3658 /* AS path local-as loop check. */
3659 if (peer
->change_local_as
) {
3660 if (peer
->allowas_in
[afi
][safi
])
3661 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3662 else if (!CHECK_FLAG(peer
->flags
,
3663 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3664 aspath_loop_count
= 1;
3666 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3667 > aspath_loop_count
) {
3668 peer
->stat_pfx_aspath_loop
++;
3669 reason
= "as-path contains our own AS A;";
3674 /* If the peer is configured for "allowas-in origin" and the last ASN in
3676 * as-path is our ASN then we do not need to call aspath_loop_check
3678 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3679 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3682 /* AS path loop check. */
3683 if (do_loop_check
) {
3684 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3685 > peer
->allowas_in
[afi
][safi
]
3686 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3687 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3688 > peer
->allowas_in
[afi
][safi
])) {
3689 peer
->stat_pfx_aspath_loop
++;
3690 reason
= "as-path contains our own AS;";
3695 /* Route reflector originator ID check. */
3696 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3697 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3698 peer
->stat_pfx_originator_loop
++;
3699 reason
= "originator is us;";
3703 /* Route reflector cluster ID check. */
3704 if (bgp_cluster_filter(peer
, attr
)) {
3705 peer
->stat_pfx_cluster_loop
++;
3706 reason
= "reflected from the same cluster;";
3710 /* Apply incoming filter. */
3711 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3712 peer
->stat_pfx_filter
++;
3717 /* RFC 8212 to prevent route leaks.
3718 * This specification intends to improve this situation by requiring the
3719 * explicit configuration of both BGP Import and Export Policies for any
3720 * External BGP (EBGP) session such as customers, peers, or
3721 * confederation boundaries for all enabled address families. Through
3722 * codification of the aforementioned requirement, operators will
3723 * benefit from consistent behavior across different BGP
3726 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3727 if (!bgp_inbound_policy_exists(peer
,
3728 &peer
->filter
[afi
][safi
])) {
3729 reason
= "inbound policy missing";
3733 /* draft-ietf-idr-deprecate-as-set-confed-set
3734 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3735 * Eventually, This document (if approved) updates RFC 4271
3736 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3737 * and obsoletes RFC 6472.
3739 if (peer
->bgp
->reject_as_sets
)
3740 if (aspath_check_as_sets(attr
->aspath
)) {
3742 "as-path contains AS_SET or AS_CONFED_SET type;";
3748 /* Apply incoming route-map.
3749 * NB: new_attr may now contain newly allocated values from route-map
3751 * commands, so we need bgp_attr_flush in the error paths, until we
3753 * the attr (which takes over the memory references) */
3754 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
, label
,
3757 peer
->stat_pfx_filter
++;
3758 reason
= "route-map;";
3759 bgp_attr_flush(&new_attr
);
3763 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3764 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3765 /* remove from RIB previous entry */
3766 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3769 if (peer
->sort
== BGP_PEER_EBGP
) {
3772 * A BGP speaker receiving an announcement tagged with the
3773 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3774 * NO_EXPORT community as defined in RFC1997, or a
3775 * similar community, to prevent propagation of the
3776 * prefix outside the local AS. The community to prevent
3777 * propagation SHOULD be chosen according to the operator's
3780 if (new_attr
.community
3781 && community_include(new_attr
.community
,
3782 COMMUNITY_BLACKHOLE
))
3783 bgp_attr_add_no_export_community(&new_attr
);
3785 /* If we receive the graceful-shutdown community from an eBGP
3786 * peer we must lower local-preference */
3787 if (new_attr
.community
3788 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3789 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3790 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3792 /* If graceful-shutdown is configured then add the GSHUT
3793 * community to all paths received from eBGP peers */
3794 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3795 bgp_attr_add_gshut_community(&new_attr
);
3800 pi_sub_type
= pi
->sub_type
;
3803 /* next hop check. */
3804 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3805 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3807 peer
->stat_pfx_nh_invalid
++;
3808 reason
= "martian or self next-hop;";
3809 bgp_attr_flush(&new_attr
);
3813 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3814 peer
->stat_pfx_nh_invalid
++;
3815 reason
= "self mac;";
3819 /* Update Overlay Index */
3820 if (afi
== AFI_L2VPN
) {
3821 overlay_index_update(&new_attr
,
3822 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3825 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3827 * Suppress fib is enabled
3828 * BGP_OPT_NO_FIB is not enabled
3829 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3830 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3832 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
3833 && (sub_type
== BGP_ROUTE_NORMAL
)
3834 && (!bgp_option_check(BGP_OPT_NO_FIB
))
3835 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
3836 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
3838 attr_new
= bgp_attr_intern(&new_attr
);
3840 /* If maximum prefix count is configured and current prefix
3843 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3846 /* If the update is implicit withdraw. */
3848 pi
->uptime
= bgp_clock();
3849 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3851 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3853 /* Same attribute comes in. */
3854 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3856 && (!has_valid_label
3857 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3858 num_labels
* sizeof(mpls_label_t
))
3860 && (overlay_index_equal(
3862 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3863 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3864 && peer
->sort
== BGP_PEER_EBGP
3865 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3866 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3867 bgp_debug_rdpfxpath2str(
3868 afi
, safi
, prd
, p
, label
,
3869 num_labels
, addpath_id
? 1 : 0,
3870 addpath_id
, pfx_buf
,
3872 zlog_debug("%s rcvd %s", peer
->host
,
3876 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3877 != BGP_DAMP_SUPPRESSED
) {
3878 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3880 bgp_process(bgp
, dest
, afi
, safi
);
3882 } else /* Duplicate - odd */
3884 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3885 if (!peer
->rcvd_attr_printed
) {
3887 "%s rcvd UPDATE w/ attr: %s",
3889 peer
->rcvd_attr_str
);
3890 peer
->rcvd_attr_printed
= 1;
3893 bgp_debug_rdpfxpath2str(
3894 afi
, safi
, prd
, p
, label
,
3895 num_labels
, addpath_id
? 1 : 0,
3896 addpath_id
, pfx_buf
,
3899 "%s rcvd %s...duplicate ignored",
3900 peer
->host
, pfx_buf
);
3903 /* graceful restart STALE flag unset. */
3904 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3905 bgp_path_info_unset_flag(
3906 dest
, pi
, BGP_PATH_STALE
);
3907 bgp_dest_set_defer_flag(dest
, false);
3908 bgp_process(bgp
, dest
, afi
, safi
);
3912 bgp_dest_unlock_node(dest
);
3913 bgp_attr_unintern(&attr_new
);
3918 /* Withdraw/Announce before we fully processed the withdraw */
3919 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3920 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3921 bgp_debug_rdpfxpath2str(
3922 afi
, safi
, prd
, p
, label
, num_labels
,
3923 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3926 "%s rcvd %s, flapped quicker than processing",
3927 peer
->host
, pfx_buf
);
3930 bgp_path_info_restore(dest
, pi
);
3933 /* Received Logging. */
3934 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3935 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3936 num_labels
, addpath_id
? 1 : 0,
3937 addpath_id
, pfx_buf
,
3939 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3942 /* graceful restart STALE flag unset. */
3943 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3944 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
3945 bgp_dest_set_defer_flag(dest
, false);
3948 /* The attribute is changed. */
3949 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
3951 /* implicit withdraw, decrement aggregate and pcount here.
3952 * only if update is accepted, they'll increment below.
3954 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3956 /* Update bgp route dampening information. */
3957 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3958 && peer
->sort
== BGP_PEER_EBGP
) {
3959 /* This is implicit withdraw so we should update
3960 * dampening information.
3962 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3963 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
3965 #ifdef ENABLE_BGP_VNC
3966 if (safi
== SAFI_MPLS_VPN
) {
3967 struct bgp_dest
*pdest
= NULL
;
3968 struct bgp_table
*table
= NULL
;
3970 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3971 (struct prefix
*)prd
);
3972 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3973 table
= bgp_dest_get_bgp_table_info(pdest
);
3975 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3976 bgp
, prd
, table
, p
, pi
);
3978 bgp_dest_unlock_node(pdest
);
3980 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3981 && (safi
== SAFI_UNICAST
)) {
3982 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3984 * Implicit withdraw case.
3986 ++vnc_implicit_withdraw
;
3987 vnc_import_bgp_del_route(bgp
, p
, pi
);
3988 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3993 /* Special handling for EVPN update of an existing route. If the
3994 * extended community attribute has changed, we need to
3996 * the route using its existing extended community. It will be
3997 * subsequently processed for import with the new extended
4000 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4003 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4005 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4008 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
4009 attr_new
->ecommunity
);
4011 if (bgp_debug_update(peer
, p
, NULL
, 1))
4013 "Change in EXT-COMM, existing %s new %s",
4015 pi
->attr
->ecommunity
),
4017 attr_new
->ecommunity
));
4018 if (safi
== SAFI_EVPN
)
4019 bgp_evpn_unimport_route(
4020 bgp
, afi
, safi
, p
, pi
);
4021 else /* SAFI_MPLS_VPN */
4022 vpn_leak_to_vrf_withdraw(bgp
,
4028 /* Update to new attribute. */
4029 bgp_attr_unintern(&pi
->attr
);
4030 pi
->attr
= attr_new
;
4032 /* Update MPLS label */
4033 if (has_valid_label
) {
4034 extra
= bgp_path_info_extra_get(pi
);
4035 if (extra
->label
!= label
) {
4036 memcpy(&extra
->label
, label
,
4037 num_labels
* sizeof(mpls_label_t
));
4038 extra
->num_labels
= num_labels
;
4040 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4041 bgp_set_valid_label(&extra
->label
[0]);
4044 /* Update SRv6 SID */
4045 if (attr
->srv6_l3vpn
) {
4046 extra
= bgp_path_info_extra_get(pi
);
4047 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
4048 sid_copy(&extra
->sid
[0],
4049 &attr
->srv6_l3vpn
->sid
);
4050 extra
->num_sids
= 1;
4052 } else if (attr
->srv6_vpn
) {
4053 extra
= bgp_path_info_extra_get(pi
);
4054 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
4055 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4056 extra
->num_sids
= 1;
4060 #ifdef ENABLE_BGP_VNC
4061 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4062 && (safi
== SAFI_UNICAST
)) {
4063 if (vnc_implicit_withdraw
) {
4065 * Add back the route with its new attributes
4067 * The route is still selected, until the route
4069 * queued by bgp_process actually runs. We have
4071 * update to the VNC side immediately to avoid
4073 * configuration changes (e.g., route-map
4075 * trigger re-importation of the entire RIB.
4077 vnc_import_bgp_add_route(bgp
, p
, pi
);
4078 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4083 /* Update bgp route dampening information. */
4084 if (get_active_bdc_from_pi(pi
, afi
, safi
)
4085 && peer
->sort
== BGP_PEER_EBGP
) {
4086 /* Now we do normal update dampening. */
4087 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4088 if (ret
== BGP_DAMP_SUPPRESSED
) {
4089 bgp_dest_unlock_node(dest
);
4094 /* Nexthop reachability check - for unicast and
4095 * labeled-unicast.. */
4096 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4097 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4098 || (safi
== SAFI_EVPN
&&
4099 bgp_evpn_is_prefix_nht_supported(p
))) {
4100 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4101 && peer
->ttl
== BGP_DEFAULT_TTL
4102 && !CHECK_FLAG(peer
->flags
,
4103 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4104 && !CHECK_FLAG(bgp
->flags
,
4105 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4110 struct bgp
*bgp_nexthop
= bgp
;
4112 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4113 bgp_nexthop
= pi
->extra
->bgp_orig
;
4115 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4117 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4118 safi
, pi
, NULL
, connected
)
4119 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4120 bgp_path_info_set_flag(dest
, pi
,
4123 if (BGP_DEBUG(nht
, NHT
)) {
4124 zlog_debug("%s(%pI4): NH unresolved",
4126 (in_addr_t
*)&attr_new
->nexthop
);
4128 bgp_path_info_unset_flag(dest
, pi
,
4132 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4134 #ifdef ENABLE_BGP_VNC
4135 if (safi
== SAFI_MPLS_VPN
) {
4136 struct bgp_dest
*pdest
= NULL
;
4137 struct bgp_table
*table
= NULL
;
4139 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4140 (struct prefix
*)prd
);
4141 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4142 table
= bgp_dest_get_bgp_table_info(pdest
);
4144 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4145 bgp
, prd
, table
, p
, pi
);
4147 bgp_dest_unlock_node(pdest
);
4151 /* If this is an EVPN route and some attribute has changed,
4153 * route for import. If the extended community has changed, we
4155 * have done the un-import earlier and the import would result
4157 * route getting injected into appropriate L2 VNIs. If it is
4159 * some other attribute change, the import will result in
4161 * the attributes for the route in the VNI(s).
4163 if (safi
== SAFI_EVPN
&& !same_attr
&&
4164 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4165 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4167 /* Process change. */
4168 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4170 bgp_process(bgp
, dest
, afi
, safi
);
4171 bgp_dest_unlock_node(dest
);
4173 if (SAFI_UNICAST
== safi
4174 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4175 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4177 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4179 if ((SAFI_MPLS_VPN
== safi
)
4180 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4182 vpn_leak_to_vrf_update(bgp
, pi
);
4185 #ifdef ENABLE_BGP_VNC
4186 if (SAFI_MPLS_VPN
== safi
) {
4187 mpls_label_t label_decoded
= decode_label(label
);
4189 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4190 type
, sub_type
, &label_decoded
);
4192 if (SAFI_ENCAP
== safi
) {
4193 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4194 type
, sub_type
, NULL
);
4199 } // End of implicit withdraw
4201 /* Received Logging. */
4202 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4203 if (!peer
->rcvd_attr_printed
) {
4204 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4205 peer
->rcvd_attr_str
);
4206 peer
->rcvd_attr_printed
= 1;
4209 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4210 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4212 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
4215 /* Make new BGP info. */
4216 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4218 /* Update MPLS label */
4219 if (has_valid_label
) {
4220 extra
= bgp_path_info_extra_get(new);
4221 if (extra
->label
!= label
) {
4222 memcpy(&extra
->label
, label
,
4223 num_labels
* sizeof(mpls_label_t
));
4224 extra
->num_labels
= num_labels
;
4226 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4227 bgp_set_valid_label(&extra
->label
[0]);
4230 /* Update SRv6 SID */
4231 if (safi
== SAFI_MPLS_VPN
) {
4232 extra
= bgp_path_info_extra_get(new);
4233 if (attr
->srv6_l3vpn
) {
4234 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
4235 extra
->num_sids
= 1;
4236 } else if (attr
->srv6_vpn
) {
4237 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4238 extra
->num_sids
= 1;
4242 /* Update Overlay Index */
4243 if (afi
== AFI_L2VPN
) {
4244 overlay_index_update(new->attr
,
4245 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
4247 /* Nexthop reachability check. */
4248 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4249 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4250 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4251 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4252 && peer
->ttl
== BGP_DEFAULT_TTL
4253 && !CHECK_FLAG(peer
->flags
,
4254 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4255 && !CHECK_FLAG(bgp
->flags
,
4256 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4261 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4263 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4265 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4266 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4268 if (BGP_DEBUG(nht
, NHT
)) {
4269 char buf1
[INET6_ADDRSTRLEN
];
4271 (const void *)&attr_new
->nexthop
,
4272 buf1
, INET6_ADDRSTRLEN
);
4273 zlog_debug("%s(%s): NH unresolved", __func__
,
4276 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4279 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4282 new->addpath_rx_id
= addpath_id
;
4284 /* Increment prefix */
4285 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4287 /* Register new BGP information. */
4288 bgp_path_info_add(dest
, new);
4290 /* route_node_get lock */
4291 bgp_dest_unlock_node(dest
);
4293 #ifdef ENABLE_BGP_VNC
4294 if (safi
== SAFI_MPLS_VPN
) {
4295 struct bgp_dest
*pdest
= NULL
;
4296 struct bgp_table
*table
= NULL
;
4298 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4299 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4300 table
= bgp_dest_get_bgp_table_info(pdest
);
4302 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4303 bgp
, prd
, table
, p
, new);
4305 bgp_dest_unlock_node(pdest
);
4309 /* If this is an EVPN route, process for import. */
4310 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4311 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4313 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4315 /* Process change. */
4316 bgp_process(bgp
, dest
, afi
, safi
);
4318 if (SAFI_UNICAST
== safi
4319 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4320 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4321 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4323 if ((SAFI_MPLS_VPN
== safi
)
4324 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4326 vpn_leak_to_vrf_update(bgp
, new);
4328 #ifdef ENABLE_BGP_VNC
4329 if (SAFI_MPLS_VPN
== safi
) {
4330 mpls_label_t label_decoded
= decode_label(label
);
4332 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4333 sub_type
, &label_decoded
);
4335 if (SAFI_ENCAP
== safi
) {
4336 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4343 /* This BGP update is filtered. Log the reason then update BGP
4346 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4348 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4349 if (!peer
->rcvd_attr_printed
) {
4350 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4351 peer
->rcvd_attr_str
);
4352 peer
->rcvd_attr_printed
= 1;
4355 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4356 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4358 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4359 peer
->host
, pfx_buf
, reason
);
4363 /* If this is an EVPN route, un-import it as it is now filtered.
4365 if (safi
== SAFI_EVPN
)
4366 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4368 if (SAFI_UNICAST
== safi
4369 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4370 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4372 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4374 if ((SAFI_MPLS_VPN
== safi
)
4375 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4377 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4380 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4383 bgp_dest_unlock_node(dest
);
4385 #ifdef ENABLE_BGP_VNC
4387 * Filtered update is treated as an implicit withdrawal (see
4389 * a few lines above)
4391 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4392 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4400 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4401 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4402 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4403 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4406 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4407 struct bgp_dest
*dest
;
4408 struct bgp_path_info
*pi
;
4410 #ifdef ENABLE_BGP_VNC
4411 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4412 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4420 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4422 /* If peer is soft reconfiguration enabled. Record input packet for
4423 * further calculation.
4425 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4426 * routes that are filtered. This tanks out Quagga RS pretty badly due
4428 * the iteration over all RS clients.
4429 * Since we need to remove the entry from adj_in anyway, do that first
4431 * if there was no entry, we don't need to do anything more.
4433 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4434 && peer
!= bgp
->peer_self
)
4435 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4436 peer
->stat_pfx_dup_withdraw
++;
4438 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4439 bgp_debug_rdpfxpath2str(
4440 afi
, safi
, prd
, p
, label
, num_labels
,
4441 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4444 "%s withdrawing route %s not in adj-in",
4445 peer
->host
, pfx_buf
);
4447 bgp_dest_unlock_node(dest
);
4451 /* Lookup withdrawn route. */
4452 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4453 if (pi
->peer
== peer
&& pi
->type
== type
4454 && pi
->sub_type
== sub_type
4455 && pi
->addpath_rx_id
== addpath_id
)
4459 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4460 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4461 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4463 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4467 /* Withdraw specified route from routing table. */
4468 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4469 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4470 if (SAFI_UNICAST
== safi
4471 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4472 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4473 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4475 if ((SAFI_MPLS_VPN
== safi
)
4476 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4478 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4480 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4481 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4482 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4484 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4487 /* Unlock bgp_node_get() lock. */
4488 bgp_dest_unlock_node(dest
);
4493 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4496 struct update_subgroup
*subgrp
;
4497 subgrp
= peer_subgroup(peer
, afi
, safi
);
4498 subgroup_default_originate(subgrp
, withdraw
);
4503 * bgp_stop_announce_route_timer
4505 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4507 if (!paf
->t_announce_route
)
4510 thread_cancel(&paf
->t_announce_route
);
4514 * bgp_announce_route_timer_expired
4516 * Callback that is invoked when the route announcement timer for a
4519 static int bgp_announce_route_timer_expired(struct thread
*t
)
4521 struct peer_af
*paf
;
4524 paf
= THREAD_ARG(t
);
4527 if (!peer_established(peer
))
4530 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4533 peer_af_announce_route(paf
, 1);
4535 /* Notify BGP conditional advertisement scanner percess */
4536 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
4542 * bgp_announce_route
4544 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4546 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4548 struct peer_af
*paf
;
4549 struct update_subgroup
*subgrp
;
4551 paf
= peer_af_find(peer
, afi
, safi
);
4554 subgrp
= PAF_SUBGRP(paf
);
4557 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4558 * or a refresh has already been triggered.
4560 if (!subgrp
|| paf
->t_announce_route
)
4564 * Start a timer to stagger/delay the announce. This serves
4565 * two purposes - announcement can potentially be combined for
4566 * multiple peers and the announcement doesn't happen in the
4569 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4570 (subgrp
->peer_count
== 1)
4571 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4572 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4573 &paf
->t_announce_route
);
4577 * Announce routes from all AF tables to a peer.
4579 * This should ONLY be called when there is a need to refresh the
4580 * routes to the peer based on a policy change for this peer alone
4581 * or a route refresh request received from the peer.
4582 * The operation will result in splitting the peer from its existing
4583 * subgroups and putting it in new subgroups.
4585 void bgp_announce_route_all(struct peer
*peer
)
4590 FOREACH_AFI_SAFI (afi
, safi
)
4591 bgp_announce_route(peer
, afi
, safi
);
4594 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4595 struct bgp_table
*table
,
4596 struct prefix_rd
*prd
)
4599 struct bgp_dest
*dest
;
4600 struct bgp_adj_in
*ain
;
4603 table
= peer
->bgp
->rib
[afi
][safi
];
4605 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4606 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4607 if (ain
->peer
!= peer
)
4610 struct bgp_path_info
*pi
;
4611 uint32_t num_labels
= 0;
4612 mpls_label_t
*label_pnt
= NULL
;
4613 struct bgp_route_evpn evpn
;
4615 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4617 if (pi
->peer
== peer
)
4620 if (pi
&& pi
->extra
)
4621 num_labels
= pi
->extra
->num_labels
;
4623 label_pnt
= &pi
->extra
->label
[0];
4626 bgp_attr_get_evpn_overlay(pi
->attr
),
4629 memset(&evpn
, 0, sizeof(evpn
));
4631 ret
= bgp_update(peer
, bgp_dest_get_prefix(dest
),
4632 ain
->addpath_rx_id
, ain
->attr
, afi
,
4633 safi
, ZEBRA_ROUTE_BGP
,
4634 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4635 num_labels
, 1, &evpn
);
4638 bgp_dest_unlock_node(dest
);
4644 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4646 struct bgp_dest
*dest
;
4647 struct bgp_table
*table
;
4649 if (!peer_established(peer
))
4652 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4653 && (safi
!= SAFI_EVPN
))
4654 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4656 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4657 dest
= bgp_route_next(dest
)) {
4658 table
= bgp_dest_get_bgp_table_info(dest
);
4663 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4664 struct prefix_rd prd
;
4666 prd
.family
= AF_UNSPEC
;
4668 memcpy(&prd
.val
, p
->u
.val
, 8);
4670 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4675 struct bgp_clear_node_queue
{
4676 struct bgp_dest
*dest
;
4679 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4681 struct bgp_clear_node_queue
*cnq
= data
;
4682 struct bgp_dest
*dest
= cnq
->dest
;
4683 struct peer
*peer
= wq
->spec
.data
;
4684 struct bgp_path_info
*pi
;
4686 afi_t afi
= bgp_dest_table(dest
)->afi
;
4687 safi_t safi
= bgp_dest_table(dest
)->safi
;
4689 assert(dest
&& peer
);
4692 /* It is possible that we have multiple paths for a prefix from a peer
4693 * if that peer is using AddPath.
4695 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
4696 if (pi
->peer
!= peer
)
4699 /* graceful restart STALE flag set. */
4700 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4701 && peer
->nsf
[afi
][safi
])
4702 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
4703 PEER_STATUS_ENHANCED_REFRESH
))
4704 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4705 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4706 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
4708 /* If this is an EVPN route, process for
4710 if (safi
== SAFI_EVPN
)
4711 bgp_evpn_unimport_route(
4713 bgp_dest_get_prefix(dest
), pi
);
4714 /* Handle withdraw for VRF route-leaking and L3VPN */
4715 if (SAFI_UNICAST
== safi
4716 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4717 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4718 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4721 if (SAFI_MPLS_VPN
== safi
&&
4722 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4723 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4726 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4732 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4734 struct bgp_clear_node_queue
*cnq
= data
;
4735 struct bgp_dest
*dest
= cnq
->dest
;
4736 struct bgp_table
*table
= bgp_dest_table(dest
);
4738 bgp_dest_unlock_node(dest
);
4739 bgp_table_unlock(table
);
4740 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4743 static void bgp_clear_node_complete(struct work_queue
*wq
)
4745 struct peer
*peer
= wq
->spec
.data
;
4747 /* Tickle FSM to start moving again */
4748 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4750 peer_unlock(peer
); /* bgp_clear_route */
4753 static void bgp_clear_node_queue_init(struct peer
*peer
)
4755 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4757 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4758 #undef CLEAR_QUEUE_NAME_LEN
4760 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4761 peer
->clear_node_queue
->spec
.hold
= 10;
4762 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4763 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4764 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4765 peer
->clear_node_queue
->spec
.max_retries
= 0;
4767 /* we only 'lock' this peer reference when the queue is actually active
4769 peer
->clear_node_queue
->spec
.data
= peer
;
4772 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4773 struct bgp_table
*table
)
4775 struct bgp_dest
*dest
;
4776 int force
= peer
->bgp
->process_queue
? 0 : 1;
4779 table
= peer
->bgp
->rib
[afi
][safi
];
4781 /* If still no table => afi/safi isn't configured at all or smth. */
4785 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4786 struct bgp_path_info
*pi
, *next
;
4787 struct bgp_adj_in
*ain
;
4788 struct bgp_adj_in
*ain_next
;
4790 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4791 * queued for every clearing peer, regardless of whether it is
4792 * relevant to the peer at hand.
4794 * Overview: There are 3 different indices which need to be
4795 * scrubbed, potentially, when a peer is removed:
4797 * 1 peer's routes visible via the RIB (ie accepted routes)
4798 * 2 peer's routes visible by the (optional) peer's adj-in index
4799 * 3 other routes visible by the peer's adj-out index
4801 * 3 there is no hurry in scrubbing, once the struct peer is
4802 * removed from bgp->peer, we could just GC such deleted peer's
4803 * adj-outs at our leisure.
4805 * 1 and 2 must be 'scrubbed' in some way, at least made
4806 * invisible via RIB index before peer session is allowed to be
4807 * brought back up. So one needs to know when such a 'search' is
4812 * - there'd be a single global queue or a single RIB walker
4813 * - rather than tracking which route_nodes still need to be
4814 * examined on a peer basis, we'd track which peers still
4817 * Given that our per-peer prefix-counts now should be reliable,
4818 * this may actually be achievable. It doesn't seem to be a huge
4819 * problem at this time,
4821 * It is possible that we have multiple paths for a prefix from
4823 * if that peer is using AddPath.
4827 ain_next
= ain
->next
;
4829 if (ain
->peer
== peer
) {
4830 bgp_adj_in_remove(dest
, ain
);
4831 bgp_dest_unlock_node(dest
);
4837 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4839 if (pi
->peer
!= peer
)
4843 bgp_path_info_reap(dest
, pi
);
4845 struct bgp_clear_node_queue
*cnq
;
4847 /* both unlocked in bgp_clear_node_queue_del */
4848 bgp_table_lock(bgp_dest_table(dest
));
4849 bgp_dest_lock_node(dest
);
4851 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4852 sizeof(struct bgp_clear_node_queue
));
4854 work_queue_add(peer
->clear_node_queue
, cnq
);
4862 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4864 struct bgp_dest
*dest
;
4865 struct bgp_table
*table
;
4867 if (peer
->clear_node_queue
== NULL
)
4868 bgp_clear_node_queue_init(peer
);
4870 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4871 * Idle until it receives a Clearing_Completed event. This protects
4872 * against peers which flap faster than we can we clear, which could
4875 * a) race with routes from the new session being installed before
4876 * clear_route_node visits the node (to delete the route of that
4878 * b) resource exhaustion, clear_route_node likely leads to an entry
4879 * on the process_main queue. Fast-flapping could cause that queue
4883 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4884 * the unlock will happen upon work-queue completion; other wise, the
4885 * unlock happens at the end of this function.
4887 if (!peer
->clear_node_queue
->thread
)
4890 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4891 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4893 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4894 dest
= bgp_route_next(dest
)) {
4895 table
= bgp_dest_get_bgp_table_info(dest
);
4899 bgp_clear_route_table(peer
, afi
, safi
, table
);
4902 /* unlock if no nodes got added to the clear-node-queue. */
4903 if (!peer
->clear_node_queue
->thread
)
4907 void bgp_clear_route_all(struct peer
*peer
)
4912 FOREACH_AFI_SAFI (afi
, safi
)
4913 bgp_clear_route(peer
, afi
, safi
);
4915 #ifdef ENABLE_BGP_VNC
4916 rfapiProcessPeerDown(peer
);
4920 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4922 struct bgp_table
*table
;
4923 struct bgp_dest
*dest
;
4924 struct bgp_adj_in
*ain
;
4925 struct bgp_adj_in
*ain_next
;
4927 table
= peer
->bgp
->rib
[afi
][safi
];
4929 /* It is possible that we have multiple paths for a prefix from a peer
4930 * if that peer is using AddPath.
4932 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4936 ain_next
= ain
->next
;
4938 if (ain
->peer
== peer
) {
4939 bgp_adj_in_remove(dest
, ain
);
4940 bgp_dest_unlock_node(dest
);
4948 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4950 struct bgp_dest
*dest
;
4951 struct bgp_path_info
*pi
;
4952 struct bgp_table
*table
;
4954 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
4955 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4956 dest
= bgp_route_next(dest
)) {
4957 struct bgp_dest
*rm
;
4959 /* look for neighbor in tables */
4960 table
= bgp_dest_get_bgp_table_info(dest
);
4964 for (rm
= bgp_table_top(table
); rm
;
4965 rm
= bgp_route_next(rm
))
4966 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
4968 if (pi
->peer
!= peer
)
4970 if (!CHECK_FLAG(pi
->flags
,
4974 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4979 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4980 dest
= bgp_route_next(dest
))
4981 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4983 if (pi
->peer
!= peer
)
4985 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4987 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4993 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4995 struct bgp_dest
*dest
, *ndest
;
4996 struct bgp_path_info
*pi
;
4997 struct bgp_table
*table
;
4999 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5000 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5001 dest
= bgp_route_next(dest
)) {
5002 table
= bgp_dest_get_bgp_table_info(dest
);
5006 for (ndest
= bgp_table_top(table
); ndest
;
5007 ndest
= bgp_route_next(ndest
)) {
5008 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5010 if (pi
->peer
!= peer
)
5014 peer
->af_sflags
[afi
][safi
],
5015 PEER_STATUS_ENHANCED_REFRESH
))
5016 && !CHECK_FLAG(pi
->flags
,
5020 BGP_PATH_UNUSEABLE
)) {
5021 if (bgp_debug_neighbor_events(
5024 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5028 bgp_dest_get_prefix(
5031 bgp_path_info_set_flag(
5039 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5040 dest
= bgp_route_next(dest
)) {
5041 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5043 if (pi
->peer
!= peer
)
5046 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5047 PEER_STATUS_ENHANCED_REFRESH
))
5048 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5049 && !CHECK_FLAG(pi
->flags
,
5050 BGP_PATH_UNUSEABLE
)) {
5051 if (bgp_debug_neighbor_events(peer
))
5053 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5057 bgp_dest_get_prefix(
5060 bgp_path_info_set_flag(dest
, pi
,
5068 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5070 if (peer
->sort
== BGP_PEER_IBGP
)
5073 if (peer
->sort
== BGP_PEER_EBGP
5074 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5075 || FILTER_LIST_OUT_NAME(filter
)
5076 || DISTRIBUTE_OUT_NAME(filter
)))
5081 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5083 if (peer
->sort
== BGP_PEER_IBGP
)
5086 if (peer
->sort
== BGP_PEER_EBGP
5087 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5088 || FILTER_LIST_IN_NAME(filter
)
5089 || DISTRIBUTE_IN_NAME(filter
)))
5094 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5097 struct bgp_dest
*dest
;
5098 struct bgp_path_info
*pi
;
5099 struct bgp_path_info
*next
;
5101 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5102 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5103 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5107 /* Unimport EVPN routes from VRFs */
5108 if (safi
== SAFI_EVPN
)
5109 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5112 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5113 && pi
->type
== ZEBRA_ROUTE_BGP
5114 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5115 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5116 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5118 if (bgp_fibupd_safi(safi
))
5119 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5122 bgp_path_info_reap(dest
, pi
);
5126 /* Delete all kernel routes. */
5127 void bgp_cleanup_routes(struct bgp
*bgp
)
5130 struct bgp_dest
*dest
;
5131 struct bgp_table
*table
;
5133 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5134 if (afi
== AFI_L2VPN
)
5136 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5139 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5141 if (afi
!= AFI_L2VPN
) {
5143 safi
= SAFI_MPLS_VPN
;
5144 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5145 dest
= bgp_route_next(dest
)) {
5146 table
= bgp_dest_get_bgp_table_info(dest
);
5147 if (table
!= NULL
) {
5148 bgp_cleanup_table(bgp
, table
, safi
);
5149 bgp_table_finish(&table
);
5150 bgp_dest_set_bgp_table_info(dest
, NULL
);
5151 bgp_dest_unlock_node(dest
);
5155 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5156 dest
= bgp_route_next(dest
)) {
5157 table
= bgp_dest_get_bgp_table_info(dest
);
5158 if (table
!= NULL
) {
5159 bgp_cleanup_table(bgp
, table
, safi
);
5160 bgp_table_finish(&table
);
5161 bgp_dest_set_bgp_table_info(dest
, NULL
);
5162 bgp_dest_unlock_node(dest
);
5167 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5168 dest
= bgp_route_next(dest
)) {
5169 table
= bgp_dest_get_bgp_table_info(dest
);
5170 if (table
!= NULL
) {
5171 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5172 bgp_table_finish(&table
);
5173 bgp_dest_set_bgp_table_info(dest
, NULL
);
5174 bgp_dest_unlock_node(dest
);
5179 void bgp_reset(void)
5182 bgp_zclient_reset();
5183 access_list_reset();
5184 prefix_list_reset();
5187 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5189 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5190 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5191 PEER_CAP_ADDPATH_AF_TX_RCV
));
5194 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5196 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5197 struct bgp_nlri
*packet
)
5206 int addpath_encoded
;
5207 uint32_t addpath_id
;
5210 lim
= pnt
+ packet
->length
;
5212 safi
= packet
->safi
;
5214 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5216 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5217 syntactic validity. If the field is syntactically incorrect,
5218 then the Error Subcode is set to Invalid Network Field. */
5219 for (; pnt
< lim
; pnt
+= psize
) {
5220 /* Clear prefix structure. */
5221 memset(&p
, 0, sizeof(struct prefix
));
5223 if (addpath_encoded
) {
5225 /* When packet overflow occurs return immediately. */
5226 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5227 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5229 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5230 addpath_id
= ntohl(addpath_id
);
5231 pnt
+= BGP_ADDPATH_ID_LEN
;
5234 /* Fetch prefix length. */
5235 p
.prefixlen
= *pnt
++;
5236 /* afi/safi validity already verified by caller,
5237 * bgp_update_receive */
5238 p
.family
= afi2family(afi
);
5240 /* Prefix length check. */
5241 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5244 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5245 peer
->host
, p
.prefixlen
, packet
->afi
);
5246 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5249 /* Packet size overflow check. */
5250 psize
= PSIZE(p
.prefixlen
);
5252 /* When packet overflow occur return immediately. */
5253 if (pnt
+ psize
> lim
) {
5256 "%s [Error] Update packet error (prefix length %d overflows packet)",
5257 peer
->host
, p
.prefixlen
);
5258 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5261 /* Defensive coding, double-check the psize fits in a struct
5263 if (psize
> (ssize_t
)sizeof(p
.u
)) {
5266 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5267 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
5268 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5271 /* Fetch prefix from NLRI packet. */
5272 memcpy(p
.u
.val
, pnt
, psize
);
5274 /* Check address. */
5275 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5276 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5277 /* From RFC4271 Section 6.3:
5279 * If a prefix in the NLRI field is semantically
5281 * (e.g., an unexpected multicast IP address),
5283 * be logged locally, and the prefix SHOULD be
5288 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5289 peer
->host
, &p
.u
.prefix4
);
5294 /* Check address. */
5295 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5296 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5299 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5300 peer
->host
, &p
.u
.prefix6
);
5304 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5307 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5308 peer
->host
, &p
.u
.prefix6
);
5314 /* Normal process. */
5316 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5317 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5318 NULL
, NULL
, 0, 0, NULL
);
5320 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5321 safi
, ZEBRA_ROUTE_BGP
,
5322 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5325 /* Do not send BGP notification twice when maximum-prefix count
5327 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5328 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5330 /* Address family configuration mismatch. */
5332 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5335 /* Packet length consistency check. */
5339 "%s [Error] Update packet error (prefix length mismatch with total length)",
5341 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5344 return BGP_NLRI_PARSE_OK
;
5347 static struct bgp_static
*bgp_static_new(void)
5349 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5352 static void bgp_static_free(struct bgp_static
*bgp_static
)
5354 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5355 route_map_counter_decrement(bgp_static
->rmap
.map
);
5357 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5358 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5361 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5362 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5364 struct bgp_dest
*dest
;
5365 struct bgp_path_info
*pi
;
5366 struct bgp_path_info
*new;
5367 struct bgp_path_info rmap_path
;
5369 struct attr
*attr_new
;
5370 route_map_result_t ret
;
5371 #ifdef ENABLE_BGP_VNC
5372 int vnc_implicit_withdraw
= 0;
5377 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5379 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5381 attr
.nexthop
= bgp_static
->igpnexthop
;
5382 attr
.med
= bgp_static
->igpmetric
;
5383 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5385 if (bgp_static
->atomic
)
5386 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5388 /* Store label index, if required. */
5389 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5390 attr
.label_index
= bgp_static
->label_index
;
5391 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5394 /* Apply route-map. */
5395 if (bgp_static
->rmap
.name
) {
5396 struct attr attr_tmp
= attr
;
5398 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5399 rmap_path
.peer
= bgp
->peer_self
;
5400 rmap_path
.attr
= &attr_tmp
;
5402 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5404 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5406 bgp
->peer_self
->rmap_type
= 0;
5408 if (ret
== RMAP_DENYMATCH
) {
5409 /* Free uninterned attribute. */
5410 bgp_attr_flush(&attr_tmp
);
5412 /* Unintern original. */
5413 aspath_unintern(&attr
.aspath
);
5414 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5418 if (bgp_in_graceful_shutdown(bgp
))
5419 bgp_attr_add_gshut_community(&attr_tmp
);
5421 attr_new
= bgp_attr_intern(&attr_tmp
);
5424 if (bgp_in_graceful_shutdown(bgp
))
5425 bgp_attr_add_gshut_community(&attr
);
5427 attr_new
= bgp_attr_intern(&attr
);
5430 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5431 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5432 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5436 if (attrhash_cmp(pi
->attr
, attr_new
)
5437 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5438 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5439 bgp_dest_unlock_node(dest
);
5440 bgp_attr_unintern(&attr_new
);
5441 aspath_unintern(&attr
.aspath
);
5444 /* The attribute is changed. */
5445 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5447 /* Rewrite BGP route information. */
5448 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5449 bgp_path_info_restore(dest
, pi
);
5451 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5452 #ifdef ENABLE_BGP_VNC
5453 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5454 && (safi
== SAFI_UNICAST
)) {
5455 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5457 * Implicit withdraw case.
5458 * We have to do this before pi is
5461 ++vnc_implicit_withdraw
;
5462 vnc_import_bgp_del_route(bgp
, p
, pi
);
5463 vnc_import_bgp_exterior_del_route(
5468 bgp_attr_unintern(&pi
->attr
);
5469 pi
->attr
= attr_new
;
5470 pi
->uptime
= bgp_clock();
5471 #ifdef ENABLE_BGP_VNC
5472 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5473 && (safi
== SAFI_UNICAST
)) {
5474 if (vnc_implicit_withdraw
) {
5475 vnc_import_bgp_add_route(bgp
, p
, pi
);
5476 vnc_import_bgp_exterior_add_route(
5482 /* Nexthop reachability check. */
5483 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5484 && (safi
== SAFI_UNICAST
5485 || safi
== SAFI_LABELED_UNICAST
)) {
5487 struct bgp
*bgp_nexthop
= bgp
;
5489 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5490 bgp_nexthop
= pi
->extra
->bgp_orig
;
5492 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5493 afi
, safi
, pi
, NULL
,
5495 bgp_path_info_set_flag(dest
, pi
,
5498 if (BGP_DEBUG(nht
, NHT
)) {
5499 char buf1
[INET6_ADDRSTRLEN
];
5500 inet_ntop(p
->family
,
5504 "%s(%s): Route not in table, not advertising",
5507 bgp_path_info_unset_flag(
5508 dest
, pi
, BGP_PATH_VALID
);
5511 /* Delete the NHT structure if any, if we're
5513 * enabling/disabling import check. We
5514 * deregister the route
5515 * from NHT to avoid overloading NHT and the
5516 * process interaction
5518 bgp_unlink_nexthop(pi
);
5519 bgp_path_info_set_flag(dest
, pi
,
5522 /* Process change. */
5523 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5524 bgp_process(bgp
, dest
, afi
, safi
);
5526 if (SAFI_UNICAST
== safi
5527 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5529 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5530 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5534 bgp_dest_unlock_node(dest
);
5535 aspath_unintern(&attr
.aspath
);
5540 /* Make new BGP info. */
5541 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5543 /* Nexthop reachability check. */
5544 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5545 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5546 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0))
5547 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5549 if (BGP_DEBUG(nht
, NHT
)) {
5550 char buf1
[INET6_ADDRSTRLEN
];
5551 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5554 "%s(%s): Route not in table, not advertising",
5557 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5560 /* Delete the NHT structure if any, if we're toggling between
5561 * enabling/disabling import check. We deregister the route
5562 * from NHT to avoid overloading NHT and the process interaction
5564 bgp_unlink_nexthop(new);
5566 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5569 /* Aggregate address increment. */
5570 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5572 /* Register new BGP information. */
5573 bgp_path_info_add(dest
, new);
5575 /* route_node_get lock */
5576 bgp_dest_unlock_node(dest
);
5578 /* Process change. */
5579 bgp_process(bgp
, dest
, afi
, safi
);
5581 if (SAFI_UNICAST
== safi
5582 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5583 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5584 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5587 /* Unintern original. */
5588 aspath_unintern(&attr
.aspath
);
5591 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
5594 struct bgp_dest
*dest
;
5595 struct bgp_path_info
*pi
;
5597 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5599 /* Check selected route and self inserted route. */
5600 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5601 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5602 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5605 /* Withdraw static BGP route from routing table. */
5607 if (SAFI_UNICAST
== safi
5608 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5609 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5610 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5612 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5613 bgp_unlink_nexthop(pi
);
5614 bgp_path_info_delete(dest
, pi
);
5615 bgp_process(bgp
, dest
, afi
, safi
);
5618 /* Unlock bgp_node_lookup. */
5619 bgp_dest_unlock_node(dest
);
5623 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5625 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
5626 afi_t afi
, safi_t safi
,
5627 struct prefix_rd
*prd
)
5629 struct bgp_dest
*dest
;
5630 struct bgp_path_info
*pi
;
5632 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5634 /* Check selected route and self inserted route. */
5635 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5636 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5637 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5640 /* Withdraw static BGP route from routing table. */
5642 #ifdef ENABLE_BGP_VNC
5643 rfapiProcessWithdraw(
5644 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5645 1); /* Kill, since it is an administrative change */
5647 if (SAFI_MPLS_VPN
== safi
5648 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5649 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5651 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5652 bgp_path_info_delete(dest
, pi
);
5653 bgp_process(bgp
, dest
, afi
, safi
);
5656 /* Unlock bgp_node_lookup. */
5657 bgp_dest_unlock_node(dest
);
5660 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
5661 struct bgp_static
*bgp_static
, afi_t afi
,
5664 struct bgp_dest
*dest
;
5665 struct bgp_path_info
*new;
5666 struct attr
*attr_new
;
5667 struct attr attr
= {0};
5668 struct bgp_path_info
*pi
;
5669 #ifdef ENABLE_BGP_VNC
5670 mpls_label_t label
= 0;
5672 uint32_t num_labels
= 0;
5677 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5679 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5682 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5684 attr
.nexthop
= bgp_static
->igpnexthop
;
5685 attr
.med
= bgp_static
->igpmetric
;
5686 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5688 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5689 || (safi
== SAFI_ENCAP
)) {
5690 if (afi
== AFI_IP
) {
5691 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5692 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5695 if (afi
== AFI_L2VPN
) {
5696 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5698 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5699 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5700 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5701 sizeof(struct in6_addr
));
5702 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
5703 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5704 struct bgp_encap_type_vxlan bet
;
5705 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5706 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5707 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5709 if (bgp_static
->router_mac
) {
5710 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5713 /* Apply route-map. */
5714 if (bgp_static
->rmap
.name
) {
5715 struct attr attr_tmp
= attr
;
5716 struct bgp_path_info rmap_path
;
5717 route_map_result_t ret
;
5719 rmap_path
.peer
= bgp
->peer_self
;
5720 rmap_path
.attr
= &attr_tmp
;
5722 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5724 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5726 bgp
->peer_self
->rmap_type
= 0;
5728 if (ret
== RMAP_DENYMATCH
) {
5729 /* Free uninterned attribute. */
5730 bgp_attr_flush(&attr_tmp
);
5732 /* Unintern original. */
5733 aspath_unintern(&attr
.aspath
);
5734 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5739 attr_new
= bgp_attr_intern(&attr_tmp
);
5741 attr_new
= bgp_attr_intern(&attr
);
5744 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5745 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5746 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5750 memset(&add
, 0, sizeof(union gw_addr
));
5751 if (attrhash_cmp(pi
->attr
, attr_new
)
5752 && overlay_index_equal(afi
, pi
, &add
)
5753 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5754 bgp_dest_unlock_node(dest
);
5755 bgp_attr_unintern(&attr_new
);
5756 aspath_unintern(&attr
.aspath
);
5759 /* The attribute is changed. */
5760 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5762 /* Rewrite BGP route information. */
5763 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5764 bgp_path_info_restore(dest
, pi
);
5766 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5767 bgp_attr_unintern(&pi
->attr
);
5768 pi
->attr
= attr_new
;
5769 pi
->uptime
= bgp_clock();
5770 #ifdef ENABLE_BGP_VNC
5772 label
= decode_label(&pi
->extra
->label
[0]);
5775 /* Process change. */
5776 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5777 bgp_process(bgp
, dest
, afi
, safi
);
5779 if (SAFI_MPLS_VPN
== safi
5780 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5781 vpn_leak_to_vrf_update(bgp
, pi
);
5783 #ifdef ENABLE_BGP_VNC
5784 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5785 pi
->attr
, afi
, safi
, pi
->type
,
5786 pi
->sub_type
, &label
);
5788 bgp_dest_unlock_node(dest
);
5789 aspath_unintern(&attr
.aspath
);
5795 /* Make new BGP info. */
5796 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5798 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5799 new->extra
= bgp_path_info_extra_new();
5801 new->extra
->label
[0] = bgp_static
->label
;
5802 new->extra
->num_labels
= num_labels
;
5804 #ifdef ENABLE_BGP_VNC
5805 label
= decode_label(&bgp_static
->label
);
5808 /* Aggregate address increment. */
5809 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5811 /* Register new BGP information. */
5812 bgp_path_info_add(dest
, new);
5813 /* route_node_get lock */
5814 bgp_dest_unlock_node(dest
);
5816 /* Process change. */
5817 bgp_process(bgp
, dest
, afi
, safi
);
5819 if (SAFI_MPLS_VPN
== safi
5820 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5821 vpn_leak_to_vrf_update(bgp
, new);
5823 #ifdef ENABLE_BGP_VNC
5824 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5825 safi
, new->type
, new->sub_type
, &label
);
5828 /* Unintern original. */
5829 aspath_unintern(&attr
.aspath
);
5832 /* Configure static BGP network. When user don't run zebra, static
5833 route should be installed as valid. */
5834 int bgp_static_set(struct bgp
*bgp
, const char *negate
, struct prefix
*pfx
,
5835 afi_t afi
, safi_t safi
, const char *rmap
, int backdoor
,
5836 uint32_t label_index
, char *errmsg
, size_t errmsg_len
)
5839 struct bgp_static
*bgp_static
;
5840 struct bgp_dest
*dest
;
5841 uint8_t need_update
= 0;
5843 prefix_copy(&p
, pfx
);
5848 /* Set BGP static route configuration. */
5849 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5852 snprintf(errmsg
, errmsg_len
,
5853 "Can't find static route specified\n");
5857 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5859 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5860 && (label_index
!= bgp_static
->label_index
)) {
5861 snprintf(errmsg
, errmsg_len
,
5862 "label-index doesn't match static route\n");
5866 if ((rmap
&& bgp_static
->rmap
.name
)
5867 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5868 snprintf(errmsg
, errmsg_len
,
5869 "route-map name doesn't match static route\n");
5873 /* Update BGP RIB. */
5874 if (!bgp_static
->backdoor
)
5875 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5877 /* Clear configuration. */
5878 bgp_static_free(bgp_static
);
5879 bgp_dest_set_bgp_static_info(dest
, NULL
);
5880 bgp_dest_unlock_node(dest
);
5881 bgp_dest_unlock_node(dest
);
5884 /* Set BGP static route configuration. */
5885 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5886 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5888 /* Configuration change. */
5889 /* Label index cannot be changed. */
5890 if (bgp_static
->label_index
!= label_index
) {
5891 snprintf(errmsg
, errmsg_len
,
5892 "cannot change label-index\n");
5896 /* Check previous routes are installed into BGP. */
5897 if (bgp_static
->valid
5898 && bgp_static
->backdoor
!= backdoor
)
5901 bgp_static
->backdoor
= backdoor
;
5904 XFREE(MTYPE_ROUTE_MAP_NAME
,
5905 bgp_static
->rmap
.name
);
5906 route_map_counter_decrement(
5907 bgp_static
->rmap
.map
);
5908 bgp_static
->rmap
.name
=
5909 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5910 bgp_static
->rmap
.map
=
5911 route_map_lookup_by_name(rmap
);
5912 route_map_counter_increment(
5913 bgp_static
->rmap
.map
);
5915 XFREE(MTYPE_ROUTE_MAP_NAME
,
5916 bgp_static
->rmap
.name
);
5917 route_map_counter_decrement(
5918 bgp_static
->rmap
.map
);
5919 bgp_static
->rmap
.map
= NULL
;
5920 bgp_static
->valid
= 0;
5922 bgp_dest_unlock_node(dest
);
5924 /* New configuration. */
5925 bgp_static
= bgp_static_new();
5926 bgp_static
->backdoor
= backdoor
;
5927 bgp_static
->valid
= 0;
5928 bgp_static
->igpmetric
= 0;
5929 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5930 bgp_static
->label_index
= label_index
;
5933 XFREE(MTYPE_ROUTE_MAP_NAME
,
5934 bgp_static
->rmap
.name
);
5935 route_map_counter_decrement(
5936 bgp_static
->rmap
.map
);
5937 bgp_static
->rmap
.name
=
5938 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5939 bgp_static
->rmap
.map
=
5940 route_map_lookup_by_name(rmap
);
5941 route_map_counter_increment(
5942 bgp_static
->rmap
.map
);
5944 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5947 bgp_static
->valid
= 1;
5949 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5951 if (!bgp_static
->backdoor
)
5952 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5958 void bgp_static_add(struct bgp
*bgp
)
5962 struct bgp_dest
*dest
;
5963 struct bgp_dest
*rm
;
5964 struct bgp_table
*table
;
5965 struct bgp_static
*bgp_static
;
5967 FOREACH_AFI_SAFI (afi
, safi
)
5968 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5969 dest
= bgp_route_next(dest
)) {
5970 if (!bgp_dest_has_bgp_path_info_data(dest
))
5973 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5974 || (safi
== SAFI_EVPN
)) {
5975 table
= bgp_dest_get_bgp_table_info(dest
);
5977 for (rm
= bgp_table_top(table
); rm
;
5978 rm
= bgp_route_next(rm
)) {
5980 bgp_dest_get_bgp_static_info(
5982 bgp_static_update_safi(
5983 bgp
, bgp_dest_get_prefix(rm
),
5984 bgp_static
, afi
, safi
);
5988 bgp
, bgp_dest_get_prefix(dest
),
5989 bgp_dest_get_bgp_static_info(dest
), afi
,
5995 /* Called from bgp_delete(). Delete all static routes from the BGP
5997 void bgp_static_delete(struct bgp
*bgp
)
6001 struct bgp_dest
*dest
;
6002 struct bgp_dest
*rm
;
6003 struct bgp_table
*table
;
6004 struct bgp_static
*bgp_static
;
6006 FOREACH_AFI_SAFI (afi
, safi
)
6007 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6008 dest
= bgp_route_next(dest
)) {
6009 if (!bgp_dest_has_bgp_path_info_data(dest
))
6012 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6013 || (safi
== SAFI_EVPN
)) {
6014 table
= bgp_dest_get_bgp_table_info(dest
);
6016 for (rm
= bgp_table_top(table
); rm
;
6017 rm
= bgp_route_next(rm
)) {
6019 bgp_dest_get_bgp_static_info(
6024 bgp_static_withdraw_safi(
6025 bgp
, bgp_dest_get_prefix(rm
),
6027 (struct prefix_rd
*)
6028 bgp_dest_get_prefix(
6030 bgp_static_free(bgp_static
);
6031 bgp_dest_set_bgp_static_info(rm
,
6033 bgp_dest_unlock_node(rm
);
6036 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6037 bgp_static_withdraw(bgp
,
6038 bgp_dest_get_prefix(dest
),
6040 bgp_static_free(bgp_static
);
6041 bgp_dest_set_bgp_static_info(dest
, NULL
);
6042 bgp_dest_unlock_node(dest
);
6047 void bgp_static_redo_import_check(struct bgp
*bgp
)
6051 struct bgp_dest
*dest
;
6052 struct bgp_dest
*rm
;
6053 struct bgp_table
*table
;
6054 struct bgp_static
*bgp_static
;
6056 /* Use this flag to force reprocessing of the route */
6057 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6058 FOREACH_AFI_SAFI (afi
, safi
) {
6059 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6060 dest
= bgp_route_next(dest
)) {
6061 if (!bgp_dest_has_bgp_path_info_data(dest
))
6064 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6065 || (safi
== SAFI_EVPN
)) {
6066 table
= bgp_dest_get_bgp_table_info(dest
);
6068 for (rm
= bgp_table_top(table
); rm
;
6069 rm
= bgp_route_next(rm
)) {
6071 bgp_dest_get_bgp_static_info(
6073 bgp_static_update_safi(
6074 bgp
, bgp_dest_get_prefix(rm
),
6075 bgp_static
, afi
, safi
);
6078 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6079 bgp_static_update(bgp
,
6080 bgp_dest_get_prefix(dest
),
6081 bgp_static
, afi
, safi
);
6085 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6088 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6091 struct bgp_table
*table
;
6092 struct bgp_dest
*dest
;
6093 struct bgp_path_info
*pi
;
6095 /* Do not install the aggregate route if BGP is in the
6096 * process of termination.
6098 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6099 || (bgp
->peer_self
== NULL
))
6102 table
= bgp
->rib
[afi
][safi
];
6103 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6104 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6105 if (pi
->peer
== bgp
->peer_self
6106 && ((pi
->type
== ZEBRA_ROUTE_BGP
6107 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6108 || (pi
->type
!= ZEBRA_ROUTE_BGP
6110 == BGP_ROUTE_REDISTRIBUTE
))) {
6111 bgp_aggregate_decrement(
6112 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6114 bgp_unlink_nexthop(pi
);
6115 bgp_path_info_delete(dest
, pi
);
6116 bgp_process(bgp
, dest
, afi
, safi
);
6123 * Purge all networks and redistributed routes from routing table.
6124 * Invoked upon the instance going down.
6126 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6131 FOREACH_AFI_SAFI (afi
, safi
)
6132 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6137 * Currently this is used to set static routes for VPN and ENCAP.
6138 * I think it can probably be factored with bgp_static_set.
6140 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6141 const char *ip_str
, const char *rd_str
,
6142 const char *label_str
, const char *rmap_str
,
6143 int evpn_type
, const char *esi
, const char *gwip
,
6144 const char *ethtag
, const char *routermac
)
6146 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6149 struct prefix_rd prd
;
6150 struct bgp_dest
*pdest
;
6151 struct bgp_dest
*dest
;
6152 struct bgp_table
*table
;
6153 struct bgp_static
*bgp_static
;
6154 mpls_label_t label
= MPLS_INVALID_LABEL
;
6155 struct prefix gw_ip
;
6157 /* validate ip prefix */
6158 ret
= str2prefix(ip_str
, &p
);
6160 vty_out(vty
, "%% Malformed prefix\n");
6161 return CMD_WARNING_CONFIG_FAILED
;
6164 if ((afi
== AFI_L2VPN
)
6165 && (bgp_build_evpn_prefix(evpn_type
,
6166 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6167 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6168 return CMD_WARNING_CONFIG_FAILED
;
6171 ret
= str2prefix_rd(rd_str
, &prd
);
6173 vty_out(vty
, "%% Malformed rd\n");
6174 return CMD_WARNING_CONFIG_FAILED
;
6178 unsigned long label_val
;
6179 label_val
= strtoul(label_str
, NULL
, 10);
6180 encode_label(label_val
, &label
);
6183 if (safi
== SAFI_EVPN
) {
6184 if (esi
&& str2esi(esi
, NULL
) == 0) {
6185 vty_out(vty
, "%% Malformed ESI\n");
6186 return CMD_WARNING_CONFIG_FAILED
;
6188 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6189 vty_out(vty
, "%% Malformed Router MAC\n");
6190 return CMD_WARNING_CONFIG_FAILED
;
6193 memset(&gw_ip
, 0, sizeof(struct prefix
));
6194 ret
= str2prefix(gwip
, &gw_ip
);
6196 vty_out(vty
, "%% Malformed GatewayIp\n");
6197 return CMD_WARNING_CONFIG_FAILED
;
6199 if ((gw_ip
.family
== AF_INET
6200 && is_evpn_prefix_ipaddr_v6(
6201 (struct prefix_evpn
*)&p
))
6202 || (gw_ip
.family
== AF_INET6
6203 && is_evpn_prefix_ipaddr_v4(
6204 (struct prefix_evpn
*)&p
))) {
6206 "%% GatewayIp family differs with IP prefix\n");
6207 return CMD_WARNING_CONFIG_FAILED
;
6211 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6212 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6213 bgp_dest_set_bgp_table_info(pdest
,
6214 bgp_table_init(bgp
, afi
, safi
));
6215 table
= bgp_dest_get_bgp_table_info(pdest
);
6217 dest
= bgp_node_get(table
, &p
);
6219 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6220 vty_out(vty
, "%% Same network configuration exists\n");
6221 bgp_dest_unlock_node(dest
);
6223 /* New configuration. */
6224 bgp_static
= bgp_static_new();
6225 bgp_static
->backdoor
= 0;
6226 bgp_static
->valid
= 0;
6227 bgp_static
->igpmetric
= 0;
6228 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6229 bgp_static
->label
= label
;
6230 bgp_static
->prd
= prd
;
6233 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6234 route_map_counter_decrement(bgp_static
->rmap
.map
);
6235 bgp_static
->rmap
.name
=
6236 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6237 bgp_static
->rmap
.map
=
6238 route_map_lookup_by_name(rmap_str
);
6239 route_map_counter_increment(bgp_static
->rmap
.map
);
6242 if (safi
== SAFI_EVPN
) {
6244 bgp_static
->eth_s_id
=
6247 str2esi(esi
, bgp_static
->eth_s_id
);
6250 bgp_static
->router_mac
=
6251 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
6252 (void)prefix_str2mac(routermac
,
6253 bgp_static
->router_mac
);
6256 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
6258 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6260 bgp_static
->valid
= 1;
6261 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
6267 /* Configure static BGP network. */
6268 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6269 const char *ip_str
, const char *rd_str
,
6270 const char *label_str
, int evpn_type
, const char *esi
,
6271 const char *gwip
, const char *ethtag
)
6273 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6276 struct prefix_rd prd
;
6277 struct bgp_dest
*pdest
;
6278 struct bgp_dest
*dest
;
6279 struct bgp_table
*table
;
6280 struct bgp_static
*bgp_static
;
6281 mpls_label_t label
= MPLS_INVALID_LABEL
;
6283 /* Convert IP prefix string to struct prefix. */
6284 ret
= str2prefix(ip_str
, &p
);
6286 vty_out(vty
, "%% Malformed prefix\n");
6287 return CMD_WARNING_CONFIG_FAILED
;
6290 if ((afi
== AFI_L2VPN
)
6291 && (bgp_build_evpn_prefix(evpn_type
,
6292 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6293 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6294 return CMD_WARNING_CONFIG_FAILED
;
6296 ret
= str2prefix_rd(rd_str
, &prd
);
6298 vty_out(vty
, "%% Malformed rd\n");
6299 return CMD_WARNING_CONFIG_FAILED
;
6303 unsigned long label_val
;
6304 label_val
= strtoul(label_str
, NULL
, 10);
6305 encode_label(label_val
, &label
);
6308 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6309 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6310 bgp_dest_set_bgp_table_info(pdest
,
6311 bgp_table_init(bgp
, afi
, safi
));
6313 bgp_dest_unlock_node(pdest
);
6314 table
= bgp_dest_get_bgp_table_info(pdest
);
6316 dest
= bgp_node_lookup(table
, &p
);
6319 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6321 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6322 bgp_static_free(bgp_static
);
6323 bgp_dest_set_bgp_static_info(dest
, NULL
);
6324 bgp_dest_unlock_node(dest
);
6325 bgp_dest_unlock_node(dest
);
6327 vty_out(vty
, "%% Can't find the route\n");
6332 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6333 const char *rmap_name
)
6335 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6336 struct bgp_rmap
*rmap
;
6338 rmap
= &bgp
->table_map
[afi
][safi
];
6340 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6341 route_map_counter_decrement(rmap
->map
);
6342 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6343 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6344 route_map_counter_increment(rmap
->map
);
6346 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6347 route_map_counter_decrement(rmap
->map
);
6351 if (bgp_fibupd_safi(safi
))
6352 bgp_zebra_announce_table(bgp
, afi
, safi
);
6357 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6358 const char *rmap_name
)
6360 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6361 struct bgp_rmap
*rmap
;
6363 rmap
= &bgp
->table_map
[afi
][safi
];
6364 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6365 route_map_counter_decrement(rmap
->map
);
6368 if (bgp_fibupd_safi(safi
))
6369 bgp_zebra_announce_table(bgp
, afi
, safi
);
6374 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6377 if (bgp
->table_map
[afi
][safi
].name
) {
6378 vty_out(vty
, " table-map %s\n",
6379 bgp
->table_map
[afi
][safi
].name
);
6383 DEFUN (bgp_table_map
,
6386 "BGP table to RIB route download filter\n"
6387 "Name of the route map\n")
6390 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6391 argv
[idx_word
]->arg
);
6393 DEFUN (no_bgp_table_map
,
6394 no_bgp_table_map_cmd
,
6395 "no table-map WORD",
6397 "BGP table to RIB route download filter\n"
6398 "Name of the route map\n")
6401 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6402 argv
[idx_word
]->arg
);
6405 DEFPY_YANG (bgp_network
, bgp_network_cmd
,
6407 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6408 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6409 backdoor$backdoor}]",
6411 "Specify a network to announce via BGP\n"
6416 "Route-map to modify the attributes\n"
6417 "Name of the route map\n"
6418 "Label index to associate with the prefix\n"
6419 "Label index value\n"
6420 "Specify a BGP backdoor route\n")
6422 char addr_prefix_str
[PREFIX_STRLEN
];
6423 char base_xpath
[XPATH_MAXLEN
];
6430 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6432 sizeof(addr_prefix_str
));
6434 vty_out(vty
, "%% Inconsistent address and mask\n");
6435 return CMD_WARNING_CONFIG_FAILED
;
6439 afi
= bgp_node_afi(vty
);
6440 safi
= bgp_node_safi(vty
);
6443 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6445 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6448 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6449 NB_OP_CREATE
, map_name
);
6451 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6452 NB_OP_DESTROY
, NULL
);
6454 if (label_index_str
)
6455 nb_cli_enqueue_change(vty
, "./label-index",
6456 NB_OP_MODIFY
, label_index_str
);
6458 nb_cli_enqueue_change(vty
, "./backdoor", NB_OP_MODIFY
,
6459 backdoor
? "true" : "false");
6463 base_xpath
, sizeof(base_xpath
),
6464 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6465 yang_afi_safi_value2identity(afi
, safi
),
6466 bgp_afi_safi_get_container_str(afi
, safi
),
6467 address_str
? addr_prefix_str
: prefix_str
);
6469 return nb_cli_apply_changes(vty
, base_xpath
);
6472 DEFPY_YANG (ipv6_bgp_network
,
6473 ipv6_bgp_network_cmd
,
6474 "[no] network X:X::X:X/M$prefix \
6475 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6477 "Specify a network to announce via BGP\n"
6479 "Route-map to modify the attributes\n"
6480 "Name of the route map\n"
6481 "Label index to associate with the prefix\n"
6482 "Label index value\n")
6484 char base_xpath
[XPATH_MAXLEN
];
6488 afi
= bgp_node_afi(vty
);
6489 safi
= bgp_node_safi(vty
);
6492 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6494 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6497 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6498 NB_OP_MODIFY
, map_name
);
6500 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6501 NB_OP_DESTROY
, NULL
);
6503 if (label_index_str
)
6504 nb_cli_enqueue_change(vty
, "./label-index",
6505 NB_OP_MODIFY
, label_index_str
);
6509 base_xpath
, sizeof(base_xpath
),
6510 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6511 yang_afi_safi_value2identity(afi
, safi
),
6512 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
6514 return nb_cli_apply_changes(vty
, base_xpath
);
6517 void cli_show_bgp_global_afi_safi_network_config(struct vty
*vty
,
6518 struct lyd_node
*dnode
,
6521 vty_out(vty
, " network %s", yang_dnode_get_string(dnode
, "./prefix"));
6523 if (yang_dnode_exists(dnode
, "./label-index"))
6524 vty_out(vty
, " label-index %s",
6525 yang_dnode_get_string(dnode
, "./label-index"));
6527 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
6528 vty_out(vty
, " route-map %s",
6529 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
6531 if (yang_dnode_get_bool(dnode
, "./backdoor"))
6532 vty_out(vty
, " backdoor");
6537 static struct bgp_aggregate
*bgp_aggregate_new(void)
6539 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6542 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6544 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
6545 route_map_counter_decrement(aggregate
->suppress_map
);
6546 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6547 route_map_counter_decrement(aggregate
->rmap
.map
);
6548 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6552 * Helper function to avoid repeated code: prepare variables for a
6553 * `route_map_apply` call.
6555 * \returns `true` on route map match, otherwise `false`.
6557 static bool aggr_suppress_map_test(struct bgp
*bgp
,
6558 struct bgp_aggregate
*aggregate
,
6559 struct bgp_path_info
*pi
)
6561 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
6562 route_map_result_t rmr
= RMAP_DENYMATCH
;
6563 struct bgp_path_info rmap_path
= {};
6564 struct attr attr
= {};
6566 /* No route map entries created, just don't match. */
6567 if (aggregate
->suppress_map
== NULL
)
6570 /* Call route map matching and return result. */
6571 attr
.aspath
= aspath_empty();
6572 rmap_path
.peer
= bgp
->peer_self
;
6573 rmap_path
.attr
= &attr
;
6575 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
6576 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
6577 bgp
->peer_self
->rmap_type
= 0;
6579 bgp_attr_flush(&attr
);
6581 return rmr
== RMAP_PERMITMATCH
;
6584 /** Test whether the aggregation has suppressed this path or not. */
6585 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
6586 struct bgp_path_info
*pi
)
6588 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
6591 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
6595 * Suppress this path and keep the reference.
6597 * \returns `true` if needs processing otherwise `false`.
6599 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
6600 struct bgp_path_info
*pi
)
6602 struct bgp_path_info_extra
*pie
;
6604 /* Path is already suppressed by this aggregation. */
6605 if (aggr_suppress_exists(aggregate
, pi
))
6608 pie
= bgp_path_info_extra_get(pi
);
6610 /* This is the first suppression, allocate memory and list it. */
6611 if (pie
->aggr_suppressors
== NULL
)
6612 pie
->aggr_suppressors
= list_new();
6614 listnode_add(pie
->aggr_suppressors
, aggregate
);
6616 /* Only mark for processing if suppressed. */
6617 if (listcount(pie
->aggr_suppressors
) == 1) {
6618 if (BGP_DEBUG(update
, UPDATE_OUT
))
6619 zlog_debug("aggregate-address suppressing: %pFX",
6620 bgp_dest_get_prefix(pi
->net
));
6622 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6630 * Unsuppress this path and remove the reference.
6632 * \returns `true` if needs processing otherwise `false`.
6634 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
6635 struct bgp_path_info
*pi
)
6637 /* Path wasn't suppressed. */
6638 if (!aggr_suppress_exists(aggregate
, pi
))
6641 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
6643 /* Unsuppress and free extra memory if last item. */
6644 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
6645 if (BGP_DEBUG(update
, UPDATE_OUT
))
6646 zlog_debug("aggregate-address unsuppressing: %pFX",
6647 bgp_dest_get_prefix(pi
->net
));
6649 list_delete(&pi
->extra
->aggr_suppressors
);
6650 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6657 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6658 struct aspath
*aspath
,
6659 struct community
*comm
,
6660 struct ecommunity
*ecomm
,
6661 struct lcommunity
*lcomm
)
6663 static struct aspath
*ae
= NULL
;
6666 ae
= aspath_empty();
6671 if (origin
!= pi
->attr
->origin
)
6674 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6677 if (!community_cmp(pi
->attr
->community
, comm
))
6680 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6683 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6686 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6692 static void bgp_aggregate_install(
6693 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6694 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6695 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6696 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6698 struct bgp_dest
*dest
;
6699 struct bgp_table
*table
;
6700 struct bgp_path_info
*pi
, *orig
, *new;
6703 table
= bgp
->rib
[afi
][safi
];
6705 dest
= bgp_node_get(table
, p
);
6707 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6708 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6709 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6713 * If we have paths with different MEDs, then don't install
6714 * (or uninstall) the aggregate route.
6716 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
6717 goto uninstall_aggregate_route
;
6719 if (aggregate
->count
> 0) {
6721 * If the aggregate information has not changed
6722 * no need to re-install it again.
6724 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6725 ecommunity
, lcommunity
)) {
6726 bgp_dest_unlock_node(dest
);
6729 aspath_free(aspath
);
6731 community_free(&community
);
6733 ecommunity_free(&ecommunity
);
6735 lcommunity_free(&lcommunity
);
6741 * Mark the old as unusable
6744 bgp_path_info_delete(dest
, pi
);
6746 attr
= bgp_attr_aggregate_intern(
6747 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6748 aggregate
, atomic_aggregate
, p
);
6751 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6752 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
6753 zlog_debug("%s: %pFX null attribute", __func__
,
6758 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6759 bgp
->peer_self
, attr
, dest
);
6761 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6763 bgp_path_info_add(dest
, new);
6764 bgp_process(bgp
, dest
, afi
, safi
);
6766 uninstall_aggregate_route
:
6767 for (pi
= orig
; pi
; pi
= pi
->next
)
6768 if (pi
->peer
== bgp
->peer_self
6769 && pi
->type
== ZEBRA_ROUTE_BGP
6770 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6773 /* Withdraw static BGP route from routing table. */
6775 bgp_path_info_delete(dest
, pi
);
6776 bgp_process(bgp
, dest
, afi
, safi
);
6780 bgp_dest_unlock_node(dest
);
6784 * Check if the current path has different MED than other known paths.
6786 * \returns `true` if the MED matched the others else `false`.
6788 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
6789 struct bgp
*bgp
, struct bgp_path_info
*pi
)
6791 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
6793 /* This is the first route being analyzed. */
6794 if (!aggregate
->med_initialized
) {
6795 aggregate
->med_initialized
= true;
6796 aggregate
->med_mismatched
= false;
6797 aggregate
->med_matched_value
= cur_med
;
6799 /* Check if routes with different MED showed up. */
6800 if (cur_med
!= aggregate
->med_matched_value
)
6801 aggregate
->med_mismatched
= true;
6804 return !aggregate
->med_mismatched
;
6808 * Initializes and tests all routes in the aggregate address path for MED
6811 * \returns `true` if all MEDs are the same otherwise `false`.
6813 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
6814 struct bgp
*bgp
, const struct prefix
*p
,
6815 afi_t afi
, safi_t safi
)
6817 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6818 const struct prefix
*dest_p
;
6819 struct bgp_dest
*dest
, *top
;
6820 struct bgp_path_info
*pi
;
6821 bool med_matched
= true;
6823 aggregate
->med_initialized
= false;
6825 top
= bgp_node_get(table
, p
);
6826 for (dest
= bgp_node_get(table
, p
); dest
;
6827 dest
= bgp_route_next_until(dest
, top
)) {
6828 dest_p
= bgp_dest_get_prefix(dest
);
6829 if (dest_p
->prefixlen
<= p
->prefixlen
)
6832 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6833 if (BGP_PATH_HOLDDOWN(pi
))
6835 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6837 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
6838 med_matched
= false;
6845 bgp_dest_unlock_node(top
);
6851 * Toggles the route suppression status for this aggregate address
6854 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
6855 struct bgp
*bgp
, const struct prefix
*p
,
6856 afi_t afi
, safi_t safi
, bool suppress
)
6858 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6859 const struct prefix
*dest_p
;
6860 struct bgp_dest
*dest
, *top
;
6861 struct bgp_path_info
*pi
;
6862 bool toggle_suppression
;
6864 /* We've found a different MED we must revert any suppressed routes. */
6865 top
= bgp_node_get(table
, p
);
6866 for (dest
= bgp_node_get(table
, p
); dest
;
6867 dest
= bgp_route_next_until(dest
, top
)) {
6868 dest_p
= bgp_dest_get_prefix(dest
);
6869 if (dest_p
->prefixlen
<= p
->prefixlen
)
6872 toggle_suppression
= false;
6873 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6874 if (BGP_PATH_HOLDDOWN(pi
))
6876 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6879 /* We are toggling suppression back. */
6881 /* Suppress route if not suppressed already. */
6882 if (aggr_suppress_path(aggregate
, pi
))
6883 toggle_suppression
= true;
6887 /* Install route if there is no more suppression. */
6888 if (aggr_unsuppress_path(aggregate
, pi
))
6889 toggle_suppression
= true;
6892 if (toggle_suppression
)
6893 bgp_process(bgp
, dest
, afi
, safi
);
6895 bgp_dest_unlock_node(top
);
6899 * Aggregate address MED matching incremental test: this function is called
6900 * when the initial aggregation occurred and we are only testing a single
6903 * In addition to testing and setting the MED validity it also installs back
6904 * suppressed routes (if summary is configured).
6906 * Must not be called in `bgp_aggregate_route`.
6908 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
6909 struct bgp
*bgp
, const struct prefix
*p
,
6910 afi_t afi
, safi_t safi
,
6911 struct bgp_path_info
*pi
, bool is_adding
)
6913 /* MED matching disabled. */
6914 if (!aggregate
->match_med
)
6917 /* Aggregation with different MED, nothing to do. */
6918 if (aggregate
->med_mismatched
)
6922 * Test the current entry:
6924 * is_adding == true: if the new entry doesn't match then we must
6925 * install all suppressed routes.
6927 * is_adding == false: if the entry being removed was the last
6928 * unmatching entry then we can suppress all routes.
6931 if (bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
)
6932 && aggregate
->summary_only
)
6933 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
,
6936 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
6938 /* No mismatches, just quit. */
6939 if (!aggregate
->med_mismatched
)
6942 /* Route summarization is disabled. */
6943 if (!aggregate
->summary_only
)
6946 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
6949 /* Update an aggregate as routes are added/removed from the BGP table */
6950 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6951 safi_t safi
, struct bgp_aggregate
*aggregate
)
6953 struct bgp_table
*table
;
6954 struct bgp_dest
*top
;
6955 struct bgp_dest
*dest
;
6957 struct aspath
*aspath
= NULL
;
6958 struct community
*community
= NULL
;
6959 struct ecommunity
*ecommunity
= NULL
;
6960 struct lcommunity
*lcommunity
= NULL
;
6961 struct bgp_path_info
*pi
;
6962 unsigned long match
= 0;
6963 uint8_t atomic_aggregate
= 0;
6965 /* If the bgp instance is being deleted or self peer is deleted
6966 * then do not create aggregate route
6968 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6969 || (bgp
->peer_self
== NULL
))
6972 /* Initialize and test routes for MED difference. */
6973 if (aggregate
->match_med
)
6974 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
6977 * Reset aggregate count: we might've been called from route map
6978 * update so in that case we must retest all more specific routes.
6980 * \see `bgp_route_map_process_update`.
6982 aggregate
->count
= 0;
6983 aggregate
->incomplete_origin_count
= 0;
6984 aggregate
->incomplete_origin_count
= 0;
6985 aggregate
->egp_origin_count
= 0;
6987 /* ORIGIN attribute: If at least one route among routes that are
6988 aggregated has ORIGIN with the value INCOMPLETE, then the
6989 aggregated route must have the ORIGIN attribute with the value
6990 INCOMPLETE. Otherwise, if at least one route among routes that
6991 are aggregated has ORIGIN with the value EGP, then the aggregated
6992 route must have the origin attribute with the value EGP. In all
6993 other case the value of the ORIGIN attribute of the aggregated
6994 route is INTERNAL. */
6995 origin
= BGP_ORIGIN_IGP
;
6997 table
= bgp
->rib
[afi
][safi
];
6999 top
= bgp_node_get(table
, p
);
7000 for (dest
= bgp_node_get(table
, p
); dest
;
7001 dest
= bgp_route_next_until(dest
, top
)) {
7002 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7004 if (dest_p
->prefixlen
<= p
->prefixlen
)
7007 /* If suppress fib is enabled and route not installed
7008 * in FIB, skip the route
7010 if (!bgp_check_advertise(bgp
, dest
))
7015 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7016 if (BGP_PATH_HOLDDOWN(pi
))
7020 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7021 atomic_aggregate
= 1;
7023 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7027 * summary-only aggregate route suppress
7028 * aggregated route announcements.
7031 * Don't create summaries if MED didn't match
7032 * otherwise neither the specific routes and the
7033 * aggregation will be announced.
7035 if (aggregate
->summary_only
7036 && AGGREGATE_MED_VALID(aggregate
)) {
7037 if (aggr_suppress_path(aggregate
, pi
))
7042 * Suppress more specific routes that match the route
7046 * Don't suppress routes if MED matching is enabled and
7047 * it mismatched otherwise we might end up with no
7048 * routes for this path.
7050 if (aggregate
->suppress_map_name
7051 && AGGREGATE_MED_VALID(aggregate
)
7052 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7053 if (aggr_suppress_path(aggregate
, pi
))
7060 * If at least one route among routes that are
7061 * aggregated has ORIGIN with the value INCOMPLETE,
7062 * then the aggregated route MUST have the ORIGIN
7063 * attribute with the value INCOMPLETE. Otherwise, if
7064 * at least one route among routes that are aggregated
7065 * has ORIGIN with the value EGP, then the aggregated
7066 * route MUST have the ORIGIN attribute with the value
7069 switch (pi
->attr
->origin
) {
7070 case BGP_ORIGIN_INCOMPLETE
:
7071 aggregate
->incomplete_origin_count
++;
7073 case BGP_ORIGIN_EGP
:
7074 aggregate
->egp_origin_count
++;
7082 if (!aggregate
->as_set
)
7086 * as-set aggregate route generate origin, as path,
7087 * and community aggregation.
7089 /* Compute aggregate route's as-path.
7091 bgp_compute_aggregate_aspath_hash(aggregate
,
7094 /* Compute aggregate route's community.
7096 if (pi
->attr
->community
)
7097 bgp_compute_aggregate_community_hash(
7099 pi
->attr
->community
);
7101 /* Compute aggregate route's extended community.
7103 if (pi
->attr
->ecommunity
)
7104 bgp_compute_aggregate_ecommunity_hash(
7106 pi
->attr
->ecommunity
);
7108 /* Compute aggregate route's large community.
7110 if (pi
->attr
->lcommunity
)
7111 bgp_compute_aggregate_lcommunity_hash(
7113 pi
->attr
->lcommunity
);
7116 bgp_process(bgp
, dest
, afi
, safi
);
7118 if (aggregate
->as_set
) {
7119 bgp_compute_aggregate_aspath_val(aggregate
);
7120 bgp_compute_aggregate_community_val(aggregate
);
7121 bgp_compute_aggregate_ecommunity_val(aggregate
);
7122 bgp_compute_aggregate_lcommunity_val(aggregate
);
7126 bgp_dest_unlock_node(top
);
7129 if (aggregate
->incomplete_origin_count
> 0)
7130 origin
= BGP_ORIGIN_INCOMPLETE
;
7131 else if (aggregate
->egp_origin_count
> 0)
7132 origin
= BGP_ORIGIN_EGP
;
7134 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7135 origin
= aggregate
->origin
;
7137 if (aggregate
->as_set
) {
7138 if (aggregate
->aspath
)
7139 /* Retrieve aggregate route's as-path.
7141 aspath
= aspath_dup(aggregate
->aspath
);
7143 if (aggregate
->community
)
7144 /* Retrieve aggregate route's community.
7146 community
= community_dup(aggregate
->community
);
7148 if (aggregate
->ecommunity
)
7149 /* Retrieve aggregate route's ecommunity.
7151 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7153 if (aggregate
->lcommunity
)
7154 /* Retrieve aggregate route's lcommunity.
7156 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7159 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7160 ecommunity
, lcommunity
, atomic_aggregate
,
7164 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7165 safi_t safi
, struct bgp_aggregate
*aggregate
)
7167 struct bgp_table
*table
;
7168 struct bgp_dest
*top
;
7169 struct bgp_dest
*dest
;
7170 struct bgp_path_info
*pi
;
7171 unsigned long match
;
7173 table
= bgp
->rib
[afi
][safi
];
7175 /* If routes exists below this node, generate aggregate routes. */
7176 top
= bgp_node_get(table
, p
);
7177 for (dest
= bgp_node_get(table
, p
); dest
;
7178 dest
= bgp_route_next_until(dest
, top
)) {
7179 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7181 if (dest_p
->prefixlen
<= p
->prefixlen
)
7185 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7186 if (BGP_PATH_HOLDDOWN(pi
))
7189 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7192 if (aggregate
->summary_only
&& pi
->extra
7193 && AGGREGATE_MED_VALID(aggregate
)) {
7194 if (aggr_unsuppress_path(aggregate
, pi
))
7198 if (aggregate
->suppress_map_name
7199 && AGGREGATE_MED_VALID(aggregate
)
7200 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7201 if (aggr_unsuppress_path(aggregate
, pi
))
7207 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7208 aggregate
->incomplete_origin_count
--;
7209 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7210 aggregate
->egp_origin_count
--;
7212 if (aggregate
->as_set
) {
7213 /* Remove as-path from aggregate.
7215 bgp_remove_aspath_from_aggregate_hash(
7219 if (pi
->attr
->community
)
7220 /* Remove community from aggregate.
7222 bgp_remove_comm_from_aggregate_hash(
7224 pi
->attr
->community
);
7226 if (pi
->attr
->ecommunity
)
7227 /* Remove ecommunity from aggregate.
7229 bgp_remove_ecomm_from_aggregate_hash(
7231 pi
->attr
->ecommunity
);
7233 if (pi
->attr
->lcommunity
)
7234 /* Remove lcommunity from aggregate.
7236 bgp_remove_lcomm_from_aggregate_hash(
7238 pi
->attr
->lcommunity
);
7242 /* If this node was suppressed, process the change. */
7244 bgp_process(bgp
, dest
, afi
, safi
);
7246 if (aggregate
->as_set
) {
7247 aspath_free(aggregate
->aspath
);
7248 aggregate
->aspath
= NULL
;
7249 if (aggregate
->community
)
7250 community_free(&aggregate
->community
);
7251 if (aggregate
->ecommunity
)
7252 ecommunity_free(&aggregate
->ecommunity
);
7253 if (aggregate
->lcommunity
)
7254 lcommunity_free(&aggregate
->lcommunity
);
7257 bgp_dest_unlock_node(top
);
7260 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7261 const struct prefix
*aggr_p
,
7262 struct bgp_path_info
*pinew
, afi_t afi
,
7264 struct bgp_aggregate
*aggregate
)
7267 struct aspath
*aspath
= NULL
;
7268 uint8_t atomic_aggregate
= 0;
7269 struct community
*community
= NULL
;
7270 struct ecommunity
*ecommunity
= NULL
;
7271 struct lcommunity
*lcommunity
= NULL
;
7273 /* If the bgp instance is being deleted or self peer is deleted
7274 * then do not create aggregate route
7276 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7277 || (bgp
->peer_self
== NULL
))
7280 /* ORIGIN attribute: If at least one route among routes that are
7281 * aggregated has ORIGIN with the value INCOMPLETE, then the
7282 * aggregated route must have the ORIGIN attribute with the value
7283 * INCOMPLETE. Otherwise, if at least one route among routes that
7284 * are aggregated has ORIGIN with the value EGP, then the aggregated
7285 * route must have the origin attribute with the value EGP. In all
7286 * other case the value of the ORIGIN attribute of the aggregated
7287 * route is INTERNAL.
7289 origin
= BGP_ORIGIN_IGP
;
7294 * This must be called before `summary` check to avoid
7295 * "suppressing" twice.
7297 if (aggregate
->match_med
)
7298 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7301 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7302 aggr_suppress_path(aggregate
, pinew
);
7304 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7305 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7306 aggr_suppress_path(aggregate
, pinew
);
7308 switch (pinew
->attr
->origin
) {
7309 case BGP_ORIGIN_INCOMPLETE
:
7310 aggregate
->incomplete_origin_count
++;
7312 case BGP_ORIGIN_EGP
:
7313 aggregate
->egp_origin_count
++;
7321 if (aggregate
->incomplete_origin_count
> 0)
7322 origin
= BGP_ORIGIN_INCOMPLETE
;
7323 else if (aggregate
->egp_origin_count
> 0)
7324 origin
= BGP_ORIGIN_EGP
;
7326 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7327 origin
= aggregate
->origin
;
7329 if (aggregate
->as_set
) {
7330 /* Compute aggregate route's as-path.
7332 bgp_compute_aggregate_aspath(aggregate
,
7333 pinew
->attr
->aspath
);
7335 /* Compute aggregate route's community.
7337 if (pinew
->attr
->community
)
7338 bgp_compute_aggregate_community(
7340 pinew
->attr
->community
);
7342 /* Compute aggregate route's extended community.
7344 if (pinew
->attr
->ecommunity
)
7345 bgp_compute_aggregate_ecommunity(
7347 pinew
->attr
->ecommunity
);
7349 /* Compute aggregate route's large community.
7351 if (pinew
->attr
->lcommunity
)
7352 bgp_compute_aggregate_lcommunity(
7354 pinew
->attr
->lcommunity
);
7356 /* Retrieve aggregate route's as-path.
7358 if (aggregate
->aspath
)
7359 aspath
= aspath_dup(aggregate
->aspath
);
7361 /* Retrieve aggregate route's community.
7363 if (aggregate
->community
)
7364 community
= community_dup(aggregate
->community
);
7366 /* Retrieve aggregate route's ecommunity.
7368 if (aggregate
->ecommunity
)
7369 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7371 /* Retrieve aggregate route's lcommunity.
7373 if (aggregate
->lcommunity
)
7374 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7377 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7378 aspath
, community
, ecommunity
,
7379 lcommunity
, atomic_aggregate
, aggregate
);
7382 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7384 struct bgp_path_info
*pi
,
7385 struct bgp_aggregate
*aggregate
,
7386 const struct prefix
*aggr_p
)
7389 struct aspath
*aspath
= NULL
;
7390 uint8_t atomic_aggregate
= 0;
7391 struct community
*community
= NULL
;
7392 struct ecommunity
*ecommunity
= NULL
;
7393 struct lcommunity
*lcommunity
= NULL
;
7394 unsigned long match
= 0;
7396 /* If the bgp instance is being deleted or self peer is deleted
7397 * then do not create aggregate route
7399 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7400 || (bgp
->peer_self
== NULL
))
7403 if (BGP_PATH_HOLDDOWN(pi
))
7406 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7409 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7410 if (aggr_unsuppress_path(aggregate
, pi
))
7413 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7414 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7415 if (aggr_unsuppress_path(aggregate
, pi
))
7419 * This must be called after `summary`, `suppress-map` check to avoid
7420 * "unsuppressing" twice.
7422 if (aggregate
->match_med
)
7423 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
,
7426 if (aggregate
->count
> 0)
7429 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7430 aggregate
->incomplete_origin_count
--;
7431 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7432 aggregate
->egp_origin_count
--;
7434 if (aggregate
->as_set
) {
7435 /* Remove as-path from aggregate.
7437 bgp_remove_aspath_from_aggregate(aggregate
,
7440 if (pi
->attr
->community
)
7441 /* Remove community from aggregate.
7443 bgp_remove_community_from_aggregate(
7445 pi
->attr
->community
);
7447 if (pi
->attr
->ecommunity
)
7448 /* Remove ecommunity from aggregate.
7450 bgp_remove_ecommunity_from_aggregate(
7452 pi
->attr
->ecommunity
);
7454 if (pi
->attr
->lcommunity
)
7455 /* Remove lcommunity from aggregate.
7457 bgp_remove_lcommunity_from_aggregate(
7459 pi
->attr
->lcommunity
);
7462 /* If this node was suppressed, process the change. */
7464 bgp_process(bgp
, pi
->net
, afi
, safi
);
7466 origin
= BGP_ORIGIN_IGP
;
7467 if (aggregate
->incomplete_origin_count
> 0)
7468 origin
= BGP_ORIGIN_INCOMPLETE
;
7469 else if (aggregate
->egp_origin_count
> 0)
7470 origin
= BGP_ORIGIN_EGP
;
7472 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7473 origin
= aggregate
->origin
;
7475 if (aggregate
->as_set
) {
7476 /* Retrieve aggregate route's as-path.
7478 if (aggregate
->aspath
)
7479 aspath
= aspath_dup(aggregate
->aspath
);
7481 /* Retrieve aggregate route's community.
7483 if (aggregate
->community
)
7484 community
= community_dup(aggregate
->community
);
7486 /* Retrieve aggregate route's ecommunity.
7488 if (aggregate
->ecommunity
)
7489 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7491 /* Retrieve aggregate route's lcommunity.
7493 if (aggregate
->lcommunity
)
7494 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7497 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7498 aspath
, community
, ecommunity
,
7499 lcommunity
, atomic_aggregate
, aggregate
);
7502 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
7503 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
7505 struct bgp_dest
*child
;
7506 struct bgp_dest
*dest
;
7507 struct bgp_aggregate
*aggregate
;
7508 struct bgp_table
*table
;
7510 table
= bgp
->aggregate
[afi
][safi
];
7512 /* No aggregates configured. */
7513 if (bgp_table_top_nolock(table
) == NULL
)
7516 if (p
->prefixlen
== 0)
7519 if (BGP_PATH_HOLDDOWN(pi
))
7522 /* If suppress fib is enabled and route not installed
7523 * in FIB, do not update the aggregate route
7525 if (!bgp_check_advertise(bgp
, pi
->net
))
7528 child
= bgp_node_get(table
, p
);
7530 /* Aggregate address configuration check. */
7531 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7532 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7534 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7535 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7536 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
7540 bgp_dest_unlock_node(child
);
7543 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
7544 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
7546 struct bgp_dest
*child
;
7547 struct bgp_dest
*dest
;
7548 struct bgp_aggregate
*aggregate
;
7549 struct bgp_table
*table
;
7551 table
= bgp
->aggregate
[afi
][safi
];
7553 /* No aggregates configured. */
7554 if (bgp_table_top_nolock(table
) == NULL
)
7557 if (p
->prefixlen
== 0)
7560 child
= bgp_node_get(table
, p
);
7562 /* Aggregate address configuration check. */
7563 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7564 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7566 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7567 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7568 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
7572 bgp_dest_unlock_node(child
);
7575 /* Aggregate route attribute. */
7576 #define AGGREGATE_SUMMARY_ONLY 1
7577 #define AGGREGATE_AS_SET 1
7578 #define AGGREGATE_AS_UNSET 0
7580 static const char *bgp_origin2str(uint8_t origin
)
7583 case BGP_ORIGIN_IGP
:
7585 case BGP_ORIGIN_EGP
:
7587 case BGP_ORIGIN_INCOMPLETE
:
7588 return "incomplete";
7593 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
7596 case RPKI_NOT_BEING_USED
:
7606 assert(!"We should never get here this is a dev escape");
7610 int bgp_aggregate_unset(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7611 safi_t safi
, char *errmsg
, size_t errmsg_len
)
7613 struct bgp_dest
*dest
;
7614 struct bgp_aggregate
*aggregate
;
7616 /* If the bgp instance is being deleted or self peer is deleted
7617 * then do not create aggregate route
7619 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7620 || (bgp
->peer_self
== NULL
))
7624 /* Old configuration check. */
7625 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], prefix
);
7627 snprintf(errmsg
, errmsg_len
,
7628 "There is no aggregate-address configuration.\n");
7632 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7633 bgp_aggregate_delete(bgp
, prefix
, afi
, safi
, aggregate
);
7634 bgp_aggregate_install(bgp
, afi
, safi
, prefix
, 0, NULL
, NULL
, NULL
, NULL
,
7637 /* Unlock aggregate address configuration. */
7638 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
7640 if (aggregate
->community
)
7641 community_free(&aggregate
->community
);
7643 if (aggregate
->community_hash
) {
7644 /* Delete all communities in the hash.
7646 hash_clean(aggregate
->community_hash
,
7647 bgp_aggr_community_remove
);
7648 /* Free up the community_hash.
7650 hash_free(aggregate
->community_hash
);
7653 if (aggregate
->ecommunity
)
7654 ecommunity_free(&aggregate
->ecommunity
);
7656 if (aggregate
->ecommunity_hash
) {
7657 /* Delete all ecommunities in the hash.
7659 hash_clean(aggregate
->ecommunity_hash
,
7660 bgp_aggr_ecommunity_remove
);
7661 /* Free up the ecommunity_hash.
7663 hash_free(aggregate
->ecommunity_hash
);
7666 if (aggregate
->lcommunity
)
7667 lcommunity_free(&aggregate
->lcommunity
);
7669 if (aggregate
->lcommunity_hash
) {
7670 /* Delete all lcommunities in the hash.
7672 hash_clean(aggregate
->lcommunity_hash
,
7673 bgp_aggr_lcommunity_remove
);
7674 /* Free up the lcommunity_hash.
7676 hash_free(aggregate
->lcommunity_hash
);
7679 if (aggregate
->aspath
)
7680 aspath_free(aggregate
->aspath
);
7682 if (aggregate
->aspath_hash
) {
7683 /* Delete all as-paths in the hash.
7685 hash_clean(aggregate
->aspath_hash
,
7686 bgp_aggr_aspath_remove
);
7687 /* Free up the aspath_hash.
7689 hash_free(aggregate
->aspath_hash
);
7692 bgp_aggregate_free(aggregate
);
7693 bgp_dest_unlock_node(dest
);
7694 bgp_dest_unlock_node(dest
);
7699 int bgp_aggregate_set(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7700 safi_t safi
, const char *rmap
, uint8_t summary_only
,
7701 uint8_t as_set
, uint8_t origin
, bool match_med
,
7702 const char *suppress_map
,
7703 char *errmsg
, size_t errmsg_len
)
7706 struct bgp_dest
*dest
;
7707 struct bgp_aggregate
*aggregate
;
7708 uint8_t as_set_new
= as_set
;
7709 char buf
[PREFIX2STR_BUFFER
];
7711 if (suppress_map
&& summary_only
) {
7712 snprintf(errmsg
, errmsg_len
,
7713 "'summary-only' and 'suppress-map' can't be used at the same time\n");
7719 if ((afi
== AFI_IP
&& prefix
->prefixlen
== IPV4_MAX_BITLEN
)
7720 || (afi
== AFI_IP6
&& prefix
->prefixlen
== IPV6_MAX_BITLEN
)) {
7723 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7724 prefix2str(prefix
, buf
, PREFIX_STRLEN
));
7728 /* Old configuration check. */
7729 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], prefix
);
7730 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7733 snprintf(errmsg
, errmsg_len
,
7734 "There is already same aggregate network.\n");
7735 /* try to remove the old entry */
7736 ret
= bgp_aggregate_unset(bgp
, prefix
, afi
, safi
, errmsg
,
7739 snprintf(errmsg
, errmsg_len
,
7740 "Error deleting aggregate.\n");
7741 bgp_dest_unlock_node(dest
);
7746 /* Make aggregate address structure. */
7747 aggregate
= bgp_aggregate_new();
7748 aggregate
->summary_only
= summary_only
;
7749 aggregate
->match_med
= match_med
;
7751 /* Network operators MUST NOT locally generate any new
7752 * announcements containing AS_SET or AS_CONFED_SET. If they have
7753 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7754 * SHOULD withdraw those routes and re-announce routes for the
7755 * aggregate or component prefixes (i.e., the more-specific routes
7756 * subsumed by the previously aggregated route) without AS_SET
7757 * or AS_CONFED_SET in the updates.
7759 if (bgp
->reject_as_sets
) {
7760 if (as_set
== AGGREGATE_AS_SET
) {
7761 as_set_new
= AGGREGATE_AS_UNSET
;
7763 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7767 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7771 aggregate
->as_set
= as_set_new
;
7772 aggregate
->safi
= safi
;
7773 /* Override ORIGIN attribute if defined.
7774 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7775 * to IGP which is not what rfc4271 says.
7776 * This enables the same behavior, optionally.
7778 aggregate
->origin
= origin
;
7781 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7782 route_map_counter_decrement(aggregate
->rmap
.map
);
7783 aggregate
->rmap
.name
=
7784 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
7785 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
7786 route_map_counter_increment(aggregate
->rmap
.map
);
7790 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7791 route_map_counter_decrement(aggregate
->suppress_map
);
7793 aggregate
->suppress_map_name
=
7794 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
7795 aggregate
->suppress_map
=
7796 route_map_lookup_by_name(aggregate
->suppress_map_name
);
7797 route_map_counter_increment(aggregate
->suppress_map
);
7800 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
7802 /* Aggregate address insert into BGP routing table. */
7803 bgp_aggregate_route(bgp
, prefix
, afi
, safi
, aggregate
);
7809 aggregate_addressv4
, aggregate_addressv4_cmd
,
7810 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
7812 "|summary-only$summary_only"
7813 "|route-map WORD$rmap_name"
7814 "|origin <egp|igp|incomplete>$origin_s"
7815 "|matching-MED-only$match_med"
7816 "|suppress-map WORD$suppress_map"
7819 "Configure BGP aggregate entries\n"
7820 "Aggregate prefix\n"
7821 "Aggregate address\n"
7823 "Generate AS set path information\n"
7824 "Filter more specific routes from updates\n"
7825 "Apply route map to aggregate network\n"
7830 "Unknown heritage\n"
7831 "Only aggregate routes with matching MED\n"
7832 "Suppress the selected more specific routes\n"
7833 "Route map with the route selectors\n")
7835 char base_xpath
[XPATH_MAXLEN
];
7836 safi_t safi
= bgp_node_safi(vty
);
7837 char prefix_buf
[PREFIX2STR_BUFFER
];
7840 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
7843 vty_out(vty
, "%% Inconsistent address and mask\n");
7844 return CMD_WARNING_CONFIG_FAILED
;
7847 strlcpy(prefix_buf
, prefix_str
, sizeof(prefix_buf
));
7850 if (!no
&& origin_s
)
7851 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
7853 if (!no
&& as_set_s
)
7854 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
7856 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
7858 if (!no
&& summary_only
)
7859 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7862 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7865 if (!no
&& match_med
)
7866 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
7868 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
7872 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
7875 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
7876 NB_OP_DESTROY
, NULL
);
7879 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
7882 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
7886 base_xpath
, sizeof(base_xpath
),
7887 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7888 yang_afi_safi_value2identity(AFI_IP
, safi
),
7889 bgp_afi_safi_get_container_str(AFI_IP
, safi
), prefix_buf
);
7892 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
7894 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
7896 return nb_cli_apply_changes(vty
, base_xpath
);
7899 DEFPY_YANG(aggregate_addressv6
, aggregate_addressv6_cmd
,
7900 "[no] aggregate-address X:X::X:X/M$prefix [{"
7902 "|summary-only$summary_only"
7903 "|route-map WORD$rmap_name"
7904 "|origin <egp|igp|incomplete>$origin_s"
7905 "|matching-MED-only$match_med"
7906 "|suppress-map WORD$suppress_map"
7909 "Configure BGP aggregate entries\n"
7910 "Aggregate prefix\n"
7911 "Generate AS set path information\n"
7912 "Filter more specific routes from updates\n"
7913 "Apply route map to aggregate network\n"
7918 "Unknown heritage\n"
7919 "Only aggregate routes with matching MED\n"
7920 "Suppress the selected more specific routes\n"
7921 "Route map with the route selectors\n")
7923 char base_xpath
[XPATH_MAXLEN
];
7924 safi_t safi
= bgp_node_safi(vty
);
7926 if (!no
&& origin_s
)
7927 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
7929 if (!no
&& as_set_s
)
7930 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
7932 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
7934 if (!no
&& summary_only
)
7935 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7938 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7941 if (!no
&& match_med
)
7942 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
7944 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
7948 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
7952 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
7955 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
7959 base_xpath
, sizeof(base_xpath
),
7960 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7961 yang_afi_safi_value2identity(AFI_IP6
, safi
),
7962 bgp_afi_safi_get_container_str(AFI_IP6
, safi
), prefix_str
);
7965 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
7967 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
7969 return nb_cli_apply_changes(vty
, base_xpath
);
7972 void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7973 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
7977 vty_out(vty
, " aggregate-address %s",
7978 yang_dnode_get_string(dnode
, "./prefix"));
7980 if (yang_dnode_get_bool(dnode
, "./as-set"))
7981 vty_out(vty
, " as-set");
7983 if (yang_dnode_get_bool(dnode
, "./summary-only"))
7984 vty_out(vty
, " summary-only");
7986 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
7987 vty_out(vty
, " route-map %s",
7988 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
7990 origin
= yang_dnode_get_enum(dnode
, "./origin");
7991 if (origin
!= BGP_ORIGIN_UNSPECIFIED
)
7992 vty_out(vty
, " origin %s", bgp_origin2str(origin
));
7994 if (yang_dnode_get_bool(dnode
, "./match-med"))
7995 vty_out(vty
, " matching-MED-only");
8000 /* Redistribute route treatment. */
8001 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8002 const union g_addr
*nexthop
, ifindex_t ifindex
,
8003 enum nexthop_types_t nhtype
, uint32_t metric
,
8004 uint8_t type
, unsigned short instance
,
8007 struct bgp_path_info
*new;
8008 struct bgp_path_info
*bpi
;
8009 struct bgp_path_info rmap_path
;
8010 struct bgp_dest
*bn
;
8012 struct attr
*new_attr
;
8014 route_map_result_t ret
;
8015 struct bgp_redist
*red
;
8017 /* Make default attribute. */
8018 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
8020 * This must not be NULL to satisfy Coverity SA
8022 assert(attr
.aspath
);
8025 case NEXTHOP_TYPE_IFINDEX
:
8027 case NEXTHOP_TYPE_IPV4
:
8028 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8029 attr
.nexthop
= nexthop
->ipv4
;
8031 case NEXTHOP_TYPE_IPV6
:
8032 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8033 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8034 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8036 case NEXTHOP_TYPE_BLACKHOLE
:
8037 switch (p
->family
) {
8039 attr
.nexthop
.s_addr
= INADDR_ANY
;
8042 memset(&attr
.mp_nexthop_global
, 0,
8043 sizeof(attr
.mp_nexthop_global
));
8044 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8049 attr
.nh_ifindex
= ifindex
;
8052 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8055 afi
= family2afi(p
->family
);
8057 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8059 struct attr attr_new
;
8061 /* Copy attribute for modification. */
8064 if (red
->redist_metric_flag
)
8065 attr_new
.med
= red
->redist_metric
;
8067 /* Apply route-map. */
8068 if (red
->rmap
.name
) {
8069 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
8070 rmap_path
.peer
= bgp
->peer_self
;
8071 rmap_path
.attr
= &attr_new
;
8073 SET_FLAG(bgp
->peer_self
->rmap_type
,
8074 PEER_RMAP_TYPE_REDISTRIBUTE
);
8076 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8078 bgp
->peer_self
->rmap_type
= 0;
8080 if (ret
== RMAP_DENYMATCH
) {
8081 /* Free uninterned attribute. */
8082 bgp_attr_flush(&attr_new
);
8084 /* Unintern original. */
8085 aspath_unintern(&attr
.aspath
);
8086 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8091 if (bgp_in_graceful_shutdown(bgp
))
8092 bgp_attr_add_gshut_community(&attr_new
);
8094 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8095 SAFI_UNICAST
, p
, NULL
);
8097 new_attr
= bgp_attr_intern(&attr_new
);
8099 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8100 if (bpi
->peer
== bgp
->peer_self
8101 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8105 /* Ensure the (source route) type is updated. */
8107 if (attrhash_cmp(bpi
->attr
, new_attr
)
8108 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8109 bgp_attr_unintern(&new_attr
);
8110 aspath_unintern(&attr
.aspath
);
8111 bgp_dest_unlock_node(bn
);
8114 /* The attribute is changed. */
8115 bgp_path_info_set_flag(bn
, bpi
,
8116 BGP_PATH_ATTR_CHANGED
);
8118 /* Rewrite BGP route information. */
8119 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8120 bgp_path_info_restore(bn
, bpi
);
8122 bgp_aggregate_decrement(
8123 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8124 bgp_attr_unintern(&bpi
->attr
);
8125 bpi
->attr
= new_attr
;
8126 bpi
->uptime
= bgp_clock();
8128 /* Process change. */
8129 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8131 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8132 bgp_dest_unlock_node(bn
);
8133 aspath_unintern(&attr
.aspath
);
8135 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8137 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8139 vpn_leak_from_vrf_update(
8140 bgp_get_default(), bgp
, bpi
);
8146 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8147 bgp
->peer_self
, new_attr
, bn
);
8148 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8150 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8151 bgp_path_info_add(bn
, new);
8152 bgp_dest_unlock_node(bn
);
8153 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8155 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8156 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8158 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8162 /* Unintern original. */
8163 aspath_unintern(&attr
.aspath
);
8166 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8167 unsigned short instance
)
8170 struct bgp_dest
*dest
;
8171 struct bgp_path_info
*pi
;
8172 struct bgp_redist
*red
;
8174 afi
= family2afi(p
->family
);
8176 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8178 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8179 SAFI_UNICAST
, p
, NULL
);
8181 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8182 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8186 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8187 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8189 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8192 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8193 bgp_path_info_delete(dest
, pi
);
8194 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8196 bgp_dest_unlock_node(dest
);
8200 /* Withdraw specified route type's route. */
8201 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8202 unsigned short instance
)
8204 struct bgp_dest
*dest
;
8205 struct bgp_path_info
*pi
;
8206 struct bgp_table
*table
;
8208 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8210 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8211 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8212 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8213 && pi
->instance
== instance
)
8217 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8218 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8220 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8223 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8224 pi
, afi
, SAFI_UNICAST
);
8225 bgp_path_info_delete(dest
, pi
);
8226 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8231 /* Static function to display route. */
8232 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8233 struct vty
*vty
, json_object
*json
, bool wide
)
8239 if (p
->family
== AF_INET
) {
8241 len
= vty_out(vty
, "%pFX", p
);
8243 json_object_string_add(json
, "prefix",
8244 inet_ntop(p
->family
,
8247 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8248 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8249 json_object_string_add(json
, "network", buf2
);
8250 json_object_int_add(json
, "version", dest
->version
);
8252 } else if (p
->family
== AF_ETHERNET
) {
8253 len
= vty_out(vty
, "%pFX", p
);
8254 } else if (p
->family
== AF_EVPN
) {
8256 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8258 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8259 } else if (p
->family
== AF_FLOWSPEC
) {
8260 route_vty_out_flowspec(vty
, p
, NULL
,
8262 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8263 NLRI_STRING_FORMAT_MIN
, json
);
8266 len
= vty_out(vty
, "%pFX", p
);
8268 json_object_string_add(json
, "prefix",
8269 inet_ntop(p
->family
,
8272 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8273 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8274 json_object_string_add(json
, "network", buf2
);
8275 json_object_int_add(json
, "version", dest
->version
);
8280 len
= wide
? (45 - len
) : (17 - len
);
8282 vty_out(vty
, "\n%*s", 20, " ");
8284 vty_out(vty
, "%*s", len
, " ");
8288 enum bgp_display_type
{
8293 bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8296 case bgp_path_selection_none
:
8297 return "Nothing to Select";
8298 case bgp_path_selection_first
:
8299 return "First path received";
8300 case bgp_path_selection_evpn_sticky_mac
:
8301 return "EVPN Sticky Mac";
8302 case bgp_path_selection_evpn_seq
:
8303 return "EVPN sequence number";
8304 case bgp_path_selection_evpn_lower_ip
:
8305 return "EVPN lower IP";
8306 case bgp_path_selection_evpn_local_path
:
8307 return "EVPN local ES path";
8308 case bgp_path_selection_evpn_non_proxy
:
8309 return "EVPN non proxy";
8310 case bgp_path_selection_weight
:
8312 case bgp_path_selection_local_pref
:
8313 return "Local Pref";
8314 case bgp_path_selection_local_route
:
8315 return "Local Route";
8316 case bgp_path_selection_confed_as_path
:
8317 return "Confederation based AS Path";
8318 case bgp_path_selection_as_path
:
8320 case bgp_path_selection_origin
:
8322 case bgp_path_selection_med
:
8324 case bgp_path_selection_peer
:
8326 case bgp_path_selection_confed
:
8327 return "Confed Peer Type";
8328 case bgp_path_selection_igp_metric
:
8329 return "IGP Metric";
8330 case bgp_path_selection_older
:
8331 return "Older Path";
8332 case bgp_path_selection_router_id
:
8334 case bgp_path_selection_cluster_length
:
8335 return "Cluster length";
8336 case bgp_path_selection_stale
:
8337 return "Path Staleness";
8338 case bgp_path_selection_local_configured
:
8339 return "Locally configured route";
8340 case bgp_path_selection_neighbor_ip
:
8341 return "Neighbor IP";
8342 case bgp_path_selection_default
:
8343 return "Nothing left to compare";
8345 return "Invalid (internal error)";
8348 /* Print the short form route status for a bgp_path_info */
8349 static void route_vty_short_status_out(struct vty
*vty
,
8350 struct bgp_path_info
*path
,
8351 const struct prefix
*p
,
8352 json_object
*json_path
)
8354 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8358 /* Route status display. */
8359 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8360 json_object_boolean_true_add(json_path
, "removed");
8362 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8363 json_object_boolean_true_add(json_path
, "stale");
8365 if (path
->extra
&& bgp_path_suppressed(path
))
8366 json_object_boolean_true_add(json_path
, "suppressed");
8368 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8369 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8370 json_object_boolean_true_add(json_path
, "valid");
8373 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8374 json_object_boolean_true_add(json_path
, "history");
8376 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8377 json_object_boolean_true_add(json_path
, "damped");
8379 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8380 json_object_boolean_true_add(json_path
, "bestpath");
8381 json_object_string_add(json_path
, "selectionReason",
8382 bgp_path_selection_reason2str(
8383 path
->net
->reason
));
8386 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8387 json_object_boolean_true_add(json_path
, "multipath");
8389 /* Internal route. */
8390 if ((path
->peer
->as
)
8391 && (path
->peer
->as
== path
->peer
->local_as
))
8392 json_object_string_add(json_path
, "pathFrom",
8395 json_object_string_add(json_path
, "pathFrom",
8401 /* RPKI validation state */
8403 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
8405 if (rpki_state
== RPKI_VALID
)
8407 else if (rpki_state
== RPKI_INVALID
)
8409 else if (rpki_state
== RPKI_NOTFOUND
)
8412 /* Route status display. */
8413 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8415 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8417 else if (bgp_path_suppressed(path
))
8419 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8420 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8426 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8428 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8430 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8432 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8437 /* Internal route. */
8438 if (path
->peer
&& (path
->peer
->as
)
8439 && (path
->peer
->as
== path
->peer
->local_as
))
8445 static char *bgp_nexthop_hostname(struct peer
*peer
,
8446 struct bgp_nexthop_cache
*bnc
)
8449 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8450 return peer
->hostname
;
8454 /* called from terminal list command */
8455 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8456 struct bgp_path_info
*path
, int display
, safi_t safi
,
8457 json_object
*json_paths
, bool wide
)
8460 struct attr
*attr
= path
->attr
;
8461 json_object
*json_path
= NULL
;
8462 json_object
*json_nexthops
= NULL
;
8463 json_object
*json_nexthop_global
= NULL
;
8464 json_object
*json_nexthop_ll
= NULL
;
8465 json_object
*json_ext_community
= NULL
;
8466 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8468 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8469 bool nexthop_othervrf
= false;
8470 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8471 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8472 char *nexthop_hostname
=
8473 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8474 char esi_buf
[ESI_STR_LEN
];
8477 json_path
= json_object_new_object();
8479 /* short status lead text */
8480 route_vty_short_status_out(vty
, path
, p
, json_path
);
8483 /* print prefix and mask */
8485 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8487 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8489 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8493 * If vrf id of nexthop is different from that of prefix,
8494 * set up printable string to append
8496 if (path
->extra
&& path
->extra
->bgp_orig
) {
8497 const char *self
= "";
8502 nexthop_othervrf
= true;
8503 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8505 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8506 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8507 "@%s%s", VRFID_NONE_STR
, self
);
8509 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8510 path
->extra
->bgp_orig
->vrf_id
, self
);
8512 if (path
->extra
->bgp_orig
->inst_type
8513 != BGP_INSTANCE_TYPE_DEFAULT
)
8515 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8517 const char *self
= "";
8522 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8526 * For ENCAP and EVPN routes, nexthop address family is not
8527 * neccessarily the same as the prefix address family.
8528 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8529 * EVPN routes are also exchanged with a MP nexthop. Currently,
8531 * is only IPv4, the value will be present in either
8533 * attr->mp_nexthop_global_in
8535 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
8538 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8542 snprintf(nexthop
, sizeof(nexthop
), "%s",
8543 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
8547 snprintf(nexthop
, sizeof(nexthop
), "%s",
8548 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
8552 snprintf(nexthop
, sizeof(nexthop
), "?");
8557 json_nexthop_global
= json_object_new_object();
8559 json_object_string_add(json_nexthop_global
, "ip",
8562 if (path
->peer
->hostname
)
8563 json_object_string_add(json_nexthop_global
,
8565 path
->peer
->hostname
);
8567 json_object_string_add(json_nexthop_global
, "afi",
8568 (af
== AF_INET
) ? "ipv4"
8570 json_object_boolean_true_add(json_nexthop_global
,
8573 if (nexthop_hostname
)
8574 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
8575 nexthop_hostname
, vrf_id_str
);
8577 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
8579 len
= wide
? (41 - len
) : (16 - len
);
8581 vty_out(vty
, "\n%*s", 36, " ");
8583 vty_out(vty
, "%*s", len
, " ");
8585 } else if (safi
== SAFI_EVPN
) {
8587 char buf
[BUFSIZ
] = {0};
8589 json_nexthop_global
= json_object_new_object();
8591 json_object_string_add(json_nexthop_global
, "ip",
8593 &attr
->nexthop
, buf
,
8596 if (path
->peer
->hostname
)
8597 json_object_string_add(json_nexthop_global
,
8599 path
->peer
->hostname
);
8601 json_object_string_add(json_nexthop_global
, "afi",
8603 json_object_boolean_true_add(json_nexthop_global
,
8606 if (nexthop_hostname
)
8607 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8608 nexthop_hostname
, vrf_id_str
);
8610 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8613 len
= wide
? (41 - len
) : (16 - len
);
8615 vty_out(vty
, "\n%*s", 36, " ");
8617 vty_out(vty
, "%*s", len
, " ");
8619 } else if (safi
== SAFI_FLOWSPEC
) {
8620 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
8622 char buf
[BUFSIZ
] = {0};
8624 json_nexthop_global
= json_object_new_object();
8626 json_object_string_add(json_nexthop_global
,
8628 json_object_string_add(
8629 json_nexthop_global
, "ip",
8630 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
8633 if (path
->peer
->hostname
)
8634 json_object_string_add(
8635 json_nexthop_global
, "hostname",
8636 path
->peer
->hostname
);
8638 json_object_boolean_true_add(
8639 json_nexthop_global
,
8642 if (nexthop_hostname
)
8643 len
= vty_out(vty
, "%pI4(%s)%s",
8648 len
= vty_out(vty
, "%pI4%s",
8652 len
= wide
? (41 - len
) : (16 - len
);
8654 vty_out(vty
, "\n%*s", 36, " ");
8656 vty_out(vty
, "%*s", len
, " ");
8659 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8661 char buf
[BUFSIZ
] = {0};
8663 json_nexthop_global
= json_object_new_object();
8665 json_object_string_add(json_nexthop_global
, "ip",
8667 &attr
->nexthop
, buf
,
8670 if (path
->peer
->hostname
)
8671 json_object_string_add(json_nexthop_global
,
8673 path
->peer
->hostname
);
8675 json_object_string_add(json_nexthop_global
, "afi",
8677 json_object_boolean_true_add(json_nexthop_global
,
8680 if (nexthop_hostname
)
8681 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8682 nexthop_hostname
, vrf_id_str
);
8684 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8687 len
= wide
? (41 - len
) : (16 - len
);
8689 vty_out(vty
, "\n%*s", 36, " ");
8691 vty_out(vty
, "%*s", len
, " ");
8696 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8700 json_nexthop_global
= json_object_new_object();
8701 json_object_string_add(
8702 json_nexthop_global
, "ip",
8703 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8706 if (path
->peer
->hostname
)
8707 json_object_string_add(json_nexthop_global
,
8709 path
->peer
->hostname
);
8711 json_object_string_add(json_nexthop_global
, "afi",
8713 json_object_string_add(json_nexthop_global
, "scope",
8716 /* We display both LL & GL if both have been
8718 if ((attr
->mp_nexthop_len
8719 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8720 || (path
->peer
->conf_if
)) {
8721 json_nexthop_ll
= json_object_new_object();
8722 json_object_string_add(
8723 json_nexthop_ll
, "ip",
8725 &attr
->mp_nexthop_local
, buf
,
8728 if (path
->peer
->hostname
)
8729 json_object_string_add(
8730 json_nexthop_ll
, "hostname",
8731 path
->peer
->hostname
);
8733 json_object_string_add(json_nexthop_ll
, "afi",
8735 json_object_string_add(json_nexthop_ll
, "scope",
8738 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
8739 &attr
->mp_nexthop_local
)
8741 && !attr
->mp_nexthop_prefer_global
)
8742 json_object_boolean_true_add(
8743 json_nexthop_ll
, "used");
8745 json_object_boolean_true_add(
8746 json_nexthop_global
, "used");
8748 json_object_boolean_true_add(
8749 json_nexthop_global
, "used");
8751 /* Display LL if LL/Global both in table unless
8752 * prefer-global is set */
8753 if (((attr
->mp_nexthop_len
8754 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8755 && !attr
->mp_nexthop_prefer_global
)
8756 || (path
->peer
->conf_if
)) {
8757 if (path
->peer
->conf_if
) {
8758 len
= vty_out(vty
, "%s",
8759 path
->peer
->conf_if
);
8760 /* len of IPv6 addr + max len of def
8762 len
= wide
? (41 - len
) : (16 - len
);
8765 vty_out(vty
, "\n%*s", 36, " ");
8767 vty_out(vty
, "%*s", len
, " ");
8769 if (nexthop_hostname
)
8772 &attr
->mp_nexthop_local
,
8778 &attr
->mp_nexthop_local
,
8781 len
= wide
? (41 - len
) : (16 - len
);
8784 vty_out(vty
, "\n%*s", 36, " ");
8786 vty_out(vty
, "%*s", len
, " ");
8789 if (nexthop_hostname
)
8790 len
= vty_out(vty
, "%pI6(%s)%s",
8791 &attr
->mp_nexthop_global
,
8795 len
= vty_out(vty
, "%pI6%s",
8796 &attr
->mp_nexthop_global
,
8799 len
= wide
? (41 - len
) : (16 - len
);
8802 vty_out(vty
, "\n%*s", 36, " ");
8804 vty_out(vty
, "%*s", len
, " ");
8810 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8812 json_object_int_add(json_path
, "metric", attr
->med
);
8814 vty_out(vty
, "%7u", attr
->med
);
8816 vty_out(vty
, "%10u", attr
->med
);
8817 else if (!json_paths
) {
8819 vty_out(vty
, "%*s", 7, " ");
8821 vty_out(vty
, "%*s", 10, " ");
8825 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8827 json_object_int_add(json_path
, "locPrf",
8830 vty_out(vty
, "%7u", attr
->local_pref
);
8831 else if (!json_paths
)
8835 json_object_int_add(json_path
, "weight", attr
->weight
);
8837 vty_out(vty
, "%7u ", attr
->weight
);
8841 json_object_string_add(
8842 json_path
, "peerId",
8843 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
8849 json_object_string_add(json_path
, "path",
8852 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8857 json_object_string_add(json_path
, "origin",
8858 bgp_origin_long_str
[attr
->origin
]);
8860 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8863 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8864 json_object_string_add(json_path
, "esi",
8865 esi_to_str(&attr
->esi
,
8866 esi_buf
, sizeof(esi_buf
)));
8868 if (safi
== SAFI_EVPN
&&
8869 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8870 json_ext_community
= json_object_new_object();
8871 json_object_string_add(json_ext_community
,
8873 attr
->ecommunity
->str
);
8874 json_object_object_add(json_path
,
8875 "extendedCommunity",
8876 json_ext_community
);
8880 json_object_boolean_true_add(json_path
,
8881 "announceNexthopSelf");
8882 if (nexthop_othervrf
) {
8883 json_object_string_add(json_path
, "nhVrfName",
8886 json_object_int_add(json_path
, "nhVrfId",
8887 ((nexthop_vrfid
== VRF_UNKNOWN
)
8889 : (int)nexthop_vrfid
));
8894 if (json_nexthop_global
|| json_nexthop_ll
) {
8895 json_nexthops
= json_object_new_array();
8897 if (json_nexthop_global
)
8898 json_object_array_add(json_nexthops
,
8899 json_nexthop_global
);
8901 if (json_nexthop_ll
)
8902 json_object_array_add(json_nexthops
,
8905 json_object_object_add(json_path
, "nexthops",
8909 json_object_array_add(json_paths
, json_path
);
8913 if (safi
== SAFI_EVPN
) {
8914 struct bgp_path_es_info
*path_es_info
= NULL
;
8916 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8917 /* XXX - add these params to the json out */
8918 vty_out(vty
, "%*s", 20, " ");
8919 vty_out(vty
, "ESI:%s",
8920 esi_to_str(&attr
->esi
, esi_buf
,
8923 if (path
->extra
&& path
->extra
->mh_info
)
8925 path
->extra
->mh_info
->es_info
;
8927 if (path_es_info
&& path_es_info
->es
)
8928 vty_out(vty
, " VNI: %u",
8933 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8934 vty_out(vty
, "%*s", 20, " ");
8935 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
8939 #ifdef ENABLE_BGP_VNC
8940 /* prints an additional line, indented, with VNC info, if
8942 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
8943 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
8948 /* called from terminal list command */
8949 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
8950 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
8951 bool use_json
, json_object
*json_ar
, bool wide
)
8953 json_object
*json_status
= NULL
;
8954 json_object
*json_net
= NULL
;
8958 /* Route status display. */
8960 json_status
= json_object_new_object();
8961 json_net
= json_object_new_object();
8968 /* print prefix and mask */
8970 if (safi
== SAFI_EVPN
)
8971 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
8972 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
8973 json_object_string_add(
8974 json_net
, "addrPrefix",
8975 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
8977 json_object_int_add(json_net
, "prefixLen",
8979 prefix2str(p
, buff
, PREFIX_STRLEN
);
8980 json_object_string_add(json_net
, "network", buff
);
8983 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
8985 /* Print attribute */
8988 char buf
[BUFSIZ
] = {0};
8990 if (p
->family
== AF_INET
8991 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8992 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8993 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8994 json_object_string_add(
8995 json_net
, "nextHop",
8998 &attr
->mp_nexthop_global_in
,
9001 json_object_string_add(
9002 json_net
, "nextHop",
9004 &attr
->nexthop
, buf
,
9006 } else if (p
->family
== AF_INET6
9007 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9010 json_object_string_add(
9011 json_net
, "nextHopGlobal",
9013 &attr
->mp_nexthop_global
, buf
,
9015 } else if (p
->family
== AF_EVPN
9016 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9017 char buf
[BUFSIZ
] = {0};
9019 json_object_string_add(
9020 json_net
, "nextHop",
9022 &attr
->mp_nexthop_global_in
,
9027 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9028 json_object_int_add(json_net
, "metric",
9031 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9032 json_object_int_add(json_net
, "locPrf",
9035 json_object_int_add(json_net
, "weight", attr
->weight
);
9039 json_object_string_add(json_net
, "path",
9043 json_object_string_add(json_net
, "bgpOriginCode",
9044 bgp_origin_str
[attr
->origin
]);
9046 if (p
->family
== AF_INET
9047 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9048 || safi
== SAFI_EVPN
9049 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9050 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9051 || safi
== SAFI_EVPN
)
9052 vty_out(vty
, "%-16pI4",
9053 &attr
->mp_nexthop_global_in
);
9055 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9057 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9058 } else if (p
->family
== AF_INET6
9059 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9065 &attr
->mp_nexthop_global
, buf
,
9067 len
= wide
? (41 - len
) : (16 - len
);
9069 vty_out(vty
, "\n%*s", 36, " ");
9071 vty_out(vty
, "%*s", len
, " ");
9074 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9076 vty_out(vty
, "%7u", attr
->med
);
9078 vty_out(vty
, "%10u", attr
->med
);
9084 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9085 vty_out(vty
, "%7u", attr
->local_pref
);
9089 vty_out(vty
, "%7u ", attr
->weight
);
9093 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9096 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9100 json_object_boolean_true_add(json_status
, "*");
9101 json_object_boolean_true_add(json_status
, ">");
9102 json_object_object_add(json_net
, "appliedStatusSymbols",
9105 prefix2str(p
, buff
, PREFIX_STRLEN
);
9106 json_object_object_add(json_ar
, buff
, json_net
);
9111 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9112 struct bgp_path_info
*path
, int display
, safi_t safi
,
9115 json_object
*json_out
= NULL
;
9117 mpls_label_t label
= MPLS_INVALID_LABEL
;
9123 json_out
= json_object_new_object();
9125 /* short status lead text */
9126 route_vty_short_status_out(vty
, path
, p
, json_out
);
9128 /* print prefix and mask */
9131 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9133 vty_out(vty
, "%*s", 17, " ");
9136 /* Print attribute */
9138 if (((p
->family
== AF_INET
)
9139 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9140 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9141 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9142 char buf
[BUFSIZ
] = {0};
9144 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9145 || safi
== SAFI_EVPN
) {
9147 json_object_string_add(
9148 json_out
, "mpNexthopGlobalIn",
9150 &attr
->mp_nexthop_global_in
,
9153 vty_out(vty
, "%-16pI4",
9154 &attr
->mp_nexthop_global_in
);
9157 json_object_string_add(
9158 json_out
, "nexthop",
9159 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9162 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9164 } else if (((p
->family
== AF_INET6
)
9165 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9166 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9167 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9170 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9172 json_object_string_add(
9173 json_out
, "mpNexthopGlobalIn",
9175 &attr
->mp_nexthop_global
,
9176 buf_a
, sizeof(buf_a
)));
9180 &attr
->mp_nexthop_global
,
9181 buf_a
, sizeof(buf_a
)));
9182 } else if (attr
->mp_nexthop_len
9183 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9184 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9185 &attr
->mp_nexthop_global
,
9186 &attr
->mp_nexthop_local
);
9188 json_object_string_add(json_out
,
9189 "mpNexthopGlobalLocal",
9192 vty_out(vty
, "%s", buf_a
);
9196 label
= decode_label(&path
->extra
->label
[0]);
9198 if (bgp_is_valid_label(&label
)) {
9200 json_object_int_add(json_out
, "notag", label
);
9201 json_object_array_add(json
, json_out
);
9203 vty_out(vty
, "notag/%d", label
);
9209 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9210 struct bgp_path_info
*path
, int display
,
9211 json_object
*json_paths
)
9214 char buf
[BUFSIZ
] = {0};
9215 json_object
*json_path
= NULL
;
9216 json_object
*json_nexthop
= NULL
;
9217 json_object
*json_overlay
= NULL
;
9223 json_path
= json_object_new_object();
9224 json_overlay
= json_object_new_object();
9225 json_nexthop
= json_object_new_object();
9228 /* short status lead text */
9229 route_vty_short_status_out(vty
, path
, p
, json_path
);
9231 /* print prefix and mask */
9233 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9235 vty_out(vty
, "%*s", 17, " ");
9237 /* Print attribute */
9240 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9244 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
9246 vty_out(vty
, "%-16s", buf
);
9248 json_object_string_add(json_nexthop
, "ip", buf
);
9250 json_object_string_add(json_nexthop
, "afi", "ipv4");
9252 json_object_object_add(json_path
, "nexthop",
9257 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
9258 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
9260 vty_out(vty
, "%s(%s)", buf
, buf1
);
9262 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
9264 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
9267 json_object_string_add(json_nexthop
, "afi", "ipv6");
9269 json_object_object_add(json_path
, "nexthop",
9277 json_object_string_add(json_nexthop
, "Error",
9278 "Unsupported address-family");
9282 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9284 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
))
9285 inet_ntop(AF_INET
, &eo
->gw_ip
.ipv4
, buf
, BUFSIZ
);
9286 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
))
9287 inet_ntop(AF_INET6
, &eo
->gw_ip
.ipv6
, buf
, BUFSIZ
);
9290 vty_out(vty
, "/%s", buf
);
9292 json_object_string_add(json_overlay
, "gw", buf
);
9294 if (attr
->ecommunity
) {
9296 struct ecommunity_val
*routermac
= ecommunity_lookup(
9297 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
9298 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9301 mac
= ecom_mac2str((char *)routermac
->val
);
9304 vty_out(vty
, "/%s", mac
);
9306 json_object_string_add(json_overlay
, "rmac",
9309 XFREE(MTYPE_TMP
, mac
);
9316 json_object_object_add(json_path
, "overlay", json_overlay
);
9318 json_object_array_add(json_paths
, json_path
);
9322 /* dampening route */
9323 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9324 struct bgp_path_info
*path
, int display
,
9325 afi_t afi
, safi_t safi
, bool use_json
,
9330 char timebuf
[BGP_UPTIME_LEN
];
9332 /* short status lead text */
9333 route_vty_short_status_out(vty
, path
, p
, json
);
9335 /* print prefix and mask */
9338 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9340 vty_out(vty
, "%*s", 17, " ");
9343 len
= vty_out(vty
, "%s", path
->peer
->host
);
9347 vty_out(vty
, "\n%*s", 34, " ");
9350 json_object_int_add(json
, "peerHost", len
);
9352 vty_out(vty
, "%*s", len
, " ");
9356 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9357 safi
, use_json
, json
);
9360 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9361 BGP_UPTIME_LEN
, afi
, safi
,
9364 /* Print attribute */
9370 json_object_string_add(json
, "asPath",
9373 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9378 json_object_string_add(json
, "origin",
9379 bgp_origin_str
[attr
->origin
]);
9381 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9388 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9389 struct bgp_path_info
*path
, int display
,
9390 afi_t afi
, safi_t safi
, bool use_json
,
9394 struct bgp_damp_info
*bdi
;
9395 char timebuf
[BGP_UPTIME_LEN
];
9401 bdi
= path
->extra
->damp_info
;
9403 /* short status lead text */
9404 route_vty_short_status_out(vty
, path
, p
, json
);
9406 /* print prefix and mask */
9409 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9411 vty_out(vty
, "%*s", 17, " ");
9414 len
= vty_out(vty
, "%s", path
->peer
->host
);
9418 vty_out(vty
, "\n%*s", 33, " ");
9421 json_object_int_add(json
, "peerHost", len
);
9423 vty_out(vty
, "%*s", len
, " ");
9426 len
= vty_out(vty
, "%d", bdi
->flap
);
9433 json_object_int_add(json
, "bdiFlap", len
);
9435 vty_out(vty
, "%*s", len
, " ");
9439 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9442 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9443 BGP_UPTIME_LEN
, 0, NULL
));
9445 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9446 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9448 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9449 BGP_UPTIME_LEN
, afi
, safi
,
9453 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9454 BGP_UPTIME_LEN
, afi
,
9455 safi
, use_json
, json
));
9458 vty_out(vty
, "%*s ", 8, " ");
9461 /* Print attribute */
9467 json_object_string_add(json
, "asPath",
9470 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9475 json_object_string_add(json
, "origin",
9476 bgp_origin_str
[attr
->origin
]);
9478 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9484 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9485 int *first
, const char *header
,
9486 json_object
*json_adv_to
)
9488 char buf1
[INET6_ADDRSTRLEN
];
9489 json_object
*json_peer
= NULL
;
9492 /* 'advertised-to' is a dictionary of peers we have advertised
9494 * prefix too. The key is the peer's IP or swpX, the value is
9496 * hostname if we know it and "" if not.
9498 json_peer
= json_object_new_object();
9501 json_object_string_add(json_peer
, "hostname",
9505 json_object_object_add(json_adv_to
, peer
->conf_if
,
9508 json_object_object_add(
9510 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
9514 vty_out(vty
, "%s", header
);
9519 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9521 vty_out(vty
, " %s(%s)", peer
->hostname
,
9524 vty_out(vty
, " %s(%s)", peer
->hostname
,
9525 sockunion2str(&peer
->su
, buf1
,
9529 vty_out(vty
, " %s", peer
->conf_if
);
9532 sockunion2str(&peer
->su
, buf1
,
9538 static void route_vty_out_tx_ids(struct vty
*vty
,
9539 struct bgp_addpath_info_data
*d
)
9543 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9544 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9545 d
->addpath_tx_id
[i
],
9546 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9550 static void route_vty_out_detail_es_info(struct vty
*vty
,
9551 struct bgp_path_info
*pi
,
9553 json_object
*json_path
)
9555 char esi_buf
[ESI_STR_LEN
];
9556 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9557 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9558 ATTR_ES_PEER_ROUTER
);
9559 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9560 ATTR_ES_PEER_ACTIVE
);
9561 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9562 ATTR_ES_PEER_PROXY
);
9563 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9565 json_object
*json_es_info
= NULL
;
9567 json_object_string_add(
9570 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9571 json_es_info
= json_object_new_object();
9573 json_object_boolean_true_add(
9574 json_es_info
, "localEs");
9576 json_object_boolean_true_add(
9577 json_es_info
, "peerActive");
9579 json_object_boolean_true_add(
9580 json_es_info
, "peerProxy");
9582 json_object_boolean_true_add(
9583 json_es_info
, "peerRouter");
9584 if (attr
->mm_sync_seqnum
)
9585 json_object_int_add(
9586 json_es_info
, "peerSeq",
9587 attr
->mm_sync_seqnum
);
9588 json_object_object_add(
9589 json_path
, "es_info",
9593 if (bgp_evpn_attr_is_sync(attr
))
9595 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9597 es_local
? "local-es":"",
9598 peer_proxy
? "proxy " : "",
9599 peer_active
? "active ":"",
9600 peer_router
? "router ":"",
9601 attr
->mm_sync_seqnum
);
9603 vty_out(vty
, " ESI %s %s\n",
9605 es_local
? "local-es":"");
9609 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
9610 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
9611 enum rpki_states rpki_curr_state
,
9612 json_object
*json_paths
)
9614 char buf
[INET6_ADDRSTRLEN
];
9616 struct attr
*attr
= path
->attr
;
9617 int sockunion_vty_out(struct vty
*, union sockunion
*);
9619 json_object
*json_bestpath
= NULL
;
9620 json_object
*json_cluster_list
= NULL
;
9621 json_object
*json_cluster_list_list
= NULL
;
9622 json_object
*json_ext_community
= NULL
;
9623 json_object
*json_last_update
= NULL
;
9624 json_object
*json_pmsi
= NULL
;
9625 json_object
*json_nexthop_global
= NULL
;
9626 json_object
*json_nexthop_ll
= NULL
;
9627 json_object
*json_nexthops
= NULL
;
9628 json_object
*json_path
= NULL
;
9629 json_object
*json_peer
= NULL
;
9630 json_object
*json_string
= NULL
;
9631 json_object
*json_adv_to
= NULL
;
9633 struct listnode
*node
, *nnode
;
9635 int addpath_capable
;
9637 unsigned int first_as
;
9639 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9641 char *nexthop_hostname
=
9642 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9645 json_path
= json_object_new_object();
9646 json_peer
= json_object_new_object();
9647 json_nexthop_global
= json_object_new_object();
9654 if (path
->extra
&& path
->extra
->num_labels
) {
9655 bgp_evpn_label2str(path
->extra
->label
,
9656 path
->extra
->num_labels
, tag_buf
,
9659 if (safi
== SAFI_EVPN
) {
9661 vty_out(vty
, " Route %pFX",
9662 (struct prefix_evpn
*)
9663 bgp_dest_get_prefix(bn
));
9664 if (tag_buf
[0] != '\0')
9665 vty_out(vty
, " VNI %s", tag_buf
);
9669 json_object_string_add(json_path
, "VNI",
9674 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9675 struct bgp_path_info
*parent_ri
;
9676 struct bgp_dest
*dest
, *pdest
;
9678 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9679 dest
= parent_ri
->net
;
9680 if (dest
&& dest
->pdest
) {
9681 pdest
= dest
->pdest
;
9683 (struct prefix_rd
*)bgp_dest_get_prefix(
9685 buf1
, sizeof(buf1
));
9686 if (is_pi_family_evpn(parent_ri
)) {
9688 " Imported from %s:%pFX, VNI %s",
9690 (struct prefix_evpn
*)
9691 bgp_dest_get_prefix(
9694 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
9695 vty_out(vty
, ", L3NHG %s",
9697 & ATTR_ES_L3_NHG_ACTIVE
)
9704 " Imported from %s:%pFX\n",
9706 (struct prefix_evpn
*)
9707 bgp_dest_get_prefix(
9713 /* Line1 display AS-path, Aggregator */
9716 if (!attr
->aspath
->json
)
9717 aspath_str_update(attr
->aspath
, true);
9718 json_object_lock(attr
->aspath
->json
);
9719 json_object_object_add(json_path
, "aspath",
9720 attr
->aspath
->json
);
9722 if (attr
->aspath
->segments
)
9723 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9725 vty_out(vty
, " Local");
9729 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9731 json_object_boolean_true_add(json_path
, "removed");
9733 vty_out(vty
, ", (removed)");
9736 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9738 json_object_boolean_true_add(json_path
, "stale");
9740 vty_out(vty
, ", (stale)");
9743 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
9745 char buf
[BUFSIZ
] = {0};
9747 json_object_int_add(json_path
, "aggregatorAs",
9748 attr
->aggregator_as
);
9749 json_object_string_add(json_path
, "aggregatorId",
9751 &attr
->aggregator_addr
,
9754 vty_out(vty
, ", (aggregated by %u %pI4)",
9755 attr
->aggregator_as
, &attr
->aggregator_addr
);
9759 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9760 PEER_FLAG_REFLECTOR_CLIENT
)) {
9762 json_object_boolean_true_add(json_path
,
9763 "rxedFromRrClient");
9765 vty_out(vty
, ", (Received from a RR-client)");
9768 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9769 PEER_FLAG_RSERVER_CLIENT
)) {
9771 json_object_boolean_true_add(json_path
,
9772 "rxedFromRsClient");
9774 vty_out(vty
, ", (Received from a RS-client)");
9777 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9779 json_object_boolean_true_add(json_path
,
9780 "dampeningHistoryEntry");
9782 vty_out(vty
, ", (history entry)");
9783 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
9785 json_object_boolean_true_add(json_path
,
9786 "dampeningSuppressed");
9788 vty_out(vty
, ", (suppressed due to dampening)");
9794 /* Line2 display Next-hop, Neighbor, Router-id */
9795 /* Display the nexthop */
9796 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
9798 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
9799 || bn_p
->family
== AF_EVPN
)
9800 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
9801 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9802 char buf
[BUFSIZ
] = {0};
9804 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9805 || safi
== SAFI_EVPN
) {
9807 json_object_string_add(
9808 json_nexthop_global
, "ip",
9810 &attr
->mp_nexthop_global_in
,
9813 if (path
->peer
->hostname
)
9814 json_object_string_add(
9815 json_nexthop_global
, "hostname",
9816 path
->peer
->hostname
);
9818 if (nexthop_hostname
)
9819 vty_out(vty
, " %pI4(%s)",
9820 &attr
->mp_nexthop_global_in
,
9823 vty_out(vty
, " %pI4",
9824 &attr
->mp_nexthop_global_in
);
9828 json_object_string_add(
9829 json_nexthop_global
, "ip",
9830 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9833 if (path
->peer
->hostname
)
9834 json_object_string_add(
9835 json_nexthop_global
, "hostname",
9836 path
->peer
->hostname
);
9838 if (nexthop_hostname
)
9839 vty_out(vty
, " %pI4(%s)",
9843 vty_out(vty
, " %pI4",
9849 json_object_string_add(json_nexthop_global
, "afi",
9853 json_object_string_add(
9854 json_nexthop_global
, "ip",
9855 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
9856 buf
, INET6_ADDRSTRLEN
));
9858 if (path
->peer
->hostname
)
9859 json_object_string_add(json_nexthop_global
,
9861 path
->peer
->hostname
);
9863 json_object_string_add(json_nexthop_global
, "afi",
9865 json_object_string_add(json_nexthop_global
, "scope",
9868 if (nexthop_hostname
)
9869 vty_out(vty
, " %pI6(%s)",
9870 &attr
->mp_nexthop_global
,
9873 vty_out(vty
, " %pI6",
9874 &attr
->mp_nexthop_global
);
9878 /* Display the IGP cost or 'inaccessible' */
9879 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9881 json_object_boolean_false_add(json_nexthop_global
,
9884 vty_out(vty
, " (inaccessible)");
9886 if (path
->extra
&& path
->extra
->igpmetric
) {
9888 json_object_int_add(json_nexthop_global
,
9890 path
->extra
->igpmetric
);
9892 vty_out(vty
, " (metric %u)",
9893 path
->extra
->igpmetric
);
9896 /* IGP cost is 0, display this only for json */
9899 json_object_int_add(json_nexthop_global
,
9904 json_object_boolean_true_add(json_nexthop_global
,
9908 /* Display peer "from" output */
9909 /* This path was originated locally */
9910 if (path
->peer
== bgp
->peer_self
) {
9912 if (safi
== SAFI_EVPN
9913 || (bn_p
->family
== AF_INET
9914 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9916 json_object_string_add(json_peer
, "peerId",
9919 vty_out(vty
, " from 0.0.0.0 ");
9922 json_object_string_add(json_peer
, "peerId",
9925 vty_out(vty
, " from :: ");
9929 char buf
[BUFSIZ
] = {0};
9931 json_object_string_add(json_peer
, "routerId",
9933 &bgp
->router_id
, buf
,
9936 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
9940 /* We RXed this path from one of our peers */
9944 json_object_string_add(json_peer
, "peerId",
9945 sockunion2str(&path
->peer
->su
,
9948 json_object_string_add(json_peer
, "routerId",
9950 &path
->peer
->remote_id
,
9951 buf1
, sizeof(buf1
)));
9953 if (path
->peer
->hostname
)
9954 json_object_string_add(json_peer
, "hostname",
9955 path
->peer
->hostname
);
9957 if (path
->peer
->domainname
)
9958 json_object_string_add(json_peer
, "domainname",
9959 path
->peer
->domainname
);
9961 if (path
->peer
->conf_if
)
9962 json_object_string_add(json_peer
, "interface",
9963 path
->peer
->conf_if
);
9965 if (path
->peer
->conf_if
) {
9966 if (path
->peer
->hostname
9967 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9968 BGP_FLAG_SHOW_HOSTNAME
))
9969 vty_out(vty
, " from %s(%s)",
9970 path
->peer
->hostname
,
9971 path
->peer
->conf_if
);
9973 vty_out(vty
, " from %s",
9974 path
->peer
->conf_if
);
9976 if (path
->peer
->hostname
9977 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9978 BGP_FLAG_SHOW_HOSTNAME
))
9979 vty_out(vty
, " from %s(%s)",
9980 path
->peer
->hostname
,
9983 vty_out(vty
, " from %s",
9984 sockunion2str(&path
->peer
->su
,
9989 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9990 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
9992 vty_out(vty
, " (%s)",
9994 &path
->peer
->remote_id
, buf1
,
10000 * Note when vrfid of nexthop is different from that of prefix
10002 if (path
->extra
&& path
->extra
->bgp_orig
) {
10003 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10008 if (path
->extra
->bgp_orig
->inst_type
10009 == BGP_INSTANCE_TYPE_DEFAULT
)
10010 vn
= VRF_DEFAULT_NAME
;
10012 vn
= path
->extra
->bgp_orig
->name
;
10014 json_object_string_add(json_path
, "nhVrfName", vn
);
10016 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10017 json_object_int_add(json_path
, "nhVrfId", -1);
10019 json_object_int_add(json_path
, "nhVrfId",
10020 (int)nexthop_vrfid
);
10023 if (nexthop_vrfid
== VRF_UNKNOWN
)
10024 vty_out(vty
, " vrf ?");
10028 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10029 vty_out(vty
, " vrf %s(%u)",
10030 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10035 if (nexthop_self
) {
10037 json_object_boolean_true_add(json_path
,
10038 "announceNexthopSelf");
10040 vty_out(vty
, " announce-nh-self");
10045 vty_out(vty
, "\n");
10047 /* display the link-local nexthop */
10048 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10050 json_nexthop_ll
= json_object_new_object();
10051 json_object_string_add(
10052 json_nexthop_ll
, "ip",
10053 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10054 buf
, INET6_ADDRSTRLEN
));
10056 if (path
->peer
->hostname
)
10057 json_object_string_add(json_nexthop_ll
,
10059 path
->peer
->hostname
);
10061 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10062 json_object_string_add(json_nexthop_ll
, "scope",
10065 json_object_boolean_true_add(json_nexthop_ll
,
10068 if (!attr
->mp_nexthop_prefer_global
)
10069 json_object_boolean_true_add(json_nexthop_ll
,
10072 json_object_boolean_true_add(
10073 json_nexthop_global
, "used");
10075 vty_out(vty
, " (%s) %s\n",
10076 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10077 buf
, INET6_ADDRSTRLEN
),
10078 attr
->mp_nexthop_prefer_global
10079 ? "(prefer-global)"
10083 /* If we do not have a link-local nexthop then we must flag the
10084 global as "used" */
10087 json_object_boolean_true_add(json_nexthop_global
,
10091 if (safi
== SAFI_EVPN
&&
10092 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10093 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10096 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10097 * Int/Ext/Local, Atomic, best */
10099 json_object_string_add(json_path
, "origin",
10100 bgp_origin_long_str
[attr
->origin
]);
10102 vty_out(vty
, " Origin %s",
10103 bgp_origin_long_str
[attr
->origin
]);
10105 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10107 json_object_int_add(json_path
, "metric", attr
->med
);
10109 vty_out(vty
, ", metric %u", attr
->med
);
10112 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10114 json_object_int_add(json_path
, "locPrf",
10117 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10120 if (attr
->weight
!= 0) {
10122 json_object_int_add(json_path
, "weight", attr
->weight
);
10124 vty_out(vty
, ", weight %u", attr
->weight
);
10127 if (attr
->tag
!= 0) {
10129 json_object_int_add(json_path
, "tag", attr
->tag
);
10131 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10134 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10136 json_object_boolean_false_add(json_path
, "valid");
10138 vty_out(vty
, ", invalid");
10139 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10141 json_object_boolean_true_add(json_path
, "valid");
10143 vty_out(vty
, ", valid");
10147 json_object_int_add(json_path
, "version", bn
->version
);
10149 if (path
->peer
!= bgp
->peer_self
) {
10150 if (path
->peer
->as
== path
->peer
->local_as
) {
10151 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10153 json_object_string_add(
10155 "confed-internal");
10157 vty_out(vty
, ", confed-internal");
10160 json_object_string_add(
10161 json_peer
, "type", "internal");
10163 vty_out(vty
, ", internal");
10166 if (bgp_confederation_peers_check(bgp
,
10169 json_object_string_add(
10171 "confed-external");
10173 vty_out(vty
, ", confed-external");
10176 json_object_string_add(
10177 json_peer
, "type", "external");
10179 vty_out(vty
, ", external");
10182 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10184 json_object_boolean_true_add(json_path
, "aggregated");
10185 json_object_boolean_true_add(json_path
, "local");
10187 vty_out(vty
, ", aggregated, local");
10189 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10191 json_object_boolean_true_add(json_path
, "sourced");
10193 vty_out(vty
, ", sourced");
10196 json_object_boolean_true_add(json_path
, "sourced");
10197 json_object_boolean_true_add(json_path
, "local");
10199 vty_out(vty
, ", sourced, local");
10203 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10205 json_object_boolean_true_add(json_path
,
10206 "atomicAggregate");
10208 vty_out(vty
, ", atomic-aggregate");
10211 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10212 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10213 && bgp_path_info_mpath_count(path
))) {
10215 json_object_boolean_true_add(json_path
, "multipath");
10217 vty_out(vty
, ", multipath");
10220 // Mark the bestpath(s)
10221 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10222 first_as
= aspath_get_first_as(attr
->aspath
);
10225 if (!json_bestpath
)
10226 json_bestpath
= json_object_new_object();
10227 json_object_int_add(json_bestpath
, "bestpathFromAs",
10231 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10233 vty_out(vty
, ", bestpath-from-AS Local");
10237 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10239 if (!json_bestpath
)
10240 json_bestpath
= json_object_new_object();
10241 json_object_boolean_true_add(json_bestpath
, "overall");
10242 json_object_string_add(
10243 json_bestpath
, "selectionReason",
10244 bgp_path_selection_reason2str(bn
->reason
));
10246 vty_out(vty
, ", best");
10247 vty_out(vty
, " (%s)",
10248 bgp_path_selection_reason2str(bn
->reason
));
10252 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10254 json_object_string_add(
10255 json_path
, "rpkiValidationState",
10256 bgp_rpki_validation2str(rpki_curr_state
));
10258 vty_out(vty
, ", rpki validation-state: %s",
10259 bgp_rpki_validation2str(rpki_curr_state
));
10263 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10266 vty_out(vty
, "\n");
10268 /* Line 4 display Community */
10269 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10271 if (!attr
->community
->json
)
10272 community_str(attr
->community
, true);
10273 json_object_lock(attr
->community
->json
);
10274 json_object_object_add(json_path
, "community",
10275 attr
->community
->json
);
10277 vty_out(vty
, " Community: %s\n",
10278 attr
->community
->str
);
10282 /* Line 5 display Extended-community */
10283 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10285 json_ext_community
= json_object_new_object();
10286 json_object_string_add(json_ext_community
, "string",
10287 attr
->ecommunity
->str
);
10288 json_object_object_add(json_path
, "extendedCommunity",
10289 json_ext_community
);
10291 vty_out(vty
, " Extended Community: %s\n",
10292 attr
->ecommunity
->str
);
10296 /* Line 6 display Large community */
10297 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10299 if (!attr
->lcommunity
->json
)
10300 lcommunity_str(attr
->lcommunity
, true);
10301 json_object_lock(attr
->lcommunity
->json
);
10302 json_object_object_add(json_path
, "largeCommunity",
10303 attr
->lcommunity
->json
);
10305 vty_out(vty
, " Large Community: %s\n",
10306 attr
->lcommunity
->str
);
10310 /* Line 7 display Originator, Cluster-id */
10311 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10312 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10313 char buf
[BUFSIZ
] = {0};
10315 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10317 json_object_string_add(
10318 json_path
, "originatorId",
10319 inet_ntop(AF_INET
, &attr
->originator_id
,
10320 buf
, sizeof(buf
)));
10322 vty_out(vty
, " Originator: %pI4",
10323 &attr
->originator_id
);
10326 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10327 struct cluster_list
*cluster
=
10328 bgp_attr_get_cluster(attr
);
10332 json_cluster_list
= json_object_new_object();
10333 json_cluster_list_list
=
10334 json_object_new_array();
10336 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10337 json_string
= json_object_new_string(
10340 buf
, sizeof(buf
)));
10341 json_object_array_add(
10342 json_cluster_list_list
,
10347 * struct cluster_list does not have
10348 * "str" variable like aspath and community
10349 * do. Add this someday if someone asks
10351 * json_object_string_add(json_cluster_list,
10352 * "string", cluster->str);
10354 json_object_object_add(json_cluster_list
,
10356 json_cluster_list_list
);
10357 json_object_object_add(json_path
, "clusterList",
10358 json_cluster_list
);
10360 vty_out(vty
, ", Cluster list: ");
10362 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10363 vty_out(vty
, "%pI4 ",
10364 &cluster
->list
[i
]);
10370 vty_out(vty
, "\n");
10373 if (path
->extra
&& path
->extra
->damp_info
)
10374 bgp_damp_info_vty(vty
, bgp
, path
, afi
, safi
, json_path
);
10377 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10378 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10379 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
10382 json_object_int_add(json_path
, "remoteLabel", label
);
10384 vty_out(vty
, " Remote label: %d\n", label
);
10388 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10389 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
10391 json_object_string_add(json_path
, "remoteSid", buf
);
10393 vty_out(vty
, " Remote SID: %s\n", buf
);
10397 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10399 json_object_int_add(json_path
, "labelIndex",
10400 attr
->label_index
);
10402 vty_out(vty
, " Label Index: %d\n",
10403 attr
->label_index
);
10406 /* Line 8 display Addpath IDs */
10407 if (path
->addpath_rx_id
10408 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10410 json_object_int_add(json_path
, "addpathRxId",
10411 path
->addpath_rx_id
);
10413 /* Keep backwards compatibility with the old API
10414 * by putting TX All's ID in the old field
10416 json_object_int_add(
10417 json_path
, "addpathTxId",
10419 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10421 /* ... but create a specific field for each
10424 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10425 json_object_int_add(
10427 bgp_addpath_names(i
)->id_json_name
,
10428 path
->tx_addpath
.addpath_tx_id
[i
]);
10431 vty_out(vty
, " AddPath ID: RX %u, ",
10432 path
->addpath_rx_id
);
10434 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10438 /* If we used addpath to TX a non-bestpath we need to display
10439 * "Advertised to" on a path-by-path basis
10441 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10444 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10446 bgp_addpath_encode_tx(peer
, afi
, safi
);
10447 has_adj
= bgp_adj_out_lookup(
10449 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10450 &path
->tx_addpath
));
10452 if ((addpath_capable
&& has_adj
)
10453 || (!addpath_capable
&& has_adj
10454 && CHECK_FLAG(path
->flags
,
10455 BGP_PATH_SELECTED
))) {
10456 if (json_path
&& !json_adv_to
)
10457 json_adv_to
= json_object_new_object();
10459 route_vty_out_advertised_to(
10461 " Advertised to:", json_adv_to
);
10467 json_object_object_add(
10468 json_path
, "advertisedTo", json_adv_to
);
10472 vty_out(vty
, "\n");
10477 /* Line 9 display Uptime */
10478 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
10480 json_last_update
= json_object_new_object();
10481 json_object_int_add(json_last_update
, "epoch", tbuf
);
10482 json_object_string_add(json_last_update
, "string",
10484 json_object_object_add(json_path
, "lastUpdate",
10487 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10489 /* Line 10 display PMSI tunnel attribute, if present */
10490 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10491 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10492 bgp_attr_get_pmsi_tnl_type(attr
),
10493 PMSI_TNLTYPE_STR_DEFAULT
);
10496 json_pmsi
= json_object_new_object();
10497 json_object_string_add(json_pmsi
, "tunnelType", str
);
10498 json_object_int_add(json_pmsi
, "label",
10499 label2vni(&attr
->label
));
10500 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10502 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10503 str
, label2vni(&attr
->label
));
10506 /* Output some debug about internal state of the dest flags */
10508 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10509 json_object_boolean_true_add(json_path
, "processScheduled");
10510 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10511 json_object_boolean_true_add(json_path
, "userCleared");
10512 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10513 json_object_boolean_true_add(json_path
, "labelChanged");
10514 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10515 json_object_boolean_true_add(json_path
, "registeredForLabel");
10516 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10517 json_object_boolean_true_add(json_path
, "selectDefered");
10518 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10519 json_object_boolean_true_add(json_path
, "fibInstalled");
10520 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10521 json_object_boolean_true_add(json_path
, "fibPending");
10524 /* We've constructed the json object for this path, add it to the json
10528 if (json_nexthop_global
|| json_nexthop_ll
) {
10529 json_nexthops
= json_object_new_array();
10531 if (json_nexthop_global
)
10532 json_object_array_add(json_nexthops
,
10533 json_nexthop_global
);
10535 if (json_nexthop_ll
)
10536 json_object_array_add(json_nexthops
,
10539 json_object_object_add(json_path
, "nexthops",
10543 json_object_object_add(json_path
, "peer", json_peer
);
10544 json_object_array_add(json_paths
, json_path
);
10548 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10549 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10550 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10552 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10553 const char *prefix_list_str
, afi_t afi
,
10554 safi_t safi
, enum bgp_show_type type
);
10555 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10556 const char *filter
, afi_t afi
, safi_t safi
,
10557 enum bgp_show_type type
);
10558 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10559 const char *rmap_str
, afi_t afi
, safi_t safi
,
10560 enum bgp_show_type type
);
10561 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10562 const char *com
, int exact
, afi_t afi
,
10564 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10565 const char *prefix
, afi_t afi
, safi_t safi
,
10566 enum bgp_show_type type
);
10567 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10568 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10570 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10571 const char *comstr
, int exact
, afi_t afi
,
10572 safi_t safi
, uint8_t show_flags
);
10574 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10575 struct bgp_table
*table
, enum bgp_show_type type
,
10576 void *output_arg
, char *rd
, int is_last
,
10577 unsigned long *output_cum
, unsigned long *total_cum
,
10578 unsigned long *json_header_depth
, uint8_t show_flags
,
10579 enum rpki_states rpki_target_state
)
10581 struct bgp_path_info
*pi
;
10582 struct bgp_dest
*dest
;
10585 unsigned long output_count
= 0;
10586 unsigned long total_count
= 0;
10588 json_object
*json_paths
= NULL
;
10590 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10591 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
10592 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10594 if (output_cum
&& *output_cum
!= 0)
10597 if (use_json
&& !*json_header_depth
) {
10599 *json_header_depth
= 1;
10601 vty_out(vty
, "{\n");
10602 *json_header_depth
= 2;
10606 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10607 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10608 " \"localAS\": %u,\n \"routes\": { ",
10609 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
10610 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
10613 table
->version
, &bgp
->router_id
,
10614 bgp
->default_local_pref
, bgp
->as
);
10616 vty_out(vty
, " \"routeDistinguishers\" : {");
10617 ++*json_header_depth
;
10621 if (use_json
&& rd
) {
10622 vty_out(vty
, " \"%s\" : { ", rd
);
10625 /* Start processing of routes. */
10626 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
10627 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10628 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
10630 pi
= bgp_dest_get_bgp_path_info(dest
);
10636 json_paths
= json_object_new_array();
10640 for (; pi
; pi
= pi
->next
) {
10643 if (type
== bgp_show_type_prefix_version
) {
10645 strtoul(output_arg
, NULL
, 10);
10646 if (dest
->version
< version
)
10650 if (type
== bgp_show_type_community_alias
) {
10651 char *alias
= output_arg
;
10652 char **communities
;
10654 bool found
= false;
10656 if (pi
->attr
->community
) {
10657 frrstr_split(pi
->attr
->community
->str
,
10658 " ", &communities
, &num
);
10659 for (int i
= 0; i
< num
; i
++) {
10660 const char *com2alias
=
10661 bgp_community2alias(
10663 if (strncmp(alias
, com2alias
,
10672 if (!found
&& pi
->attr
->lcommunity
) {
10673 frrstr_split(pi
->attr
->lcommunity
->str
,
10674 " ", &communities
, &num
);
10675 for (int i
= 0; i
< num
; i
++) {
10676 const char *com2alias
=
10677 bgp_community2alias(
10679 if (strncmp(alias
, com2alias
,
10692 if (type
== bgp_show_type_rpki
) {
10693 if (dest_p
->family
== AF_INET
10694 || dest_p
->family
== AF_INET6
)
10695 rpki_curr_state
= hook_call(
10696 bgp_rpki_prefix_status
,
10697 pi
->peer
, pi
->attr
, dest_p
);
10698 if (rpki_target_state
!= RPKI_NOT_BEING_USED
10699 && rpki_curr_state
!= rpki_target_state
)
10703 if (type
== bgp_show_type_flap_statistics
10704 || type
== bgp_show_type_flap_neighbor
10705 || type
== bgp_show_type_dampend_paths
10706 || type
== bgp_show_type_damp_neighbor
) {
10707 if (!(pi
->extra
&& pi
->extra
->damp_info
))
10710 if (type
== bgp_show_type_regexp
) {
10711 regex_t
*regex
= output_arg
;
10713 if (bgp_regexec(regex
, pi
->attr
->aspath
)
10717 if (type
== bgp_show_type_prefix_list
) {
10718 struct prefix_list
*plist
= output_arg
;
10720 if (prefix_list_apply(plist
, dest_p
)
10724 if (type
== bgp_show_type_filter_list
) {
10725 struct as_list
*as_list
= output_arg
;
10727 if (as_list_apply(as_list
, pi
->attr
->aspath
)
10728 != AS_FILTER_PERMIT
)
10731 if (type
== bgp_show_type_route_map
) {
10732 struct route_map
*rmap
= output_arg
;
10733 struct bgp_path_info path
;
10734 struct attr dummy_attr
;
10735 route_map_result_t ret
;
10737 dummy_attr
= *pi
->attr
;
10739 path
.peer
= pi
->peer
;
10740 path
.attr
= &dummy_attr
;
10742 ret
= route_map_apply(rmap
, dest_p
, &path
);
10743 if (ret
== RMAP_DENYMATCH
)
10746 if (type
== bgp_show_type_neighbor
10747 || type
== bgp_show_type_flap_neighbor
10748 || type
== bgp_show_type_damp_neighbor
) {
10749 union sockunion
*su
= output_arg
;
10751 if (pi
->peer
== NULL
10752 || pi
->peer
->su_remote
== NULL
10753 || !sockunion_same(pi
->peer
->su_remote
, su
))
10756 if (type
== bgp_show_type_cidr_only
) {
10757 uint32_t destination
;
10759 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
10760 if (IN_CLASSC(destination
)
10761 && dest_p
->prefixlen
== 24)
10763 if (IN_CLASSB(destination
)
10764 && dest_p
->prefixlen
== 16)
10766 if (IN_CLASSA(destination
)
10767 && dest_p
->prefixlen
== 8)
10770 if (type
== bgp_show_type_prefix_longer
) {
10772 if (!prefix_match(p
, dest_p
))
10775 if (type
== bgp_show_type_community_all
) {
10776 if (!pi
->attr
->community
)
10779 if (type
== bgp_show_type_community
) {
10780 struct community
*com
= output_arg
;
10782 if (!pi
->attr
->community
10783 || !community_match(pi
->attr
->community
,
10787 if (type
== bgp_show_type_community_exact
) {
10788 struct community
*com
= output_arg
;
10790 if (!pi
->attr
->community
10791 || !community_cmp(pi
->attr
->community
, com
))
10794 if (type
== bgp_show_type_community_list
) {
10795 struct community_list
*list
= output_arg
;
10797 if (!community_list_match(pi
->attr
->community
,
10801 if (type
== bgp_show_type_community_list_exact
) {
10802 struct community_list
*list
= output_arg
;
10804 if (!community_list_exact_match(
10805 pi
->attr
->community
, list
))
10808 if (type
== bgp_show_type_lcommunity
) {
10809 struct lcommunity
*lcom
= output_arg
;
10811 if (!pi
->attr
->lcommunity
10812 || !lcommunity_match(pi
->attr
->lcommunity
,
10817 if (type
== bgp_show_type_lcommunity_exact
) {
10818 struct lcommunity
*lcom
= output_arg
;
10820 if (!pi
->attr
->lcommunity
10821 || !lcommunity_cmp(pi
->attr
->lcommunity
,
10825 if (type
== bgp_show_type_lcommunity_list
) {
10826 struct community_list
*list
= output_arg
;
10828 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
10833 == bgp_show_type_lcommunity_list_exact
) {
10834 struct community_list
*list
= output_arg
;
10836 if (!lcommunity_list_exact_match(
10837 pi
->attr
->lcommunity
, list
))
10840 if (type
== bgp_show_type_lcommunity_all
) {
10841 if (!pi
->attr
->lcommunity
)
10844 if (type
== bgp_show_type_dampend_paths
10845 || type
== bgp_show_type_damp_neighbor
) {
10846 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
10847 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10851 if (!use_json
&& header
) {
10853 "BGP table version is %" PRIu64
10854 ", local router ID is %pI4, vrf id ",
10855 table
->version
, &bgp
->router_id
);
10856 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10857 vty_out(vty
, "%s", VRFID_NONE_STR
);
10859 vty_out(vty
, "%u", bgp
->vrf_id
);
10860 vty_out(vty
, "\n");
10861 vty_out(vty
, "Default local pref %u, ",
10862 bgp
->default_local_pref
);
10863 vty_out(vty
, "local AS %u\n", bgp
->as
);
10864 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10865 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10866 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10867 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
10868 if (type
== bgp_show_type_dampend_paths
10869 || type
== bgp_show_type_damp_neighbor
)
10870 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
10871 else if (type
== bgp_show_type_flap_statistics
10872 || type
== bgp_show_type_flap_neighbor
)
10873 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
10875 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
10876 : BGP_SHOW_HEADER
));
10879 if (rd
!= NULL
&& !display
&& !output_count
) {
10882 "Route Distinguisher: %s\n",
10885 if (type
== bgp_show_type_dampend_paths
10886 || type
== bgp_show_type_damp_neighbor
)
10887 damp_route_vty_out(vty
, dest_p
, pi
, display
,
10888 AFI_IP
, safi
, use_json
,
10890 else if (type
== bgp_show_type_flap_statistics
10891 || type
== bgp_show_type_flap_neighbor
)
10892 flap_route_vty_out(vty
, dest_p
, pi
, display
,
10893 AFI_IP
, safi
, use_json
,
10896 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
10897 route_vty_out_detail(
10898 vty
, bgp
, dest
, pi
,
10899 family2afi(dest_p
->family
),
10900 safi
, RPKI_NOT_BEING_USED
,
10903 route_vty_out(vty
, dest_p
, pi
, display
,
10904 safi
, json_paths
, wide
);
10914 /* encode prefix */
10915 if (dest_p
->family
== AF_FLOWSPEC
) {
10916 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
10919 bgp_fs_nlri_get_string(
10921 dest_p
->u
.prefix_flowspec
.ptr
,
10922 dest_p
->u
.prefix_flowspec
.prefixlen
,
10923 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
10924 family2afi(dest_p
->u
10925 .prefix_flowspec
.family
));
10927 vty_out(vty
, "\"%s/%d\": ", retstr
,
10928 dest_p
->u
.prefix_flowspec
10931 vty_out(vty
, ",\"%s/%d\": ", retstr
,
10932 dest_p
->u
.prefix_flowspec
10936 vty_out(vty
, "\"%pFX\": ", dest_p
);
10938 vty_out(vty
, ",\"%pFX\": ", dest_p
);
10941 json_object_to_json_string_ext(
10942 json_paths
, JSON_C_TO_STRING_PRETTY
));
10943 json_object_free(json_paths
);
10947 json_object_free(json_paths
);
10951 output_count
+= *output_cum
;
10952 *output_cum
= output_count
;
10955 total_count
+= *total_cum
;
10956 *total_cum
= total_count
;
10960 vty_out(vty
, " }%s ", (is_last
? "" : ","));
10964 for (i
= 0; i
< *json_header_depth
; ++i
)
10965 vty_out(vty
, " } ");
10967 vty_out(vty
, "\n");
10971 /* No route is displayed */
10972 if (output_count
== 0) {
10973 if (type
== bgp_show_type_normal
)
10975 "No BGP prefixes displayed, %ld exist\n",
10979 "\nDisplayed %ld routes and %ld total paths\n",
10980 output_count
, total_count
);
10984 return CMD_SUCCESS
;
10987 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10988 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
10989 enum bgp_show_type type
, void *output_arg
, bool use_json
)
10991 struct bgp_dest
*dest
, *next
;
10992 unsigned long output_cum
= 0;
10993 unsigned long total_cum
= 0;
10994 unsigned long json_header_depth
= 0;
10995 struct bgp_table
*itable
;
10997 uint8_t show_flags
= 0;
10999 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11002 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11004 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11005 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11007 next
= bgp_route_next(dest
);
11008 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11011 itable
= bgp_dest_get_bgp_table_info(dest
);
11012 if (itable
!= NULL
) {
11013 struct prefix_rd prd
;
11014 char rd
[RD_ADDRSTRLEN
];
11016 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11017 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11018 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11019 rd
, next
== NULL
, &output_cum
,
11020 &total_cum
, &json_header_depth
,
11021 show_flags
, RPKI_NOT_BEING_USED
);
11027 if (output_cum
== 0)
11028 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11032 "\nDisplayed %ld routes and %ld total paths\n",
11033 output_cum
, total_cum
);
11035 return CMD_SUCCESS
;
11037 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11038 enum bgp_show_type type
, void *output_arg
,
11039 uint8_t show_flags
, enum rpki_states rpki_target_state
)
11041 struct bgp_table
*table
;
11042 unsigned long json_header_depth
= 0;
11043 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11046 bgp
= bgp_get_default();
11051 vty_out(vty
, "No BGP process is configured\n");
11053 vty_out(vty
, "{}\n");
11054 return CMD_WARNING
;
11057 table
= bgp
->rib
[afi
][safi
];
11058 /* use MPLS and ENCAP specific shows until they are merged */
11059 if (safi
== SAFI_MPLS_VPN
) {
11060 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11061 output_arg
, use_json
);
11064 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11065 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11066 output_arg
, use_json
,
11069 /* labeled-unicast routes live in the unicast table */
11070 else if (safi
== SAFI_LABELED_UNICAST
)
11071 safi
= SAFI_UNICAST
;
11073 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11074 NULL
, NULL
, &json_header_depth
, show_flags
,
11075 rpki_target_state
);
11078 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11079 safi_t safi
, uint8_t show_flags
)
11081 struct listnode
*node
, *nnode
;
11084 bool route_output
= false;
11085 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11088 vty_out(vty
, "{\n");
11090 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11091 route_output
= true;
11094 vty_out(vty
, ",\n");
11098 vty_out(vty
, "\"%s\":",
11099 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11103 vty_out(vty
, "\nInstance %s:\n",
11104 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11108 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11109 show_flags
, RPKI_NOT_BEING_USED
);
11113 vty_out(vty
, "}\n");
11114 else if (!route_output
)
11115 vty_out(vty
, "%% BGP instance not found\n");
11118 /* Header of detailed BGP route information */
11119 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11120 struct bgp_dest
*dest
, struct prefix_rd
*prd
,
11121 afi_t afi
, safi_t safi
, json_object
*json
)
11123 struct bgp_path_info
*pi
;
11124 const struct prefix
*p
;
11126 struct listnode
*node
, *nnode
;
11127 char buf1
[RD_ADDRSTRLEN
];
11128 char prefix_str
[BUFSIZ
];
11132 int accept_own
= 0;
11133 int route_filter_translated_v4
= 0;
11134 int route_filter_v4
= 0;
11135 int route_filter_translated_v6
= 0;
11136 int route_filter_v6
= 0;
11137 int llgr_stale
= 0;
11139 int accept_own_nexthop
= 0;
11142 int no_advertise
= 0;
11146 int has_valid_label
= 0;
11147 mpls_label_t label
= 0;
11148 json_object
*json_adv_to
= NULL
;
11150 p
= bgp_dest_get_prefix(dest
);
11151 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
11153 if (has_valid_label
)
11154 label
= label_pton(&dest
->local_label
);
11156 if (safi
== SAFI_EVPN
) {
11159 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11160 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11162 prd
? ":" : "", (struct prefix_evpn
*)p
);
11164 json_object_string_add(json
, "rd",
11165 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11167 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11172 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11174 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11175 ? prefix_rd2str(prd
, buf1
,
11178 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11182 json_object_string_add(json
, "prefix",
11183 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
11184 json_object_int_add(json
, "version", dest
->version
);
11189 if (has_valid_label
) {
11191 json_object_int_add(json
, "localLabel", label
);
11193 vty_out(vty
, "Local label: %d\n", label
);
11197 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11198 vty_out(vty
, "not allocated\n");
11200 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11202 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11204 if (bgp_path_suppressed(pi
))
11207 if (pi
->attr
->community
== NULL
)
11210 no_advertise
+= community_include(
11211 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
11212 no_export
+= community_include(pi
->attr
->community
,
11213 COMMUNITY_NO_EXPORT
);
11214 local_as
+= community_include(pi
->attr
->community
,
11215 COMMUNITY_LOCAL_AS
);
11216 accept_own
+= community_include(pi
->attr
->community
,
11217 COMMUNITY_ACCEPT_OWN
);
11218 route_filter_translated_v4
+= community_include(
11219 pi
->attr
->community
,
11220 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11221 route_filter_translated_v6
+= community_include(
11222 pi
->attr
->community
,
11223 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11224 route_filter_v4
+= community_include(
11225 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
11226 route_filter_v6
+= community_include(
11227 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
11228 llgr_stale
+= community_include(pi
->attr
->community
,
11229 COMMUNITY_LLGR_STALE
);
11230 no_llgr
+= community_include(pi
->attr
->community
,
11231 COMMUNITY_NO_LLGR
);
11232 accept_own_nexthop
+=
11233 community_include(pi
->attr
->community
,
11234 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11235 blackhole
+= community_include(pi
->attr
->community
,
11236 COMMUNITY_BLACKHOLE
);
11237 no_peer
+= community_include(pi
->attr
->community
,
11238 COMMUNITY_NO_PEER
);
11243 vty_out(vty
, "Paths: (%d available", count
);
11245 vty_out(vty
, ", best #%d", best
);
11246 if (safi
== SAFI_UNICAST
) {
11247 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11248 vty_out(vty
, ", table %s",
11251 vty_out(vty
, ", vrf %s",
11255 vty_out(vty
, ", no best path");
11259 ", accept own local route exported and imported in different VRF");
11260 else if (route_filter_translated_v4
)
11262 ", mark translated RTs for VPNv4 route filtering");
11263 else if (route_filter_v4
)
11265 ", attach RT as-is for VPNv4 route filtering");
11266 else if (route_filter_translated_v6
)
11268 ", mark translated RTs for VPNv6 route filtering");
11269 else if (route_filter_v6
)
11271 ", attach RT as-is for VPNv6 route filtering");
11272 else if (llgr_stale
)
11274 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11277 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11278 else if (accept_own_nexthop
)
11280 ", accept local nexthop");
11281 else if (blackhole
)
11282 vty_out(vty
, ", inform peer to blackhole prefix");
11283 else if (no_export
)
11284 vty_out(vty
, ", not advertised to EBGP peer");
11285 else if (no_advertise
)
11286 vty_out(vty
, ", not advertised to any peer");
11288 vty_out(vty
, ", not advertised outside local AS");
11291 ", inform EBGP peer not to advertise to their EBGP peers");
11295 ", Advertisements suppressed by an aggregate.");
11296 vty_out(vty
, ")\n");
11299 /* If we are not using addpath then we can display Advertised to and
11301 * show what peers we advertised the bestpath to. If we are using
11303 * though then we must display Advertised to on a path-by-path basis. */
11304 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11305 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11306 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11307 if (json
&& !json_adv_to
)
11308 json_adv_to
= json_object_new_object();
11310 route_vty_out_advertised_to(
11312 " Advertised to non peer-group peers:\n ",
11319 json_object_object_add(json
, "advertisedTo",
11324 vty_out(vty
, " Not advertised to any peer");
11325 vty_out(vty
, "\n");
11330 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
11331 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11332 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11333 json_object
*json
, enum bgp_path_type pathtype
,
11334 int *display
, enum rpki_states rpki_target_state
)
11336 struct bgp_path_info
*pi
;
11338 char rdbuf
[RD_ADDRSTRLEN
];
11339 json_object
*json_header
= NULL
;
11340 json_object
*json_paths
= NULL
;
11341 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
11343 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11344 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11346 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
11347 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
11348 pi
->peer
, pi
->attr
, p
);
11350 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11351 && rpki_curr_state
!= rpki_target_state
)
11354 if (json
&& !json_paths
) {
11355 /* Instantiate json_paths only if path is valid */
11356 json_paths
= json_object_new_array();
11358 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11359 json_header
= json_object_new_object();
11361 json_header
= json
;
11365 route_vty_out_detail_header(
11366 vty
, bgp
, bgp_node
, pfx_rd
,
11367 AFI_IP
, safi
, json_header
);
11372 if (pathtype
== BGP_PATH_SHOW_ALL
11373 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11374 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11375 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11376 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11377 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11378 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
11379 safi
, rpki_curr_state
, json_paths
);
11382 if (json
&& json_paths
) {
11383 json_object_object_add(json_header
, "paths", json_paths
);
11386 json_object_object_add(json
, rdbuf
, json_header
);
11390 /* Display specified route of BGP table. */
11391 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11392 struct bgp_table
*rib
, const char *ip_str
,
11393 afi_t afi
, safi_t safi
,
11394 enum rpki_states rpki_target_state
,
11395 struct prefix_rd
*prd
, int prefix_check
,
11396 enum bgp_path_type pathtype
, bool use_json
)
11400 struct prefix match
;
11401 struct bgp_dest
*dest
;
11402 struct bgp_dest
*rm
;
11403 struct bgp_table
*table
;
11404 json_object
*json
= NULL
;
11405 json_object
*json_paths
= NULL
;
11407 /* Check IP address argument. */
11408 ret
= str2prefix(ip_str
, &match
);
11410 vty_out(vty
, "address is malformed\n");
11411 return CMD_WARNING
;
11414 match
.family
= afi2family(afi
);
11417 json
= json_object_new_object();
11419 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11420 for (dest
= bgp_table_top(rib
); dest
;
11421 dest
= bgp_route_next(dest
)) {
11422 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11424 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11426 table
= bgp_dest_get_bgp_table_info(dest
);
11430 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11433 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11435 && rm_p
->prefixlen
!= match
.prefixlen
) {
11436 bgp_dest_unlock_node(rm
);
11440 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11441 bgp
, afi
, safi
, json
, pathtype
,
11442 &display
, rpki_target_state
);
11444 bgp_dest_unlock_node(rm
);
11446 } else if (safi
== SAFI_EVPN
) {
11447 struct bgp_dest
*longest_pfx
;
11448 bool is_exact_pfxlen_match
= false;
11450 for (dest
= bgp_table_top(rib
); dest
;
11451 dest
= bgp_route_next(dest
)) {
11452 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11454 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11456 table
= bgp_dest_get_bgp_table_info(dest
);
11460 longest_pfx
= NULL
;
11461 is_exact_pfxlen_match
= false;
11463 * Search through all the prefixes for a match. The
11464 * pfx's are enumerated in ascending order of pfxlens.
11465 * So, the last pfx match is the longest match. Set
11466 * is_exact_pfxlen_match when we get exact pfxlen match
11468 for (rm
= bgp_table_top(table
); rm
;
11469 rm
= bgp_route_next(rm
)) {
11470 const struct prefix
*rm_p
=
11471 bgp_dest_get_prefix(rm
);
11473 * Get prefixlen of the ip-prefix within type5
11476 if (evpn_type5_prefix_match(rm_p
, &match
)
11480 bgp_evpn_get_type5_prefixlen(
11482 if (type5_pfxlen
== match
.prefixlen
) {
11483 is_exact_pfxlen_match
= true;
11484 bgp_dest_unlock_node(rm
);
11493 if (prefix_check
&& !is_exact_pfxlen_match
)
11497 bgp_dest_lock_node(rm
);
11499 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11500 bgp
, afi
, safi
, json
, pathtype
,
11501 &display
, rpki_target_state
);
11503 bgp_dest_unlock_node(rm
);
11505 } else if (safi
== SAFI_FLOWSPEC
) {
11507 json_paths
= json_object_new_array();
11509 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11510 &match
, prefix_check
,
11516 json_object_object_add(json
, "paths",
11519 json_object_free(json_paths
);
11522 if ((dest
= bgp_node_match(rib
, &match
)) != NULL
) {
11523 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11525 || dest_p
->prefixlen
== match
.prefixlen
) {
11526 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
11527 safi
, json
, pathtype
,
11528 &display
, rpki_target_state
);
11531 bgp_dest_unlock_node(dest
);
11536 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11537 json
, JSON_C_TO_STRING_PRETTY
|
11538 JSON_C_TO_STRING_NOSLASHESCAPE
));
11539 json_object_free(json
);
11542 vty_out(vty
, "%% Network not in table\n");
11543 return CMD_WARNING
;
11547 return CMD_SUCCESS
;
11550 /* Display specified route of Main RIB */
11551 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
11552 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
11553 int prefix_check
, enum bgp_path_type pathtype
,
11554 enum rpki_states rpki_target_state
, bool use_json
)
11557 bgp
= bgp_get_default();
11560 vty_out(vty
, "No BGP process is configured\n");
11562 vty_out(vty
, "{}\n");
11563 return CMD_WARNING
;
11567 /* labeled-unicast routes live in the unicast table */
11568 if (safi
== SAFI_LABELED_UNICAST
)
11569 safi
= SAFI_UNICAST
;
11571 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
11572 afi
, safi
, rpki_target_state
, prd
,
11573 prefix_check
, pathtype
, use_json
);
11576 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
11577 struct cmd_token
**argv
, bool exact
, afi_t afi
,
11578 safi_t safi
, bool uj
)
11580 struct lcommunity
*lcom
;
11585 uint8_t show_flags
= 0;
11589 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11591 b
= buffer_new(1024);
11592 for (i
= 0; i
< argc
; i
++) {
11594 buffer_putc(b
, ' ');
11596 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
11598 buffer_putstr(b
, argv
[i
]->arg
);
11602 buffer_putc(b
, '\0');
11604 str
= buffer_getstr(b
);
11607 lcom
= lcommunity_str2com(str
);
11608 XFREE(MTYPE_TMP
, str
);
11610 vty_out(vty
, "%% Large-community malformed\n");
11611 return CMD_WARNING
;
11614 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11615 (exact
? bgp_show_type_lcommunity_exact
11616 : bgp_show_type_lcommunity
),
11617 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
11619 lcommunity_free(&lcom
);
11623 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
11624 const char *lcom
, bool exact
, afi_t afi
,
11625 safi_t safi
, bool uj
)
11627 struct community_list
*list
;
11628 uint8_t show_flags
= 0;
11631 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11634 list
= community_list_lookup(bgp_clist
, lcom
, 0,
11635 LARGE_COMMUNITY_LIST_MASTER
);
11636 if (list
== NULL
) {
11637 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
11639 return CMD_WARNING
;
11642 return bgp_show(vty
, bgp
, afi
, safi
,
11643 (exact
? bgp_show_type_lcommunity_list_exact
11644 : bgp_show_type_lcommunity_list
),
11645 list
, show_flags
, RPKI_NOT_BEING_USED
);
11648 DEFUN (show_ip_bgp_large_community_list
,
11649 show_ip_bgp_large_community_list_cmd
,
11650 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
11654 BGP_INSTANCE_HELP_STR
11656 BGP_SAFI_WITH_LABEL_HELP_STR
11657 "Display routes matching the large-community-list\n"
11658 "large-community-list number\n"
11659 "large-community-list name\n"
11660 "Exact match of the large-communities\n"
11663 afi_t afi
= AFI_IP6
;
11664 safi_t safi
= SAFI_UNICAST
;
11666 bool exact_match
= 0;
11667 struct bgp
*bgp
= NULL
;
11668 bool uj
= use_json(argc
, argv
);
11673 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11676 return CMD_WARNING
;
11678 argv_find(argv
, argc
, "large-community-list", &idx
);
11680 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11682 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11685 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
11686 exact_match
, afi
, safi
, uj
);
11688 DEFUN (show_ip_bgp_large_community
,
11689 show_ip_bgp_large_community_cmd
,
11690 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11694 BGP_INSTANCE_HELP_STR
11696 BGP_SAFI_WITH_LABEL_HELP_STR
11697 "Display routes matching the large-communities\n"
11698 "List of large-community numbers\n"
11699 "Exact match of the large-communities\n"
11702 afi_t afi
= AFI_IP6
;
11703 safi_t safi
= SAFI_UNICAST
;
11705 bool exact_match
= 0;
11706 struct bgp
*bgp
= NULL
;
11707 bool uj
= use_json(argc
, argv
);
11708 uint8_t show_flags
= 0;
11712 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11715 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11718 return CMD_WARNING
;
11720 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
11721 if (argv_find(argv
, argc
, "exact-match", &idx
))
11723 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
11724 exact_match
, afi
, safi
, uj
);
11726 return bgp_show(vty
, bgp
, afi
, safi
,
11727 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
11728 RPKI_NOT_BEING_USED
);
11731 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11732 safi_t safi
, struct json_object
*json_array
);
11733 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11734 safi_t safi
, struct json_object
*json
);
11737 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
11738 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11739 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11740 "Display number of prefixes for all afi/safi\n" JSON_STR
)
11742 bool uj
= use_json(argc
, argv
);
11743 struct bgp
*bgp
= NULL
;
11744 safi_t safi
= SAFI_UNICAST
;
11745 afi_t afi
= AFI_IP6
;
11747 struct json_object
*json_all
= NULL
;
11748 struct json_object
*json_afi_safi
= NULL
;
11750 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11753 return CMD_WARNING
;
11756 json_all
= json_object_new_object();
11758 FOREACH_AFI_SAFI (afi
, safi
) {
11760 * So limit output to those afi/safi pairs that
11761 * actually have something interesting in them
11763 if (strmatch(get_afi_safi_str(afi
, safi
, true),
11768 json_afi_safi
= json_object_new_array();
11769 json_object_object_add(
11771 get_afi_safi_str(afi
, safi
, true),
11774 json_afi_safi
= NULL
;
11777 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11782 json_object_to_json_string_ext(
11783 json_all
, JSON_C_TO_STRING_PRETTY
));
11784 json_object_free(json_all
);
11787 return CMD_SUCCESS
;
11790 /* BGP route print out function without JSON */
11791 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
11792 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
11793 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
11797 BGP_INSTANCE_HELP_STR
11800 "BGP RIB advertisement statistics\n"
11803 afi_t afi
= AFI_IP6
;
11804 safi_t safi
= SAFI_UNICAST
;
11805 struct bgp
*bgp
= NULL
;
11807 bool uj
= use_json(argc
, argv
);
11808 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11810 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11813 return CMD_WARNING
;
11816 json_afi_safi
= json_object_new_array();
11818 json_afi_safi
= NULL
;
11820 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11823 json
= json_object_new_object();
11824 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11826 vty_out(vty
, "%s", json_object_to_json_string_ext(
11827 json
, JSON_C_TO_STRING_PRETTY
));
11828 json_object_free(json
);
11833 /* BGP route print out function without JSON */
11834 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
11835 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11836 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11838 statistics [json]",
11839 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11840 BGP_SAFI_WITH_LABEL_HELP_STR
11841 "BGP RIB advertisement statistics\n" JSON_STR
)
11843 afi_t afi
= AFI_IP6
;
11844 safi_t safi
= SAFI_UNICAST
;
11845 struct bgp
*bgp
= NULL
;
11847 bool uj
= use_json(argc
, argv
);
11848 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11850 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11853 return CMD_WARNING
;
11856 json_afi_safi
= json_object_new_array();
11858 json_afi_safi
= NULL
;
11860 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11863 json
= json_object_new_object();
11864 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11867 json_object_to_json_string_ext(
11868 json
, JSON_C_TO_STRING_PRETTY
));
11869 json_object_free(json
);
11874 /* BGP route print out function without JSON */
11875 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
11876 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11877 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11879 <[all$all] dampening <parameters>\
11883 |community-list <(1-500)|WORD> [exact-match]\
11884 |A.B.C.D/M longer-prefixes\
11885 |X:X::X:X/M longer-prefixes\
11887 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11888 BGP_SAFI_WITH_LABEL_HELP_STR
11889 "Display the entries for all address families\n"
11890 "Display detailed information about dampening\n"
11891 "Display detail of configured dampening parameters\n"
11892 "Display routes matching the route-map\n"
11893 "A route-map to match on\n"
11894 "Display routes conforming to the prefix-list\n"
11895 "Prefix-list name\n"
11896 "Display routes conforming to the filter-list\n"
11897 "Regular expression access list name\n"
11898 "Display routes matching the community-list\n"
11899 "community-list number\n"
11900 "community-list name\n"
11901 "Exact match of the communities\n"
11903 "Display route and more specific routes\n"
11905 "Display route and more specific routes\n")
11907 afi_t afi
= AFI_IP6
;
11908 safi_t safi
= SAFI_UNICAST
;
11909 int exact_match
= 0;
11910 struct bgp
*bgp
= NULL
;
11912 uint8_t show_flags
= 0;
11914 /* [<ipv4|ipv6> [all]] */
11916 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11917 if (argv_find(argv
, argc
, "ipv4", &idx
))
11918 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11920 if (argv_find(argv
, argc
, "ipv6", &idx
))
11921 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11924 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11927 return CMD_WARNING
;
11929 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11930 if (argv_find(argv
, argc
, "parameters", &idx
))
11931 return bgp_show_dampening_parameters(vty
, afi
, safi
,
11935 if (argv_find(argv
, argc
, "prefix-list", &idx
))
11936 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11937 safi
, bgp_show_type_prefix_list
);
11939 if (argv_find(argv
, argc
, "filter-list", &idx
))
11940 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11941 safi
, bgp_show_type_filter_list
);
11943 if (argv_find(argv
, argc
, "route-map", &idx
))
11944 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11945 safi
, bgp_show_type_route_map
);
11947 if (argv_find(argv
, argc
, "community-list", &idx
)) {
11948 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11949 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11951 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
11952 exact_match
, afi
, safi
);
11954 /* prefix-longer */
11955 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11956 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11957 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
11959 bgp_show_type_prefix_longer
);
11961 return CMD_WARNING
;
11964 /* BGP route print out function with JSON */
11965 DEFPY(show_ip_bgp_json
, show_ip_bgp_json_cmd
,
11966 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11967 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11971 |dampening <flap-statistics|dampened-paths>\
11972 |community [AA:NN|local-AS|no-advertise|no-export\
11973 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11974 |accept-own|accept-own-nexthop|route-filter-v6\
11975 |route-filter-v4|route-filter-translated-v6\
11976 |route-filter-translated-v4] [exact-match]\
11977 |rpki <invalid|valid|notfound>\
11978 |version (1-4294967295)\
11980 ] [json$uj [detail$detail] | wide$wide]",
11981 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11982 BGP_SAFI_WITH_LABEL_HELP_STR
11983 "Display the entries for all address families\n"
11984 "Display only routes with non-natural netmasks\n"
11985 "Display detailed information about dampening\n"
11986 "Display flap statistics of routes\n"
11987 "Display paths suppressed due to dampening\n"
11988 "Display routes matching the communities\n" COMMUNITY_AANN_STR
11989 "Do not send outside local AS (well-known community)\n"
11990 "Do not advertise to any peer (well-known community)\n"
11991 "Do not export to next AS (well-known community)\n"
11992 "Graceful shutdown (well-known community)\n"
11993 "Do not export to any peer (well-known community)\n"
11994 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11995 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11996 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11997 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11998 "Should accept VPN route with local nexthop (well-known community)\n"
11999 "RT VPNv6 route filtering (well-known community)\n"
12000 "RT VPNv4 route filtering (well-known community)\n"
12001 "RT translated VPNv6 route filtering (well-known community)\n"
12002 "RT translated VPNv4 route filtering (well-known community)\n"
12003 "Exact match of the communities\n"
12004 "RPKI route types\n"
12005 "A valid path as determined by rpki\n"
12006 "A invalid path as determined by rpki\n"
12007 "A path that has no rpki data\n"
12008 "Display prefixes with matching version numbers\n"
12009 "Version number and above\n"
12010 "Display prefixes with matching BGP community alias\n"
12011 "BGP community alias\n" JSON_STR
12012 "Display detailed version of JSON output\n"
12013 "Increase table width for longer prefixes\n")
12015 afi_t afi
= AFI_IP6
;
12016 safi_t safi
= SAFI_UNICAST
;
12017 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12018 struct bgp
*bgp
= NULL
;
12020 int exact_match
= 0;
12021 char *community
= NULL
;
12022 char *prefix_version
= NULL
;
12023 char *bgp_community_alias
= NULL
;
12025 uint8_t show_flags
= 0;
12026 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12030 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12034 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12036 /* [<ipv4|ipv6> [all]] */
12038 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12040 if (argv_find(argv
, argc
, "ipv4", &idx
))
12041 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12043 if (argv_find(argv
, argc
, "ipv6", &idx
))
12044 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12048 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12050 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12053 return CMD_WARNING
;
12055 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12056 sh_type
= bgp_show_type_cidr_only
;
12058 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12059 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12060 sh_type
= bgp_show_type_dampend_paths
;
12061 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12062 sh_type
= bgp_show_type_flap_statistics
;
12065 if (argv_find(argv
, argc
, "community", &idx
)) {
12066 char *maybecomm
= NULL
;
12068 if (idx
+ 1 < argc
) {
12069 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12070 maybecomm
= argv
[idx
+ 1]->arg
;
12072 maybecomm
= argv
[idx
+ 1]->text
;
12075 if (maybecomm
&& !strmatch(maybecomm
, "json")
12076 && !strmatch(maybecomm
, "exact-match"))
12077 community
= maybecomm
;
12079 if (argv_find(argv
, argc
, "exact-match", &idx
))
12083 sh_type
= bgp_show_type_community_all
;
12086 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12087 sh_type
= bgp_show_type_rpki
;
12088 if (argv_find(argv
, argc
, "valid", &idx
))
12089 rpki_target_state
= RPKI_VALID
;
12090 else if (argv_find(argv
, argc
, "invalid", &idx
))
12091 rpki_target_state
= RPKI_INVALID
;
12094 /* Display prefixes with matching version numbers */
12095 if (argv_find(argv
, argc
, "version", &idx
)) {
12096 sh_type
= bgp_show_type_prefix_version
;
12097 prefix_version
= argv
[idx
+ 1]->arg
;
12100 /* Display prefixes with matching BGP community alias */
12101 if (argv_find(argv
, argc
, "alias", &idx
)) {
12102 sh_type
= bgp_show_type_community_alias
;
12103 bgp_community_alias
= argv
[idx
+ 1]->arg
;
12107 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12109 return bgp_show_community(vty
, bgp
, community
,
12110 exact_match
, afi
, safi
,
12112 else if (prefix_version
)
12113 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12114 prefix_version
, show_flags
,
12115 rpki_target_state
);
12116 else if (bgp_community_alias
)
12117 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12118 bgp_community_alias
, show_flags
,
12119 rpki_target_state
);
12121 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
,
12122 show_flags
, rpki_target_state
);
12124 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12128 vty_out(vty
, "{\n");
12130 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12131 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12132 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12135 FOREACH_SAFI (safi
) {
12136 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12143 vty_out(vty
, ",\n");
12144 vty_out(vty
, "\"%s\":{\n",
12145 get_afi_safi_str(afi
, safi
,
12149 "\nFor address family: %s\n",
12150 get_afi_safi_str(afi
, safi
,
12154 bgp_show_community(vty
, bgp
, community
,
12157 else if (prefix_version
)
12158 return bgp_show(vty
, bgp
, afi
, safi
,
12159 sh_type
, prefix_version
,
12161 rpki_target_state
);
12162 else if (bgp_community_alias
)
12164 vty
, bgp
, afi
, safi
, sh_type
,
12165 bgp_community_alias
, show_flags
,
12166 rpki_target_state
);
12168 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12170 rpki_target_state
);
12172 vty_out(vty
, "}\n");
12175 /* show <ip> bgp all: for each AFI and SAFI*/
12176 FOREACH_AFI_SAFI (afi
, safi
) {
12177 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12184 vty_out(vty
, ",\n");
12186 vty_out(vty
, "\"%s\":{\n",
12187 get_afi_safi_str(afi
, safi
,
12191 "\nFor address family: %s\n",
12192 get_afi_safi_str(afi
, safi
,
12196 bgp_show_community(vty
, bgp
, community
,
12199 else if (prefix_version
)
12200 return bgp_show(vty
, bgp
, afi
, safi
,
12201 sh_type
, prefix_version
,
12203 rpki_target_state
);
12205 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12207 rpki_target_state
);
12209 vty_out(vty
, "}\n");
12213 vty_out(vty
, "}\n");
12215 return CMD_SUCCESS
;
12218 DEFUN (show_ip_bgp_route
,
12219 show_ip_bgp_route_cmd
,
12220 "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]",
12224 BGP_INSTANCE_HELP_STR
12226 BGP_SAFI_WITH_LABEL_HELP_STR
12227 "Network in the BGP routing table to display\n"
12229 "Network in the BGP routing table to display\n"
12231 "Display only the bestpath\n"
12232 "Display only multipaths\n"
12233 "Display only paths that match the specified rpki state\n"
12234 "A valid path as determined by rpki\n"
12235 "A invalid path as determined by rpki\n"
12236 "A path that has no rpki data\n"
12239 int prefix_check
= 0;
12241 afi_t afi
= AFI_IP6
;
12242 safi_t safi
= SAFI_UNICAST
;
12243 char *prefix
= NULL
;
12244 struct bgp
*bgp
= NULL
;
12245 enum bgp_path_type path_type
;
12246 bool uj
= use_json(argc
, argv
);
12250 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12253 return CMD_WARNING
;
12257 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12258 return CMD_WARNING
;
12261 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12262 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12263 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12265 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12266 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12269 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12270 && afi
!= AFI_IP6
) {
12272 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12273 return CMD_WARNING
;
12275 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12276 && afi
!= AFI_IP
) {
12278 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12279 return CMD_WARNING
;
12282 prefix
= argv
[idx
]->arg
;
12284 /* [<bestpath|multipath>] */
12285 if (argv_find(argv
, argc
, "bestpath", &idx
))
12286 path_type
= BGP_PATH_SHOW_BESTPATH
;
12287 else if (argv_find(argv
, argc
, "multipath", &idx
))
12288 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12290 path_type
= BGP_PATH_SHOW_ALL
;
12292 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12293 path_type
, RPKI_NOT_BEING_USED
, uj
);
12296 DEFUN (show_ip_bgp_regexp
,
12297 show_ip_bgp_regexp_cmd
,
12298 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12302 BGP_INSTANCE_HELP_STR
12304 BGP_SAFI_WITH_LABEL_HELP_STR
12305 "Display routes matching the AS path regular expression\n"
12306 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12309 afi_t afi
= AFI_IP6
;
12310 safi_t safi
= SAFI_UNICAST
;
12311 struct bgp
*bgp
= NULL
;
12312 bool uj
= use_json(argc
, argv
);
12313 char *regstr
= NULL
;
12316 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12319 return CMD_WARNING
;
12321 // get index of regex
12322 if (argv_find(argv
, argc
, "REGEX", &idx
))
12323 regstr
= argv
[idx
]->arg
;
12326 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12327 bgp_show_type_regexp
, uj
);
12330 DEFPY (show_ip_bgp_instance_all
,
12331 show_ip_bgp_instance_all_cmd
,
12332 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12336 BGP_INSTANCE_ALL_HELP_STR
12338 BGP_SAFI_WITH_LABEL_HELP_STR
12340 "Increase table width for longer prefixes\n")
12342 afi_t afi
= AFI_IP
;
12343 safi_t safi
= SAFI_UNICAST
;
12344 struct bgp
*bgp
= NULL
;
12346 uint8_t show_flags
= 0;
12350 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12354 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12356 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12359 return CMD_WARNING
;
12361 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12362 return CMD_SUCCESS
;
12365 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12366 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12371 uint8_t show_flags
= 0;
12374 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12376 if (!config_bgp_aspath_validate(regstr
)) {
12377 vty_out(vty
, "Invalid character in REGEX %s\n",
12379 return CMD_WARNING_CONFIG_FAILED
;
12382 regex
= bgp_regcomp(regstr
);
12384 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12385 return CMD_WARNING
;
12388 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
12389 RPKI_NOT_BEING_USED
);
12390 bgp_regex_free(regex
);
12394 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
12395 const char *prefix_list_str
, afi_t afi
,
12396 safi_t safi
, enum bgp_show_type type
)
12398 struct prefix_list
*plist
;
12399 uint8_t show_flags
= 0;
12401 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12402 if (plist
== NULL
) {
12403 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
12405 return CMD_WARNING
;
12408 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, show_flags
,
12409 RPKI_NOT_BEING_USED
);
12412 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
12413 const char *filter
, afi_t afi
, safi_t safi
,
12414 enum bgp_show_type type
)
12416 struct as_list
*as_list
;
12417 uint8_t show_flags
= 0;
12419 as_list
= as_list_lookup(filter
);
12420 if (as_list
== NULL
) {
12421 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
12423 return CMD_WARNING
;
12426 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, show_flags
,
12427 RPKI_NOT_BEING_USED
);
12430 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
12431 const char *rmap_str
, afi_t afi
, safi_t safi
,
12432 enum bgp_show_type type
)
12434 struct route_map
*rmap
;
12435 uint8_t show_flags
= 0;
12437 rmap
= route_map_lookup_by_name(rmap_str
);
12439 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
12440 return CMD_WARNING
;
12443 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, show_flags
,
12444 RPKI_NOT_BEING_USED
);
12447 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12448 const char *comstr
, int exact
, afi_t afi
,
12449 safi_t safi
, uint8_t show_flags
)
12451 struct community
*com
;
12454 com
= community_str2com(comstr
);
12456 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12457 return CMD_WARNING
;
12460 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12461 (exact
? bgp_show_type_community_exact
12462 : bgp_show_type_community
),
12463 com
, show_flags
, RPKI_NOT_BEING_USED
);
12464 community_free(&com
);
12469 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
12470 const char *com
, int exact
, afi_t afi
,
12473 struct community_list
*list
;
12474 uint8_t show_flags
= 0;
12476 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
12477 if (list
== NULL
) {
12478 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
12479 return CMD_WARNING
;
12482 return bgp_show(vty
, bgp
, afi
, safi
,
12483 (exact
? bgp_show_type_community_list_exact
12484 : bgp_show_type_community_list
),
12485 list
, show_flags
, RPKI_NOT_BEING_USED
);
12488 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
12489 const char *prefix
, afi_t afi
, safi_t safi
,
12490 enum bgp_show_type type
)
12494 uint8_t show_flags
= 0;
12498 ret
= str2prefix(prefix
, p
);
12500 vty_out(vty
, "%% Malformed Prefix\n");
12501 return CMD_WARNING
;
12504 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, show_flags
,
12505 RPKI_NOT_BEING_USED
);
12511 BGP_STATS_MAXBITLEN
= 0,
12513 BGP_STATS_PREFIXES
,
12515 BGP_STATS_UNAGGREGATEABLE
,
12516 BGP_STATS_MAX_AGGREGATEABLE
,
12517 BGP_STATS_AGGREGATES
,
12519 BGP_STATS_ASPATH_COUNT
,
12520 BGP_STATS_ASPATH_MAXHOPS
,
12521 BGP_STATS_ASPATH_TOTHOPS
,
12522 BGP_STATS_ASPATH_MAXSIZE
,
12523 BGP_STATS_ASPATH_TOTSIZE
,
12524 BGP_STATS_ASN_HIGHEST
,
12528 #define TABLE_STATS_IDX_VTY 0
12529 #define TABLE_STATS_IDX_JSON 1
12531 static const char *table_stats_strs
[][2] = {
12532 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12533 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12534 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12535 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12536 "unaggregateablePrefixes"},
12537 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12538 "maximumAggregateablePrefixes"},
12539 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12540 "bgpAggregateAdvertisements"},
12541 [BGP_STATS_SPACE
] = {"Address space advertised",
12542 "addressSpaceAdvertised"},
12543 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12544 "advertisementsWithPaths"},
12545 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12547 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12549 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12550 "averageAsPathLengthHops"},
12551 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12552 "averageAsPathSizeBytes"},
12553 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12554 [BGP_STATS_MAX
] = {NULL
, NULL
}
12557 struct bgp_table_stats
{
12558 struct bgp_table
*table
;
12559 unsigned long long counts
[BGP_STATS_MAX
];
12560 double total_space
;
12563 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
12564 struct bgp_table_stats
*ts
, unsigned int space
)
12566 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
12567 struct bgp_path_info
*pi
;
12568 const struct prefix
*rn_p
;
12570 if (!bgp_dest_has_bgp_path_info_data(dest
))
12573 rn_p
= bgp_dest_get_prefix(dest
);
12574 ts
->counts
[BGP_STATS_PREFIXES
]++;
12575 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
12577 /* check if the prefix is included by any other announcements */
12578 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
12579 pdest
= bgp_dest_parent_nolock(pdest
);
12581 if (pdest
== NULL
|| pdest
== top
) {
12582 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
12583 /* announced address space */
12585 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
12586 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
12587 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
12590 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
12591 ts
->counts
[BGP_STATS_RIB
]++;
12593 if (CHECK_FLAG(pi
->attr
->flag
,
12594 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
12595 ts
->counts
[BGP_STATS_AGGREGATES
]++;
12597 /* as-path stats */
12598 if (pi
->attr
->aspath
) {
12599 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
12600 unsigned int size
= aspath_size(pi
->attr
->aspath
);
12601 as_t highest
= aspath_highest(pi
->attr
->aspath
);
12603 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
12605 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
12606 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
12608 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
12609 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
12611 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
12612 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
12613 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
12614 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
12619 static int bgp_table_stats_walker(struct thread
*t
)
12621 struct bgp_dest
*dest
, *ndest
;
12622 struct bgp_dest
*top
;
12623 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
12624 unsigned int space
= 0;
12626 if (!(top
= bgp_table_top(ts
->table
)))
12629 switch (ts
->table
->afi
) {
12631 space
= IPV4_MAX_BITLEN
;
12634 space
= IPV6_MAX_BITLEN
;
12637 space
= EVPN_ROUTE_PREFIXLEN
;
12643 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
12645 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
12646 if (ts
->table
->safi
== SAFI_MPLS_VPN
12647 || ts
->table
->safi
== SAFI_ENCAP
12648 || ts
->table
->safi
== SAFI_EVPN
) {
12649 struct bgp_table
*table
;
12651 table
= bgp_dest_get_bgp_table_info(dest
);
12655 top
= bgp_table_top(table
);
12656 for (ndest
= bgp_table_top(table
); ndest
;
12657 ndest
= bgp_route_next(ndest
))
12658 bgp_table_stats_rn(ndest
, top
, ts
, space
);
12660 bgp_table_stats_rn(dest
, top
, ts
, space
);
12667 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
12668 struct json_object
*json_array
)
12670 struct listnode
*node
, *nnode
;
12673 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
12674 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12677 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12678 safi_t safi
, struct json_object
*json_array
)
12680 struct bgp_table_stats ts
;
12682 int ret
= CMD_SUCCESS
;
12684 struct json_object
*json
= NULL
;
12687 json
= json_object_new_object();
12689 if (!bgp
->rib
[afi
][safi
]) {
12690 char warning_msg
[50];
12692 snprintf(warning_msg
, sizeof(warning_msg
),
12693 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
12697 vty_out(vty
, "%s\n", warning_msg
);
12699 json_object_string_add(json
, "warning", warning_msg
);
12702 goto end_table_stats
;
12706 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
12707 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
12709 json_object_string_add(json
, "instance", bgp
->name_pretty
);
12711 /* labeled-unicast routes live in the unicast table */
12712 if (safi
== SAFI_LABELED_UNICAST
)
12713 safi
= SAFI_UNICAST
;
12715 memset(&ts
, 0, sizeof(ts
));
12716 ts
.table
= bgp
->rib
[afi
][safi
];
12717 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
12719 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
12720 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
12721 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
12725 case BGP_STATS_ASPATH_TOTHOPS
:
12726 case BGP_STATS_ASPATH_TOTSIZE
:
12729 temp_buf
, sizeof(temp_buf
), "%12.2f",
12731 ? (float)ts
.counts
[i
]
12733 [BGP_STATS_ASPATH_COUNT
]
12735 vty_out(vty
, "%-30s: %s",
12736 table_stats_strs
[i
]
12737 [TABLE_STATS_IDX_VTY
],
12740 json_object_double_add(
12742 table_stats_strs
[i
]
12743 [TABLE_STATS_IDX_JSON
],
12745 ? (double)ts
.counts
[i
]
12746 / (double)ts
.counts
12747 [BGP_STATS_ASPATH_COUNT
]
12751 case BGP_STATS_TOTPLEN
:
12754 temp_buf
, sizeof(temp_buf
), "%12.2f",
12756 ? (float)ts
.counts
[i
]
12758 [BGP_STATS_PREFIXES
]
12760 vty_out(vty
, "%-30s: %s",
12761 table_stats_strs
[i
]
12762 [TABLE_STATS_IDX_VTY
],
12765 json_object_double_add(
12767 table_stats_strs
[i
]
12768 [TABLE_STATS_IDX_JSON
],
12770 ? (double)ts
.counts
[i
]
12771 / (double)ts
.counts
12772 [BGP_STATS_PREFIXES
]
12776 case BGP_STATS_SPACE
:
12778 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
12780 vty_out(vty
, "%-30s: %s\n",
12781 table_stats_strs
[i
]
12782 [TABLE_STATS_IDX_VTY
],
12785 json_object_double_add(
12787 table_stats_strs
[i
]
12788 [TABLE_STATS_IDX_JSON
],
12789 (double)ts
.total_space
);
12791 if (afi
== AFI_IP6
) {
12793 snprintf(temp_buf
, sizeof(temp_buf
),
12796 * pow(2.0, -128 + 32));
12797 vty_out(vty
, "%30s: %s\n",
12798 "/32 equivalent %s\n",
12801 json_object_double_add(
12802 json
, "/32equivalent",
12803 (double)(ts
.total_space
12808 snprintf(temp_buf
, sizeof(temp_buf
),
12811 * pow(2.0, -128 + 48));
12812 vty_out(vty
, "%30s: %s\n",
12813 "/48 equivalent %s\n",
12816 json_object_double_add(
12817 json
, "/48equivalent",
12818 (double)(ts
.total_space
12824 snprintf(temp_buf
, sizeof(temp_buf
),
12826 ts
.total_space
* 100.
12828 vty_out(vty
, "%30s: %s\n",
12829 "% announced ", temp_buf
);
12831 json_object_double_add(
12832 json
, "%announced",
12833 (double)(ts
.total_space
* 100.
12837 snprintf(temp_buf
, sizeof(temp_buf
),
12840 * pow(2.0, -32 + 8));
12841 vty_out(vty
, "%30s: %s\n",
12842 "/8 equivalent ", temp_buf
);
12844 json_object_double_add(
12845 json
, "/8equivalent",
12846 (double)(ts
.total_space
12847 * pow(2.0, -32 + 8)));
12850 snprintf(temp_buf
, sizeof(temp_buf
),
12853 * pow(2.0, -32 + 24));
12854 vty_out(vty
, "%30s: %s\n",
12855 "/24 equivalent ", temp_buf
);
12857 json_object_double_add(
12858 json
, "/24equivalent",
12859 (double)(ts
.total_space
12860 * pow(2.0, -32 + 24)));
12866 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
12868 vty_out(vty
, "%-30s: %s",
12869 table_stats_strs
[i
]
12870 [TABLE_STATS_IDX_VTY
],
12873 json_object_int_add(
12875 table_stats_strs
[i
]
12876 [TABLE_STATS_IDX_JSON
],
12881 vty_out(vty
, "\n");
12885 json_object_array_add(json_array
, json
);
12889 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12890 safi_t safi
, struct json_object
*json_array
)
12893 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
12894 return CMD_SUCCESS
;
12897 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12909 PCOUNT_BPATH_SELECTED
,
12910 PCOUNT_PFCNT
, /* the figure we display to users */
12914 static const char *const pcount_strs
[] = {
12915 [PCOUNT_ADJ_IN
] = "Adj-in",
12916 [PCOUNT_DAMPED
] = "Damped",
12917 [PCOUNT_REMOVED
] = "Removed",
12918 [PCOUNT_HISTORY
] = "History",
12919 [PCOUNT_STALE
] = "Stale",
12920 [PCOUNT_VALID
] = "Valid",
12921 [PCOUNT_ALL
] = "All RIB",
12922 [PCOUNT_COUNTED
] = "PfxCt counted",
12923 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
12924 [PCOUNT_PFCNT
] = "Useable",
12925 [PCOUNT_MAX
] = NULL
,
12928 struct peer_pcounts
{
12929 unsigned int count
[PCOUNT_MAX
];
12930 const struct peer
*peer
;
12931 const struct bgp_table
*table
;
12935 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
12937 const struct bgp_adj_in
*ain
;
12938 const struct bgp_path_info
*pi
;
12939 const struct peer
*peer
= pc
->peer
;
12941 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
12942 if (ain
->peer
== peer
)
12943 pc
->count
[PCOUNT_ADJ_IN
]++;
12945 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
12947 if (pi
->peer
!= peer
)
12950 pc
->count
[PCOUNT_ALL
]++;
12952 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
12953 pc
->count
[PCOUNT_DAMPED
]++;
12954 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
12955 pc
->count
[PCOUNT_HISTORY
]++;
12956 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
12957 pc
->count
[PCOUNT_REMOVED
]++;
12958 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
12959 pc
->count
[PCOUNT_STALE
]++;
12960 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
12961 pc
->count
[PCOUNT_VALID
]++;
12962 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12963 pc
->count
[PCOUNT_PFCNT
]++;
12964 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12965 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
12967 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
12968 pc
->count
[PCOUNT_COUNTED
]++;
12969 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12971 EC_LIB_DEVELOPMENT
,
12972 "Attempting to count but flags say it is unusable");
12974 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12976 EC_LIB_DEVELOPMENT
,
12977 "Not counted but flags say we should");
12982 static int bgp_peer_count_walker(struct thread
*t
)
12984 struct bgp_dest
*rn
, *rm
;
12985 const struct bgp_table
*table
;
12986 struct peer_pcounts
*pc
= THREAD_ARG(t
);
12988 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
12989 || pc
->safi
== SAFI_EVPN
) {
12990 /* Special handling for 2-level routing tables. */
12991 for (rn
= bgp_table_top(pc
->table
); rn
;
12992 rn
= bgp_route_next(rn
)) {
12993 table
= bgp_dest_get_bgp_table_info(rn
);
12995 for (rm
= bgp_table_top(table
); rm
;
12996 rm
= bgp_route_next(rm
))
12997 bgp_peer_count_proc(rm
, pc
);
13000 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13001 bgp_peer_count_proc(rn
, pc
);
13006 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13007 safi_t safi
, bool use_json
)
13009 struct peer_pcounts pcounts
= {.peer
= peer
};
13011 json_object
*json
= NULL
;
13012 json_object
*json_loop
= NULL
;
13015 json
= json_object_new_object();
13016 json_loop
= json_object_new_object();
13019 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13020 || !peer
->bgp
->rib
[afi
][safi
]) {
13022 json_object_string_add(
13024 "No such neighbor or address family");
13025 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13026 json_object_free(json
);
13027 json_object_free(json_loop
);
13029 vty_out(vty
, "%% No such neighbor or address family\n");
13031 return CMD_WARNING
;
13034 memset(&pcounts
, 0, sizeof(pcounts
));
13035 pcounts
.peer
= peer
;
13036 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13037 pcounts
.safi
= safi
;
13039 /* in-place call via thread subsystem so as to record execution time
13040 * stats for the thread-walk (i.e. ensure this can't be blamed on
13041 * on just vty_read()).
13043 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13046 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13047 json_object_string_add(json
, "multiProtocol",
13048 get_afi_safi_str(afi
, safi
, true));
13049 json_object_int_add(json
, "pfxCounter",
13050 peer
->pcount
[afi
][safi
]);
13052 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13053 json_object_int_add(json_loop
, pcount_strs
[i
],
13056 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13058 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13059 json_object_string_add(json
, "pfxctDriftFor",
13061 json_object_string_add(
13062 json
, "recommended",
13063 "Please report this bug, with the above command output");
13065 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
13066 json
, JSON_C_TO_STRING_PRETTY
));
13067 json_object_free(json
);
13071 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13072 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13073 peer
->hostname
, peer
->host
,
13074 get_afi_safi_str(afi
, safi
, false));
13076 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13077 get_afi_safi_str(afi
, safi
, false));
13080 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13081 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13083 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13084 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13087 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13088 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13090 "Please report this bug, with the above command output\n");
13094 return CMD_SUCCESS
;
13097 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13098 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13099 "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]",
13103 BGP_INSTANCE_HELP_STR
13106 "Detailed information on TCP and BGP neighbor connections\n"
13107 "Neighbor to display information about\n"
13108 "Neighbor to display information about\n"
13109 "Neighbor on BGP configured interface\n"
13110 "Display detailed prefix count information\n"
13113 afi_t afi
= AFI_IP6
;
13114 safi_t safi
= SAFI_UNICAST
;
13117 struct bgp
*bgp
= NULL
;
13118 bool uj
= use_json(argc
, argv
);
13123 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13126 return CMD_WARNING
;
13128 argv_find(argv
, argc
, "neighbors", &idx
);
13129 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13131 return CMD_WARNING
;
13133 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13136 #ifdef KEEP_OLD_VPN_COMMANDS
13137 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13138 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13139 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13144 "Display information about all VPNv4 NLRIs\n"
13145 "Detailed information on TCP and BGP neighbor connections\n"
13146 "Neighbor to display information about\n"
13147 "Neighbor to display information about\n"
13148 "Neighbor on BGP configured interface\n"
13149 "Display detailed prefix count information\n"
13154 bool uj
= use_json(argc
, argv
);
13156 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13158 return CMD_WARNING
;
13160 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13163 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13164 show_ip_bgp_vpn_all_route_prefix_cmd
,
13165 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13170 "Display information about all VPNv4 NLRIs\n"
13171 "Network in the BGP routing table to display\n"
13172 "Network in the BGP routing table to display\n"
13176 char *network
= NULL
;
13177 struct bgp
*bgp
= bgp_get_default();
13179 vty_out(vty
, "Can't find default instance\n");
13180 return CMD_WARNING
;
13183 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13184 network
= argv
[idx
]->arg
;
13185 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13186 network
= argv
[idx
]->arg
;
13188 vty_out(vty
, "Unable to figure out Network\n");
13189 return CMD_WARNING
;
13192 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13193 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13194 use_json(argc
, argv
));
13196 #endif /* KEEP_OLD_VPN_COMMANDS */
13198 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13199 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13200 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13205 "Network in the BGP routing table to display\n"
13206 "Network in the BGP routing table to display\n"
13207 "Network in the BGP routing table to display\n"
13208 "Network in the BGP routing table to display\n"
13212 char *network
= NULL
;
13213 int prefix_check
= 0;
13215 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13216 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13217 network
= argv
[idx
]->arg
;
13218 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13219 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13220 network
= argv
[idx
]->arg
;
13223 vty_out(vty
, "Unable to figure out Network\n");
13224 return CMD_WARNING
;
13226 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13227 prefix_check
, BGP_PATH_SHOW_ALL
,
13228 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13231 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
13232 struct bgp_table
*table
, int *header1
,
13233 int *header2
, json_object
*json
,
13234 json_object
*json_scode
,
13235 json_object
*json_ocode
, bool wide
)
13237 uint64_t version
= table
? table
->version
: 0;
13238 char buf
[BUFSIZ
] = {0};
13242 json_object_int_add(json
, "bgpTableVersion", version
);
13243 json_object_string_add(json
, "bgpLocalRouterId",
13245 &bgp
->router_id
, buf
,
13247 json_object_int_add(json
, "defaultLocPrf",
13248 bgp
->default_local_pref
);
13249 json_object_int_add(json
, "localAS", bgp
->as
);
13250 json_object_object_add(json
, "bgpStatusCodes",
13252 json_object_object_add(json
, "bgpOriginCodes",
13256 "BGP table version is %" PRIu64
13257 ", local router ID is %pI4, vrf id ",
13258 version
, &bgp
->router_id
);
13259 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13260 vty_out(vty
, "%s", VRFID_NONE_STR
);
13262 vty_out(vty
, "%u", bgp
->vrf_id
);
13263 vty_out(vty
, "\n");
13264 vty_out(vty
, "Default local pref %u, ",
13265 bgp
->default_local_pref
);
13266 vty_out(vty
, "local AS %u\n", bgp
->as
);
13267 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13268 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13269 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13270 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13276 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13277 : BGP_SHOW_HEADER
));
13283 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13284 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13285 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13286 json_object
*json_scode
, json_object
*json_ocode
,
13287 uint8_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13288 unsigned long *output_count
, unsigned long *filtered_count
)
13290 struct bgp_adj_in
*ain
;
13291 struct bgp_adj_out
*adj
;
13292 struct bgp_dest
*dest
;
13296 struct update_subgroup
*subgrp
;
13297 struct peer_af
*paf
;
13298 bool route_filtered
;
13299 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13300 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13301 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13302 || (safi
== SAFI_EVPN
))
13310 json_object_string_add(json
, "alert", "no BGP");
13311 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13312 json_object_free(json
);
13314 vty_out(vty
, "%% No bgp\n");
13318 subgrp
= peer_subgroup(peer
, afi
, safi
);
13320 if (type
== bgp_show_adj_route_advertised
&& subgrp
13321 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13322 char buf
[BUFSIZ
] = {0};
13325 json_object_int_add(json
, "bgpTableVersion",
13327 json_object_string_add(json
, "bgpLocalRouterId",
13329 &bgp
->router_id
, buf
,
13331 json_object_int_add(json
, "defaultLocPrf",
13332 bgp
->default_local_pref
);
13333 json_object_int_add(json
, "localAS", bgp
->as
);
13334 json_object_object_add(json
, "bgpStatusCodes",
13336 json_object_object_add(json
, "bgpOriginCodes",
13338 json_object_string_add(
13339 json
, "bgpOriginatingDefaultNetwork",
13340 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13343 "BGP table version is %" PRIu64
13344 ", local router ID is %pI4, vrf id ",
13345 table
->version
, &bgp
->router_id
);
13346 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13347 vty_out(vty
, "%s", VRFID_NONE_STR
);
13349 vty_out(vty
, "%u", bgp
->vrf_id
);
13350 vty_out(vty
, "\n");
13351 vty_out(vty
, "Default local pref %u, ",
13352 bgp
->default_local_pref
);
13353 vty_out(vty
, "local AS %u\n", bgp
->as
);
13354 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13355 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13356 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13357 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13359 vty_out(vty
, "Originating default network %s\n\n",
13360 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13365 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13366 if (type
== bgp_show_adj_route_received
13367 || type
== bgp_show_adj_route_filtered
) {
13368 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13369 if (ain
->peer
!= peer
)
13372 show_adj_route_header(vty
, bgp
, table
, header1
,
13373 header2
, json
, json_scode
,
13376 if ((safi
== SAFI_MPLS_VPN
)
13377 || (safi
== SAFI_ENCAP
)
13378 || (safi
== SAFI_EVPN
)) {
13380 json_object_string_add(
13381 json_ar
, "rd", rd_str
);
13382 else if (show_rd
&& rd_str
) {
13384 "Route Distinguisher: %s\n",
13391 route_filtered
= false;
13393 /* Filter prefix using distribute list,
13394 * filter list or prefix list
13396 const struct prefix
*rn_p
=
13397 bgp_dest_get_prefix(dest
);
13398 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13401 route_filtered
= true;
13403 /* Filter prefix using route-map */
13404 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13405 safi
, rmap_name
, NULL
,
13408 if (type
== bgp_show_adj_route_filtered
&&
13409 !route_filtered
&& ret
!= RMAP_DENY
) {
13410 bgp_attr_undup(&attr
, ain
->attr
);
13414 if (type
== bgp_show_adj_route_received
13415 && (route_filtered
|| ret
== RMAP_DENY
))
13416 (*filtered_count
)++;
13418 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
13419 use_json
, json_ar
, wide
);
13420 bgp_attr_undup(&attr
, ain
->attr
);
13423 } else if (type
== bgp_show_adj_route_advertised
) {
13424 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13425 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13426 if (paf
->peer
!= peer
|| !adj
->attr
)
13429 show_adj_route_header(vty
, bgp
, table
,
13434 const struct prefix
*rn_p
=
13435 bgp_dest_get_prefix(dest
);
13438 ret
= bgp_output_modifier(
13439 peer
, rn_p
, &attr
, afi
, safi
,
13442 if (ret
!= RMAP_DENY
) {
13443 if ((safi
== SAFI_MPLS_VPN
)
13444 || (safi
== SAFI_ENCAP
)
13445 || (safi
== SAFI_EVPN
)) {
13447 json_object_string_add(
13454 "Route Distinguisher: %s\n",
13460 vty
, dest
, rn_p
, &attr
,
13461 safi
, use_json
, json_ar
,
13465 (*filtered_count
)++;
13468 bgp_attr_undup(&attr
, adj
->attr
);
13470 } else if (type
== bgp_show_adj_route_bestpath
) {
13471 struct bgp_path_info
*pi
;
13473 show_adj_route_header(vty
, bgp
, table
, header1
, header2
,
13474 json
, json_scode
, json_ocode
,
13477 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13479 if (pi
->peer
!= peer
)
13482 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13485 route_vty_out_tmp(vty
, dest
,
13486 bgp_dest_get_prefix(dest
),
13487 pi
->attr
, safi
, use_json
,
13495 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13496 safi_t safi
, enum bgp_show_adj_route_type type
,
13497 const char *rmap_name
, uint8_t show_flags
)
13500 struct bgp_table
*table
;
13501 json_object
*json
= NULL
;
13502 json_object
*json_scode
= NULL
;
13503 json_object
*json_ocode
= NULL
;
13504 json_object
*json_ar
= NULL
;
13505 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13507 /* Init BGP headers here so they're only displayed once
13508 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13514 * Initialize variables for each RD
13515 * All prefixes under an RD is aggregated within "json_routes"
13517 char rd_str
[BUFSIZ
] = {0};
13518 json_object
*json_routes
= NULL
;
13521 /* For 2-tier tables, prefix counts need to be
13522 * maintained across multiple runs of show_adj_route()
13524 unsigned long output_count_per_rd
;
13525 unsigned long filtered_count_per_rd
;
13526 unsigned long output_count
= 0;
13527 unsigned long filtered_count
= 0;
13530 json
= json_object_new_object();
13531 json_ar
= json_object_new_object();
13532 json_scode
= json_object_new_object();
13533 json_ocode
= json_object_new_object();
13535 json_object_string_add(json_scode
, "suppressed", "s");
13536 json_object_string_add(json_scode
, "damped", "d");
13537 json_object_string_add(json_scode
, "history", "h");
13538 json_object_string_add(json_scode
, "valid", "*");
13539 json_object_string_add(json_scode
, "best", ">");
13540 json_object_string_add(json_scode
, "multipath", "=");
13541 json_object_string_add(json_scode
, "internal", "i");
13542 json_object_string_add(json_scode
, "ribFailure", "r");
13543 json_object_string_add(json_scode
, "stale", "S");
13544 json_object_string_add(json_scode
, "removed", "R");
13546 json_object_string_add(json_ocode
, "igp", "i");
13547 json_object_string_add(json_ocode
, "egp", "e");
13548 json_object_string_add(json_ocode
, "incomplete", "?");
13551 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13553 json_object_string_add(
13555 "No such neighbor or address family");
13556 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13557 json_object_free(json
);
13559 vty_out(vty
, "%% No such neighbor or address family\n");
13561 return CMD_WARNING
;
13564 if ((type
== bgp_show_adj_route_received
13565 || type
== bgp_show_adj_route_filtered
)
13566 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
13567 PEER_FLAG_SOFT_RECONFIG
)) {
13569 json_object_string_add(
13571 "Inbound soft reconfiguration not enabled");
13572 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13573 json_object_free(json
);
13576 "%% Inbound soft reconfiguration not enabled\n");
13578 return CMD_WARNING
;
13583 /* labeled-unicast routes live in the unicast table */
13584 if (safi
== SAFI_LABELED_UNICAST
)
13585 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
13587 table
= bgp
->rib
[afi
][safi
];
13589 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13590 || (safi
== SAFI_EVPN
)) {
13592 struct bgp_dest
*dest
;
13594 for (dest
= bgp_table_top(table
); dest
;
13595 dest
= bgp_route_next(dest
)) {
13596 table
= bgp_dest_get_bgp_table_info(dest
);
13600 output_count_per_rd
= 0;
13601 filtered_count_per_rd
= 0;
13604 json_routes
= json_object_new_object();
13606 const struct prefix_rd
*prd
;
13607 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13610 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
13612 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
13613 rmap_name
, json
, json_routes
, json_scode
,
13614 json_ocode
, show_flags
, &header1
,
13615 &header2
, rd_str
, &output_count_per_rd
,
13616 &filtered_count_per_rd
);
13618 /* Don't include an empty RD in the output! */
13619 if (json_routes
&& (output_count_per_rd
> 0))
13620 json_object_object_add(json_ar
, rd_str
,
13623 output_count
+= output_count_per_rd
;
13624 filtered_count
+= filtered_count_per_rd
;
13627 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
13628 json
, json_ar
, json_scode
, json_ocode
,
13629 show_flags
, &header1
, &header2
, rd_str
,
13630 &output_count
, &filtered_count
);
13633 json_object_object_add(json
, "advertisedRoutes", json_ar
);
13634 json_object_int_add(json
, "totalPrefixCounter", output_count
);
13635 json_object_int_add(json
, "filteredPrefixCounter",
13638 vty_out(vty
, "%s\n",
13639 json_object_to_json_string_ext(
13640 json
, JSON_C_TO_STRING_PRETTY
));
13642 if (!output_count
&& !filtered_count
) {
13643 json_object_free(json_scode
);
13644 json_object_free(json_ocode
);
13648 json_object_free(json
);
13650 } else if (output_count
> 0) {
13651 if (filtered_count
> 0)
13653 "\nTotal number of prefixes %ld (%ld filtered)\n",
13654 output_count
, filtered_count
);
13656 vty_out(vty
, "\nTotal number of prefixes %ld\n",
13660 return CMD_SUCCESS
;
13663 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
13664 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
13665 "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]",
13669 BGP_INSTANCE_HELP_STR
13671 BGP_SAFI_WITH_LABEL_HELP_STR
13672 "Detailed information on TCP and BGP neighbor connections\n"
13673 "Neighbor to display information about\n"
13674 "Neighbor to display information about\n"
13675 "Neighbor on BGP configured interface\n"
13676 "Display the routes selected by best path\n"
13678 "Increase table width for longer prefixes\n")
13680 afi_t afi
= AFI_IP6
;
13681 safi_t safi
= SAFI_UNICAST
;
13682 char *rmap_name
= NULL
;
13683 char *peerstr
= NULL
;
13684 struct bgp
*bgp
= NULL
;
13686 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
13688 uint8_t show_flags
= 0;
13691 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13694 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13696 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13700 return CMD_WARNING
;
13702 argv_find(argv
, argc
, "neighbors", &idx
);
13703 peerstr
= argv
[++idx
]->arg
;
13705 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13707 return CMD_WARNING
;
13709 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13713 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
13714 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
13715 "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]",
13719 BGP_INSTANCE_HELP_STR
13721 BGP_SAFI_WITH_LABEL_HELP_STR
13722 "Display the entries for all address families\n"
13723 "Detailed information on TCP and BGP neighbor connections\n"
13724 "Neighbor to display information about\n"
13725 "Neighbor to display information about\n"
13726 "Neighbor on BGP configured interface\n"
13727 "Display the routes advertised to a BGP neighbor\n"
13728 "Display the received routes from neighbor\n"
13729 "Display the filtered routes received from neighbor\n"
13730 "Route-map to modify the attributes\n"
13731 "Name of the route map\n"
13733 "Increase table width for longer prefixes\n")
13735 afi_t afi
= AFI_IP6
;
13736 safi_t safi
= SAFI_UNICAST
;
13737 char *rmap_name
= NULL
;
13738 char *peerstr
= NULL
;
13739 struct bgp
*bgp
= NULL
;
13741 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
13744 uint8_t show_flags
= 0;
13748 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13752 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
13753 if (argv_find(argv
, argc
, "ipv4", &idx
))
13754 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
13756 if (argv_find(argv
, argc
, "ipv6", &idx
))
13757 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
13761 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13763 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13766 return CMD_WARNING
;
13768 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13769 argv_find(argv
, argc
, "neighbors", &idx
);
13770 peerstr
= argv
[++idx
]->arg
;
13772 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13774 return CMD_WARNING
;
13776 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
13777 type
= bgp_show_adj_route_advertised
;
13778 else if (argv_find(argv
, argc
, "received-routes", &idx
))
13779 type
= bgp_show_adj_route_received
;
13780 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
13781 type
= bgp_show_adj_route_filtered
;
13783 if (argv_find(argv
, argc
, "route-map", &idx
))
13784 rmap_name
= argv
[++idx
]->arg
;
13787 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13790 vty_out(vty
, "{\n");
13792 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13793 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
13794 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
13796 FOREACH_SAFI (safi
) {
13797 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13804 vty_out(vty
, ",\n");
13805 vty_out(vty
, "\"%s\":",
13806 get_afi_safi_str(afi
, safi
, true));
13808 vty_out(vty
, "\nFor address family: %s\n",
13809 get_afi_safi_str(afi
, safi
, false));
13811 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13815 FOREACH_AFI_SAFI (afi
, safi
) {
13816 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13823 vty_out(vty
, ",\n");
13824 vty_out(vty
, "\"%s\":",
13825 get_afi_safi_str(afi
, safi
, true));
13827 vty_out(vty
, "\nFor address family: %s\n",
13828 get_afi_safi_str(afi
, safi
, false));
13830 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13835 vty_out(vty
, "}\n");
13837 return CMD_SUCCESS
;
13840 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
13841 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
13842 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
13848 "Address Family modifier\n"
13849 "Detailed information on TCP and BGP neighbor connections\n"
13850 "Neighbor to display information about\n"
13851 "Neighbor to display information about\n"
13852 "Neighbor on BGP configured interface\n"
13853 "Display information received from a BGP neighbor\n"
13854 "Display the prefixlist filter\n"
13857 afi_t afi
= AFI_IP6
;
13858 safi_t safi
= SAFI_UNICAST
;
13859 char *peerstr
= NULL
;
13862 union sockunion su
;
13868 /* show [ip] bgp */
13869 if (argv_find(argv
, argc
, "ip", &idx
))
13871 /* [<ipv4|ipv6> [unicast]] */
13872 if (argv_find(argv
, argc
, "ipv4", &idx
))
13874 if (argv_find(argv
, argc
, "ipv6", &idx
))
13876 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13877 argv_find(argv
, argc
, "neighbors", &idx
);
13878 peerstr
= argv
[++idx
]->arg
;
13880 bool uj
= use_json(argc
, argv
);
13882 ret
= str2sockunion(peerstr
, &su
);
13884 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
13887 vty_out(vty
, "{}\n");
13890 "%% Malformed address or name: %s\n",
13892 return CMD_WARNING
;
13895 peer
= peer_lookup(NULL
, &su
);
13898 vty_out(vty
, "{}\n");
13900 vty_out(vty
, "No peer\n");
13901 return CMD_WARNING
;
13905 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
13906 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
13909 vty_out(vty
, "Address Family: %s\n",
13910 get_afi_safi_str(afi
, safi
, false));
13911 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
13914 vty_out(vty
, "{}\n");
13916 vty_out(vty
, "No functional output\n");
13919 return CMD_SUCCESS
;
13922 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
13923 afi_t afi
, safi_t safi
,
13924 enum bgp_show_type type
, bool use_json
)
13926 uint8_t show_flags
= 0;
13929 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13931 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13933 json_object
*json_no
= NULL
;
13934 json_no
= json_object_new_object();
13935 json_object_string_add(
13936 json_no
, "warning",
13937 "No such neighbor or address family");
13938 vty_out(vty
, "%s\n",
13939 json_object_to_json_string(json_no
));
13940 json_object_free(json_no
);
13942 vty_out(vty
, "%% No such neighbor or address family\n");
13943 return CMD_WARNING
;
13946 /* labeled-unicast routes live in the unicast table */
13947 if (safi
== SAFI_LABELED_UNICAST
)
13948 safi
= SAFI_UNICAST
;
13950 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
13951 RPKI_NOT_BEING_USED
);
13954 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
13955 show_ip_bgp_flowspec_routes_detailed_cmd
,
13956 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
13960 BGP_INSTANCE_HELP_STR
13963 "Detailed information on flowspec entries\n"
13966 afi_t afi
= AFI_IP
;
13967 safi_t safi
= SAFI_UNICAST
;
13968 struct bgp
*bgp
= NULL
;
13970 bool uj
= use_json(argc
, argv
);
13971 uint8_t show_flags
= 0;
13975 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13978 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13981 return CMD_WARNING
;
13983 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
13984 show_flags
, RPKI_NOT_BEING_USED
);
13987 DEFUN (show_ip_bgp_neighbor_routes
,
13988 show_ip_bgp_neighbor_routes_cmd
,
13989 "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]",
13993 BGP_INSTANCE_HELP_STR
13995 BGP_SAFI_WITH_LABEL_HELP_STR
13996 "Detailed information on TCP and BGP neighbor connections\n"
13997 "Neighbor to display information about\n"
13998 "Neighbor to display information about\n"
13999 "Neighbor on BGP configured interface\n"
14000 "Display flap statistics of the routes learned from neighbor\n"
14001 "Display the dampened routes received from neighbor\n"
14002 "Display routes learned from neighbor\n"
14005 char *peerstr
= NULL
;
14006 struct bgp
*bgp
= NULL
;
14007 afi_t afi
= AFI_IP6
;
14008 safi_t safi
= SAFI_UNICAST
;
14010 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14012 bool uj
= use_json(argc
, argv
);
14017 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14020 return CMD_WARNING
;
14022 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14023 argv_find(argv
, argc
, "neighbors", &idx
);
14024 peerstr
= argv
[++idx
]->arg
;
14026 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14028 return CMD_WARNING
;
14030 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14031 sh_type
= bgp_show_type_flap_neighbor
;
14032 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14033 sh_type
= bgp_show_type_damp_neighbor
;
14034 else if (argv_find(argv
, argc
, "routes", &idx
))
14035 sh_type
= bgp_show_type_neighbor
;
14037 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14040 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14042 struct bgp_distance
{
14043 /* Distance value for the IP source prefix. */
14046 /* Name of the access-list to be matched. */
14050 DEFUN (show_bgp_afi_vpn_rd_route
,
14051 show_bgp_afi_vpn_rd_route_cmd
,
14052 "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]",
14056 "Address Family modifier\n"
14057 "Display information for a route distinguisher\n"
14058 "Route Distinguisher\n"
14059 "All Route Distinguishers\n"
14060 "Network in the BGP routing table to display\n"
14061 "Network in the BGP routing table to display\n"
14065 struct prefix_rd prd
;
14066 afi_t afi
= AFI_MAX
;
14069 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14070 vty_out(vty
, "%% Malformed Address Family\n");
14071 return CMD_WARNING
;
14074 if (!strcmp(argv
[5]->arg
, "all"))
14075 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14076 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14077 RPKI_NOT_BEING_USED
,
14078 use_json(argc
, argv
));
14080 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14082 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14083 return CMD_WARNING
;
14086 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14087 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14088 use_json(argc
, argv
));
14091 static struct bgp_distance
*bgp_distance_new(void)
14093 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14096 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14098 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14101 int bgp_distance_set(uint8_t distance
, const char *ip_str
,
14102 const char *access_list_str
, afi_t afi
, safi_t safi
,
14103 char *errmsg
, size_t errmsg_len
)
14107 struct bgp_dest
*dest
;
14108 struct bgp_distance
*bdistance
;
14110 ret
= str2prefix(ip_str
, &p
);
14112 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
14113 return CMD_WARNING_CONFIG_FAILED
;
14116 /* Get BGP distance node. */
14117 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14118 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14120 bgp_dest_unlock_node(dest
);
14122 bdistance
= bgp_distance_new();
14123 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14126 /* Set distance value. */
14127 bdistance
->distance
= distance
;
14129 /* Reset access-list configuration. */
14130 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14131 if (access_list_str
)
14132 bdistance
->access_list
=
14133 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14135 return CMD_SUCCESS
;
14138 int bgp_distance_unset(uint8_t distance
, const char *ip_str
,
14139 const char *access_list_str
, afi_t afi
, safi_t safi
,
14140 char *errmsg
, size_t errmsg_len
)
14144 struct bgp_dest
*dest
;
14145 struct bgp_distance
*bdistance
;
14147 ret
= str2prefix(ip_str
, &p
);
14149 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
14150 return CMD_WARNING_CONFIG_FAILED
;
14153 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14155 snprintf(errmsg
, errmsg_len
, "Can't find specified prefix\n");
14156 return CMD_WARNING_CONFIG_FAILED
;
14159 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14161 if (bdistance
->distance
!= distance
) {
14162 snprintf(errmsg
, errmsg_len
,
14163 "Distance does not match configured\n");
14164 return CMD_WARNING_CONFIG_FAILED
;
14167 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14168 bgp_distance_free(bdistance
);
14170 bgp_dest_set_bgp_path_info(dest
, NULL
);
14171 bgp_dest_unlock_node(dest
);
14172 bgp_dest_unlock_node(dest
);
14174 return CMD_SUCCESS
;
14177 /* Apply BGP information to distance method. */
14178 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14179 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14181 struct bgp_dest
*dest
;
14182 struct prefix q
= {0};
14184 struct bgp_distance
*bdistance
;
14185 struct access_list
*alist
;
14186 struct bgp_static
*bgp_static
;
14191 peer
= pinfo
->peer
;
14193 if (pinfo
->attr
->distance
)
14194 return pinfo
->attr
->distance
;
14196 /* Check source address.
14197 * Note: for aggregate route, peer can have unspec af type.
14199 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14200 && !sockunion2hostprefix(&peer
->su
, &q
))
14203 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14205 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14206 bgp_dest_unlock_node(dest
);
14208 if (bdistance
->access_list
) {
14209 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14211 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14212 return bdistance
->distance
;
14214 return bdistance
->distance
;
14217 /* Backdoor check. */
14218 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14220 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14221 bgp_dest_unlock_node(dest
);
14223 if (bgp_static
->backdoor
) {
14224 if (bgp
->distance_local
[afi
][safi
])
14225 return bgp
->distance_local
[afi
][safi
];
14227 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14231 if (peer
->sort
== BGP_PEER_EBGP
) {
14232 if (bgp
->distance_ebgp
[afi
][safi
])
14233 return bgp
->distance_ebgp
[afi
][safi
];
14234 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14235 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14236 if (bgp
->distance_ibgp
[afi
][safi
])
14237 return bgp
->distance_ibgp
[afi
][safi
];
14238 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14240 if (bgp
->distance_local
[afi
][safi
])
14241 return bgp
->distance_local
[afi
][safi
];
14242 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14246 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14247 * we should tell ZEBRA update the routes for a specific
14248 * AFI/SAFI to reflect changes in RIB.
14250 void bgp_announce_routes_distance_update(struct bgp
*bgp
, afi_t update_afi
,
14251 safi_t update_safi
)
14256 FOREACH_AFI_SAFI (afi
, safi
) {
14257 if (!bgp_fibupd_safi(safi
))
14260 if (afi
!= update_afi
&& safi
!= update_safi
)
14263 if (BGP_DEBUG(zebra
, ZEBRA
))
14265 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14266 __func__
, afi
, safi
);
14267 bgp_zebra_announce_table(bgp
, afi
, safi
);
14271 DEFUN_YANG(bgp_distance
, bgp_distance_cmd
,
14272 "distance bgp (1-255) (1-255) (1-255)",
14273 "Define an administrative distance\n"
14275 "Distance for routes external to the AS\n"
14276 "Distance for routes internal to the AS\n"
14277 "Distance for local routes\n")
14279 int idx_number
= 2;
14280 int idx_number_2
= 3;
14281 int idx_number_3
= 4;
14284 char xpath
[XPATH_MAXLEN
];
14286 afi
= bgp_node_afi(vty
);
14287 safi
= bgp_node_safi(vty
);
14290 xpath
, sizeof(xpath
),
14291 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14292 yang_afi_safi_value2identity(afi
, safi
),
14293 bgp_afi_safi_get_container_str(afi
, safi
));
14294 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[idx_number
]->arg
);
14296 xpath
, sizeof(xpath
),
14297 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14298 yang_afi_safi_value2identity(afi
, safi
),
14299 bgp_afi_safi_get_container_str(afi
, safi
));
14300 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
14301 argv
[idx_number_2
]->arg
);
14303 xpath
, sizeof(xpath
),
14304 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14305 yang_afi_safi_value2identity(afi
, safi
),
14306 bgp_afi_safi_get_container_str(afi
, safi
));
14308 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
14309 argv
[idx_number_3
]->arg
);
14311 return nb_cli_apply_changes(vty
, NULL
);
14314 DEFUN_YANG(no_bgp_distance
, no_bgp_distance_cmd
,
14315 "no distance bgp [(1-255) (1-255) (1-255)]",
14317 "Define an administrative distance\n"
14319 "Distance for routes external to the AS\n"
14320 "Distance for routes internal to the AS\n"
14321 "Distance for local routes\n")
14325 char xpath
[XPATH_MAXLEN
];
14327 afi
= bgp_node_afi(vty
);
14328 safi
= bgp_node_safi(vty
);
14331 xpath
, sizeof(xpath
),
14332 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14333 yang_afi_safi_value2identity(afi
, safi
),
14334 bgp_afi_safi_get_container_str(afi
, safi
));
14335 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14337 xpath
, sizeof(xpath
),
14338 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14339 yang_afi_safi_value2identity(afi
, safi
),
14340 bgp_afi_safi_get_container_str(afi
, safi
));
14341 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14343 xpath
, sizeof(xpath
),
14344 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14345 yang_afi_safi_value2identity(afi
, safi
),
14346 bgp_afi_safi_get_container_str(afi
, safi
));
14348 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14350 return nb_cli_apply_changes(vty
, NULL
);
14353 void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty
*vty
,
14354 struct lyd_node
*dnode
,
14355 bool show_defaults
)
14357 uint8_t distance_ebgp
, distance_ibgp
, distance_local
;
14359 distance_ebgp
= yang_dnode_get_uint8(dnode
, "./external");
14360 distance_ibgp
= yang_dnode_get_uint8(dnode
, "./internal");
14361 distance_local
= yang_dnode_get_uint8(dnode
, "./local");
14363 vty_out(vty
, " distance bgp %d %d %d\n", distance_ebgp
, distance_ibgp
,
14367 DEFPY_YANG(bgp_distance_source
,
14368 bgp_distance_source_cmd
,
14369 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
14371 "Define an administrative distance\n"
14373 "IPv4 source prefix\n"
14374 "IPv6 source prefix\n"
14375 "Access list name\n")
14379 char xpath
[XPATH_MAXLEN
];
14381 afi
= bgp_node_afi(vty
);
14382 safi
= bgp_node_safi(vty
);
14385 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
14386 nb_cli_enqueue_change(vty
, "./distance", NB_OP_MODIFY
,
14389 nb_cli_enqueue_change(vty
,
14390 "./access-list-policy-export",
14391 NB_OP_CREATE
, acl
);
14393 nb_cli_enqueue_change(vty
,
14394 "./access-list-policy-export",
14395 NB_OP_DESTROY
, NULL
);
14397 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
14401 xpath
, sizeof(xpath
),
14402 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14403 yang_afi_safi_value2identity(afi
, safi
),
14404 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
14406 return nb_cli_apply_changes(vty
, xpath
);
14409 void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14410 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
14412 vty_out(vty
, " distance %d %s %s\n",
14413 yang_dnode_get_uint8(dnode
, "./distance"),
14414 yang_dnode_get_string(dnode
, "./prefix"),
14415 (yang_dnode_exists(dnode
, "./access-list-policy-export"))
14416 ? yang_dnode_get_string(dnode
,
14417 "./access-list-policy-export")
14422 bgp_dampening
, bgp_dampening_cmd
,
14423 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14425 "BGP Specific commands\n"
14426 "Enable route-flap dampening\n"
14427 "Half-life time for the penalty\n"
14428 "Value to start reusing a route\n"
14429 "Value to start suppressing a route\n"
14430 "Maximum duration to suppress a stable route\n")
14434 char xpath
[XPATH_MAXLEN
];
14436 afi
= bgp_node_afi(vty
);
14437 safi
= bgp_node_safi(vty
);
14440 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
14442 nb_cli_enqueue_change(vty
, "./reach-decay",
14443 NB_OP_MODIFY
, halflife_str
);
14444 nb_cli_enqueue_change(vty
, "./reuse-above",
14445 NB_OP_MODIFY
, reuse_str
);
14446 nb_cli_enqueue_change(vty
, "./suppress-above",
14447 NB_OP_MODIFY
, suppress_str
);
14448 nb_cli_enqueue_change(vty
, "./unreach-decay",
14449 NB_OP_MODIFY
, max_suppress_str
);
14451 nb_cli_enqueue_change(vty
, "./reach-decay",
14452 NB_OP_MODIFY
, halflife_str
);
14455 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "false");
14459 xpath
, sizeof(xpath
),
14460 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14461 yang_afi_safi_value2identity(afi
, safi
),
14462 bgp_afi_safi_get_container_str(afi
, safi
));
14464 return nb_cli_apply_changes(vty
, xpath
);
14467 void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty
*vty
,
14468 struct lyd_node
*dnode
,
14469 bool show_defaults
)
14471 if (!yang_dnode_get_bool(dnode
, "./enable"))
14474 int half
= DEFAULT_HALF_LIFE
* 60;
14475 int reuse
= DEFAULT_REUSE
;
14476 int suppress
= DEFAULT_SUPPRESS
;
14479 half
= yang_dnode_get_uint8(dnode
, "../reach-decay");
14480 reuse
= yang_dnode_get_uint16(dnode
, "../reuse-above");
14481 suppress
= yang_dnode_get_uint16(dnode
, "../suppress-above");
14482 max
= yang_dnode_get_uint8(dnode
, "../unreach-decay");
14484 if (half
== DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14485 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14486 vty_out(vty
, " bgp dampening\n");
14487 else if (half
!= DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14488 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14489 vty_out(vty
, " bgp dampening %u\n", half
);
14491 vty_out(vty
, " bgp dampening %u %d %d %d\n", half
, reuse
,
14495 /* Display specified route of BGP table. */
14496 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14497 const char *ip_str
, afi_t afi
, safi_t safi
,
14498 struct prefix_rd
*prd
, int prefix_check
)
14501 struct prefix match
;
14502 struct bgp_dest
*dest
;
14503 struct bgp_dest
*rm
;
14504 struct bgp_path_info
*pi
;
14505 struct bgp_path_info
*pi_temp
;
14507 struct bgp_table
*table
;
14509 /* BGP structure lookup. */
14511 bgp
= bgp_lookup_by_name(view_name
);
14513 vty_out(vty
, "%% Can't find BGP instance %s\n",
14515 return CMD_WARNING
;
14518 bgp
= bgp_get_default();
14520 vty_out(vty
, "%% No BGP process is configured\n");
14521 return CMD_WARNING
;
14525 /* Check IP address argument. */
14526 ret
= str2prefix(ip_str
, &match
);
14528 vty_out(vty
, "%% address is malformed\n");
14529 return CMD_WARNING
;
14532 match
.family
= afi2family(afi
);
14534 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14535 || (safi
== SAFI_EVPN
)) {
14536 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
14537 dest
= bgp_route_next(dest
)) {
14538 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14540 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
14542 table
= bgp_dest_get_bgp_table_info(dest
);
14545 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
14548 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
14551 || rm_p
->prefixlen
== match
.prefixlen
) {
14552 pi
= bgp_dest_get_bgp_path_info(rm
);
14554 if (pi
->extra
&& pi
->extra
->damp_info
) {
14555 pi_temp
= pi
->next
;
14556 bgp_damp_info_free(
14557 &pi
->extra
->damp_info
,
14558 &bgp
->damp
[afi
][safi
],
14566 bgp_dest_unlock_node(rm
);
14569 if ((dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
14571 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14574 || dest_p
->prefixlen
== match
.prefixlen
) {
14575 pi
= bgp_dest_get_bgp_path_info(dest
);
14577 if (pi
->extra
&& pi
->extra
->damp_info
) {
14578 pi_temp
= pi
->next
;
14579 struct bgp_damp_info
*bdi
=
14580 pi
->extra
->damp_info
;
14581 if (bdi
->lastrecord
14582 == BGP_RECORD_UPDATE
) {
14583 bgp_aggregate_increment(
14594 bgp_damp_info_free(
14595 &pi
->extra
->damp_info
,
14596 &bgp
->damp
[afi
][safi
],
14604 bgp_dest_unlock_node(dest
);
14608 return CMD_SUCCESS
;
14611 DEFUN (clear_ip_bgp_dampening
,
14612 clear_ip_bgp_dampening_cmd
,
14613 "clear ip bgp dampening",
14617 "Clear route flap dampening information\n")
14619 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14620 bgp_damp_info_clean(bgp
, &bgp
->damp
[AFI_IP
][SAFI_UNICAST
], AFI_IP
,
14622 return CMD_SUCCESS
;
14625 DEFUN (clear_ip_bgp_dampening_prefix
,
14626 clear_ip_bgp_dampening_prefix_cmd
,
14627 "clear ip bgp dampening A.B.C.D/M",
14631 "Clear route flap dampening information\n"
14634 int idx_ipv4_prefixlen
= 4;
14635 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
14636 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
14639 DEFUN (clear_ip_bgp_dampening_address
,
14640 clear_ip_bgp_dampening_address_cmd
,
14641 "clear ip bgp dampening A.B.C.D",
14645 "Clear route flap dampening information\n"
14646 "Network to clear damping information\n")
14649 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
14650 SAFI_UNICAST
, NULL
, 0);
14653 DEFUN (clear_ip_bgp_dampening_address_mask
,
14654 clear_ip_bgp_dampening_address_mask_cmd
,
14655 "clear ip bgp dampening A.B.C.D A.B.C.D",
14659 "Clear route flap dampening information\n"
14660 "Network to clear damping information\n"
14664 int idx_ipv4_2
= 5;
14666 char prefix_str
[BUFSIZ
];
14668 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
14669 prefix_str
, sizeof(prefix_str
));
14671 vty_out(vty
, "%% Inconsistent address and mask\n");
14672 return CMD_WARNING
;
14675 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
14679 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
14681 struct vty
*vty
= arg
;
14682 struct peer
*peer
= bucket
->data
;
14683 char buf
[SU_ADDRSTRLEN
];
14685 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
14686 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
14689 DEFUN (show_bgp_listeners
,
14690 show_bgp_listeners_cmd
,
14691 "show bgp listeners",
14694 "Display Listen Sockets and who created them\n")
14696 bgp_dump_listener_info(vty
);
14698 return CMD_SUCCESS
;
14701 DEFUN (show_bgp_peerhash
,
14702 show_bgp_peerhash_cmd
,
14703 "show bgp peerhash",
14706 "Display information about the BGP peerhash\n")
14708 struct list
*instances
= bm
->bgp
;
14709 struct listnode
*node
;
14712 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
14713 vty_out(vty
, "BGP: %s\n", bgp
->name
);
14714 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
14718 return CMD_SUCCESS
;
14721 /* also used for encap safi */
14722 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
14723 afi_t afi
, safi_t safi
)
14725 struct bgp_dest
*pdest
;
14726 struct bgp_dest
*dest
;
14727 struct bgp_table
*table
;
14728 const struct prefix
*p
;
14729 const struct prefix_rd
*prd
;
14730 struct bgp_static
*bgp_static
;
14731 mpls_label_t label
;
14732 char rdbuf
[RD_ADDRSTRLEN
];
14734 /* Network configuration. */
14735 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14736 pdest
= bgp_route_next(pdest
)) {
14737 table
= bgp_dest_get_bgp_table_info(pdest
);
14741 for (dest
= bgp_table_top(table
); dest
;
14742 dest
= bgp_route_next(dest
)) {
14743 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14744 if (bgp_static
== NULL
)
14747 p
= bgp_dest_get_prefix(dest
);
14748 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14751 /* "network" configuration display. */
14752 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14753 label
= decode_label(&bgp_static
->label
);
14755 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
14756 if (safi
== SAFI_MPLS_VPN
)
14757 vty_out(vty
, " label %u", label
);
14759 if (bgp_static
->rmap
.name
)
14760 vty_out(vty
, " route-map %s",
14761 bgp_static
->rmap
.name
);
14763 if (bgp_static
->backdoor
)
14764 vty_out(vty
, " backdoor");
14766 vty_out(vty
, "\n");
14771 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
14772 afi_t afi
, safi_t safi
)
14774 struct bgp_dest
*pdest
;
14775 struct bgp_dest
*dest
;
14776 struct bgp_table
*table
;
14777 const struct prefix
*p
;
14778 const struct prefix_rd
*prd
;
14779 struct bgp_static
*bgp_static
;
14780 char buf
[PREFIX_STRLEN
* 2];
14781 char buf2
[SU_ADDRSTRLEN
];
14782 char rdbuf
[RD_ADDRSTRLEN
];
14783 char esi_buf
[ESI_BYTES
];
14785 /* Network configuration. */
14786 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14787 pdest
= bgp_route_next(pdest
)) {
14788 table
= bgp_dest_get_bgp_table_info(pdest
);
14792 for (dest
= bgp_table_top(table
); dest
;
14793 dest
= bgp_route_next(dest
)) {
14794 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14795 if (bgp_static
== NULL
)
14798 char *macrouter
= NULL
;
14800 if (bgp_static
->router_mac
)
14801 macrouter
= prefix_mac2str(
14802 bgp_static
->router_mac
, NULL
, 0);
14803 if (bgp_static
->eth_s_id
)
14804 esi_to_str(bgp_static
->eth_s_id
,
14805 esi_buf
, sizeof(esi_buf
));
14806 p
= bgp_dest_get_prefix(dest
);
14807 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
14809 /* "network" configuration display. */
14810 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14811 if (p
->u
.prefix_evpn
.route_type
== 5) {
14812 char local_buf
[PREFIX_STRLEN
];
14813 uint8_t family
= is_evpn_prefix_ipaddr_v4((
14814 struct prefix_evpn
*)p
)
14818 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
14819 local_buf
, PREFIX_STRLEN
);
14820 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
14821 p
->u
.prefix_evpn
.prefix_addr
14822 .ip_prefix_length
);
14824 prefix2str(p
, buf
, sizeof(buf
));
14827 if (bgp_static
->gatewayIp
.family
== AF_INET
14828 || bgp_static
->gatewayIp
.family
== AF_INET6
)
14829 inet_ntop(bgp_static
->gatewayIp
.family
,
14830 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
14833 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
14835 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
14836 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
14839 XFREE(MTYPE_TMP
, macrouter
);
14844 /* Configuration of static route announcement and aggregate
14846 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14849 struct bgp_dest
*dest
;
14850 const struct prefix
*p
;
14851 struct bgp_static
*bgp_static
;
14852 struct bgp_aggregate
*bgp_aggregate
;
14854 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
14855 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
14859 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
14860 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
14864 /* Network configuration. */
14865 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
14866 dest
= bgp_route_next(dest
)) {
14867 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14868 if (bgp_static
== NULL
)
14871 p
= bgp_dest_get_prefix(dest
);
14873 vty_out(vty
, " network %pFX", p
);
14875 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
14876 vty_out(vty
, " label-index %u",
14877 bgp_static
->label_index
);
14879 if (bgp_static
->rmap
.name
)
14880 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
14882 if (bgp_static
->backdoor
)
14883 vty_out(vty
, " backdoor");
14885 vty_out(vty
, "\n");
14888 /* Aggregate-address configuration. */
14889 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
14890 dest
= bgp_route_next(dest
)) {
14891 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
14892 if (bgp_aggregate
== NULL
)
14895 p
= bgp_dest_get_prefix(dest
);
14897 vty_out(vty
, " aggregate-address %pFX", p
);
14899 if (bgp_aggregate
->as_set
)
14900 vty_out(vty
, " as-set");
14902 if (bgp_aggregate
->summary_only
)
14903 vty_out(vty
, " summary-only");
14905 if (bgp_aggregate
->rmap
.name
)
14906 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
14908 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
14909 vty_out(vty
, " origin %s",
14910 bgp_origin2str(bgp_aggregate
->origin
));
14912 if (bgp_aggregate
->match_med
)
14913 vty_out(vty
, " matching-MED-only");
14915 if (bgp_aggregate
->suppress_map_name
)
14916 vty_out(vty
, " suppress-map %s",
14917 bgp_aggregate
->suppress_map_name
);
14919 vty_out(vty
, "\n");
14923 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14926 struct bgp_dest
*dest
;
14927 struct bgp_distance
*bdistance
;
14929 /* Distance configuration. */
14930 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
14931 && bgp
->distance_local
[afi
][safi
]
14932 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
14933 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
14934 || bgp
->distance_local
[afi
][safi
]
14935 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
14936 vty_out(vty
, " distance bgp %d %d %d\n",
14937 bgp
->distance_ebgp
[afi
][safi
],
14938 bgp
->distance_ibgp
[afi
][safi
],
14939 bgp
->distance_local
[afi
][safi
]);
14942 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
14943 dest
= bgp_route_next(dest
)) {
14944 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14945 if (bdistance
!= NULL
)
14946 vty_out(vty
, " distance %d %pBD %s\n",
14947 bdistance
->distance
, dest
,
14948 bdistance
->access_list
? bdistance
->access_list
14953 /* Allocate routing table structure and install commands. */
14954 void bgp_route_init(void)
14959 /* Init BGP distance table. */
14960 FOREACH_AFI_SAFI (afi
, safi
)
14961 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
14963 /* IPv4 BGP commands. */
14964 install_element(BGP_NODE
, &bgp_table_map_cmd
);
14965 install_element(BGP_NODE
, &bgp_network_cmd
);
14966 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
14968 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
14970 /* IPv4 unicast configuration. */
14971 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
14972 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
14973 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
14975 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
14977 /* IPv4 multicast configuration. */
14978 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
14979 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
14980 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
14981 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
14983 /* IPv4 labeled-unicast configuration. */
14984 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
14985 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
14987 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
14988 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
14989 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
14990 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
14991 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
14992 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
14993 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
14994 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
14996 install_element(VIEW_NODE
,
14997 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
14998 install_element(VIEW_NODE
,
14999 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15000 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15001 install_element(VIEW_NODE
,
15002 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15003 #ifdef KEEP_OLD_VPN_COMMANDS
15004 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15005 #endif /* KEEP_OLD_VPN_COMMANDS */
15006 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15007 install_element(VIEW_NODE
,
15008 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15010 /* BGP dampening clear commands */
15011 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15012 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15014 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15015 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15018 install_element(ENABLE_NODE
,
15019 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15020 #ifdef KEEP_OLD_VPN_COMMANDS
15021 install_element(ENABLE_NODE
,
15022 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15023 #endif /* KEEP_OLD_VPN_COMMANDS */
15025 /* New config IPv6 BGP commands. */
15026 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15027 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15028 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15030 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15032 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15034 /* IPv6 labeled unicast address family. */
15035 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15036 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15038 install_element(BGP_NODE
, &bgp_distance_cmd
);
15039 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15040 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15041 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15042 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15043 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15044 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15045 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15046 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15047 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15048 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15049 install_element(BGP_IPV6_NODE
, &bgp_distance_source_cmd
);
15050 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15051 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15052 install_element(BGP_IPV6M_NODE
, &bgp_distance_source_cmd
);
15054 /* BGP dampening */
15055 install_element(BGP_NODE
, &bgp_dampening_cmd
);
15056 install_element(BGP_IPV4_NODE
, &bgp_dampening_cmd
);
15057 install_element(BGP_IPV4M_NODE
, &bgp_dampening_cmd
);
15058 install_element(BGP_IPV4L_NODE
, &bgp_dampening_cmd
);
15059 install_element(BGP_IPV6_NODE
, &bgp_dampening_cmd
);
15060 install_element(BGP_IPV6M_NODE
, &bgp_dampening_cmd
);
15061 install_element(BGP_IPV6L_NODE
, &bgp_dampening_cmd
);
15063 /* Large Communities */
15064 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15065 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15067 /* show bgp ipv4 flowspec detailed */
15068 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15070 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15071 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15074 void bgp_route_finish(void)
15079 FOREACH_AFI_SAFI (afi
, safi
) {
15080 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15081 bgp_distance_table
[afi
][safi
] = NULL
;