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_orr.h"
76 #include "bgpd/bgp_trace.h"
77 #include "bgpd/bgp_rpki.h"
80 #include "bgpd/rfapi/rfapi_backend.h"
81 #include "bgpd/rfapi/vnc_import_bgp.h"
82 #include "bgpd/rfapi/vnc_export_bgp.h"
84 #include "bgpd/bgp_encap_types.h"
85 #include "bgpd/bgp_encap_tlv.h"
86 #include "bgpd/bgp_evpn.h"
87 #include "bgpd/bgp_evpn_mh.h"
88 #include "bgpd/bgp_evpn_vty.h"
89 #include "bgpd/bgp_flowspec.h"
90 #include "bgpd/bgp_flowspec_util.h"
91 #include "bgpd/bgp_pbr.h"
93 #include "bgpd/bgp_route_clippy.c"
95 DEFINE_HOOK(bgp_snmp_update_stats
,
96 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
99 DEFINE_HOOK(bgp_rpki_prefix_status
,
100 (struct peer
*peer
, struct attr
*attr
,
101 const struct prefix
*prefix
),
102 (peer
, attr
, prefix
));
104 /* Extern from bgp_dump.c */
105 extern const char *bgp_origin_str
[];
106 extern const char *bgp_origin_long_str
[];
109 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
110 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
111 static const struct message bgp_pmsi_tnltype_str
[] = {
112 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
113 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
114 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
115 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
116 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
117 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
118 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
119 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
123 #define VRFID_NONE_STR "-"
124 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
126 DEFINE_HOOK(bgp_process
,
127 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
128 struct peer
*peer
, bool withdraw
),
129 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
131 /** Test if path is suppressed. */
132 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
134 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
137 return listcount(pi
->extra
->aggr_suppressors
) > 0;
140 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
141 safi_t safi
, const struct prefix
*p
,
142 struct prefix_rd
*prd
)
144 struct bgp_dest
*dest
;
145 struct bgp_dest
*pdest
= NULL
;
149 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
150 || (safi
== SAFI_EVPN
)) {
151 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
153 if (!bgp_dest_has_bgp_path_info_data(pdest
))
154 bgp_dest_set_bgp_table_info(
155 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
157 bgp_dest_unlock_node(pdest
);
158 table
= bgp_dest_get_bgp_table_info(pdest
);
161 dest
= bgp_node_get(table
, p
);
163 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
164 || (safi
== SAFI_EVPN
))
170 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
171 safi_t safi
, const struct prefix
*p
,
172 struct prefix_rd
*prd
)
174 struct bgp_dest
*dest
;
175 struct bgp_dest
*pdest
= NULL
;
180 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
181 || (safi
== SAFI_EVPN
)) {
182 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
186 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
187 bgp_dest_unlock_node(pdest
);
191 table
= bgp_dest_get_bgp_table_info(pdest
);
194 dest
= bgp_node_lookup(table
, p
);
199 /* Allocate bgp_path_info_extra */
200 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
202 struct bgp_path_info_extra
*new;
203 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
204 sizeof(struct bgp_path_info_extra
));
205 new->label
[0] = MPLS_INVALID_LABEL
;
207 new->bgp_fs_pbr
= NULL
;
208 new->bgp_fs_iprule
= NULL
;
212 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
214 struct bgp_path_info_extra
*e
;
216 if (!extra
|| !*extra
)
221 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
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
);
254 peer_unlock(e
->peer_orig
);
256 if (e
->aggr_suppressors
)
257 list_delete(&e
->aggr_suppressors
);
260 bgp_evpn_path_mh_info_free(e
->mh_info
);
262 if ((*extra
)->bgp_fs_iprule
)
263 list_delete(&((*extra
)->bgp_fs_iprule
));
264 if ((*extra
)->bgp_fs_pbr
)
265 list_delete(&((*extra
)->bgp_fs_pbr
));
266 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
269 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
270 * allocated if required.
272 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
275 pi
->extra
= bgp_path_info_extra_new();
279 /* Free bgp route information. */
280 static void bgp_path_info_free(struct bgp_path_info
*path
)
282 bgp_attr_unintern(&path
->attr
);
284 bgp_unlink_nexthop(path
);
285 bgp_path_info_extra_free(&path
->extra
);
286 bgp_path_info_mpath_free(&path
->mpath
);
288 bgp_addpath_free_info_data(&path
->tx_addpath
,
289 &path
->net
->tx_addpath
);
291 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
293 XFREE(MTYPE_BGP_ROUTE
, path
);
296 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
302 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
304 assert(path
&& path
->lock
> 0);
307 if (path
->lock
== 0) {
308 bgp_path_info_free(path
);
315 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
316 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
319 struct bgp_path_info
*old_pi
, *nextpi
;
320 bool set_flag
= false;
321 struct bgp
*bgp
= NULL
;
322 struct bgp_table
*table
= NULL
;
326 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
327 * then the route selection is deferred
329 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
332 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
333 if (BGP_DEBUG(update
, UPDATE_OUT
))
335 "Route %pBD is in workqueue and being processed, not deferred.",
341 table
= bgp_dest_table(dest
);
348 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
349 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
350 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
353 /* Route selection is deferred if there is a stale path which
354 * which indicates peer is in restart mode
356 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
357 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
360 /* If the peer is graceful restart capable and peer is
361 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
364 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
365 && BGP_PEER_RESTARTING_MODE(peer
)
367 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
375 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
378 if (set_flag
&& table
) {
379 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
380 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
381 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
382 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
383 if (BGP_DEBUG(update
, UPDATE_OUT
))
384 zlog_debug("DEFER route %pBD, dest %p", dest
,
392 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
394 struct bgp_path_info
*top
;
396 top
= bgp_dest_get_bgp_path_info(dest
);
402 bgp_dest_set_bgp_path_info(dest
, pi
);
404 bgp_path_info_lock(pi
);
405 bgp_dest_lock_node(dest
);
406 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
407 bgp_dest_set_defer_flag(dest
, false);
408 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
411 /* Do the actual removal of info from RIB, for use by bgp_process
412 completion callback *only* */
413 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
416 pi
->next
->prev
= pi
->prev
;
418 pi
->prev
->next
= pi
->next
;
420 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
422 bgp_path_info_mpath_dequeue(pi
);
423 bgp_path_info_unlock(pi
);
424 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
425 bgp_dest_unlock_node(dest
);
428 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
430 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
431 /* set of previous already took care of pcount */
432 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
435 /* undo the effects of a previous call to bgp_path_info_delete; typically
436 called when a route is deleted and then quickly re-added before the
437 deletion has been processed */
438 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
440 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
441 /* unset of previous already took care of pcount */
442 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
445 /* Adjust pcount as required */
446 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
448 struct bgp_table
*table
;
450 assert(dest
&& bgp_dest_table(dest
));
451 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
453 table
= bgp_dest_table(dest
);
455 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
458 if (!BGP_PATH_COUNTABLE(pi
)
459 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
461 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
463 /* slight hack, but more robust against errors. */
464 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
465 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
467 flog_err(EC_LIB_DEVELOPMENT
,
468 "Asked to decrement 0 prefix count for peer");
469 } else if (BGP_PATH_COUNTABLE(pi
)
470 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
471 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
472 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
476 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
477 struct bgp_path_info
*pi2
)
479 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
482 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
483 * This is here primarily to keep prefix-count in check.
485 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
488 SET_FLAG(pi
->flags
, flag
);
490 /* early bath if we know it's not a flag that changes countability state
492 if (!CHECK_FLAG(flag
,
493 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
496 bgp_pcount_adjust(dest
, pi
);
499 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
502 UNSET_FLAG(pi
->flags
, flag
);
504 /* early bath if we know it's not a flag that changes countability state
506 if (!CHECK_FLAG(flag
,
507 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
510 bgp_pcount_adjust(dest
, pi
);
513 /* Get MED value. If MED value is missing and "bgp bestpath
514 missing-as-worst" is specified, treat it as the worst value. */
515 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
517 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
520 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
527 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
530 if (pi
->addpath_rx_id
)
531 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
532 pi
->peer
->host
, pi
->addpath_rx_id
);
534 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
539 * Get the ultimate path info.
541 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
543 struct bgp_path_info
*bpi_ultimate
;
545 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
548 for (bpi_ultimate
= info
;
549 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
550 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
556 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
558 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
559 struct bgp_path_info
*exist
, int *paths_eq
,
560 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
561 char *pfx_buf
, afi_t afi
, safi_t safi
,
562 enum bgp_path_selection_reason
*reason
)
564 const struct prefix
*new_p
;
565 struct prefix exist_p
;
566 struct attr
*newattr
, *existattr
;
567 enum bgp_peer_sort new_sort
;
568 enum bgp_peer_sort exist_sort
;
574 uint32_t exist_weight
;
575 uint32_t newm
, existm
;
576 struct in_addr new_id
;
577 struct in_addr exist_id
;
580 int internal_as_route
;
583 int igp_metric_ret
= 0;
584 int peer_sort_ret
= -1;
585 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
586 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
588 uint32_t exist_mm_seq
;
595 bool new_origin
, exist_origin
;
596 struct bgp_path_info
*bpi_ultimate
;
598 struct bgp_orr_group
*orr_group
= NULL
;
599 struct listnode
*node
;
600 struct bgp_orr_igp_metric
*igp_metric
= NULL
;
601 struct list
*orr_group_igp_metric_info
= NULL
;
607 *reason
= bgp_path_selection_none
;
609 zlog_debug("%s: new is NULL", pfx_buf
);
614 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
615 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
620 *reason
= bgp_path_selection_first
;
622 zlog_debug("%s(%s): %s is the initial bestpath",
623 pfx_buf
, bgp
->name_pretty
, new_buf
);
628 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
629 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
631 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
632 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
633 exist_buf
, exist
->flags
);
637 existattr
= exist
->attr
;
639 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
640 * Capability" to a neighbor MUST perform the following upon receiving
641 * a route from that neighbor with the "LLGR_STALE" community, or upon
642 * attaching the "LLGR_STALE" community itself per Section 4.2:
644 * Treat the route as the least-preferred in route selection (see
645 * below). See the Risks of Depreferencing Routes section (Section 5.2)
646 * for a discussion of potential risks inherent in doing this.
648 if (bgp_attr_get_community(newattr
) &&
649 community_include(bgp_attr_get_community(newattr
),
650 COMMUNITY_LLGR_STALE
)) {
653 "%s: %s wins over %s due to LLGR_STALE community",
654 pfx_buf
, new_buf
, exist_buf
);
658 if (bgp_attr_get_community(existattr
) &&
659 community_include(bgp_attr_get_community(existattr
),
660 COMMUNITY_LLGR_STALE
)) {
663 "%s: %s loses to %s due to LLGR_STALE community",
664 pfx_buf
, new_buf
, exist_buf
);
668 new_p
= bgp_dest_get_prefix(new->net
);
670 /* For EVPN routes, we cannot just go by local vs remote, we have to
671 * look at the MAC mobility sequence number, if present.
673 if ((safi
== SAFI_EVPN
)
674 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
675 /* This is an error condition described in RFC 7432 Section
677 * states that in this scenario "the PE MUST alert the operator"
679 * does not state what other action to take. In order to provide
681 * consistency in this scenario we are going to prefer the path
685 if (newattr
->sticky
!= existattr
->sticky
) {
687 prefix2str(new_p
, pfx_buf
,
689 * PREFIX2STR_BUFFER
);
690 bgp_path_info_path_with_addpath_rx_str(
691 new, new_buf
, sizeof(new_buf
));
692 bgp_path_info_path_with_addpath_rx_str(
693 exist
, exist_buf
, sizeof(exist_buf
));
696 if (newattr
->sticky
&& !existattr
->sticky
) {
697 *reason
= bgp_path_selection_evpn_sticky_mac
;
700 "%s: %s wins over %s due to sticky MAC flag",
701 pfx_buf
, new_buf
, exist_buf
);
705 if (!newattr
->sticky
&& existattr
->sticky
) {
706 *reason
= bgp_path_selection_evpn_sticky_mac
;
709 "%s: %s loses to %s due to sticky MAC flag",
710 pfx_buf
, new_buf
, exist_buf
);
715 new_esi
= bgp_evpn_attr_get_esi(newattr
);
716 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
717 if (bgp_evpn_is_esi_valid(new_esi
) &&
718 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
724 /* If both paths have the same non-zero ES and
725 * one path is local it wins.
726 * PS: Note the local path wins even if the remote
727 * has the higher MM seq. The local path's
728 * MM seq will be fixed up to match the highest
729 * rem seq, subsequently.
732 char esi_buf
[ESI_STR_LEN
];
734 if (bgp_evpn_is_path_local(bgp
, new)) {
735 *reason
= bgp_path_selection_evpn_local_path
;
738 "%s: %s wins over %s as ES %s is same and local",
739 pfx_buf
, new_buf
, exist_buf
,
740 esi_to_str(new_esi
, esi_buf
,
744 if (bgp_evpn_is_path_local(bgp
, exist
)) {
745 *reason
= bgp_path_selection_evpn_local_path
;
748 "%s: %s loses to %s as ES %s is same and local",
749 pfx_buf
, new_buf
, exist_buf
,
750 esi_to_str(new_esi
, esi_buf
,
756 new_mm_seq
= mac_mobility_seqnum(newattr
);
757 exist_mm_seq
= mac_mobility_seqnum(existattr
);
759 if (new_mm_seq
> exist_mm_seq
) {
760 *reason
= bgp_path_selection_evpn_seq
;
763 "%s: %s wins over %s due to MM seq %u > %u",
764 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
769 if (new_mm_seq
< exist_mm_seq
) {
770 *reason
= bgp_path_selection_evpn_seq
;
773 "%s: %s loses to %s due to MM seq %u < %u",
774 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
779 /* if the sequence numbers and ESI are the same and one path
780 * is non-proxy it wins (over proxy)
782 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
783 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
784 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
785 old_proxy
!= new_proxy
) {
787 *reason
= bgp_path_selection_evpn_non_proxy
;
790 "%s: %s wins over %s, same seq/es and non-proxy",
791 pfx_buf
, new_buf
, exist_buf
);
795 *reason
= bgp_path_selection_evpn_non_proxy
;
798 "%s: %s loses to %s, same seq/es and non-proxy",
799 pfx_buf
, new_buf
, exist_buf
);
804 * if sequence numbers are the same path with the lowest IP
807 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
809 *reason
= bgp_path_selection_evpn_lower_ip
;
812 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
813 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
814 &new->attr
->nexthop
);
818 *reason
= bgp_path_selection_evpn_lower_ip
;
821 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
822 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
823 &new->attr
->nexthop
);
828 /* 1. Weight check. */
829 new_weight
= newattr
->weight
;
830 exist_weight
= existattr
->weight
;
832 if (new_weight
> exist_weight
) {
833 *reason
= bgp_path_selection_weight
;
835 zlog_debug("%s: %s wins over %s due to weight %d > %d",
836 pfx_buf
, new_buf
, exist_buf
, new_weight
,
841 if (new_weight
< exist_weight
) {
842 *reason
= bgp_path_selection_weight
;
844 zlog_debug("%s: %s loses to %s due to weight %d < %d",
845 pfx_buf
, new_buf
, exist_buf
, new_weight
,
850 /* 2. Local preference check. */
851 new_pref
= exist_pref
= bgp
->default_local_pref
;
853 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
854 new_pref
= newattr
->local_pref
;
855 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
856 exist_pref
= existattr
->local_pref
;
858 if (new_pref
> exist_pref
) {
859 *reason
= bgp_path_selection_local_pref
;
862 "%s: %s wins over %s due to localpref %d > %d",
863 pfx_buf
, new_buf
, exist_buf
, new_pref
,
868 if (new_pref
< exist_pref
) {
869 *reason
= bgp_path_selection_local_pref
;
872 "%s: %s loses to %s due to localpref %d < %d",
873 pfx_buf
, new_buf
, exist_buf
, new_pref
,
878 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
879 * extensions defined in this document, the following step is inserted
880 * after the LOCAL_PREF comparison step in the BGP decision process:
881 * When comparing a pair of routes for a BGP destination, the
882 * route with the ACCEPT_OWN community attached is preferred over
883 * the route that does not have the community.
884 * This extra step MUST only be invoked during the best path selection
885 * process of VPN-IP routes.
887 if (safi
== SAFI_MPLS_VPN
&&
888 (CHECK_FLAG(new->peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
) ||
889 CHECK_FLAG(exist
->peer
->af_flags
[afi
][safi
],
890 PEER_FLAG_ACCEPT_OWN
))) {
891 bool new_accept_own
= false;
892 bool exist_accept_own
= false;
893 uint32_t accept_own
= COMMUNITY_ACCEPT_OWN
;
895 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
896 new_accept_own
= community_include(
897 bgp_attr_get_community(newattr
), accept_own
);
898 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
899 exist_accept_own
= community_include(
900 bgp_attr_get_community(existattr
), accept_own
);
902 if (new_accept_own
&& !exist_accept_own
) {
903 *reason
= bgp_path_selection_accept_own
;
906 "%s: %s wins over %s due to accept-own",
907 pfx_buf
, new_buf
, exist_buf
);
911 if (!new_accept_own
&& exist_accept_own
) {
912 *reason
= bgp_path_selection_accept_own
;
915 "%s: %s loses to %s due to accept-own",
916 pfx_buf
, new_buf
, exist_buf
);
921 /* Tie-breaker - AIGP (Metric TLV) attribute */
922 if (CHECK_FLAG(newattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
923 CHECK_FLAG(existattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
924 CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_AIGP
)) {
925 uint64_t new_aigp
= bgp_attr_get_aigp_metric(newattr
);
926 uint64_t exist_aigp
= bgp_attr_get_aigp_metric(existattr
);
928 if (new_aigp
< exist_aigp
) {
929 *reason
= bgp_path_selection_aigp
;
932 "%s: %s wins over %s due to AIGP %" PRIu64
934 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
939 if (new_aigp
> exist_aigp
) {
940 *reason
= bgp_path_selection_aigp
;
943 "%s: %s loses to %s due to AIGP %" PRIu64
945 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
951 /* 3. Local route check. We prefer:
953 * - BGP_ROUTE_AGGREGATE
954 * - BGP_ROUTE_REDISTRIBUTE
956 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
957 new->sub_type
== BGP_ROUTE_IMPORTED
);
958 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
959 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
961 if (new_origin
&& !exist_origin
) {
962 *reason
= bgp_path_selection_local_route
;
965 "%s: %s wins over %s due to preferred BGP_ROUTE type",
966 pfx_buf
, new_buf
, exist_buf
);
970 if (!new_origin
&& exist_origin
) {
971 *reason
= bgp_path_selection_local_route
;
974 "%s: %s loses to %s due to preferred BGP_ROUTE type",
975 pfx_buf
, new_buf
, exist_buf
);
979 /* Here if these are imported routes then get ultimate pi for
982 new = bgp_get_imported_bpi_ultimate(new);
983 exist
= bgp_get_imported_bpi_ultimate(exist
);
985 existattr
= exist
->attr
;
987 /* 4. AS path length check. */
988 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
989 int exist_hops
= aspath_count_hops(existattr
->aspath
);
990 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
992 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
995 aspath_hops
= aspath_count_hops(newattr
->aspath
);
996 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
998 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
999 *reason
= bgp_path_selection_confed_as_path
;
1002 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
1003 pfx_buf
, new_buf
, exist_buf
,
1005 (exist_hops
+ exist_confeds
));
1009 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
1010 *reason
= bgp_path_selection_confed_as_path
;
1013 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1014 pfx_buf
, new_buf
, exist_buf
,
1016 (exist_hops
+ exist_confeds
));
1020 int newhops
= aspath_count_hops(newattr
->aspath
);
1022 if (newhops
< exist_hops
) {
1023 *reason
= bgp_path_selection_as_path
;
1026 "%s: %s wins over %s due to aspath hopcount %d < %d",
1027 pfx_buf
, new_buf
, exist_buf
,
1028 newhops
, exist_hops
);
1032 if (newhops
> exist_hops
) {
1033 *reason
= bgp_path_selection_as_path
;
1036 "%s: %s loses to %s due to aspath hopcount %d > %d",
1037 pfx_buf
, new_buf
, exist_buf
,
1038 newhops
, exist_hops
);
1044 /* 5. Origin check. */
1045 if (newattr
->origin
< existattr
->origin
) {
1046 *reason
= bgp_path_selection_origin
;
1048 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1049 pfx_buf
, new_buf
, exist_buf
,
1050 bgp_origin_long_str
[newattr
->origin
],
1051 bgp_origin_long_str
[existattr
->origin
]);
1055 if (newattr
->origin
> existattr
->origin
) {
1056 *reason
= bgp_path_selection_origin
;
1058 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1059 pfx_buf
, new_buf
, exist_buf
,
1060 bgp_origin_long_str
[newattr
->origin
],
1061 bgp_origin_long_str
[existattr
->origin
]);
1066 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
1067 && aspath_count_hops(existattr
->aspath
) == 0);
1068 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
1069 && aspath_count_confeds(existattr
->aspath
) > 0
1070 && aspath_count_hops(newattr
->aspath
) == 0
1071 && aspath_count_hops(existattr
->aspath
) == 0);
1073 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1074 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1075 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1076 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1077 || internal_as_route
) {
1078 new_med
= bgp_med_value(new->attr
, bgp
);
1079 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1081 if (new_med
< exist_med
) {
1082 *reason
= bgp_path_selection_med
;
1085 "%s: %s wins over %s due to MED %d < %d",
1086 pfx_buf
, new_buf
, exist_buf
, new_med
,
1091 if (new_med
> exist_med
) {
1092 *reason
= bgp_path_selection_med
;
1095 "%s: %s loses to %s due to MED %d > %d",
1096 pfx_buf
, new_buf
, exist_buf
, new_med
,
1102 /* 7. Peer type check. */
1103 new_sort
= new->peer
->sort
;
1104 exist_sort
= exist
->peer
->sort
;
1106 if (new_sort
== BGP_PEER_EBGP
1107 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1108 *reason
= bgp_path_selection_peer
;
1111 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1112 pfx_buf
, new_buf
, exist_buf
);
1113 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1118 if (exist_sort
== BGP_PEER_EBGP
1119 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1120 *reason
= bgp_path_selection_peer
;
1123 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1124 pfx_buf
, new_buf
, exist_buf
);
1125 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1130 /* 8. IGP metric check. */
1134 newm
= new->extra
->igpmetric
;
1136 existm
= exist
->extra
->igpmetric
;
1138 if (new->peer
->orr_group_name
[afi
][safi
]) {
1139 ret
= str2prefix(new->peer
->host
, &exist_p
);
1140 orr_group
= bgp_orr_group_lookup_by_name(
1141 bgp
, afi
, safi
, new->peer
->orr_group_name
[afi
][safi
]);
1143 orr_group_igp_metric_info
= orr_group
->igp_metric_info
;
1144 if (orr_group_igp_metric_info
) {
1145 for (ALL_LIST_ELEMENTS_RO(
1146 orr_group_igp_metric_info
, node
,
1149 prefix_cmp(&exist_p
,
1150 &igp_metric
->prefix
) ==
1152 newm
= igp_metric
->igp_metric
;
1159 if (exist
->peer
->orr_group_name
[afi
][safi
]) {
1160 ret
= str2prefix(exist
->peer
->host
, &exist_p
);
1161 orr_group
= bgp_orr_group_lookup_by_name(
1162 bgp
, afi
, safi
, exist
->peer
->orr_group_name
[afi
][safi
]);
1164 orr_group_igp_metric_info
= orr_group
->igp_metric_info
;
1165 if (orr_group_igp_metric_info
) {
1166 for (ALL_LIST_ELEMENTS_RO(
1167 orr_group_igp_metric_info
, node
,
1170 prefix_cmp(&exist_p
,
1171 &igp_metric
->prefix
) ==
1173 existm
= igp_metric
->igp_metric
;
1181 if (newm
< existm
) {
1182 if (debug
&& peer_sort_ret
< 0)
1184 "%s: %s wins over %s due to IGP metric %u < %u",
1185 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1189 if (newm
> existm
) {
1190 if (debug
&& peer_sort_ret
< 0)
1192 "%s: %s loses to %s due to IGP metric %u > %u",
1193 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1197 /* 9. Same IGP metric. Compare the cluster list length as
1198 representative of IGP hops metric. Rewrite the metric value
1199 pair (newm, existm) with the cluster list length. Prefer the
1200 path with smaller cluster list length. */
1201 if (newm
== existm
) {
1202 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
&&
1203 peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
&&
1204 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1205 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1206 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1208 if (newm
< existm
) {
1209 if (debug
&& peer_sort_ret
< 0)
1211 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1212 pfx_buf
, new_buf
, exist_buf
,
1217 if (newm
> existm
) {
1218 if (debug
&& peer_sort_ret
< 0)
1220 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1221 pfx_buf
, new_buf
, exist_buf
,
1228 /* 10. confed-external vs. confed-internal */
1229 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1230 if (new_sort
== BGP_PEER_CONFED
1231 && exist_sort
== BGP_PEER_IBGP
) {
1232 *reason
= bgp_path_selection_confed
;
1235 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1236 pfx_buf
, new_buf
, exist_buf
);
1237 if (!CHECK_FLAG(bgp
->flags
,
1238 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1243 if (exist_sort
== BGP_PEER_CONFED
1244 && new_sort
== BGP_PEER_IBGP
) {
1245 *reason
= bgp_path_selection_confed
;
1248 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1249 pfx_buf
, new_buf
, exist_buf
);
1250 if (!CHECK_FLAG(bgp
->flags
,
1251 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1257 /* 11. Maximum path check. */
1258 if (newm
== existm
) {
1259 /* If one path has a label but the other does not, do not treat
1260 * them as equals for multipath
1262 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1264 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1267 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1268 pfx_buf
, new_buf
, exist_buf
);
1269 } else if (CHECK_FLAG(bgp
->flags
,
1270 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1273 * For the two paths, all comparison steps till IGP
1275 * have succeeded - including AS_PATH hop count. Since
1277 * bestpath as-path multipath-relax' knob is on, we
1279 * an exact match of AS_PATH. Thus, mark the paths are
1281 * That will trigger both these paths to get into the
1289 "%s: %s and %s are equal via multipath-relax",
1290 pfx_buf
, new_buf
, exist_buf
);
1291 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1292 if (aspath_cmp(new->attr
->aspath
,
1293 exist
->attr
->aspath
)) {
1298 "%s: %s and %s are equal via matching aspaths",
1299 pfx_buf
, new_buf
, exist_buf
);
1301 } else if (new->peer
->as
== exist
->peer
->as
) {
1306 "%s: %s and %s are equal via same remote-as",
1307 pfx_buf
, new_buf
, exist_buf
);
1311 * TODO: If unequal cost ibgp multipath is enabled we can
1312 * mark the paths as equal here instead of returning
1315 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1316 * if either step 7 or 10 (peer type checks) yielded a winner,
1317 * that result was returned immediately. Returning from step 10
1318 * ignored the return value computed in steps 8 and 9 (IGP
1319 * metric checks). In order to preserve that behavior, if
1320 * peer_sort_ret is set, return that rather than igp_metric_ret.
1322 ret
= peer_sort_ret
;
1323 if (peer_sort_ret
< 0) {
1324 ret
= igp_metric_ret
;
1328 "%s: %s wins over %s after IGP metric comparison",
1329 pfx_buf
, new_buf
, exist_buf
);
1332 "%s: %s loses to %s after IGP metric comparison",
1333 pfx_buf
, new_buf
, exist_buf
);
1335 *reason
= bgp_path_selection_igp_metric
;
1341 * At this point, the decision whether to set *paths_eq = 1 has been
1342 * completed. If we deferred returning because of bestpath peer-type
1343 * relax configuration, return now.
1345 if (peer_sort_ret
>= 0)
1346 return peer_sort_ret
;
1348 /* 12. If both paths are external, prefer the path that was received
1349 first (the oldest one). This step minimizes route-flap, since a
1350 newer path won't displace an older one, even if it was the
1351 preferred route based on the additional decision criteria below. */
1352 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1353 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1354 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1355 *reason
= bgp_path_selection_older
;
1358 "%s: %s wins over %s due to oldest external",
1359 pfx_buf
, new_buf
, exist_buf
);
1363 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1364 *reason
= bgp_path_selection_older
;
1367 "%s: %s loses to %s due to oldest external",
1368 pfx_buf
, new_buf
, exist_buf
);
1373 /* 13. Router-ID comparison. */
1374 /* If one of the paths is "stale", the corresponding peer router-id will
1375 * be 0 and would always win over the other path. If originator id is
1376 * used for the comparison, it will decide which path is better.
1378 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1379 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1381 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1382 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1383 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1385 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1387 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1388 *reason
= bgp_path_selection_router_id
;
1391 "%s: %s wins over %s due to Router-ID comparison",
1392 pfx_buf
, new_buf
, exist_buf
);
1396 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1397 *reason
= bgp_path_selection_router_id
;
1400 "%s: %s loses to %s due to Router-ID comparison",
1401 pfx_buf
, new_buf
, exist_buf
);
1405 /* 14. Cluster length comparison. */
1406 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1407 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1409 if (new_cluster
< exist_cluster
) {
1410 *reason
= bgp_path_selection_cluster_length
;
1413 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1414 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1419 if (new_cluster
> exist_cluster
) {
1420 *reason
= bgp_path_selection_cluster_length
;
1423 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1424 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1429 /* 15. Neighbor address comparison. */
1430 /* Do this only if neither path is "stale" as stale paths do not have
1431 * valid peer information (as the connection may or may not be up).
1433 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1434 *reason
= bgp_path_selection_stale
;
1437 "%s: %s wins over %s due to latter path being STALE",
1438 pfx_buf
, new_buf
, exist_buf
);
1442 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1443 *reason
= bgp_path_selection_stale
;
1446 "%s: %s loses to %s due to former path being STALE",
1447 pfx_buf
, new_buf
, exist_buf
);
1451 /* locally configured routes to advertise do not have su_remote */
1452 if (new->peer
->su_remote
== NULL
) {
1453 *reason
= bgp_path_selection_local_configured
;
1456 if (exist
->peer
->su_remote
== NULL
) {
1457 *reason
= bgp_path_selection_local_configured
;
1461 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1464 *reason
= bgp_path_selection_neighbor_ip
;
1467 "%s: %s loses to %s due to Neighor IP comparison",
1468 pfx_buf
, new_buf
, exist_buf
);
1473 *reason
= bgp_path_selection_neighbor_ip
;
1476 "%s: %s wins over %s due to Neighor IP comparison",
1477 pfx_buf
, new_buf
, exist_buf
);
1481 *reason
= bgp_path_selection_default
;
1483 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1484 pfx_buf
, new_buf
, exist_buf
);
1490 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1491 struct bgp_path_info
*exist
, int *paths_eq
)
1493 enum bgp_path_selection_reason reason
;
1494 char pfx_buf
[PREFIX2STR_BUFFER
];
1496 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1497 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1500 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1501 * is preferred, or 0 if they are the same (usually will only occur if
1502 * multipath is enabled
1503 * This version is compatible with */
1504 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1505 struct bgp_path_info
*exist
, char *pfx_buf
,
1506 afi_t afi
, safi_t safi
,
1507 enum bgp_path_selection_reason
*reason
)
1511 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1525 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1526 const struct prefix
*p
,
1527 struct attr
*attr
, afi_t afi
,
1530 struct bgp_filter
*filter
;
1531 enum filter_type ret
= FILTER_PERMIT
;
1533 filter
= &peer
->filter
[afi
][safi
];
1535 #define FILTER_EXIST_WARN(F, f, filter) \
1536 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1537 zlog_debug("%s: Could not find configured input %s-list %s!", \
1538 peer->host, #f, F##_IN_NAME(filter));
1540 if (DISTRIBUTE_IN_NAME(filter
)) {
1541 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1543 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1550 if (PREFIX_LIST_IN_NAME(filter
)) {
1551 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1553 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1560 if (FILTER_LIST_IN_NAME(filter
)) {
1561 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1563 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1564 == AS_FILTER_DENY
) {
1571 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1572 char pfxprint
[PREFIX2STR_BUFFER
];
1574 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1575 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1576 ret
== FILTER_PERMIT
? "permit" : "deny");
1580 #undef FILTER_EXIST_WARN
1583 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1584 const struct prefix
*p
,
1585 struct attr
*attr
, afi_t afi
,
1588 struct bgp_filter
*filter
;
1589 enum filter_type ret
= FILTER_PERMIT
;
1591 filter
= &peer
->filter
[afi
][safi
];
1593 #define FILTER_EXIST_WARN(F, f, filter) \
1594 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1595 zlog_debug("%s: Could not find configured output %s-list %s!", \
1596 peer->host, #f, F##_OUT_NAME(filter));
1598 if (DISTRIBUTE_OUT_NAME(filter
)) {
1599 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1601 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1608 if (PREFIX_LIST_OUT_NAME(filter
)) {
1609 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1611 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1618 if (FILTER_LIST_OUT_NAME(filter
)) {
1619 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1621 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1622 == AS_FILTER_DENY
) {
1628 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1629 char pfxprint
[PREFIX2STR_BUFFER
];
1631 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1632 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1633 ret
== FILTER_PERMIT
? "permit" : "deny");
1638 #undef FILTER_EXIST_WARN
1641 /* If community attribute includes no_export then return 1. */
1642 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1644 if (bgp_attr_get_community(attr
)) {
1645 /* NO_ADVERTISE check. */
1646 if (community_include(bgp_attr_get_community(attr
),
1647 COMMUNITY_NO_ADVERTISE
))
1650 /* NO_EXPORT check. */
1651 if (peer
->sort
== BGP_PEER_EBGP
&&
1652 community_include(bgp_attr_get_community(attr
),
1653 COMMUNITY_NO_EXPORT
))
1656 /* NO_EXPORT_SUBCONFED check. */
1657 if (peer
->sort
== BGP_PEER_EBGP
1658 || peer
->sort
== BGP_PEER_CONFED
)
1659 if (community_include(bgp_attr_get_community(attr
),
1660 COMMUNITY_NO_EXPORT_SUBCONFED
))
1666 /* Route reflection loop check. */
1667 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1669 struct in_addr cluster_id
;
1670 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1673 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1674 cluster_id
= peer
->bgp
->cluster_id
;
1676 cluster_id
= peer
->bgp
->router_id
;
1678 if (cluster_loop_check(cluster
, cluster_id
))
1684 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1686 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1687 if (peer
->local_role
== ROLE_PROVIDER
||
1688 peer
->local_role
== ROLE_RS_SERVER
)
1690 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1694 if (peer
->local_role
== ROLE_CUSTOMER
||
1695 peer
->local_role
== ROLE_PEER
||
1696 peer
->local_role
== ROLE_RS_CLIENT
) {
1697 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1698 attr
->otc
= peer
->as
;
1703 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1705 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1706 if (peer
->local_role
== ROLE_CUSTOMER
||
1707 peer
->local_role
== ROLE_RS_CLIENT
||
1708 peer
->local_role
== ROLE_PEER
)
1712 if (peer
->local_role
== ROLE_PROVIDER
||
1713 peer
->local_role
== ROLE_PEER
||
1714 peer
->local_role
== ROLE_RS_SERVER
) {
1715 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1716 attr
->otc
= peer
->bgp
->as
;
1721 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1723 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1726 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1727 struct attr
*attr
, afi_t afi
, safi_t safi
,
1728 const char *rmap_name
, mpls_label_t
*label
,
1729 uint32_t num_labels
, struct bgp_dest
*dest
)
1731 struct bgp_filter
*filter
;
1732 struct bgp_path_info rmap_path
= { 0 };
1733 struct bgp_path_info_extra extra
= { 0 };
1734 route_map_result_t ret
;
1735 struct route_map
*rmap
= NULL
;
1737 filter
= &peer
->filter
[afi
][safi
];
1739 /* Apply default weight value. */
1740 if (peer
->weight
[afi
][safi
])
1741 attr
->weight
= peer
->weight
[afi
][safi
];
1744 rmap
= route_map_lookup_by_name(rmap_name
);
1749 if (ROUTE_MAP_IN_NAME(filter
)) {
1750 rmap
= ROUTE_MAP_IN(filter
);
1757 /* Route map apply. */
1759 memset(&rmap_path
, 0, sizeof(rmap_path
));
1760 /* Duplicate current value to new structure for modification. */
1761 rmap_path
.peer
= peer
;
1762 rmap_path
.attr
= attr
;
1763 rmap_path
.extra
= &extra
;
1764 rmap_path
.net
= dest
;
1766 extra
.num_labels
= num_labels
;
1767 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1768 memcpy(extra
.label
, label
,
1769 num_labels
* sizeof(mpls_label_t
));
1771 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1773 /* Apply BGP route map to the attribute. */
1774 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1776 peer
->rmap_type
= 0;
1778 if (ret
== RMAP_DENYMATCH
)
1784 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1785 struct attr
*attr
, afi_t afi
, safi_t safi
,
1786 const char *rmap_name
)
1788 struct bgp_path_info rmap_path
;
1789 route_map_result_t ret
;
1790 struct route_map
*rmap
= NULL
;
1794 * So if we get to this point and have no rmap_name
1795 * we want to just show the output as it currently
1801 /* Apply default weight value. */
1802 if (peer
->weight
[afi
][safi
])
1803 attr
->weight
= peer
->weight
[afi
][safi
];
1805 rmap
= route_map_lookup_by_name(rmap_name
);
1808 * If we have a route map name and we do not find
1809 * the routemap that means we have an implicit
1815 memset(&rmap_path
, 0, sizeof(rmap_path
));
1816 /* Route map apply. */
1817 /* Duplicate current value to new structure for modification. */
1818 rmap_path
.peer
= peer
;
1819 rmap_path
.attr
= attr
;
1821 rmap_type
= peer
->rmap_type
;
1822 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1824 /* Apply BGP route map to the attribute. */
1825 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1827 peer
->rmap_type
= rmap_type
;
1829 if (ret
== RMAP_DENYMATCH
)
1831 * caller has multiple error paths with bgp_attr_flush()
1838 /* If this is an EBGP peer with remove-private-AS */
1839 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1840 struct peer
*peer
, struct attr
*attr
)
1842 if (peer
->sort
== BGP_PEER_EBGP
1843 && (peer_af_flag_check(peer
, afi
, safi
,
1844 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1845 || peer_af_flag_check(peer
, afi
, safi
,
1846 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1847 || peer_af_flag_check(peer
, afi
, safi
,
1848 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1849 || peer_af_flag_check(peer
, afi
, safi
,
1850 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1851 // Take action on the entire aspath
1852 if (peer_af_flag_check(peer
, afi
, safi
,
1853 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1854 || peer_af_flag_check(peer
, afi
, safi
,
1855 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1856 if (peer_af_flag_check(
1858 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1859 attr
->aspath
= aspath_replace_private_asns(
1860 attr
->aspath
, bgp
->as
, peer
->as
);
1863 * Even if the aspath consists of just private ASNs we
1864 * need to walk the AS-Path to maintain all instances
1865 * of the peer's ASN to break possible loops.
1868 attr
->aspath
= aspath_remove_private_asns(
1869 attr
->aspath
, peer
->as
);
1872 // 'all' was not specified so the entire aspath must be private
1874 // for us to do anything
1875 else if (aspath_private_as_check(attr
->aspath
)) {
1876 if (peer_af_flag_check(
1878 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1879 attr
->aspath
= aspath_replace_private_asns(
1880 attr
->aspath
, bgp
->as
, peer
->as
);
1883 * Walk the aspath to retain any instances of
1886 attr
->aspath
= aspath_remove_private_asns(
1887 attr
->aspath
, peer
->as
);
1892 /* If this is an EBGP peer with as-override */
1893 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1894 struct peer
*peer
, struct attr
*attr
)
1896 struct aspath
*aspath
;
1898 if (peer
->sort
== BGP_PEER_EBGP
&&
1899 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1900 if (attr
->aspath
->refcnt
)
1901 aspath
= aspath_dup(attr
->aspath
);
1903 aspath
= attr
->aspath
;
1905 attr
->aspath
= aspath_intern(
1906 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1908 aspath_free(aspath
);
1912 void bgp_attr_add_llgr_community(struct attr
*attr
)
1914 struct community
*old
;
1915 struct community
*new;
1916 struct community
*merge
;
1917 struct community
*llgr
;
1919 old
= bgp_attr_get_community(attr
);
1920 llgr
= community_str2com("llgr-stale");
1925 merge
= community_merge(community_dup(old
), llgr
);
1927 if (old
->refcnt
== 0)
1928 community_free(&old
);
1930 new = community_uniq_sort(merge
);
1931 community_free(&merge
);
1933 new = community_dup(llgr
);
1936 community_free(&llgr
);
1938 bgp_attr_set_community(attr
, new);
1941 void bgp_attr_add_gshut_community(struct attr
*attr
)
1943 struct community
*old
;
1944 struct community
*new;
1945 struct community
*merge
;
1946 struct community
*gshut
;
1948 old
= bgp_attr_get_community(attr
);
1949 gshut
= community_str2com("graceful-shutdown");
1954 merge
= community_merge(community_dup(old
), gshut
);
1956 if (old
->refcnt
== 0)
1957 community_free(&old
);
1959 new = community_uniq_sort(merge
);
1960 community_free(&merge
);
1962 new = community_dup(gshut
);
1965 community_free(&gshut
);
1966 bgp_attr_set_community(attr
, new);
1968 /* When we add the graceful-shutdown community we must also
1969 * lower the local-preference */
1970 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1971 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1975 /* Notify BGP Conditional advertisement scanner process. */
1976 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1978 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1979 afi_t afi
= SUBGRP_AFI(subgrp
);
1980 safi_t safi
= SUBGRP_SAFI(subgrp
);
1981 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1983 if (!ADVERTISE_MAP_NAME(filter
))
1986 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1989 peer
->advmap_table_change
= true;
1993 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1995 if (family
== AF_INET
) {
1996 attr
->nexthop
.s_addr
= INADDR_ANY
;
1997 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1999 if (family
== AF_INET6
)
2000 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
2001 if (family
== AF_EVPN
)
2002 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
2005 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
2006 struct update_subgroup
*subgrp
,
2007 const struct prefix
*p
, struct attr
*attr
,
2008 struct attr
*post_attr
)
2010 struct bgp_filter
*filter
;
2013 struct peer
*onlypeer
;
2015 struct attr
*piattr
;
2016 route_map_result_t ret
;
2021 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
2022 bool nh_reset
= false;
2025 if (DISABLE_BGP_ANNOUNCE
)
2028 afi
= SUBGRP_AFI(subgrp
);
2029 safi
= SUBGRP_SAFI(subgrp
);
2030 peer
= SUBGRP_PEER(subgrp
);
2032 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
2033 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
2036 filter
= &peer
->filter
[afi
][safi
];
2037 bgp
= SUBGRP_INST(subgrp
);
2038 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
2041 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
2042 peer
->pmax_out
[afi
][safi
] != 0 &&
2043 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
2044 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
2045 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
2046 zlog_debug("%s reached maximum prefix to be send (%u)",
2047 peer
->host
, peer
->pmax_out
[afi
][safi
]);
2052 #ifdef ENABLE_BGP_VNC
2053 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
2054 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
2055 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
2058 * direct and direct_ext type routes originate internally even
2059 * though they can have peer pointers that reference other
2062 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2068 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
2069 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
2070 && (pi
->type
== ZEBRA_ROUTE_BGP
)
2071 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2073 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2078 /* With addpath we may be asked to TX all kinds of paths so make sure
2080 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
2081 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
2082 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
2086 /* If this is not the bestpath then check to see if there is an enabled
2088 * feature that requires us to advertise it */
2089 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2090 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
2095 /* Aggregate-address suppress check. */
2096 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
2100 * If we are doing VRF 2 VRF leaking via the import
2101 * statement, we want to prevent the route going
2102 * off box as that the RT and RD created are localy
2103 * significant and globaly useless.
2105 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
2106 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
2109 /* If it's labeled safi, make sure the route has a valid label. */
2110 if (safi
== SAFI_LABELED_UNICAST
) {
2111 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
2112 if (!bgp_is_valid_label(&label
)) {
2113 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2114 zlog_debug("u%" PRIu64
":s%" PRIu64
2115 " %pFX is filtered - no label (%p)",
2116 subgrp
->update_group
->id
, subgrp
->id
,
2122 /* Do not send back route to sender. */
2123 if (onlypeer
&& from
== onlypeer
) {
2127 /* Do not send the default route in the BGP table if the neighbor is
2128 * configured for default-originate */
2129 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2130 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2131 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2133 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2137 /* Transparency check. */
2138 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2139 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2144 /* If community is not disabled check the no-export and local. */
2145 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2146 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2147 zlog_debug("%s: community filter check fail for %pFX",
2152 /* If the attribute has originator-id and it is same as remote
2154 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2155 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2156 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2158 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2163 /* ORF prefix-list filter check */
2164 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2165 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2166 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2167 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2168 if (peer
->orf_plist
[afi
][safi
]) {
2169 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2171 if (bgp_debug_update(NULL
, p
,
2172 subgrp
->update_group
, 0))
2174 "%pBP [Update:SEND] %pFX is filtered via ORF",
2180 /* Output filter check. */
2181 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2182 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2183 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2188 /* AS path loop check. */
2189 if (onlypeer
&& onlypeer
->as_path_loop_detection
2190 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
2191 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2193 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2194 onlypeer
, onlypeer
->as
);
2198 /* If we're a CONFED we need to loop check the CONFED ID too */
2199 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2200 if (aspath_loop_check_confed(piattr
->aspath
, bgp
->confed_id
)) {
2201 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2203 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2204 peer
, bgp
->confed_id
);
2209 /* Route-Reflect check. */
2210 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2215 /* IBGP reflection check. */
2216 if (reflect
&& !samepeer_safe
) {
2217 /* A route from a Client peer. */
2218 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2219 PEER_FLAG_REFLECTOR_CLIENT
)) {
2220 /* Reflect to all the Non-Client peers and also to the
2221 Client peers other than the originator. Originator
2223 is already done. So there is noting to do. */
2224 /* no bgp client-to-client reflection check. */
2225 if (CHECK_FLAG(bgp
->flags
,
2226 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2227 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2228 PEER_FLAG_REFLECTOR_CLIENT
))
2231 /* A route from a Non-client peer. Reflect to all other
2233 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2234 PEER_FLAG_REFLECTOR_CLIENT
))
2239 /* For modify attribute, copy it to temporary structure.
2240 * post_attr comes from BGP conditional advertisements, where
2241 * attributes are already processed by advertise-map route-map,
2242 * and this needs to be saved instead of overwriting from the
2250 /* If local-preference is not set. */
2251 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2252 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2253 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2254 attr
->local_pref
= bgp
->default_local_pref
;
2257 /* If originator-id is not set and the route is to be reflected,
2258 set the originator id */
2260 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2261 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2262 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2265 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2267 if (peer
->sort
== BGP_PEER_EBGP
2268 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2269 if (from
!= bgp
->peer_self
&& !transparent
2270 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2271 PEER_FLAG_MED_UNCHANGED
))
2273 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2276 /* Since the nexthop attribute can vary per peer, it is not explicitly
2278 * in announce check, only certain flags and length (or number of
2280 * -- for IPv6/MP_REACH) are set here in order to guide the update
2282 * code in setting the nexthop(s) on a per peer basis in
2284 * Typically, the source nexthop in the attribute is preserved but in
2286 * scenarios where we know it will always be overwritten, we reset the
2287 * nexthop to "0" in an attempt to achieve better Update packing. An
2288 * example of this is when a prefix from each of 2 IBGP peers needs to
2290 * announced to an EBGP peer (and they have the same attributes barring
2294 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2296 #define NEXTHOP_IS_V6 \
2297 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2298 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2299 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2300 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2302 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2304 * the peer (group) is configured to receive link-local nexthop
2306 * and it is available in the prefix OR we're not reflecting the route,
2307 * link-local nexthop address is valid and
2308 * the peer (group) to whom we're going to announce is on a shared
2310 * and this is either a self-originated route or the peer is EBGP.
2311 * By checking if nexthop LL address is valid we are sure that
2312 * we do not announce LL address as `::`.
2314 if (NEXTHOP_IS_V6
) {
2315 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2316 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2317 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2318 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2319 || (!reflect
&& !transparent
2320 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2321 && peer
->shared_network
2322 && (from
== bgp
->peer_self
2323 || peer
->sort
== BGP_PEER_EBGP
))) {
2324 attr
->mp_nexthop_len
=
2325 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2328 /* Clear off link-local nexthop in source, whenever it is not
2330 * ensure more prefixes share the same attribute for
2333 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2334 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2335 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2338 if (bgp_check_role_applicability(afi
, safi
) &&
2339 bgp_otc_egress(peer
, attr
))
2342 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2343 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2345 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2346 filter
->advmap
.aname
&&
2347 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2348 struct bgp_path_info rmap_path
= {0};
2349 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2350 struct attr dummy_attr
= *attr
;
2352 /* Fill temp path_info */
2353 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2354 pi
, peer
, &dummy_attr
);
2356 struct route_map
*amap
=
2357 route_map_lookup_by_name(filter
->advmap
.aname
);
2359 ret
= route_map_apply(amap
, p
, &rmap_path
);
2361 bgp_attr_flush(&dummy_attr
);
2364 * The conditional advertisement mode is Withdraw and this
2365 * prefix is a conditional prefix. Don't advertise it
2367 if (ret
== RMAP_PERMITMATCH
)
2371 /* Route map & unsuppress-map apply. */
2373 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2374 struct bgp_path_info rmap_path
= {0};
2375 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2376 struct attr dummy_attr
= {0};
2378 /* Fill temp path_info */
2379 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2382 /* don't confuse inbound and outbound setting */
2383 RESET_FLAG(attr
->rmap_change_flags
);
2386 * The route reflector is not allowed to modify the attributes
2387 * of the reflected IBGP routes unless explicitly allowed.
2389 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2390 && !CHECK_FLAG(bgp
->flags
,
2391 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2393 rmap_path
.attr
= &dummy_attr
;
2396 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2398 if (bgp_path_suppressed(pi
))
2399 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2402 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2405 bgp_attr_flush(&dummy_attr
);
2406 peer
->rmap_type
= 0;
2408 if (ret
== RMAP_DENYMATCH
) {
2409 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2411 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2412 peer
, p
, ROUTE_MAP_OUT_NAME(filter
));
2413 bgp_attr_flush(rmap_path
.attr
);
2418 /* RFC 8212 to prevent route leaks.
2419 * This specification intends to improve this situation by requiring the
2420 * explicit configuration of both BGP Import and Export Policies for any
2421 * External BGP (EBGP) session such as customers, peers, or
2422 * confederation boundaries for all enabled address families. Through
2423 * codification of the aforementioned requirement, operators will
2424 * benefit from consistent behavior across different BGP
2427 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2428 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2429 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2430 NULL
) > FIFTEENMINUTE2USEC
||
2431 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2433 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2434 monotime(&bgp
->ebgprequirespolicywarning
);
2439 /* draft-ietf-idr-deprecate-as-set-confed-set
2440 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2441 * Eventually, This document (if approved) updates RFC 4271
2442 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2443 * and obsoletes RFC 6472.
2445 if (peer
->bgp
->reject_as_sets
)
2446 if (aspath_check_as_sets(attr
->aspath
))
2449 /* If neighbor soo is configured, then check if the route has
2450 * SoO extended community and validate against the configured
2451 * one. If they match, do not announce, to prevent routing
2454 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2455 peer
->soo
[afi
][safi
]) {
2456 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2457 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2459 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2460 ECOMMUNITY_SITE_ORIGIN
) ||
2461 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2462 ECOMMUNITY_SITE_ORIGIN
) ||
2463 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2464 ECOMMUNITY_SITE_ORIGIN
)) &&
2465 ecommunity_include(ecomm
, ecomm_soo
)) {
2466 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2468 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2469 peer
, p
, ecommunity_str(ecomm_soo
));
2474 /* Codification of AS 0 Processing */
2475 if (aspath_check_as_zero(attr
->aspath
))
2478 if (bgp_in_graceful_shutdown(bgp
)) {
2479 if (peer
->sort
== BGP_PEER_IBGP
2480 || peer
->sort
== BGP_PEER_CONFED
) {
2481 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2482 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2484 bgp_attr_add_gshut_community(attr
);
2488 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2489 * Capability" to a neighbor MUST perform the following upon receiving
2490 * a route from that neighbor with the "LLGR_STALE" community, or upon
2491 * attaching the "LLGR_STALE" community itself per Section 4.2:
2493 * The route SHOULD NOT be advertised to any neighbor from which the
2494 * Long-lived Graceful Restart Capability has not been received.
2496 if (bgp_attr_get_community(attr
) &&
2497 community_include(bgp_attr_get_community(attr
),
2498 COMMUNITY_LLGR_STALE
) &&
2499 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2500 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2503 /* After route-map has been applied, we check to see if the nexthop to
2504 * be carried in the attribute (that is used for the announcement) can
2505 * be cleared off or not. We do this in all cases where we would be
2506 * setting the nexthop to "ourselves". For IPv6, we only need to
2508 * the global nexthop here; the link-local nexthop would have been
2510 * already, and if not, it is required by the update formation code.
2511 * Also see earlier comments in this function.
2514 * If route-map has performed some operation on the nexthop or the peer
2515 * configuration says to pass it unchanged, we cannot reset the nexthop
2516 * here, so only attempt to do it if these aren't true. Note that the
2517 * route-map handler itself might have cleared the nexthop, if for
2519 * it is configured as 'peer-address'.
2521 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2522 piattr
->rmap_change_flags
)
2524 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2525 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2526 /* We can reset the nexthop, if setting (or forcing) it to
2528 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2529 PEER_FLAG_NEXTHOP_SELF
)
2530 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2531 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2533 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2534 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2535 subgroup_announce_reset_nhop(
2536 (peer_cap_enhe(peer
, afi
, safi
)
2542 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2543 /* Can also reset the nexthop if announcing to EBGP, but
2545 * no peer in the subgroup is on a shared subnet.
2546 * Note: 3rd party nexthop currently implemented for
2549 if ((p
->family
== AF_INET
) &&
2550 (!bgp_subgrp_multiaccess_check_v4(
2553 subgroup_announce_reset_nhop(
2554 (peer_cap_enhe(peer
, afi
, safi
)
2561 if ((p
->family
== AF_INET6
) &&
2562 (!bgp_subgrp_multiaccess_check_v6(
2563 piattr
->mp_nexthop_global
,
2565 subgroup_announce_reset_nhop(
2566 (peer_cap_enhe(peer
, afi
, safi
)
2575 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2577 * This flag is used for leaked vpn-vrf routes
2579 int family
= p
->family
;
2581 if (peer_cap_enhe(peer
, afi
, safi
))
2584 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2586 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2587 __func__
, family2str(family
));
2588 subgroup_announce_reset_nhop(family
, attr
);
2593 /* If IPv6/MP and nexthop does not have any override and happens
2595 * be a link-local address, reset it so that we don't pass along
2597 * source's link-local IPv6 address to recipients who may not be
2599 * the same interface.
2601 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2602 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2603 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2608 /* If this is an iBGP, send Origin Validation State (OVS)
2609 * extended community (rfc8097).
2611 if (peer
->sort
== BGP_PEER_IBGP
) {
2612 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2614 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2616 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2617 bgp_attr_set_ecommunity(
2618 attr
, ecommunity_add_origin_validation_state(
2620 bgp_attr_get_ecommunity(attr
)));
2624 * When the next hop is set to ourselves, if all multipaths have
2625 * link-bandwidth announce the cumulative bandwidth as that makes
2626 * the most sense. However, don't modify if the link-bandwidth has
2627 * been explicitly set by user policy.
2630 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2631 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2632 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2633 bgp_attr_set_ecommunity(
2635 ecommunity_replace_linkbw(
2636 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2639 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2644 static void bgp_route_select_timer_expire(struct thread
*thread
)
2646 struct afi_safi_info
*info
;
2651 info
= THREAD_ARG(thread
);
2656 if (BGP_DEBUG(update
, UPDATE_OUT
))
2657 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2660 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2662 XFREE(MTYPE_TMP
, info
);
2664 /* Best path selection */
2665 bgp_best_path_select_defer(bgp
, afi
, safi
);
2668 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2669 struct bgp_maxpaths_cfg
*mpath_cfg
,
2670 struct bgp_path_info_pair
*result
, afi_t afi
,
2673 struct bgp_path_info
*new_select
;
2674 struct bgp_path_info
*old_select
;
2675 struct bgp_path_info
*pi
;
2676 struct bgp_path_info
*pi1
;
2677 struct bgp_path_info
*pi2
;
2678 struct bgp_path_info
*nextpi
= NULL
;
2679 int paths_eq
, do_mpath
, debug
;
2680 struct list mp_list
;
2681 char pfx_buf
[PREFIX2STR_BUFFER
];
2682 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2684 bgp_mp_list_init(&mp_list
);
2686 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2688 debug
= bgp_debug_bestpath(dest
);
2691 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2693 dest
->reason
= bgp_path_selection_none
;
2694 /* bgp deterministic-med */
2696 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2698 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2699 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2701 bgp_path_info_unset_flag(dest
, pi1
,
2702 BGP_PATH_DMED_SELECTED
);
2704 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2706 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2708 if (BGP_PATH_HOLDDOWN(pi1
))
2710 if (pi1
->peer
!= bgp
->peer_self
)
2711 if (!peer_established(pi1
->peer
))
2716 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2717 if (CHECK_FLAG(pi2
->flags
,
2718 BGP_PATH_DMED_CHECK
))
2720 if (BGP_PATH_HOLDDOWN(pi2
))
2722 if (pi2
->peer
!= bgp
->peer_self
2725 PEER_STATUS_NSF_WAIT
))
2726 if (pi2
->peer
->status
2730 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2732 && !aspath_cmp_left_confed(
2737 if (bgp_path_info_cmp(
2738 bgp
, pi2
, new_select
,
2739 &paths_eq
, mpath_cfg
, debug
,
2742 bgp_path_info_unset_flag(
2744 BGP_PATH_DMED_SELECTED
);
2748 bgp_path_info_set_flag(
2749 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2752 bgp_path_info_set_flag(dest
, new_select
,
2753 BGP_PATH_DMED_CHECK
);
2754 bgp_path_info_set_flag(dest
, new_select
,
2755 BGP_PATH_DMED_SELECTED
);
2758 bgp_path_info_path_with_addpath_rx_str(
2759 new_select
, path_buf
, sizeof(path_buf
));
2761 "%pBD(%s): %s is the bestpath from AS %u",
2762 dest
, bgp
->name_pretty
, path_buf
,
2763 aspath_get_first_as(
2764 new_select
->attr
->aspath
));
2769 /* Check old selected route and new selected route. */
2772 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2773 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2774 enum bgp_path_selection_reason reason
;
2776 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2779 if (BGP_PATH_HOLDDOWN(pi
)) {
2780 /* reap REMOVED routes, if needs be
2781 * selected route must stay for a while longer though
2783 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2784 && (pi
!= old_select
))
2785 bgp_path_info_reap(dest
, pi
);
2788 zlog_debug("%s: pi %p in holddown", __func__
,
2794 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2795 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2796 if (!peer_established(pi
->peer
)) {
2800 "%s: pi %p non self peer %s not estab state",
2801 __func__
, pi
, pi
->peer
->host
);
2806 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2807 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2808 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2810 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2814 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2816 reason
= dest
->reason
;
2817 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2818 debug
, pfx_buf
, afi
, safi
,
2820 if (new_select
== NULL
&&
2821 reason
!= bgp_path_selection_none
)
2822 dest
->reason
= reason
;
2827 /* Now that we know which path is the bestpath see if any of the other
2829 * qualify as multipaths
2833 bgp_path_info_path_with_addpath_rx_str(
2834 new_select
, path_buf
, sizeof(path_buf
));
2836 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2838 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2839 dest
, bgp
->name_pretty
, path_buf
,
2840 old_select
? old_select
->peer
->host
: "NONE");
2843 if (do_mpath
&& new_select
) {
2844 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2845 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2848 bgp_path_info_path_with_addpath_rx_str(
2849 pi
, path_buf
, sizeof(path_buf
));
2851 if (pi
== new_select
) {
2854 "%pBD(%s): %s is the bestpath, add to the multipath list",
2855 dest
, bgp
->name_pretty
,
2857 bgp_mp_list_add(&mp_list
, pi
);
2861 if (BGP_PATH_HOLDDOWN(pi
))
2864 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2865 && !CHECK_FLAG(pi
->peer
->sflags
,
2866 PEER_STATUS_NSF_WAIT
))
2867 if (!peer_established(pi
->peer
))
2870 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2873 "%pBD: %s has the same nexthop as the bestpath, skip it",
2878 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2879 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2885 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2887 bgp_mp_list_add(&mp_list
, pi
);
2892 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2894 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2895 bgp_mp_list_clear(&mp_list
);
2897 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2899 result
->old
= old_select
;
2900 result
->new = new_select
;
2906 * A new route/change in bestpath of an existing route. Evaluate the path
2907 * for advertisement to the subgroup.
2909 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2910 struct bgp_path_info
*selected
,
2911 struct bgp_dest
*dest
,
2912 uint32_t addpath_tx_id
)
2914 const struct prefix
*p
;
2915 struct peer
*onlypeer
;
2922 p
= bgp_dest_get_prefix(dest
);
2923 afi
= SUBGRP_AFI(subgrp
);
2924 safi
= SUBGRP_SAFI(subgrp
);
2925 bgp
= SUBGRP_INST(subgrp
);
2926 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2929 if (BGP_DEBUG(update
, UPDATE_OUT
))
2930 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2932 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2933 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2934 PEER_STATUS_ORF_WAIT_REFRESH
))
2937 memset(&attr
, 0, sizeof(attr
));
2938 /* It's initialized in bgp_announce_check() */
2940 /* Announcement to the subgroup. If the route is filtered withdraw it.
2941 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2942 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2945 advertise
= bgp_check_advertise(bgp
, dest
);
2948 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2950 /* Route is selected, if the route is already installed
2951 * in FIB, then it is advertised
2954 if (!bgp_check_withdrawal(bgp
, dest
))
2955 bgp_adj_out_set_subgroup(
2956 dest
, subgrp
, &attr
, selected
);
2958 bgp_adj_out_unset_subgroup(
2959 dest
, subgrp
, 1, addpath_tx_id
);
2962 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2966 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2968 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2973 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2974 * This is called at the end of route processing.
2976 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2978 struct bgp_path_info
*pi
;
2980 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2981 if (BGP_PATH_HOLDDOWN(pi
))
2983 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2984 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2989 * Has the route changed from the RIB's perspective? This is invoked only
2990 * if the route selection returns the same best route as earlier - to
2991 * determine if we need to update zebra or not.
2993 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2995 struct bgp_path_info
*mpinfo
;
2997 /* If this is multipath, check all selected paths for any nexthop
2998 * change or attribute change. Some attribute changes (e.g., community)
2999 * aren't of relevance to the RIB, but we'll update zebra to ensure
3000 * we handle the case of BGP nexthop change. This is the behavior
3001 * when the best path has an attribute change anyway.
3003 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
3004 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
3005 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
3009 * If this is multipath, check all selected paths for any nexthop change
3011 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
3012 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
3013 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
3014 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
3018 /* Nothing has changed from the RIB's perspective. */
3022 struct bgp_process_queue
{
3024 STAILQ_HEAD(, bgp_dest
) pqueue
;
3025 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3027 unsigned int queued
;
3030 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
3031 safi_t safi
, struct bgp_dest
*dest
,
3032 struct bgp_path_info
*new_select
,
3033 struct bgp_path_info
*old_select
)
3035 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3037 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
3040 if (advertise_type5_routes(bgp
, afi
) && new_select
3041 && is_route_injectable_into_evpn(new_select
)) {
3043 /* apply the route-map */
3044 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
3045 route_map_result_t ret
;
3046 struct bgp_path_info rmap_path
;
3047 struct bgp_path_info_extra rmap_path_extra
;
3048 struct attr dummy_attr
;
3050 dummy_attr
= *new_select
->attr
;
3052 /* Fill temp path_info */
3053 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3054 new_select
, new_select
->peer
,
3057 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3059 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3062 if (ret
== RMAP_DENYMATCH
) {
3063 bgp_attr_flush(&dummy_attr
);
3064 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3067 bgp_evpn_advertise_type5_route(
3068 bgp
, p
, &dummy_attr
, afi
, safi
);
3070 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3073 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3074 && is_route_injectable_into_evpn(old_select
))
3075 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3079 * Utility to determine whether a particular path_info should use
3080 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3081 * in a path where we basically _know_ this is a BGP-LU route.
3083 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
3085 /* Certain types get imp null; so do paths where the nexthop is
3088 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3089 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3090 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3092 else if (new_select
->extra
== NULL
||
3093 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
3094 /* TODO -- should be configurable? */
3101 * old_select = The old best path
3102 * new_select = the new best path
3104 * if (!old_select && new_select)
3105 * We are sending new information on.
3107 * if (old_select && new_select) {
3108 * if (new_select != old_select)
3109 * We have a new best path send a change
3111 * We've received a update with new attributes that needs
3115 * if (old_select && !new_select)
3116 * We have no eligible route that we can announce or the rn
3119 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3120 afi_t afi
, safi_t safi
)
3122 struct bgp_path_info
*new_select
;
3123 struct bgp_path_info
*old_select
;
3124 struct bgp_path_info_pair old_and_new
;
3127 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3129 debug
= bgp_debug_bestpath(dest
);
3132 "%s: bgp delete in progress, ignoring event, p=%pBD",
3136 /* Is it end of initial update? (after startup) */
3138 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3139 sizeof(bgp
->update_delay_zebra_resume_time
));
3141 bgp
->main_zebra_update_hold
= 0;
3142 FOREACH_AFI_SAFI (afi
, safi
) {
3143 if (bgp_fibupd_safi(safi
))
3144 bgp_zebra_announce_table(bgp
, afi
, safi
);
3146 bgp
->main_peers_update_hold
= 0;
3148 bgp_start_routeadv(bgp
);
3152 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3154 debug
= bgp_debug_bestpath(dest
);
3156 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__
,
3157 dest
, bgp
->name_pretty
, afi2str(afi
),
3160 /* The best path calculation for the route is deferred if
3161 * BGP_NODE_SELECT_DEFER is set
3163 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3164 if (BGP_DEBUG(update
, UPDATE_OUT
))
3165 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
3169 /* Best path selection. */
3170 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3172 old_select
= old_and_new
.old
;
3173 new_select
= old_and_new
.new;
3175 /* Do we need to allocate or free labels?
3176 * Right now, since we only deal with per-prefix labels, it is not
3177 * necessary to do this upon changes to best path. Exceptions:
3178 * - label index has changed -> recalculate resulting label
3179 * - path_info sub_type changed -> switch to/from implicit-null
3180 * - no valid label (due to removed static label binding) -> get new one
3182 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3185 || bgp_label_index_differs(new_select
, old_select
)
3186 || new_select
->sub_type
!= old_select
->sub_type
3187 || !bgp_is_valid_label(&dest
->local_label
)) {
3188 /* Enforced penultimate hop popping:
3189 * implicit-null for local routes, aggregate
3190 * and redistributed routes
3192 if (bgp_lu_need_imp_null(new_select
)) {
3195 BGP_NODE_REGISTERED_FOR_LABEL
)
3198 BGP_NODE_LABEL_REQUESTED
))
3199 bgp_unregister_for_label(dest
);
3200 dest
->local_label
= mpls_lse_encode(
3201 MPLS_LABEL_IMPLICIT_NULL
, 0, 0,
3203 bgp_set_valid_label(&dest
->local_label
);
3205 bgp_register_for_label(dest
,
3208 } else if (CHECK_FLAG(dest
->flags
,
3209 BGP_NODE_REGISTERED_FOR_LABEL
)
3210 || CHECK_FLAG(dest
->flags
,
3211 BGP_NODE_LABEL_REQUESTED
)) {
3212 bgp_unregister_for_label(dest
);
3214 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3215 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3216 bgp_unregister_for_label(dest
);
3221 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3222 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3223 safi2str(safi
), old_select
, new_select
);
3225 /* If best route remains the same and this is not due to user-initiated
3226 * clear, see exactly what needs to be done.
3228 if (old_select
&& old_select
== new_select
3229 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3230 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3231 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3232 if (bgp_zebra_has_route_changed(old_select
)) {
3233 #ifdef ENABLE_BGP_VNC
3234 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3235 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3237 if (bgp_fibupd_safi(safi
)
3238 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3240 if (BGP_SUPPRESS_FIB_ENABLED(bgp
)
3241 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
3242 SET_FLAG(dest
->flags
,
3243 BGP_NODE_FIB_INSTALL_PENDING
);
3245 if (new_select
->type
== ZEBRA_ROUTE_BGP
3246 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3247 || new_select
->sub_type
3248 == BGP_ROUTE_IMPORTED
))
3250 bgp_zebra_announce(dest
, p
, old_select
,
3255 /* If there is a change of interest to peers, reannounce the
3257 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3258 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3259 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3260 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3262 /* unicast routes must also be annouced to
3263 * labeled-unicast update-groups */
3264 if (safi
== SAFI_UNICAST
)
3265 group_announce_route(bgp
, afi
,
3266 SAFI_LABELED_UNICAST
, dest
,
3269 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3270 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3273 /* advertise/withdraw type-5 routes */
3274 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3275 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3276 bgp_process_evpn_route_injection(
3277 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3279 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3280 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3281 bgp_zebra_clear_route_change_flags(dest
);
3282 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3286 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3288 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3290 /* bestpath has changed; bump version */
3291 if (old_select
|| new_select
) {
3292 bgp_bump_version(dest
);
3294 if (!bgp
->t_rmap_def_originate_eval
) {
3298 update_group_refresh_default_originate_route_map
,
3299 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3300 &bgp
->t_rmap_def_originate_eval
);
3305 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3308 zlog_debug("%s: setting SELECTED flag", __func__
);
3309 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3310 bgp_path_info_unset_flag(dest
, new_select
,
3311 BGP_PATH_ATTR_CHANGED
);
3312 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3313 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3316 #ifdef ENABLE_BGP_VNC
3317 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3318 if (old_select
!= new_select
) {
3320 vnc_import_bgp_exterior_del_route(bgp
, p
,
3322 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3325 vnc_import_bgp_exterior_add_route(bgp
, p
,
3327 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3333 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3335 /* unicast routes must also be annouced to labeled-unicast update-groups
3337 if (safi
== SAFI_UNICAST
)
3338 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3342 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3343 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3345 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3346 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3347 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3348 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3350 if (BGP_SUPPRESS_FIB_ENABLED(bgp
))
3351 SET_FLAG(dest
->flags
,
3352 BGP_NODE_FIB_INSTALL_PENDING
);
3354 /* if this is an evpn imported type-5 prefix,
3355 * we need to withdraw the route first to clear
3356 * the nh neigh and the RMAC entry.
3359 is_route_parent_evpn(old_select
))
3360 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3362 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3364 /* Withdraw the route from the kernel. */
3365 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3366 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3367 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3368 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3370 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3374 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3377 /* Clear any route change flags. */
3378 bgp_zebra_clear_route_change_flags(dest
);
3380 /* Reap old select bgp_path_info, if it has been removed */
3381 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3382 bgp_path_info_reap(dest
, old_select
);
3384 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3388 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3389 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3391 struct bgp_dest
*dest
;
3393 struct afi_safi_info
*thread_info
;
3395 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3396 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3398 thread_info
= THREAD_ARG(t
);
3399 XFREE(MTYPE_TMP
, thread_info
);
3400 THREAD_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3403 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3404 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3405 get_afi_safi_str(afi
, safi
, false),
3406 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3409 /* Process the route list */
3410 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3411 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3412 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3413 dest
= bgp_route_next(dest
)) {
3414 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3417 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3418 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3419 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3422 /* If iteration stopped before the entire table was traversed then the
3423 * node needs to be unlocked.
3426 bgp_dest_unlock_node(dest
);
3430 /* Send EOR message when all routes are processed */
3431 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3432 bgp_send_delayed_eor(bgp
);
3433 /* Send route processing complete message to RIB */
3434 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3435 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3439 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3441 thread_info
->afi
= afi
;
3442 thread_info
->safi
= safi
;
3443 thread_info
->bgp
= bgp
;
3445 /* If there are more routes to be processed, start the
3448 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3449 BGP_ROUTE_SELECT_DELAY
,
3450 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3453 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3455 struct bgp_process_queue
*pqnode
= data
;
3456 struct bgp
*bgp
= pqnode
->bgp
;
3457 struct bgp_table
*table
;
3458 struct bgp_dest
*dest
;
3461 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3462 bgp_process_main_one(bgp
, NULL
, 0, 0);
3463 /* should always have dedicated wq call */
3464 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3468 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3469 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3470 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3471 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3472 table
= bgp_dest_table(dest
);
3473 /* note, new DESTs may be added as part of processing */
3474 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3476 bgp_dest_unlock_node(dest
);
3477 bgp_table_unlock(table
);
3483 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3485 struct bgp_process_queue
*pqnode
= data
;
3487 bgp_unlock(pqnode
->bgp
);
3489 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3492 void bgp_process_queue_init(struct bgp
*bgp
)
3494 if (!bgp
->process_queue
) {
3497 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3498 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3501 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3502 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3503 bgp
->process_queue
->spec
.max_retries
= 0;
3504 bgp
->process_queue
->spec
.hold
= 50;
3505 /* Use a higher yield value of 50ms for main queue processing */
3506 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3509 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3511 struct bgp_process_queue
*pqnode
;
3513 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3514 sizeof(struct bgp_process_queue
));
3516 /* unlocked in bgp_processq_del */
3517 pqnode
->bgp
= bgp_lock(bgp
);
3518 STAILQ_INIT(&pqnode
->pqueue
);
3523 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3525 #define ARBITRARY_PROCESS_QLEN 10000
3526 struct work_queue
*wq
= bgp
->process_queue
;
3527 struct bgp_process_queue
*pqnode
;
3528 int pqnode_reuse
= 0;
3530 /* already scheduled for processing? */
3531 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3534 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3537 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3538 if (BGP_DEBUG(update
, UPDATE_OUT
))
3539 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3544 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3545 if (BGP_DEBUG(update
, UPDATE_OUT
))
3547 "Soft reconfigure table in progress for route %p",
3555 /* Add route nodes to an existing work queue item until reaching the
3556 limit only if is from the same BGP view and it's not an EOIU marker
3558 if (work_queue_item_count(wq
)) {
3559 struct work_queue_item
*item
= work_queue_last_item(wq
);
3560 pqnode
= item
->data
;
3562 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3563 || pqnode
->bgp
!= bgp
3564 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3565 pqnode
= bgp_processq_alloc(bgp
);
3569 pqnode
= bgp_processq_alloc(bgp
);
3570 /* all unlocked in bgp_process_wq */
3571 bgp_table_lock(bgp_dest_table(dest
));
3573 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3574 bgp_dest_lock_node(dest
);
3576 /* can't be enqueued twice */
3577 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3578 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3582 work_queue_add(wq
, pqnode
);
3587 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3589 struct bgp_process_queue
*pqnode
;
3591 if (bgp
->process_queue
== NULL
)
3594 pqnode
= bgp_processq_alloc(bgp
);
3596 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3597 work_queue_add(bgp
->process_queue
, pqnode
);
3600 static void bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3604 peer
= THREAD_ARG(thread
);
3605 peer
->t_pmax_restart
= NULL
;
3607 if (bgp_debug_neighbor_events(peer
))
3609 "%s Maximum-prefix restart timer expired, restore peering",
3612 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3613 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3616 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3620 bool filtered
= false;
3621 struct bgp_dest
*dest
;
3622 struct bgp_adj_in
*ain
;
3623 struct attr attr
= {};
3624 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3626 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3627 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3628 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3632 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3636 if (bgp_input_modifier(
3637 peer
, rn_p
, &attr
, afi
, safi
,
3638 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3646 bgp_attr_flush(&attr
);
3653 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3657 iana_safi_t pkt_safi
;
3658 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3659 PEER_FLAG_MAX_PREFIX_FORCE
))
3660 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3661 + peer
->pcount
[afi
][safi
]
3662 : peer
->pcount
[afi
][safi
];
3664 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3667 if (pcount
> peer
->pmax
[afi
][safi
]) {
3668 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3669 PEER_STATUS_PREFIX_LIMIT
)
3674 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3675 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3676 peer
->pmax
[afi
][safi
]);
3677 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3679 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3680 PEER_FLAG_MAX_PREFIX_WARNING
))
3683 /* Convert AFI, SAFI to values for packet. */
3684 pkt_afi
= afi_int2iana(afi
);
3685 pkt_safi
= safi_int2iana(safi
);
3689 ndata
[0] = (pkt_afi
>> 8);
3691 ndata
[2] = pkt_safi
;
3692 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3693 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3694 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3695 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3697 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3698 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3699 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3703 /* Dynamic peers will just close their connection. */
3704 if (peer_dynamic_neighbor(peer
))
3707 /* restart timer start */
3708 if (peer
->pmax_restart
[afi
][safi
]) {
3709 peer
->v_pmax_restart
=
3710 peer
->pmax_restart
[afi
][safi
] * 60;
3712 if (bgp_debug_neighbor_events(peer
))
3714 "%pBP Maximum-prefix restart timer started for %d secs",
3715 peer
, peer
->v_pmax_restart
);
3717 BGP_TIMER_ON(peer
->t_pmax_restart
,
3718 bgp_maximum_prefix_restart_timer
,
3719 peer
->v_pmax_restart
);
3724 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3725 PEER_STATUS_PREFIX_LIMIT
);
3728 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3729 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3730 PEER_STATUS_PREFIX_THRESHOLD
)
3735 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3736 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3737 peer
->pmax
[afi
][safi
]);
3738 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3739 PEER_STATUS_PREFIX_THRESHOLD
);
3741 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3742 PEER_STATUS_PREFIX_THRESHOLD
);
3746 /* Unconditionally remove the route from the RIB, without taking
3747 * damping into consideration (eg, because the session went down)
3749 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3750 struct peer
*peer
, afi_t afi
, safi_t safi
)
3753 struct bgp
*bgp
= NULL
;
3754 bool delete_route
= false;
3756 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3759 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3760 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3762 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3765 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3766 delete_route
= true;
3767 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3768 delete_route
= true;
3770 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3771 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3772 bgp
= pi
->peer
->bgp
;
3773 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3778 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3779 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3782 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3783 struct peer
*peer
, afi_t afi
, safi_t safi
,
3784 struct prefix_rd
*prd
)
3786 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3788 /* apply dampening, if result is suppressed, we'll be retaining
3789 * the bgp_path_info in the RIB for historical reference.
3791 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3792 && peer
->sort
== BGP_PEER_EBGP
)
3793 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3794 == BGP_DAMP_SUPPRESSED
) {
3795 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3800 #ifdef ENABLE_BGP_VNC
3801 if (safi
== SAFI_MPLS_VPN
) {
3802 struct bgp_dest
*pdest
= NULL
;
3803 struct bgp_table
*table
= NULL
;
3805 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3806 (struct prefix
*)prd
);
3807 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3808 table
= bgp_dest_get_bgp_table_info(pdest
);
3810 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3811 peer
->bgp
, prd
, table
, p
, pi
);
3813 bgp_dest_unlock_node(pdest
);
3815 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3816 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3818 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3819 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3824 /* If this is an EVPN route, process for un-import. */
3825 if (safi
== SAFI_EVPN
)
3826 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3828 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3831 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3832 struct peer
*peer
, struct attr
*attr
,
3833 struct bgp_dest
*dest
)
3835 struct bgp_path_info
*new;
3837 /* Make new BGP info. */
3838 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3840 new->instance
= instance
;
3841 new->sub_type
= sub_type
;
3844 new->uptime
= monotime(NULL
);
3849 /* Check if received nexthop is valid or not. */
3850 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3851 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3852 struct bgp_dest
*dest
)
3855 bool is_bgp_static_route
=
3856 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3860 * Only validated for unicast and multicast currently.
3861 * Also valid for EVPN where the nexthop is an IP address.
3862 * If we are a bgp static route being checked then there is
3863 * no need to check to see if the nexthop is martian as
3864 * that it should be ok.
3866 if (is_bgp_static_route
||
3867 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3870 /* If NEXT_HOP is present, validate it. */
3871 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3872 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3873 !ipv4_unicast_valid(&attr
->nexthop
) ||
3874 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3878 /* If MP_NEXTHOP is present, validate it. */
3879 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3880 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3881 * it is not an IPv6 link-local address.
3883 * If we receive an UPDATE with nexthop length set to 32 bytes
3884 * we shouldn't discard an UPDATE if it's set to (::).
3885 * The link-local (2st) is validated along the code path later.
3887 if (attr
->mp_nexthop_len
) {
3888 switch (attr
->mp_nexthop_len
) {
3889 case BGP_ATTR_NHLEN_IPV4
:
3890 case BGP_ATTR_NHLEN_VPNV4
:
3891 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3893 !ipv4_unicast_valid(
3894 &attr
->mp_nexthop_global_in
) ||
3895 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3899 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3900 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3901 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3902 &attr
->mp_nexthop_global
)
3903 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3904 || IN6_IS_ADDR_MULTICAST(
3905 &attr
->mp_nexthop_global
)
3906 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3909 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3910 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3911 || IN6_IS_ADDR_MULTICAST(
3912 &attr
->mp_nexthop_global
)
3913 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3926 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3928 struct community
*old
;
3929 struct community
*new;
3930 struct community
*merge
;
3931 struct community
*no_export
;
3933 old
= bgp_attr_get_community(attr
);
3934 no_export
= community_str2com("no-export");
3939 merge
= community_merge(community_dup(old
), no_export
);
3942 community_free(&old
);
3944 new = community_uniq_sort(merge
);
3945 community_free(&merge
);
3947 new = community_dup(no_export
);
3950 community_free(&no_export
);
3952 bgp_attr_set_community(attr
, new);
3955 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3956 struct attr
*attr
, const struct prefix
*prefix
,
3959 struct listnode
*node
, *nnode
;
3961 bool accept_own_found
= false;
3963 if (safi
!= SAFI_MPLS_VPN
)
3966 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3967 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3970 /* The route in question carries the ACCEPT_OWN community */
3971 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3972 struct community
*comm
= bgp_attr_get_community(attr
);
3974 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3975 accept_own_found
= true;
3978 /* The route in question is targeted to one or more destination VRFs
3979 * on the router (as determined by inspecting the Route Target(s)).
3981 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3982 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3985 if (accept_own_found
&&
3987 bgp
->vpn_policy
[afi
]
3988 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3989 bgp_attr_get_ecommunity(attr
))) {
3990 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3992 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3995 /* Treat this route as imported, because it's leaked
3996 * already from another VRF, and we got an updated
3997 * version from route-reflector with ACCEPT_OWN
4000 *sub_type
= BGP_ROUTE_IMPORTED
;
4009 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4010 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4011 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4012 uint32_t num_labels
, int soft_reconfig
,
4013 struct bgp_route_evpn
*evpn
)
4016 int aspath_loop_count
= 0;
4017 struct bgp_dest
*dest
;
4019 struct attr new_attr
;
4020 struct attr
*attr_new
;
4021 struct bgp_path_info
*pi
;
4022 struct bgp_path_info
*new;
4023 struct bgp_path_info_extra
*extra
;
4025 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4027 int do_loop_check
= 1;
4028 int has_valid_label
= 0;
4030 bool force_evpn_import
= false;
4031 safi_t orig_safi
= safi
;
4032 bool leak_success
= true;
4035 if (frrtrace_enabled(frr_bgp
, process_update
)) {
4036 char pfxprint
[PREFIX2STR_BUFFER
];
4038 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
4039 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
4043 #ifdef ENABLE_BGP_VNC
4044 int vnc_implicit_withdraw
= 0;
4048 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4049 if (orig_safi
== SAFI_LABELED_UNICAST
)
4050 safi
= SAFI_UNICAST
;
4052 memset(&new_attr
, 0, sizeof(new_attr
));
4053 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4054 new_attr
.label
= MPLS_INVALID_LABEL
;
4057 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4058 /* TODO: Check to see if we can get rid of "is_valid_label" */
4059 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4060 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4062 has_valid_label
= bgp_is_valid_label(label
);
4064 if (has_valid_label
)
4065 assert(label
!= NULL
);
4067 /* Update overlay index of the attribute */
4068 if (afi
== AFI_L2VPN
&& evpn
)
4069 memcpy(&attr
->evpn_overlay
, evpn
,
4070 sizeof(struct bgp_route_evpn
));
4072 /* When peer's soft reconfiguration enabled. Record input packet in
4075 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4076 && peer
!= bgp
->peer_self
)
4077 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4079 /* Update permitted loop count */
4080 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4081 allowas_in
= peer
->allowas_in
[afi
][safi
];
4083 /* Check previously received route. */
4084 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4085 if (pi
->peer
== peer
&& pi
->type
== type
4086 && pi
->sub_type
== sub_type
4087 && pi
->addpath_rx_id
== addpath_id
)
4090 /* AS path local-as loop check. */
4091 if (peer
->change_local_as
) {
4093 aspath_loop_count
= allowas_in
;
4094 else if (!CHECK_FLAG(peer
->flags
,
4095 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4096 aspath_loop_count
= 1;
4098 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4099 > aspath_loop_count
) {
4100 peer
->stat_pfx_aspath_loop
++;
4101 reason
= "as-path contains our own AS;";
4106 /* If the peer is configured for "allowas-in origin" and the last ASN in
4108 * as-path is our ASN then we do not need to call aspath_loop_check
4110 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4111 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4114 /* AS path loop check. */
4115 if (do_loop_check
) {
4116 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4117 peer
->allowas_in
[afi
][safi
]) {
4118 peer
->stat_pfx_aspath_loop
++;
4119 reason
= "as-path contains our own AS;";
4124 /* If we're a CONFED we need to loop check the CONFED ID too */
4125 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4126 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4127 peer
->allowas_in
[afi
][safi
]) {
4128 peer
->stat_pfx_aspath_loop
++;
4129 reason
= "as-path contains our own confed AS;";
4133 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4134 * enabled, then take care of that too.
4136 bool accept_own
= false;
4138 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4139 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4141 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4143 peer
->stat_pfx_originator_loop
++;
4144 reason
= "originator is us;";
4149 /* Route reflector cluster ID check. */
4150 if (bgp_cluster_filter(peer
, attr
)) {
4151 peer
->stat_pfx_cluster_loop
++;
4152 reason
= "reflected from the same cluster;";
4156 /* Apply incoming filter. */
4157 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4158 peer
->stat_pfx_filter
++;
4163 /* RFC 8212 to prevent route leaks.
4164 * This specification intends to improve this situation by requiring the
4165 * explicit configuration of both BGP Import and Export Policies for any
4166 * External BGP (EBGP) session such as customers, peers, or
4167 * confederation boundaries for all enabled address families. Through
4168 * codification of the aforementioned requirement, operators will
4169 * benefit from consistent behavior across different BGP
4172 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4173 if (!bgp_inbound_policy_exists(peer
,
4174 &peer
->filter
[afi
][safi
])) {
4175 reason
= "inbound policy missing";
4176 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4177 NULL
) > FIFTEENMINUTE2USEC
||
4178 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4180 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4181 monotime(&bgp
->ebgprequirespolicywarning
);
4186 /* draft-ietf-idr-deprecate-as-set-confed-set
4187 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4188 * Eventually, This document (if approved) updates RFC 4271
4189 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4190 * and obsoletes RFC 6472.
4192 if (peer
->bgp
->reject_as_sets
)
4193 if (aspath_check_as_sets(attr
->aspath
)) {
4195 "as-path contains AS_SET or AS_CONFED_SET type;";
4201 /* Apply incoming route-map.
4202 * NB: new_attr may now contain newly allocated values from route-map
4204 * commands, so we need bgp_attr_flush in the error paths, until we
4206 * the attr (which takes over the memory references) */
4207 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4210 peer
->stat_pfx_filter
++;
4211 reason
= "route-map;";
4212 bgp_attr_flush(&new_attr
);
4216 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4217 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4218 /* remove from RIB previous entry */
4219 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4222 if (peer
->sort
== BGP_PEER_EBGP
) {
4225 * A BGP speaker receiving an announcement tagged with the
4226 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4227 * NO_EXPORT community as defined in RFC1997, or a
4228 * similar community, to prevent propagation of the
4229 * prefix outside the local AS. The community to prevent
4230 * propagation SHOULD be chosen according to the operator's
4233 if (bgp_attr_get_community(&new_attr
) &&
4234 community_include(bgp_attr_get_community(&new_attr
),
4235 COMMUNITY_BLACKHOLE
))
4236 bgp_attr_add_no_export_community(&new_attr
);
4238 /* If we receive the graceful-shutdown community from an eBGP
4239 * peer we must lower local-preference */
4240 if (bgp_attr_get_community(&new_attr
) &&
4241 community_include(bgp_attr_get_community(&new_attr
),
4243 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4244 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4246 /* If graceful-shutdown is configured then add the GSHUT
4247 * community to all paths received from eBGP peers */
4248 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
4249 bgp_attr_add_gshut_community(&new_attr
);
4252 /* next hop check. */
4253 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4254 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4256 peer
->stat_pfx_nh_invalid
++;
4257 reason
= "martian or self next-hop;";
4258 bgp_attr_flush(&new_attr
);
4262 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4263 peer
->stat_pfx_nh_invalid
++;
4264 reason
= "self mac;";
4265 bgp_attr_flush(&new_attr
);
4269 if (bgp_check_role_applicability(afi
, safi
) &&
4270 bgp_otc_filter(peer
, &new_attr
)) {
4271 reason
= "failing otc validation";
4272 bgp_attr_flush(&new_attr
);
4275 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4277 * Suppress fib is enabled
4278 * BGP_OPT_NO_FIB is not enabled
4279 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4280 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4282 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
4283 && (sub_type
== BGP_ROUTE_NORMAL
)
4284 && (!bgp_option_check(BGP_OPT_NO_FIB
))
4285 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
4286 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
4288 /* If maximum prefix count is configured and current prefix
4291 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4292 bgp_attr_flush(&new_attr
);
4296 /* If neighbor soo is configured, tag all incoming routes with
4297 * this SoO tag and then filter out advertisements in
4298 * subgroup_announce_check() if it matches the configured SoO
4299 * on the other peer.
4301 if (peer
->soo
[afi
][safi
]) {
4302 struct ecommunity
*old_ecomm
=
4303 bgp_attr_get_ecommunity(&new_attr
);
4304 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4305 struct ecommunity
*new_ecomm
;
4308 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4311 if (!old_ecomm
->refcnt
)
4312 ecommunity_free(&old_ecomm
);
4314 new_ecomm
= ecommunity_dup(ecomm_soo
);
4317 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4320 attr_new
= bgp_attr_intern(&new_attr
);
4322 /* If the update is implicit withdraw. */
4324 pi
->uptime
= monotime(NULL
);
4325 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4327 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4329 /* Same attribute comes in. */
4330 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4332 && (!has_valid_label
4333 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4334 num_labels
* sizeof(mpls_label_t
))
4336 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4337 BGP_CONFIG_DAMPENING
)
4338 && peer
->sort
== BGP_PEER_EBGP
4339 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4340 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4341 bgp_debug_rdpfxpath2str(
4342 afi
, safi
, prd
, p
, label
,
4343 num_labels
, addpath_id
? 1 : 0,
4344 addpath_id
, evpn
, pfx_buf
,
4346 zlog_debug("%pBP rcvd %s", peer
,
4350 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4351 != BGP_DAMP_SUPPRESSED
) {
4352 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4354 bgp_process(bgp
, dest
, afi
, safi
);
4356 } else /* Duplicate - odd */
4358 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4359 if (!peer
->rcvd_attr_printed
) {
4361 "%pBP rcvd UPDATE w/ attr: %s",
4363 peer
->rcvd_attr_str
);
4364 peer
->rcvd_attr_printed
= 1;
4367 bgp_debug_rdpfxpath2str(
4368 afi
, safi
, prd
, p
, label
,
4369 num_labels
, addpath_id
? 1 : 0,
4370 addpath_id
, evpn
, pfx_buf
,
4373 "%pBP rcvd %s...duplicate ignored",
4377 /* graceful restart STALE flag unset. */
4378 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4379 bgp_path_info_unset_flag(
4380 dest
, pi
, BGP_PATH_STALE
);
4381 bgp_dest_set_defer_flag(dest
, false);
4382 bgp_process(bgp
, dest
, afi
, safi
);
4386 bgp_dest_unlock_node(dest
);
4387 bgp_attr_unintern(&attr_new
);
4392 /* Withdraw/Announce before we fully processed the withdraw */
4393 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4394 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4395 bgp_debug_rdpfxpath2str(
4396 afi
, safi
, prd
, p
, label
, num_labels
,
4397 addpath_id
? 1 : 0, addpath_id
, evpn
,
4398 pfx_buf
, sizeof(pfx_buf
));
4400 "%pBP rcvd %s, flapped quicker than processing",
4404 bgp_path_info_restore(dest
, pi
);
4407 * If the BGP_PATH_REMOVED flag is set, then EVPN
4408 * routes would have been unimported already when a
4409 * prior BGP withdraw processing happened. Such routes
4410 * need to be imported again, so flag accordingly.
4412 force_evpn_import
= true;
4415 /* Received Logging. */
4416 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4417 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4418 num_labels
, addpath_id
? 1 : 0,
4419 addpath_id
, evpn
, pfx_buf
,
4421 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4424 /* graceful restart STALE flag unset. */
4425 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4426 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4427 bgp_dest_set_defer_flag(dest
, false);
4430 /* The attribute is changed. */
4431 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4433 /* implicit withdraw, decrement aggregate and pcount here.
4434 * only if update is accepted, they'll increment below.
4436 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4438 /* Update bgp route dampening information. */
4439 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4440 && peer
->sort
== BGP_PEER_EBGP
) {
4441 /* This is implicit withdraw so we should update
4444 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4445 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4447 #ifdef ENABLE_BGP_VNC
4448 if (safi
== SAFI_MPLS_VPN
) {
4449 struct bgp_dest
*pdest
= NULL
;
4450 struct bgp_table
*table
= NULL
;
4452 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4453 (struct prefix
*)prd
);
4454 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4455 table
= bgp_dest_get_bgp_table_info(pdest
);
4457 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4458 bgp
, prd
, table
, p
, pi
);
4460 bgp_dest_unlock_node(pdest
);
4462 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4463 && (safi
== SAFI_UNICAST
)) {
4464 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4466 * Implicit withdraw case.
4468 ++vnc_implicit_withdraw
;
4469 vnc_import_bgp_del_route(bgp
, p
, pi
);
4470 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4475 /* Special handling for EVPN update of an existing route. If the
4476 * extended community attribute has changed, we need to
4478 * the route using its existing extended community. It will be
4479 * subsequently processed for import with the new extended
4482 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4485 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4487 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4490 cmp
= ecommunity_cmp(
4491 bgp_attr_get_ecommunity(pi
->attr
),
4492 bgp_attr_get_ecommunity(attr_new
));
4494 if (bgp_debug_update(peer
, p
, NULL
, 1))
4496 "Change in EXT-COMM, existing %s new %s",
4498 bgp_attr_get_ecommunity(
4501 bgp_attr_get_ecommunity(
4503 if (safi
== SAFI_EVPN
)
4504 bgp_evpn_unimport_route(
4505 bgp
, afi
, safi
, p
, pi
);
4506 else /* SAFI_MPLS_VPN */
4507 vpn_leak_to_vrf_withdraw(bgp
,
4513 /* Update to new attribute. */
4514 bgp_attr_unintern(&pi
->attr
);
4515 pi
->attr
= attr_new
;
4517 /* Update MPLS label */
4518 if (has_valid_label
) {
4519 extra
= bgp_path_info_extra_get(pi
);
4520 if (extra
->label
!= label
) {
4521 memcpy(&extra
->label
, label
,
4522 num_labels
* sizeof(mpls_label_t
));
4523 extra
->num_labels
= num_labels
;
4525 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4526 bgp_set_valid_label(&extra
->label
[0]);
4529 /* Update SRv6 SID */
4530 if (attr
->srv6_l3vpn
) {
4531 extra
= bgp_path_info_extra_get(pi
);
4532 if (sid_diff(&extra
->sid
[0].sid
,
4533 &attr
->srv6_l3vpn
->sid
)) {
4534 sid_copy(&extra
->sid
[0].sid
,
4535 &attr
->srv6_l3vpn
->sid
);
4536 extra
->num_sids
= 1;
4538 extra
->sid
[0].loc_block_len
= 0;
4539 extra
->sid
[0].loc_node_len
= 0;
4540 extra
->sid
[0].func_len
= 0;
4541 extra
->sid
[0].arg_len
= 0;
4542 extra
->sid
[0].transposition_len
= 0;
4543 extra
->sid
[0].transposition_offset
= 0;
4545 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4546 extra
->sid
[0].loc_block_len
=
4547 attr
->srv6_l3vpn
->loc_block_len
;
4548 extra
->sid
[0].loc_node_len
=
4549 attr
->srv6_l3vpn
->loc_node_len
;
4550 extra
->sid
[0].func_len
=
4551 attr
->srv6_l3vpn
->func_len
;
4552 extra
->sid
[0].arg_len
=
4553 attr
->srv6_l3vpn
->arg_len
;
4554 extra
->sid
[0].transposition_len
=
4556 ->transposition_len
;
4557 extra
->sid
[0].transposition_offset
=
4559 ->transposition_offset
;
4562 } else if (attr
->srv6_vpn
) {
4563 extra
= bgp_path_info_extra_get(pi
);
4564 if (sid_diff(&extra
->sid
[0].sid
,
4565 &attr
->srv6_vpn
->sid
)) {
4566 sid_copy(&extra
->sid
[0].sid
,
4567 &attr
->srv6_vpn
->sid
);
4568 extra
->num_sids
= 1;
4572 #ifdef ENABLE_BGP_VNC
4573 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4574 && (safi
== SAFI_UNICAST
)) {
4575 if (vnc_implicit_withdraw
) {
4577 * Add back the route with its new attributes
4579 * The route is still selected, until the route
4581 * queued by bgp_process actually runs. We have
4583 * update to the VNC side immediately to avoid
4585 * configuration changes (e.g., route-map
4587 * trigger re-importation of the entire RIB.
4589 vnc_import_bgp_add_route(bgp
, p
, pi
);
4590 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4595 /* Update bgp route dampening information. */
4596 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4597 && peer
->sort
== BGP_PEER_EBGP
) {
4598 /* Now we do normal update dampening. */
4599 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4600 if (ret
== BGP_DAMP_SUPPRESSED
) {
4601 bgp_dest_unlock_node(dest
);
4606 /* Nexthop reachability check - for unicast and
4607 * labeled-unicast.. */
4608 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4609 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4610 || (safi
== SAFI_EVPN
&&
4611 bgp_evpn_is_prefix_nht_supported(p
))) {
4612 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4613 && peer
->ttl
== BGP_DEFAULT_TTL
4614 && !CHECK_FLAG(peer
->flags
,
4615 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4616 && !CHECK_FLAG(bgp
->flags
,
4617 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4622 struct bgp
*bgp_nexthop
= bgp
;
4624 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4625 bgp_nexthop
= pi
->extra
->bgp_orig
;
4627 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4629 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4630 safi
, pi
, NULL
, connected
,
4632 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4633 bgp_path_info_set_flag(dest
, pi
,
4636 if (BGP_DEBUG(nht
, NHT
)) {
4637 zlog_debug("%s(%pI4): NH unresolved",
4639 (in_addr_t
*)&attr_new
->nexthop
);
4641 bgp_path_info_unset_flag(dest
, pi
,
4646 bgp_path_info_set_flag(dest
, pi
,
4647 BGP_PATH_ACCEPT_OWN
);
4649 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4652 #ifdef ENABLE_BGP_VNC
4653 if (safi
== SAFI_MPLS_VPN
) {
4654 struct bgp_dest
*pdest
= NULL
;
4655 struct bgp_table
*table
= NULL
;
4657 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4658 (struct prefix
*)prd
);
4659 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4660 table
= bgp_dest_get_bgp_table_info(pdest
);
4662 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4663 bgp
, prd
, table
, p
, pi
);
4665 bgp_dest_unlock_node(pdest
);
4669 /* If this is an EVPN route and some attribute has changed,
4670 * or we are explicitly told to perform a route import, process
4671 * route for import. If the extended community has changed, we
4673 * have done the un-import earlier and the import would result
4675 * route getting injected into appropriate L2 VNIs. If it is
4677 * some other attribute change, the import will result in
4679 * the attributes for the route in the VNI(s).
4681 if (safi
== SAFI_EVPN
&&
4682 (!same_attr
|| force_evpn_import
) &&
4683 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4684 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4686 /* Process change. */
4687 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4689 bgp_process(bgp
, dest
, afi
, safi
);
4690 bgp_dest_unlock_node(dest
);
4692 if (SAFI_UNICAST
== safi
4693 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4694 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4696 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4698 if ((SAFI_MPLS_VPN
== safi
)
4699 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4700 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4703 #ifdef ENABLE_BGP_VNC
4704 if (SAFI_MPLS_VPN
== safi
) {
4705 mpls_label_t label_decoded
= decode_label(label
);
4707 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4708 type
, sub_type
, &label_decoded
);
4710 if (SAFI_ENCAP
== safi
) {
4711 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4712 type
, sub_type
, NULL
);
4715 if ((safi
== SAFI_MPLS_VPN
) &&
4716 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4717 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4719 bgp_unlink_nexthop(pi
);
4720 bgp_path_info_delete(dest
, pi
);
4723 } // End of implicit withdraw
4725 /* Received Logging. */
4726 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4727 if (!peer
->rcvd_attr_printed
) {
4728 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4729 peer
->rcvd_attr_str
);
4730 peer
->rcvd_attr_printed
= 1;
4733 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4734 addpath_id
? 1 : 0, addpath_id
, evpn
,
4735 pfx_buf
, sizeof(pfx_buf
));
4736 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4739 /* Make new BGP info. */
4740 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4742 /* Update MPLS label */
4743 if (has_valid_label
) {
4744 extra
= bgp_path_info_extra_get(new);
4745 if (extra
->label
!= label
) {
4746 memcpy(&extra
->label
, label
,
4747 num_labels
* sizeof(mpls_label_t
));
4748 extra
->num_labels
= num_labels
;
4750 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4751 bgp_set_valid_label(&extra
->label
[0]);
4754 /* Update SRv6 SID */
4755 if (safi
== SAFI_MPLS_VPN
) {
4756 extra
= bgp_path_info_extra_get(new);
4757 if (attr
->srv6_l3vpn
) {
4758 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4759 extra
->num_sids
= 1;
4761 extra
->sid
[0].loc_block_len
=
4762 attr
->srv6_l3vpn
->loc_block_len
;
4763 extra
->sid
[0].loc_node_len
=
4764 attr
->srv6_l3vpn
->loc_node_len
;
4765 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4766 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4767 extra
->sid
[0].transposition_len
=
4768 attr
->srv6_l3vpn
->transposition_len
;
4769 extra
->sid
[0].transposition_offset
=
4770 attr
->srv6_l3vpn
->transposition_offset
;
4771 } else if (attr
->srv6_vpn
) {
4772 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4773 extra
->num_sids
= 1;
4777 /* Nexthop reachability check. */
4778 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4779 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4780 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4781 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4782 && peer
->ttl
== BGP_DEFAULT_TTL
4783 && !CHECK_FLAG(peer
->flags
,
4784 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4785 && !CHECK_FLAG(bgp
->flags
,
4786 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4791 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4793 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4795 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4796 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4798 if (BGP_DEBUG(nht
, NHT
)) {
4799 char buf1
[INET6_ADDRSTRLEN
];
4801 (const void *)&attr_new
->nexthop
,
4802 buf1
, INET6_ADDRSTRLEN
);
4803 zlog_debug("%s(%s): NH unresolved", __func__
,
4806 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4810 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4812 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4816 new->addpath_rx_id
= addpath_id
;
4818 /* Increment prefix */
4819 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4821 /* Register new BGP information. */
4822 bgp_path_info_add(dest
, new);
4824 /* route_node_get lock */
4825 bgp_dest_unlock_node(dest
);
4827 #ifdef ENABLE_BGP_VNC
4828 if (safi
== SAFI_MPLS_VPN
) {
4829 struct bgp_dest
*pdest
= NULL
;
4830 struct bgp_table
*table
= NULL
;
4832 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4833 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4834 table
= bgp_dest_get_bgp_table_info(pdest
);
4836 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4837 bgp
, prd
, table
, p
, new);
4839 bgp_dest_unlock_node(pdest
);
4843 /* If this is an EVPN route, process for import. */
4844 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4845 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4847 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4849 /* Process change. */
4850 bgp_process(bgp
, dest
, afi
, safi
);
4852 if (SAFI_UNICAST
== safi
4853 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4854 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4855 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4857 if ((SAFI_MPLS_VPN
== safi
)
4858 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4859 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4861 #ifdef ENABLE_BGP_VNC
4862 if (SAFI_MPLS_VPN
== safi
) {
4863 mpls_label_t label_decoded
= decode_label(label
);
4865 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4866 sub_type
, &label_decoded
);
4868 if (SAFI_ENCAP
== safi
) {
4869 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4873 if ((safi
== SAFI_MPLS_VPN
) &&
4874 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4875 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4877 bgp_unlink_nexthop(new);
4878 bgp_path_info_delete(dest
, new);
4883 /* This BGP update is filtered. Log the reason then update BGP
4886 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4888 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4889 if (!peer
->rcvd_attr_printed
) {
4890 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4891 peer
->rcvd_attr_str
);
4892 peer
->rcvd_attr_printed
= 1;
4895 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4896 addpath_id
? 1 : 0, addpath_id
, evpn
,
4897 pfx_buf
, sizeof(pfx_buf
));
4898 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4899 peer
, pfx_buf
, reason
);
4903 /* If this is an EVPN route, un-import it as it is now filtered.
4905 if (safi
== SAFI_EVPN
)
4906 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4908 if (SAFI_UNICAST
== safi
4909 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4910 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4912 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4914 if ((SAFI_MPLS_VPN
== safi
)
4915 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4917 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4920 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4923 bgp_dest_unlock_node(dest
);
4925 #ifdef ENABLE_BGP_VNC
4927 * Filtered update is treated as an implicit withdrawal (see
4929 * a few lines above)
4931 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4932 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4940 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4941 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4942 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4943 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4946 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4947 struct bgp_dest
*dest
;
4948 struct bgp_path_info
*pi
;
4950 #ifdef ENABLE_BGP_VNC
4951 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4952 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4960 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4962 /* If peer is soft reconfiguration enabled. Record input packet for
4963 * further calculation.
4965 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4966 * routes that are filtered. This tanks out Quagga RS pretty badly due
4968 * the iteration over all RS clients.
4969 * Since we need to remove the entry from adj_in anyway, do that first
4971 * if there was no entry, we don't need to do anything more.
4973 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4974 && peer
!= bgp
->peer_self
)
4975 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4976 peer
->stat_pfx_dup_withdraw
++;
4978 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4979 bgp_debug_rdpfxpath2str(
4980 afi
, safi
, prd
, p
, label
, num_labels
,
4981 addpath_id
? 1 : 0, addpath_id
, NULL
,
4982 pfx_buf
, sizeof(pfx_buf
));
4984 "%s withdrawing route %s not in adj-in",
4985 peer
->host
, pfx_buf
);
4987 bgp_dest_unlock_node(dest
);
4991 /* Lookup withdrawn route. */
4992 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4993 if (pi
->peer
== peer
&& pi
->type
== type
4994 && pi
->sub_type
== sub_type
4995 && pi
->addpath_rx_id
== addpath_id
)
4999 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5000 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5001 addpath_id
? 1 : 0, addpath_id
, NULL
,
5002 pfx_buf
, sizeof(pfx_buf
));
5003 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
5007 /* Withdraw specified route from routing table. */
5008 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
5009 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
5010 if (SAFI_UNICAST
== safi
5011 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5012 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5013 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5015 if ((SAFI_MPLS_VPN
== safi
)
5016 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5018 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5020 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5021 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5022 addpath_id
? 1 : 0, addpath_id
, NULL
,
5023 pfx_buf
, sizeof(pfx_buf
));
5024 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
5027 /* Unlock bgp_node_get() lock. */
5028 bgp_dest_unlock_node(dest
);
5033 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
5036 struct update_subgroup
*subgrp
;
5037 subgrp
= peer_subgroup(peer
, afi
, safi
);
5038 subgroup_default_originate(subgrp
, withdraw
);
5043 * bgp_stop_announce_route_timer
5045 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5047 if (!paf
->t_announce_route
)
5050 THREAD_OFF(paf
->t_announce_route
);
5054 * bgp_announce_route_timer_expired
5056 * Callback that is invoked when the route announcement timer for a
5059 static void bgp_announce_route_timer_expired(struct thread
*t
)
5061 struct peer_af
*paf
;
5064 paf
= THREAD_ARG(t
);
5067 if (!peer_established(peer
))
5070 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5073 peer_af_announce_route(paf
, 1);
5075 /* Notify BGP conditional advertisement scanner percess */
5076 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5080 * bgp_announce_route
5082 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5084 * if force is true we will force an update even if the update
5085 * limiting code is attempted to kick in.
5087 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5089 struct peer_af
*paf
;
5090 struct update_subgroup
*subgrp
;
5092 paf
= peer_af_find(peer
, afi
, safi
);
5095 subgrp
= PAF_SUBGRP(paf
);
5098 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5099 * or a refresh has already been triggered.
5101 if (!subgrp
|| paf
->t_announce_route
)
5105 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5108 * Start a timer to stagger/delay the announce. This serves
5109 * two purposes - announcement can potentially be combined for
5110 * multiple peers and the announcement doesn't happen in the
5113 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5114 (subgrp
->peer_count
== 1)
5115 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5116 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5117 &paf
->t_announce_route
);
5121 * Announce routes from all AF tables to a peer.
5123 * This should ONLY be called when there is a need to refresh the
5124 * routes to the peer based on a policy change for this peer alone
5125 * or a route refresh request received from the peer.
5126 * The operation will result in splitting the peer from its existing
5127 * subgroups and putting it in new subgroups.
5129 void bgp_announce_route_all(struct peer
*peer
)
5134 FOREACH_AFI_SAFI (afi
, safi
)
5135 bgp_announce_route(peer
, afi
, safi
, false);
5138 /* Flag or unflag bgp_dest to determine whether it should be treated by
5139 * bgp_soft_reconfig_table_task.
5140 * Flag if flag is true. Unflag if flag is false.
5142 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5144 struct bgp_dest
*dest
;
5145 struct bgp_adj_in
*ain
;
5150 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5151 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5152 if (ain
->peer
!= NULL
)
5155 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5156 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5158 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5162 static int bgp_soft_reconfig_table_update(struct peer
*peer
,
5163 struct bgp_dest
*dest
,
5164 struct bgp_adj_in
*ain
, afi_t afi
,
5165 safi_t safi
, struct prefix_rd
*prd
)
5167 struct bgp_path_info
*pi
;
5168 uint32_t num_labels
= 0;
5169 mpls_label_t
*label_pnt
= NULL
;
5170 struct bgp_route_evpn evpn
;
5172 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5173 if (pi
->peer
== peer
)
5176 if (pi
&& pi
->extra
)
5177 num_labels
= pi
->extra
->num_labels
;
5179 label_pnt
= &pi
->extra
->label
[0];
5181 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5184 memset(&evpn
, 0, sizeof(evpn
));
5186 return bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5187 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
5188 BGP_ROUTE_NORMAL
, prd
, label_pnt
, num_labels
, 1,
5192 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5193 struct bgp_table
*table
,
5194 struct prefix_rd
*prd
)
5197 struct bgp_dest
*dest
;
5198 struct bgp_adj_in
*ain
;
5201 table
= peer
->bgp
->rib
[afi
][safi
];
5203 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5204 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5205 if (ain
->peer
!= peer
)
5208 ret
= bgp_soft_reconfig_table_update(peer
, dest
, ain
,
5212 bgp_dest_unlock_node(dest
);
5218 /* Do soft reconfig table per bgp table.
5219 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5220 * when BGP_NODE_SOFT_RECONFIG is set,
5221 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5222 * Schedule a new thread to continue the job.
5223 * Without splitting the full job into several part,
5224 * vtysh waits for the job to finish before responding to a BGP command
5226 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
5228 uint32_t iter
, max_iter
;
5230 struct bgp_dest
*dest
;
5231 struct bgp_adj_in
*ain
;
5233 struct bgp_table
*table
;
5234 struct prefix_rd
*prd
;
5235 struct listnode
*node
, *nnode
;
5237 table
= THREAD_ARG(thread
);
5240 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5241 if (table
->soft_reconfig_init
) {
5242 /* first call of the function with a new srta structure.
5243 * Don't do any treatment this time on nodes
5244 * in order vtysh to respond quickly
5249 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5250 dest
= bgp_route_next(dest
)) {
5251 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5254 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5256 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5257 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5259 if (ain
->peer
!= peer
)
5262 ret
= bgp_soft_reconfig_table_update(
5263 peer
, dest
, ain
, table
->afi
,
5268 bgp_dest_unlock_node(dest
);
5270 table
->soft_reconfig_peers
,
5272 bgp_announce_route(peer
, table
->afi
,
5273 table
->safi
, false);
5275 table
->soft_reconfig_peers
)) {
5277 &table
->soft_reconfig_peers
);
5278 bgp_soft_reconfig_table_flag(
5287 /* we're either starting the initial iteration,
5288 * or we're going to continue an ongoing iteration
5290 if (dest
|| table
->soft_reconfig_init
) {
5291 table
->soft_reconfig_init
= false;
5292 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
5293 table
, 0, &table
->soft_reconfig_thread
);
5296 /* we're done, clean up the background iteration context info and
5297 schedule route annoucement
5299 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5300 listnode_delete(table
->soft_reconfig_peers
, peer
);
5301 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5304 list_delete(&table
->soft_reconfig_peers
);
5308 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5310 * - bgp cannot be NULL
5311 * - if table and peer are NULL, cancel all threads within the bgp instance
5312 * - if table is NULL and peer is not,
5313 * remove peer in all threads within the bgp instance
5314 * - if peer is NULL, cancel all threads matching table within the bgp instance
5316 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5317 const struct bgp_table
*table
,
5318 const struct peer
*peer
)
5321 struct listnode
*node
, *nnode
;
5323 struct bgp_table
*ntable
;
5328 FOREACH_AFI_SAFI (afi
, safi
) {
5329 ntable
= bgp
->rib
[afi
][safi
];
5332 if (table
&& table
!= ntable
)
5335 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5337 if (peer
&& peer
!= npeer
)
5339 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5342 if (!ntable
->soft_reconfig_peers
5343 || !list_isempty(ntable
->soft_reconfig_peers
))
5346 list_delete(&ntable
->soft_reconfig_peers
);
5347 bgp_soft_reconfig_table_flag(ntable
, false);
5348 THREAD_OFF(ntable
->soft_reconfig_thread
);
5353 * Returns false if the peer is not configured for soft reconfig in
5355 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5357 struct bgp_dest
*dest
;
5358 struct bgp_table
*table
;
5359 struct listnode
*node
, *nnode
;
5361 struct peer_af
*paf
;
5363 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5366 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5367 && (safi
!= SAFI_EVPN
)) {
5368 table
= peer
->bgp
->rib
[afi
][safi
];
5372 table
->soft_reconfig_init
= true;
5374 if (!table
->soft_reconfig_peers
)
5375 table
->soft_reconfig_peers
= list_new();
5377 /* add peer to the table soft_reconfig_peers if not already
5380 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5386 listnode_add(table
->soft_reconfig_peers
, peer
);
5388 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5389 * on table would start back at the beginning.
5391 bgp_soft_reconfig_table_flag(table
, true);
5393 if (!table
->soft_reconfig_thread
)
5394 thread_add_event(bm
->master
,
5395 bgp_soft_reconfig_table_task
, table
, 0,
5396 &table
->soft_reconfig_thread
);
5397 /* Cancel bgp_announce_route_timer_expired threads.
5398 * bgp_announce_route_timer_expired threads have been scheduled
5399 * to announce routes as soon as the soft_reconfigure process
5401 * In this case, soft_reconfigure is also scheduled by using
5402 * a thread but is planned after the
5403 * bgp_announce_route_timer_expired threads. It means that,
5404 * without cancelling the threads, the route announcement task
5405 * would run before the soft reconfiguration one. That would
5406 * useless and would block vtysh during several seconds. Route
5407 * announcements are rescheduled as soon as the soft_reconfigure
5410 paf
= peer_af_find(peer
, afi
, safi
);
5412 bgp_stop_announce_route_timer(paf
);
5414 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5415 dest
= bgp_route_next(dest
)) {
5416 table
= bgp_dest_get_bgp_table_info(dest
);
5421 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5422 struct prefix_rd prd
;
5424 prd
.family
= AF_UNSPEC
;
5426 memcpy(&prd
.val
, p
->u
.val
, 8);
5428 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5435 struct bgp_clear_node_queue
{
5436 struct bgp_dest
*dest
;
5439 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5441 struct bgp_clear_node_queue
*cnq
= data
;
5442 struct bgp_dest
*dest
= cnq
->dest
;
5443 struct peer
*peer
= wq
->spec
.data
;
5444 struct bgp_path_info
*pi
;
5446 afi_t afi
= bgp_dest_table(dest
)->afi
;
5447 safi_t safi
= bgp_dest_table(dest
)->safi
;
5449 assert(dest
&& peer
);
5452 /* It is possible that we have multiple paths for a prefix from a peer
5453 * if that peer is using AddPath.
5455 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5456 if (pi
->peer
!= peer
)
5459 /* graceful restart STALE flag set. */
5460 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5461 && peer
->nsf
[afi
][safi
])
5462 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5463 PEER_STATUS_ENHANCED_REFRESH
))
5464 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5465 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5466 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5468 /* If this is an EVPN route, process for
5470 if (safi
== SAFI_EVPN
)
5471 bgp_evpn_unimport_route(
5473 bgp_dest_get_prefix(dest
), pi
);
5474 /* Handle withdraw for VRF route-leaking and L3VPN */
5475 if (SAFI_UNICAST
== safi
5476 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5477 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5478 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5481 if (SAFI_MPLS_VPN
== safi
&&
5482 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5483 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5486 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5492 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5494 struct bgp_clear_node_queue
*cnq
= data
;
5495 struct bgp_dest
*dest
= cnq
->dest
;
5496 struct bgp_table
*table
= bgp_dest_table(dest
);
5498 bgp_dest_unlock_node(dest
);
5499 bgp_table_unlock(table
);
5500 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5503 static void bgp_clear_node_complete(struct work_queue
*wq
)
5505 struct peer
*peer
= wq
->spec
.data
;
5507 /* Tickle FSM to start moving again */
5508 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5510 peer_unlock(peer
); /* bgp_clear_route */
5513 static void bgp_clear_node_queue_init(struct peer
*peer
)
5515 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5517 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5518 #undef CLEAR_QUEUE_NAME_LEN
5520 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5521 peer
->clear_node_queue
->spec
.hold
= 10;
5522 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5523 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5524 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5525 peer
->clear_node_queue
->spec
.max_retries
= 0;
5527 /* we only 'lock' this peer reference when the queue is actually active
5529 peer
->clear_node_queue
->spec
.data
= peer
;
5532 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5533 struct bgp_table
*table
)
5535 struct bgp_dest
*dest
;
5536 int force
= peer
->bgp
->process_queue
? 0 : 1;
5539 table
= peer
->bgp
->rib
[afi
][safi
];
5541 /* If still no table => afi/safi isn't configured at all or smth. */
5545 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5546 struct bgp_path_info
*pi
, *next
;
5547 struct bgp_adj_in
*ain
;
5548 struct bgp_adj_in
*ain_next
;
5550 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5551 * queued for every clearing peer, regardless of whether it is
5552 * relevant to the peer at hand.
5554 * Overview: There are 3 different indices which need to be
5555 * scrubbed, potentially, when a peer is removed:
5557 * 1 peer's routes visible via the RIB (ie accepted routes)
5558 * 2 peer's routes visible by the (optional) peer's adj-in index
5559 * 3 other routes visible by the peer's adj-out index
5561 * 3 there is no hurry in scrubbing, once the struct peer is
5562 * removed from bgp->peer, we could just GC such deleted peer's
5563 * adj-outs at our leisure.
5565 * 1 and 2 must be 'scrubbed' in some way, at least made
5566 * invisible via RIB index before peer session is allowed to be
5567 * brought back up. So one needs to know when such a 'search' is
5572 * - there'd be a single global queue or a single RIB walker
5573 * - rather than tracking which route_nodes still need to be
5574 * examined on a peer basis, we'd track which peers still
5577 * Given that our per-peer prefix-counts now should be reliable,
5578 * this may actually be achievable. It doesn't seem to be a huge
5579 * problem at this time,
5581 * It is possible that we have multiple paths for a prefix from
5583 * if that peer is using AddPath.
5587 ain_next
= ain
->next
;
5589 if (ain
->peer
== peer
)
5590 bgp_adj_in_remove(dest
, ain
);
5595 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5597 if (pi
->peer
!= peer
)
5601 bgp_path_info_reap(dest
, pi
);
5603 struct bgp_clear_node_queue
*cnq
;
5605 /* both unlocked in bgp_clear_node_queue_del */
5606 bgp_table_lock(bgp_dest_table(dest
));
5607 bgp_dest_lock_node(dest
);
5609 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5610 sizeof(struct bgp_clear_node_queue
));
5612 work_queue_add(peer
->clear_node_queue
, cnq
);
5620 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5622 struct bgp_dest
*dest
;
5623 struct bgp_table
*table
;
5625 if (peer
->clear_node_queue
== NULL
)
5626 bgp_clear_node_queue_init(peer
);
5628 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5629 * Idle until it receives a Clearing_Completed event. This protects
5630 * against peers which flap faster than we can we clear, which could
5633 * a) race with routes from the new session being installed before
5634 * clear_route_node visits the node (to delete the route of that
5636 * b) resource exhaustion, clear_route_node likely leads to an entry
5637 * on the process_main queue. Fast-flapping could cause that queue
5641 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5642 * the unlock will happen upon work-queue completion; other wise, the
5643 * unlock happens at the end of this function.
5645 if (!peer
->clear_node_queue
->thread
)
5648 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5649 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5651 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5652 dest
= bgp_route_next(dest
)) {
5653 table
= bgp_dest_get_bgp_table_info(dest
);
5657 bgp_clear_route_table(peer
, afi
, safi
, table
);
5660 /* unlock if no nodes got added to the clear-node-queue. */
5661 if (!peer
->clear_node_queue
->thread
)
5665 void bgp_clear_route_all(struct peer
*peer
)
5670 FOREACH_AFI_SAFI (afi
, safi
)
5671 bgp_clear_route(peer
, afi
, safi
);
5673 #ifdef ENABLE_BGP_VNC
5674 rfapiProcessPeerDown(peer
);
5678 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5680 struct bgp_table
*table
;
5681 struct bgp_dest
*dest
;
5682 struct bgp_adj_in
*ain
;
5683 struct bgp_adj_in
*ain_next
;
5685 table
= peer
->bgp
->rib
[afi
][safi
];
5687 /* It is possible that we have multiple paths for a prefix from a peer
5688 * if that peer is using AddPath.
5690 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5694 ain_next
= ain
->next
;
5696 if (ain
->peer
== peer
)
5697 bgp_adj_in_remove(dest
, ain
);
5704 /* If any of the routes from the peer have been marked with the NO_LLGR
5705 * community, either as sent by the peer, or as the result of a configured
5706 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5707 * operation of [RFC4271].
5709 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5711 struct bgp_dest
*dest
;
5712 struct bgp_path_info
*pi
;
5713 struct bgp_table
*table
;
5715 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5716 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5717 dest
= bgp_route_next(dest
)) {
5718 struct bgp_dest
*rm
;
5720 /* look for neighbor in tables */
5721 table
= bgp_dest_get_bgp_table_info(dest
);
5725 for (rm
= bgp_table_top(table
); rm
;
5726 rm
= bgp_route_next(rm
))
5727 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5729 if (pi
->peer
!= peer
)
5732 peer
->af_sflags
[afi
][safi
],
5733 PEER_STATUS_LLGR_WAIT
) &&
5734 bgp_attr_get_community(pi
->attr
) &&
5736 bgp_attr_get_community(
5740 if (!CHECK_FLAG(pi
->flags
,
5745 * If this is VRF leaked route
5746 * process for withdraw.
5749 BGP_ROUTE_IMPORTED
&&
5750 peer
->bgp
->inst_type
==
5751 BGP_INSTANCE_TYPE_DEFAULT
)
5752 vpn_leak_to_vrf_withdraw(
5755 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5760 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5761 dest
= bgp_route_next(dest
))
5762 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5764 if (pi
->peer
!= peer
)
5766 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5767 PEER_STATUS_LLGR_WAIT
) &&
5768 bgp_attr_get_community(pi
->attr
) &&
5770 bgp_attr_get_community(pi
->attr
),
5773 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5775 if (safi
== SAFI_UNICAST
&&
5776 (peer
->bgp
->inst_type
==
5777 BGP_INSTANCE_TYPE_VRF
||
5778 peer
->bgp
->inst_type
==
5779 BGP_INSTANCE_TYPE_DEFAULT
))
5780 vpn_leak_from_vrf_withdraw(
5781 bgp_get_default(), peer
->bgp
,
5784 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5790 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5792 struct bgp_dest
*dest
, *ndest
;
5793 struct bgp_path_info
*pi
;
5794 struct bgp_table
*table
;
5796 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5797 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5798 dest
= bgp_route_next(dest
)) {
5799 table
= bgp_dest_get_bgp_table_info(dest
);
5803 for (ndest
= bgp_table_top(table
); ndest
;
5804 ndest
= bgp_route_next(ndest
)) {
5805 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5807 if (pi
->peer
!= peer
)
5811 peer
->af_sflags
[afi
][safi
],
5812 PEER_STATUS_ENHANCED_REFRESH
))
5813 && !CHECK_FLAG(pi
->flags
,
5817 BGP_PATH_UNUSEABLE
)) {
5818 if (bgp_debug_neighbor_events(
5821 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5825 bgp_dest_get_prefix(
5828 bgp_path_info_set_flag(
5836 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5837 dest
= bgp_route_next(dest
)) {
5838 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5840 if (pi
->peer
!= peer
)
5843 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5844 PEER_STATUS_ENHANCED_REFRESH
))
5845 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5846 && !CHECK_FLAG(pi
->flags
,
5847 BGP_PATH_UNUSEABLE
)) {
5848 if (bgp_debug_neighbor_events(peer
))
5850 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5853 bgp_dest_get_prefix(
5856 bgp_path_info_set_flag(dest
, pi
,
5864 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5866 if (peer
->sort
== BGP_PEER_IBGP
)
5869 if (peer
->sort
== BGP_PEER_EBGP
5870 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5871 || FILTER_LIST_OUT_NAME(filter
)
5872 || DISTRIBUTE_OUT_NAME(filter
)))
5877 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5879 if (peer
->sort
== BGP_PEER_IBGP
)
5882 if (peer
->sort
== BGP_PEER_EBGP
5883 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5884 || FILTER_LIST_IN_NAME(filter
)
5885 || DISTRIBUTE_IN_NAME(filter
)))
5890 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5893 struct bgp_dest
*dest
;
5894 struct bgp_path_info
*pi
;
5895 struct bgp_path_info
*next
;
5897 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5898 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5899 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5903 /* Unimport EVPN routes from VRFs */
5904 if (safi
== SAFI_EVPN
)
5905 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5908 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5909 && pi
->type
== ZEBRA_ROUTE_BGP
5910 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5911 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5912 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5914 if (bgp_fibupd_safi(safi
))
5915 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5918 bgp_path_info_reap(dest
, pi
);
5922 /* Delete all kernel routes. */
5923 void bgp_cleanup_routes(struct bgp
*bgp
)
5926 struct bgp_dest
*dest
;
5927 struct bgp_table
*table
;
5929 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5930 if (afi
== AFI_L2VPN
)
5932 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5935 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5937 if (afi
!= AFI_L2VPN
) {
5939 safi
= SAFI_MPLS_VPN
;
5940 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5941 dest
= bgp_route_next(dest
)) {
5942 table
= bgp_dest_get_bgp_table_info(dest
);
5943 if (table
!= NULL
) {
5944 bgp_cleanup_table(bgp
, table
, safi
);
5945 bgp_table_finish(&table
);
5946 bgp_dest_set_bgp_table_info(dest
, NULL
);
5947 bgp_dest_unlock_node(dest
);
5951 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5952 dest
= bgp_route_next(dest
)) {
5953 table
= bgp_dest_get_bgp_table_info(dest
);
5954 if (table
!= NULL
) {
5955 bgp_cleanup_table(bgp
, table
, safi
);
5956 bgp_table_finish(&table
);
5957 bgp_dest_set_bgp_table_info(dest
, NULL
);
5958 bgp_dest_unlock_node(dest
);
5963 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5964 dest
= bgp_route_next(dest
)) {
5965 table
= bgp_dest_get_bgp_table_info(dest
);
5966 if (table
!= NULL
) {
5967 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5968 bgp_table_finish(&table
);
5969 bgp_dest_set_bgp_table_info(dest
, NULL
);
5970 bgp_dest_unlock_node(dest
);
5975 void bgp_reset(void)
5978 bgp_zclient_reset();
5979 access_list_reset();
5980 prefix_list_reset();
5983 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5985 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5986 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5987 PEER_CAP_ADDPATH_AF_TX_RCV
));
5990 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5992 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5993 struct bgp_nlri
*packet
)
6002 bool addpath_capable
;
6003 uint32_t addpath_id
;
6006 lim
= pnt
+ packet
->length
;
6008 safi
= packet
->safi
;
6010 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
6012 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6013 syntactic validity. If the field is syntactically incorrect,
6014 then the Error Subcode is set to Invalid Network Field. */
6015 for (; pnt
< lim
; pnt
+= psize
) {
6016 /* Clear prefix structure. */
6017 memset(&p
, 0, sizeof(p
));
6019 if (addpath_capable
) {
6021 /* When packet overflow occurs return immediately. */
6022 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
6023 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6025 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
6026 addpath_id
= ntohl(addpath_id
);
6027 pnt
+= BGP_ADDPATH_ID_LEN
;
6030 /* Fetch prefix length. */
6031 p
.prefixlen
= *pnt
++;
6032 /* afi/safi validity already verified by caller,
6033 * bgp_update_receive */
6034 p
.family
= afi2family(afi
);
6036 /* Prefix length check. */
6037 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
6040 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
6041 peer
->host
, p
.prefixlen
, packet
->afi
);
6042 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
6045 /* Packet size overflow check. */
6046 psize
= PSIZE(p
.prefixlen
);
6048 /* When packet overflow occur return immediately. */
6049 if (pnt
+ psize
> lim
) {
6052 "%s [Error] Update packet error (prefix length %d overflows packet)",
6053 peer
->host
, p
.prefixlen
);
6054 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6057 /* Defensive coding, double-check the psize fits in a struct
6058 * prefix for the v4 and v6 afi's and unicast/multicast */
6059 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6062 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6063 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6064 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6067 /* Fetch prefix from NLRI packet. */
6068 memcpy(p
.u
.val
, pnt
, psize
);
6070 /* Check address. */
6071 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6072 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6073 /* From RFC4271 Section 6.3:
6075 * If a prefix in the NLRI field is semantically
6077 * (e.g., an unexpected multicast IP address),
6079 * be logged locally, and the prefix SHOULD be
6084 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6085 peer
->host
, &p
.u
.prefix4
);
6090 /* Check address. */
6091 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6092 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6095 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6096 peer
->host
, &p
.u
.prefix6
);
6100 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6103 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6104 peer
->host
, &p
.u
.prefix6
);
6110 /* Normal process. */
6112 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6113 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
6114 NULL
, NULL
, 0, 0, NULL
);
6116 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
6117 safi
, ZEBRA_ROUTE_BGP
,
6118 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
6121 /* Do not send BGP notification twice when maximum-prefix count
6123 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6124 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6126 /* Address family configuration mismatch. */
6128 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
6131 /* Packet length consistency check. */
6135 "%s [Error] Update packet error (prefix length mismatch with total length)",
6137 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6140 return BGP_NLRI_PARSE_OK
;
6143 static struct bgp_static
*bgp_static_new(void)
6145 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6148 static void bgp_static_free(struct bgp_static
*bgp_static
)
6150 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6151 route_map_counter_decrement(bgp_static
->rmap
.map
);
6153 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6154 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6157 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6158 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6160 struct bgp_dest
*dest
;
6161 struct bgp_path_info
*pi
;
6162 struct bgp_path_info
*new;
6163 struct bgp_path_info rmap_path
;
6165 struct attr
*attr_new
;
6166 route_map_result_t ret
;
6167 #ifdef ENABLE_BGP_VNC
6168 int vnc_implicit_withdraw
= 0;
6173 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6175 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6177 attr
.nexthop
= bgp_static
->igpnexthop
;
6178 attr
.med
= bgp_static
->igpmetric
;
6179 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6182 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6184 if (bgp_static
->igpmetric
)
6185 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6187 if (bgp_static
->atomic
)
6188 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6190 /* Store label index, if required. */
6191 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6192 attr
.label_index
= bgp_static
->label_index
;
6193 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6196 /* Apply route-map. */
6197 if (bgp_static
->rmap
.name
) {
6198 struct attr attr_tmp
= attr
;
6200 memset(&rmap_path
, 0, sizeof(rmap_path
));
6201 rmap_path
.peer
= bgp
->peer_self
;
6202 rmap_path
.attr
= &attr_tmp
;
6204 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6206 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6208 bgp
->peer_self
->rmap_type
= 0;
6210 if (ret
== RMAP_DENYMATCH
) {
6211 /* Free uninterned attribute. */
6212 bgp_attr_flush(&attr_tmp
);
6214 /* Unintern original. */
6215 aspath_unintern(&attr
.aspath
);
6216 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6217 bgp_dest_unlock_node(dest
);
6221 if (bgp_in_graceful_shutdown(bgp
))
6222 bgp_attr_add_gshut_community(&attr_tmp
);
6224 attr_new
= bgp_attr_intern(&attr_tmp
);
6227 if (bgp_in_graceful_shutdown(bgp
))
6228 bgp_attr_add_gshut_community(&attr
);
6230 attr_new
= bgp_attr_intern(&attr
);
6233 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6234 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6235 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6239 if (attrhash_cmp(pi
->attr
, attr_new
)
6240 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6241 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6242 bgp_dest_unlock_node(dest
);
6243 bgp_attr_unintern(&attr_new
);
6244 aspath_unintern(&attr
.aspath
);
6247 /* The attribute is changed. */
6248 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6250 /* Rewrite BGP route information. */
6251 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6252 bgp_path_info_restore(dest
, pi
);
6254 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6255 #ifdef ENABLE_BGP_VNC
6256 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6257 && (safi
== SAFI_UNICAST
)) {
6258 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6260 * Implicit withdraw case.
6261 * We have to do this before pi is
6264 ++vnc_implicit_withdraw
;
6265 vnc_import_bgp_del_route(bgp
, p
, pi
);
6266 vnc_import_bgp_exterior_del_route(
6271 bgp_attr_unintern(&pi
->attr
);
6272 pi
->attr
= attr_new
;
6273 pi
->uptime
= monotime(NULL
);
6274 #ifdef ENABLE_BGP_VNC
6275 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6276 && (safi
== SAFI_UNICAST
)) {
6277 if (vnc_implicit_withdraw
) {
6278 vnc_import_bgp_add_route(bgp
, p
, pi
);
6279 vnc_import_bgp_exterior_add_route(
6285 /* Nexthop reachability check. */
6286 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6287 && (safi
== SAFI_UNICAST
6288 || safi
== SAFI_LABELED_UNICAST
)) {
6290 struct bgp
*bgp_nexthop
= bgp
;
6292 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6293 bgp_nexthop
= pi
->extra
->bgp_orig
;
6295 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6296 afi
, safi
, pi
, NULL
,
6298 bgp_path_info_set_flag(dest
, pi
,
6301 if (BGP_DEBUG(nht
, NHT
)) {
6302 char buf1
[INET6_ADDRSTRLEN
];
6303 inet_ntop(p
->family
,
6307 "%s(%s): Route not in table, not advertising",
6310 bgp_path_info_unset_flag(
6311 dest
, pi
, BGP_PATH_VALID
);
6314 /* Delete the NHT structure if any, if we're
6316 * enabling/disabling import check. We
6317 * deregister the route
6318 * from NHT to avoid overloading NHT and the
6319 * process interaction
6321 bgp_unlink_nexthop(pi
);
6322 bgp_path_info_set_flag(dest
, pi
,
6325 /* Process change. */
6326 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6327 bgp_process(bgp
, dest
, afi
, safi
);
6329 if (SAFI_UNICAST
== safi
6330 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6332 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6333 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6337 bgp_dest_unlock_node(dest
);
6338 aspath_unintern(&attr
.aspath
);
6343 /* Make new BGP info. */
6344 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6346 /* Nexthop reachability check. */
6347 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6348 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6349 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6351 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6353 if (BGP_DEBUG(nht
, NHT
)) {
6354 char buf1
[INET6_ADDRSTRLEN
];
6355 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6358 "%s(%s): Route not in table, not advertising",
6361 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6364 /* Delete the NHT structure if any, if we're toggling between
6365 * enabling/disabling import check. We deregister the route
6366 * from NHT to avoid overloading NHT and the process interaction
6368 bgp_unlink_nexthop(new);
6370 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6373 /* Aggregate address increment. */
6374 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6376 /* Register new BGP information. */
6377 bgp_path_info_add(dest
, new);
6379 /* route_node_get lock */
6380 bgp_dest_unlock_node(dest
);
6382 /* Process change. */
6383 bgp_process(bgp
, dest
, afi
, safi
);
6385 if (SAFI_UNICAST
== safi
6386 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6387 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6388 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6391 /* Unintern original. */
6392 aspath_unintern(&attr
.aspath
);
6395 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6398 struct bgp_dest
*dest
;
6399 struct bgp_path_info
*pi
;
6401 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6403 /* Check selected route and self inserted route. */
6404 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6405 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6406 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6409 /* Withdraw static BGP route from routing table. */
6411 if (SAFI_UNICAST
== safi
6412 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6413 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6414 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6416 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6417 bgp_unlink_nexthop(pi
);
6418 bgp_path_info_delete(dest
, pi
);
6419 bgp_process(bgp
, dest
, afi
, safi
);
6422 /* Unlock bgp_node_lookup. */
6423 bgp_dest_unlock_node(dest
);
6427 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6429 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6430 afi_t afi
, safi_t safi
,
6431 struct prefix_rd
*prd
)
6433 struct bgp_dest
*dest
;
6434 struct bgp_path_info
*pi
;
6436 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6438 /* Check selected route and self inserted route. */
6439 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6440 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6441 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6444 /* Withdraw static BGP route from routing table. */
6446 #ifdef ENABLE_BGP_VNC
6447 rfapiProcessWithdraw(
6448 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6449 1); /* Kill, since it is an administrative change */
6451 if (SAFI_MPLS_VPN
== safi
6452 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6453 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6455 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6456 bgp_path_info_delete(dest
, pi
);
6457 bgp_process(bgp
, dest
, afi
, safi
);
6460 /* Unlock bgp_node_lookup. */
6461 bgp_dest_unlock_node(dest
);
6464 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6465 struct bgp_static
*bgp_static
, afi_t afi
,
6468 struct bgp_dest
*dest
;
6469 struct bgp_path_info
*new;
6470 struct attr
*attr_new
;
6471 struct attr attr
= {0};
6472 struct bgp_path_info
*pi
;
6473 #ifdef ENABLE_BGP_VNC
6474 mpls_label_t label
= 0;
6476 uint32_t num_labels
= 0;
6480 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6482 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6485 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6487 attr
.nexthop
= bgp_static
->igpnexthop
;
6488 attr
.med
= bgp_static
->igpmetric
;
6489 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6491 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6492 || (safi
== SAFI_ENCAP
)) {
6493 if (afi
== AFI_IP
) {
6494 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6495 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6498 if (afi
== AFI_L2VPN
) {
6499 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6500 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6501 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6502 &bgp_static
->gatewayIp
.u
.prefix4
,
6504 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6505 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6506 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6507 &bgp_static
->gatewayIp
.u
.prefix6
,
6510 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6511 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6512 struct bgp_encap_type_vxlan bet
;
6513 memset(&bet
, 0, sizeof(bet
));
6514 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6515 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6517 if (bgp_static
->router_mac
) {
6518 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6521 /* Apply route-map. */
6522 if (bgp_static
->rmap
.name
) {
6523 struct attr attr_tmp
= attr
;
6524 struct bgp_path_info rmap_path
;
6525 route_map_result_t ret
;
6527 rmap_path
.peer
= bgp
->peer_self
;
6528 rmap_path
.attr
= &attr_tmp
;
6530 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6532 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6534 bgp
->peer_self
->rmap_type
= 0;
6536 if (ret
== RMAP_DENYMATCH
) {
6537 /* Free uninterned attribute. */
6538 bgp_attr_flush(&attr_tmp
);
6540 /* Unintern original. */
6541 aspath_unintern(&attr
.aspath
);
6542 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6544 bgp_dest_unlock_node(dest
);
6548 attr_new
= bgp_attr_intern(&attr_tmp
);
6550 attr_new
= bgp_attr_intern(&attr
);
6553 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6554 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6555 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6559 if (attrhash_cmp(pi
->attr
, attr_new
)
6560 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6561 bgp_dest_unlock_node(dest
);
6562 bgp_attr_unintern(&attr_new
);
6563 aspath_unintern(&attr
.aspath
);
6566 /* The attribute is changed. */
6567 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6569 /* Rewrite BGP route information. */
6570 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6571 bgp_path_info_restore(dest
, pi
);
6573 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6574 bgp_attr_unintern(&pi
->attr
);
6575 pi
->attr
= attr_new
;
6576 pi
->uptime
= monotime(NULL
);
6577 #ifdef ENABLE_BGP_VNC
6579 label
= decode_label(&pi
->extra
->label
[0]);
6582 /* Process change. */
6583 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6584 bgp_process(bgp
, dest
, afi
, safi
);
6586 if (SAFI_MPLS_VPN
== safi
6587 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6588 vpn_leak_to_vrf_update(bgp
, pi
,
6591 #ifdef ENABLE_BGP_VNC
6592 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6593 pi
->attr
, afi
, safi
, pi
->type
,
6594 pi
->sub_type
, &label
);
6596 bgp_dest_unlock_node(dest
);
6597 aspath_unintern(&attr
.aspath
);
6603 /* Make new BGP info. */
6604 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6606 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6607 bgp_path_info_extra_get(new);
6609 new->extra
->label
[0] = bgp_static
->label
;
6610 new->extra
->num_labels
= num_labels
;
6612 #ifdef ENABLE_BGP_VNC
6613 label
= decode_label(&bgp_static
->label
);
6616 /* Aggregate address increment. */
6617 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6619 /* Register new BGP information. */
6620 bgp_path_info_add(dest
, new);
6621 /* route_node_get lock */
6622 bgp_dest_unlock_node(dest
);
6624 /* Process change. */
6625 bgp_process(bgp
, dest
, afi
, safi
);
6627 if (SAFI_MPLS_VPN
== safi
6628 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6629 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6631 #ifdef ENABLE_BGP_VNC
6632 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6633 safi
, new->type
, new->sub_type
, &label
);
6636 /* Unintern original. */
6637 aspath_unintern(&attr
.aspath
);
6640 /* Configure static BGP network. When user don't run zebra, static
6641 route should be installed as valid. */
6642 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6643 const char *ip_str
, afi_t afi
, safi_t safi
,
6644 const char *rmap
, int backdoor
, uint32_t label_index
)
6646 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6649 struct bgp_static
*bgp_static
;
6650 struct bgp_dest
*dest
;
6651 uint8_t need_update
= 0;
6653 /* Convert IP prefix string to struct prefix. */
6654 ret
= str2prefix(ip_str
, &p
);
6656 vty_out(vty
, "%% Malformed prefix\n");
6657 return CMD_WARNING_CONFIG_FAILED
;
6659 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6660 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6661 return CMD_WARNING_CONFIG_FAILED
;
6668 /* Set BGP static route configuration. */
6669 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6672 vty_out(vty
, "%% Can't find static route specified\n");
6673 return CMD_WARNING_CONFIG_FAILED
;
6676 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6678 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6679 && (label_index
!= bgp_static
->label_index
)) {
6681 "%% label-index doesn't match static route\n");
6682 bgp_dest_unlock_node(dest
);
6683 return CMD_WARNING_CONFIG_FAILED
;
6686 if ((rmap
&& bgp_static
->rmap
.name
)
6687 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6689 "%% route-map name doesn't match static route\n");
6690 bgp_dest_unlock_node(dest
);
6691 return CMD_WARNING_CONFIG_FAILED
;
6694 /* Update BGP RIB. */
6695 if (!bgp_static
->backdoor
)
6696 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6698 /* Clear configuration. */
6699 bgp_static_free(bgp_static
);
6700 bgp_dest_set_bgp_static_info(dest
, NULL
);
6701 bgp_dest_unlock_node(dest
);
6702 bgp_dest_unlock_node(dest
);
6705 /* Set BGP static route configuration. */
6706 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6707 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6709 /* Configuration change. */
6710 /* Label index cannot be changed. */
6711 if (bgp_static
->label_index
!= label_index
) {
6712 vty_out(vty
, "%% cannot change label-index\n");
6713 bgp_dest_unlock_node(dest
);
6714 return CMD_WARNING_CONFIG_FAILED
;
6717 /* Check previous routes are installed into BGP. */
6718 if (bgp_static
->valid
6719 && bgp_static
->backdoor
!= backdoor
)
6722 bgp_static
->backdoor
= backdoor
;
6725 XFREE(MTYPE_ROUTE_MAP_NAME
,
6726 bgp_static
->rmap
.name
);
6727 route_map_counter_decrement(
6728 bgp_static
->rmap
.map
);
6729 bgp_static
->rmap
.name
=
6730 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6731 bgp_static
->rmap
.map
=
6732 route_map_lookup_by_name(rmap
);
6733 route_map_counter_increment(
6734 bgp_static
->rmap
.map
);
6736 XFREE(MTYPE_ROUTE_MAP_NAME
,
6737 bgp_static
->rmap
.name
);
6738 route_map_counter_decrement(
6739 bgp_static
->rmap
.map
);
6740 bgp_static
->rmap
.map
= NULL
;
6741 bgp_static
->valid
= 0;
6743 bgp_dest_unlock_node(dest
);
6745 /* New configuration. */
6746 bgp_static
= bgp_static_new();
6747 bgp_static
->backdoor
= backdoor
;
6748 bgp_static
->valid
= 0;
6749 bgp_static
->igpmetric
= 0;
6750 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6751 bgp_static
->label_index
= label_index
;
6754 XFREE(MTYPE_ROUTE_MAP_NAME
,
6755 bgp_static
->rmap
.name
);
6756 route_map_counter_decrement(
6757 bgp_static
->rmap
.map
);
6758 bgp_static
->rmap
.name
=
6759 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6760 bgp_static
->rmap
.map
=
6761 route_map_lookup_by_name(rmap
);
6762 route_map_counter_increment(
6763 bgp_static
->rmap
.map
);
6765 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6768 bgp_static
->valid
= 1;
6770 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6772 if (!bgp_static
->backdoor
)
6773 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6779 void bgp_static_add(struct bgp
*bgp
)
6783 struct bgp_dest
*dest
;
6784 struct bgp_dest
*rm
;
6785 struct bgp_table
*table
;
6786 struct bgp_static
*bgp_static
;
6788 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6789 FOREACH_AFI_SAFI (afi
, safi
)
6790 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6791 dest
= bgp_route_next(dest
)) {
6792 if (!bgp_dest_has_bgp_path_info_data(dest
))
6795 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6796 || (safi
== SAFI_EVPN
)) {
6797 table
= bgp_dest_get_bgp_table_info(dest
);
6799 for (rm
= bgp_table_top(table
); rm
;
6800 rm
= bgp_route_next(rm
)) {
6802 bgp_dest_get_bgp_static_info(
6804 bgp_static_update_safi(
6805 bgp
, bgp_dest_get_prefix(rm
),
6806 bgp_static
, afi
, safi
);
6810 bgp
, bgp_dest_get_prefix(dest
),
6811 bgp_dest_get_bgp_static_info(dest
), afi
,
6815 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6818 /* Called from bgp_delete(). Delete all static routes from the BGP
6820 void bgp_static_delete(struct bgp
*bgp
)
6824 struct bgp_dest
*dest
;
6825 struct bgp_dest
*rm
;
6826 struct bgp_table
*table
;
6827 struct bgp_static
*bgp_static
;
6829 FOREACH_AFI_SAFI (afi
, safi
)
6830 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6831 dest
= bgp_route_next(dest
)) {
6832 if (!bgp_dest_has_bgp_path_info_data(dest
))
6835 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6836 || (safi
== SAFI_EVPN
)) {
6837 table
= bgp_dest_get_bgp_table_info(dest
);
6839 for (rm
= bgp_table_top(table
); rm
;
6840 rm
= bgp_route_next(rm
)) {
6842 bgp_dest_get_bgp_static_info(
6847 bgp_static_withdraw_safi(
6848 bgp
, bgp_dest_get_prefix(rm
),
6850 (struct prefix_rd
*)
6851 bgp_dest_get_prefix(
6853 bgp_static_free(bgp_static
);
6854 bgp_dest_set_bgp_static_info(rm
,
6856 bgp_dest_unlock_node(rm
);
6859 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6860 bgp_static_withdraw(bgp
,
6861 bgp_dest_get_prefix(dest
),
6863 bgp_static_free(bgp_static
);
6864 bgp_dest_set_bgp_static_info(dest
, NULL
);
6865 bgp_dest_unlock_node(dest
);
6870 void bgp_static_redo_import_check(struct bgp
*bgp
)
6874 struct bgp_dest
*dest
;
6875 struct bgp_dest
*rm
;
6876 struct bgp_table
*table
;
6877 struct bgp_static
*bgp_static
;
6879 /* Use this flag to force reprocessing of the route */
6880 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6881 FOREACH_AFI_SAFI (afi
, safi
) {
6882 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6883 dest
= bgp_route_next(dest
)) {
6884 if (!bgp_dest_has_bgp_path_info_data(dest
))
6887 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6888 || (safi
== SAFI_EVPN
)) {
6889 table
= bgp_dest_get_bgp_table_info(dest
);
6891 for (rm
= bgp_table_top(table
); rm
;
6892 rm
= bgp_route_next(rm
)) {
6894 bgp_dest_get_bgp_static_info(
6896 bgp_static_update_safi(
6897 bgp
, bgp_dest_get_prefix(rm
),
6898 bgp_static
, afi
, safi
);
6901 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6902 bgp_static_update(bgp
,
6903 bgp_dest_get_prefix(dest
),
6904 bgp_static
, afi
, safi
);
6908 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6911 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6914 struct bgp_table
*table
;
6915 struct bgp_dest
*dest
;
6916 struct bgp_path_info
*pi
;
6918 /* Do not install the aggregate route if BGP is in the
6919 * process of termination.
6921 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6922 || (bgp
->peer_self
== NULL
))
6925 table
= bgp
->rib
[afi
][safi
];
6926 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6927 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6928 if (pi
->peer
== bgp
->peer_self
6929 && ((pi
->type
== ZEBRA_ROUTE_BGP
6930 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6931 || (pi
->type
!= ZEBRA_ROUTE_BGP
6933 == BGP_ROUTE_REDISTRIBUTE
))) {
6934 bgp_aggregate_decrement(
6935 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6937 bgp_unlink_nexthop(pi
);
6938 bgp_path_info_delete(dest
, pi
);
6939 bgp_process(bgp
, dest
, afi
, safi
);
6946 * Purge all networks and redistributed routes from routing table.
6947 * Invoked upon the instance going down.
6949 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6954 FOREACH_AFI_SAFI (afi
, safi
)
6955 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6960 * Currently this is used to set static routes for VPN and ENCAP.
6961 * I think it can probably be factored with bgp_static_set.
6963 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6964 const char *ip_str
, const char *rd_str
,
6965 const char *label_str
, const char *rmap_str
,
6966 int evpn_type
, const char *esi
, const char *gwip
,
6967 const char *ethtag
, const char *routermac
)
6969 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6972 struct prefix_rd prd
;
6973 struct bgp_dest
*pdest
;
6974 struct bgp_dest
*dest
;
6975 struct bgp_table
*table
;
6976 struct bgp_static
*bgp_static
;
6977 mpls_label_t label
= MPLS_INVALID_LABEL
;
6978 struct prefix gw_ip
;
6980 /* validate ip prefix */
6981 ret
= str2prefix(ip_str
, &p
);
6983 vty_out(vty
, "%% Malformed prefix\n");
6984 return CMD_WARNING_CONFIG_FAILED
;
6987 if ((afi
== AFI_L2VPN
)
6988 && (bgp_build_evpn_prefix(evpn_type
,
6989 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6990 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6991 return CMD_WARNING_CONFIG_FAILED
;
6994 ret
= str2prefix_rd(rd_str
, &prd
);
6996 vty_out(vty
, "%% Malformed rd\n");
6997 return CMD_WARNING_CONFIG_FAILED
;
7001 unsigned long label_val
;
7002 label_val
= strtoul(label_str
, NULL
, 10);
7003 encode_label(label_val
, &label
);
7006 if (safi
== SAFI_EVPN
) {
7007 if (esi
&& str2esi(esi
, NULL
) == 0) {
7008 vty_out(vty
, "%% Malformed ESI\n");
7009 return CMD_WARNING_CONFIG_FAILED
;
7011 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
7012 vty_out(vty
, "%% Malformed Router MAC\n");
7013 return CMD_WARNING_CONFIG_FAILED
;
7016 memset(&gw_ip
, 0, sizeof(gw_ip
));
7017 ret
= str2prefix(gwip
, &gw_ip
);
7019 vty_out(vty
, "%% Malformed GatewayIp\n");
7020 return CMD_WARNING_CONFIG_FAILED
;
7022 if ((gw_ip
.family
== AF_INET
7023 && is_evpn_prefix_ipaddr_v6(
7024 (struct prefix_evpn
*)&p
))
7025 || (gw_ip
.family
== AF_INET6
7026 && is_evpn_prefix_ipaddr_v4(
7027 (struct prefix_evpn
*)&p
))) {
7029 "%% GatewayIp family differs with IP prefix\n");
7030 return CMD_WARNING_CONFIG_FAILED
;
7034 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7035 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7036 bgp_dest_set_bgp_table_info(pdest
,
7037 bgp_table_init(bgp
, afi
, safi
));
7038 table
= bgp_dest_get_bgp_table_info(pdest
);
7040 dest
= bgp_node_get(table
, &p
);
7042 if (bgp_dest_has_bgp_path_info_data(dest
)) {
7043 vty_out(vty
, "%% Same network configuration exists\n");
7044 bgp_dest_unlock_node(dest
);
7046 /* New configuration. */
7047 bgp_static
= bgp_static_new();
7048 bgp_static
->backdoor
= 0;
7049 bgp_static
->valid
= 0;
7050 bgp_static
->igpmetric
= 0;
7051 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7052 bgp_static
->label
= label
;
7053 bgp_static
->prd
= prd
;
7056 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7057 route_map_counter_decrement(bgp_static
->rmap
.map
);
7058 bgp_static
->rmap
.name
=
7059 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7060 bgp_static
->rmap
.map
=
7061 route_map_lookup_by_name(rmap_str
);
7062 route_map_counter_increment(bgp_static
->rmap
.map
);
7065 if (safi
== SAFI_EVPN
) {
7067 bgp_static
->eth_s_id
=
7070 str2esi(esi
, bgp_static
->eth_s_id
);
7073 bgp_static
->router_mac
=
7074 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7075 (void)prefix_str2mac(routermac
,
7076 bgp_static
->router_mac
);
7079 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7081 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7083 bgp_static
->valid
= 1;
7084 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7090 /* Configure static BGP network. */
7091 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7092 const char *ip_str
, const char *rd_str
,
7093 const char *label_str
, int evpn_type
, const char *esi
,
7094 const char *gwip
, const char *ethtag
)
7096 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7099 struct prefix_rd prd
;
7100 struct bgp_dest
*pdest
;
7101 struct bgp_dest
*dest
;
7102 struct bgp_table
*table
;
7103 struct bgp_static
*bgp_static
;
7104 mpls_label_t label
= MPLS_INVALID_LABEL
;
7106 /* Convert IP prefix string to struct prefix. */
7107 ret
= str2prefix(ip_str
, &p
);
7109 vty_out(vty
, "%% Malformed prefix\n");
7110 return CMD_WARNING_CONFIG_FAILED
;
7113 if ((afi
== AFI_L2VPN
)
7114 && (bgp_build_evpn_prefix(evpn_type
,
7115 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7116 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7117 return CMD_WARNING_CONFIG_FAILED
;
7119 ret
= str2prefix_rd(rd_str
, &prd
);
7121 vty_out(vty
, "%% Malformed rd\n");
7122 return CMD_WARNING_CONFIG_FAILED
;
7126 unsigned long label_val
;
7127 label_val
= strtoul(label_str
, NULL
, 10);
7128 encode_label(label_val
, &label
);
7131 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7132 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7133 bgp_dest_set_bgp_table_info(pdest
,
7134 bgp_table_init(bgp
, afi
, safi
));
7136 bgp_dest_unlock_node(pdest
);
7137 table
= bgp_dest_get_bgp_table_info(pdest
);
7139 dest
= bgp_node_lookup(table
, &p
);
7142 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7144 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7145 bgp_static_free(bgp_static
);
7146 bgp_dest_set_bgp_static_info(dest
, NULL
);
7147 bgp_dest_unlock_node(dest
);
7148 bgp_dest_unlock_node(dest
);
7150 vty_out(vty
, "%% Can't find the route\n");
7155 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7156 const char *rmap_name
)
7158 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7159 struct bgp_rmap
*rmap
;
7161 rmap
= &bgp
->table_map
[afi
][safi
];
7163 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7164 route_map_counter_decrement(rmap
->map
);
7165 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7166 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7167 route_map_counter_increment(rmap
->map
);
7169 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7170 route_map_counter_decrement(rmap
->map
);
7174 if (bgp_fibupd_safi(safi
))
7175 bgp_zebra_announce_table(bgp
, afi
, safi
);
7180 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7181 const char *rmap_name
)
7183 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7184 struct bgp_rmap
*rmap
;
7186 rmap
= &bgp
->table_map
[afi
][safi
];
7187 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7188 route_map_counter_decrement(rmap
->map
);
7191 if (bgp_fibupd_safi(safi
))
7192 bgp_zebra_announce_table(bgp
, afi
, safi
);
7197 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7200 if (bgp
->table_map
[afi
][safi
].name
) {
7201 vty_out(vty
, " table-map %s\n",
7202 bgp
->table_map
[afi
][safi
].name
);
7206 DEFUN (bgp_table_map
,
7209 "BGP table to RIB route download filter\n"
7210 "Name of the route map\n")
7213 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7214 argv
[idx_word
]->arg
);
7216 DEFUN (no_bgp_table_map
,
7217 no_bgp_table_map_cmd
,
7218 "no table-map WORD",
7220 "BGP table to RIB route download filter\n"
7221 "Name of the route map\n")
7224 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7225 argv
[idx_word
]->arg
);
7231 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7232 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7233 backdoor$backdoor}]",
7235 "Specify a network to announce via BGP\n"
7240 "Route-map to modify the attributes\n"
7241 "Name of the route map\n"
7242 "Label index to associate with the prefix\n"
7243 "Label index value\n"
7244 "Specify a BGP backdoor route\n")
7246 char addr_prefix_str
[BUFSIZ
];
7251 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7253 sizeof(addr_prefix_str
));
7255 vty_out(vty
, "%% Inconsistent address and mask\n");
7256 return CMD_WARNING_CONFIG_FAILED
;
7260 return bgp_static_set(
7261 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7262 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7263 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7266 DEFPY(ipv6_bgp_network
,
7267 ipv6_bgp_network_cmd
,
7268 "[no] network X:X::X:X/M$prefix \
7269 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7271 "Specify a network to announce via BGP\n"
7273 "Route-map to modify the attributes\n"
7274 "Name of the route map\n"
7275 "Label index to associate with the prefix\n"
7276 "Label index value\n")
7278 return bgp_static_set(
7279 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7280 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7283 static struct bgp_aggregate
*bgp_aggregate_new(void)
7285 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7288 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7290 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7291 route_map_counter_decrement(aggregate
->suppress_map
);
7292 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7293 route_map_counter_decrement(aggregate
->rmap
.map
);
7294 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7298 * Helper function to avoid repeated code: prepare variables for a
7299 * `route_map_apply` call.
7301 * \returns `true` on route map match, otherwise `false`.
7303 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7304 struct bgp_aggregate
*aggregate
,
7305 struct bgp_path_info
*pi
)
7307 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7308 route_map_result_t rmr
= RMAP_DENYMATCH
;
7309 struct bgp_path_info rmap_path
= {};
7310 struct attr attr
= {};
7312 /* No route map entries created, just don't match. */
7313 if (aggregate
->suppress_map
== NULL
)
7316 /* Call route map matching and return result. */
7317 attr
.aspath
= aspath_empty();
7318 rmap_path
.peer
= bgp
->peer_self
;
7319 rmap_path
.attr
= &attr
;
7321 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7322 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7323 bgp
->peer_self
->rmap_type
= 0;
7325 bgp_attr_flush(&attr
);
7326 aspath_unintern(&attr
.aspath
);
7328 return rmr
== RMAP_PERMITMATCH
;
7331 /** Test whether the aggregation has suppressed this path or not. */
7332 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7333 struct bgp_path_info
*pi
)
7335 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7338 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7342 * Suppress this path and keep the reference.
7344 * \returns `true` if needs processing otherwise `false`.
7346 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7347 struct bgp_path_info
*pi
)
7349 struct bgp_path_info_extra
*pie
;
7351 /* Path is already suppressed by this aggregation. */
7352 if (aggr_suppress_exists(aggregate
, pi
))
7355 pie
= bgp_path_info_extra_get(pi
);
7357 /* This is the first suppression, allocate memory and list it. */
7358 if (pie
->aggr_suppressors
== NULL
)
7359 pie
->aggr_suppressors
= list_new();
7361 listnode_add(pie
->aggr_suppressors
, aggregate
);
7363 /* Only mark for processing if suppressed. */
7364 if (listcount(pie
->aggr_suppressors
) == 1) {
7365 if (BGP_DEBUG(update
, UPDATE_OUT
))
7366 zlog_debug("aggregate-address suppressing: %pFX",
7367 bgp_dest_get_prefix(pi
->net
));
7369 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7377 * Unsuppress this path and remove the reference.
7379 * \returns `true` if needs processing otherwise `false`.
7381 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7382 struct bgp_path_info
*pi
)
7384 /* Path wasn't suppressed. */
7385 if (!aggr_suppress_exists(aggregate
, pi
))
7388 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7390 /* Unsuppress and free extra memory if last item. */
7391 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7392 if (BGP_DEBUG(update
, UPDATE_OUT
))
7393 zlog_debug("aggregate-address unsuppressing: %pFX",
7394 bgp_dest_get_prefix(pi
->net
));
7396 list_delete(&pi
->extra
->aggr_suppressors
);
7397 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7404 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7405 struct aspath
*aspath
,
7406 struct community
*comm
,
7407 struct ecommunity
*ecomm
,
7408 struct lcommunity
*lcomm
)
7410 static struct aspath
*ae
= NULL
;
7413 ae
= aspath_empty();
7418 if (origin
!= pi
->attr
->origin
)
7421 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7424 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7427 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7430 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7433 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7439 static void bgp_aggregate_install(
7440 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7441 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7442 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7443 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7445 struct bgp_dest
*dest
;
7446 struct bgp_table
*table
;
7447 struct bgp_path_info
*pi
, *orig
, *new;
7450 table
= bgp
->rib
[afi
][safi
];
7452 dest
= bgp_node_get(table
, p
);
7454 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7455 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7456 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7460 * If we have paths with different MEDs, then don't install
7461 * (or uninstall) the aggregate route.
7463 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7464 goto uninstall_aggregate_route
;
7466 if (aggregate
->count
> 0) {
7468 * If the aggregate information has not changed
7469 * no need to re-install it again.
7471 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7472 ecommunity
, lcommunity
)) {
7473 bgp_dest_unlock_node(dest
);
7476 aspath_free(aspath
);
7478 community_free(&community
);
7480 ecommunity_free(&ecommunity
);
7482 lcommunity_free(&lcommunity
);
7488 * Mark the old as unusable
7491 bgp_path_info_delete(dest
, pi
);
7493 attr
= bgp_attr_aggregate_intern(
7494 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7495 aggregate
, atomic_aggregate
, p
);
7498 bgp_dest_unlock_node(dest
);
7499 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7500 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7501 zlog_debug("%s: %pFX null attribute", __func__
,
7506 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7507 bgp
->peer_self
, attr
, dest
);
7509 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7511 bgp_path_info_add(dest
, new);
7512 bgp_process(bgp
, dest
, afi
, safi
);
7514 uninstall_aggregate_route
:
7515 for (pi
= orig
; pi
; pi
= pi
->next
)
7516 if (pi
->peer
== bgp
->peer_self
7517 && pi
->type
== ZEBRA_ROUTE_BGP
7518 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7521 /* Withdraw static BGP route from routing table. */
7523 bgp_path_info_delete(dest
, pi
);
7524 bgp_process(bgp
, dest
, afi
, safi
);
7528 bgp_dest_unlock_node(dest
);
7532 * Check if the current path has different MED than other known paths.
7534 * \returns `true` if the MED matched the others else `false`.
7536 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7537 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7539 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7541 /* This is the first route being analyzed. */
7542 if (!aggregate
->med_initialized
) {
7543 aggregate
->med_initialized
= true;
7544 aggregate
->med_mismatched
= false;
7545 aggregate
->med_matched_value
= cur_med
;
7547 /* Check if routes with different MED showed up. */
7548 if (cur_med
!= aggregate
->med_matched_value
)
7549 aggregate
->med_mismatched
= true;
7552 return !aggregate
->med_mismatched
;
7556 * Initializes and tests all routes in the aggregate address path for MED
7559 * \returns `true` if all MEDs are the same otherwise `false`.
7561 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7562 struct bgp
*bgp
, const struct prefix
*p
,
7563 afi_t afi
, safi_t safi
)
7565 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7566 const struct prefix
*dest_p
;
7567 struct bgp_dest
*dest
, *top
;
7568 struct bgp_path_info
*pi
;
7569 bool med_matched
= true;
7571 aggregate
->med_initialized
= false;
7573 top
= bgp_node_get(table
, p
);
7574 for (dest
= bgp_node_get(table
, p
); dest
;
7575 dest
= bgp_route_next_until(dest
, top
)) {
7576 dest_p
= bgp_dest_get_prefix(dest
);
7577 if (dest_p
->prefixlen
<= p
->prefixlen
)
7580 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7581 if (BGP_PATH_HOLDDOWN(pi
))
7583 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7585 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7586 med_matched
= false;
7593 bgp_dest_unlock_node(top
);
7599 * Toggles the route suppression status for this aggregate address
7602 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7603 struct bgp
*bgp
, const struct prefix
*p
,
7604 afi_t afi
, safi_t safi
, bool suppress
)
7606 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7607 const struct prefix
*dest_p
;
7608 struct bgp_dest
*dest
, *top
;
7609 struct bgp_path_info
*pi
;
7610 bool toggle_suppression
;
7612 /* We've found a different MED we must revert any suppressed routes. */
7613 top
= bgp_node_get(table
, p
);
7614 for (dest
= bgp_node_get(table
, p
); dest
;
7615 dest
= bgp_route_next_until(dest
, top
)) {
7616 dest_p
= bgp_dest_get_prefix(dest
);
7617 if (dest_p
->prefixlen
<= p
->prefixlen
)
7620 toggle_suppression
= false;
7621 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7622 if (BGP_PATH_HOLDDOWN(pi
))
7624 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7627 /* We are toggling suppression back. */
7629 /* Suppress route if not suppressed already. */
7630 if (aggr_suppress_path(aggregate
, pi
))
7631 toggle_suppression
= true;
7635 /* Install route if there is no more suppression. */
7636 if (aggr_unsuppress_path(aggregate
, pi
))
7637 toggle_suppression
= true;
7640 if (toggle_suppression
)
7641 bgp_process(bgp
, dest
, afi
, safi
);
7643 bgp_dest_unlock_node(top
);
7647 * Aggregate address MED matching incremental test: this function is called
7648 * when the initial aggregation occurred and we are only testing a single
7651 * In addition to testing and setting the MED validity it also installs back
7652 * suppressed routes (if summary is configured).
7654 * Must not be called in `bgp_aggregate_route`.
7656 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7657 struct bgp
*bgp
, const struct prefix
*p
,
7658 afi_t afi
, safi_t safi
,
7659 struct bgp_path_info
*pi
)
7661 /* MED matching disabled. */
7662 if (!aggregate
->match_med
)
7665 /* Aggregation with different MED, recheck if we have got equal MEDs
7668 if (aggregate
->med_mismatched
&&
7669 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7670 aggregate
->summary_only
)
7671 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7674 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7676 /* No mismatches, just quit. */
7677 if (!aggregate
->med_mismatched
)
7680 /* Route summarization is disabled. */
7681 if (!aggregate
->summary_only
)
7684 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7687 /* Update an aggregate as routes are added/removed from the BGP table */
7688 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7689 safi_t safi
, struct bgp_aggregate
*aggregate
)
7691 struct bgp_table
*table
;
7692 struct bgp_dest
*top
;
7693 struct bgp_dest
*dest
;
7695 struct aspath
*aspath
= NULL
;
7696 struct community
*community
= NULL
;
7697 struct ecommunity
*ecommunity
= NULL
;
7698 struct lcommunity
*lcommunity
= NULL
;
7699 struct bgp_path_info
*pi
;
7700 unsigned long match
= 0;
7701 uint8_t atomic_aggregate
= 0;
7703 /* If the bgp instance is being deleted or self peer is deleted
7704 * then do not create aggregate route
7706 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7707 || (bgp
->peer_self
== NULL
))
7710 /* Initialize and test routes for MED difference. */
7711 if (aggregate
->match_med
)
7712 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7715 * Reset aggregate count: we might've been called from route map
7716 * update so in that case we must retest all more specific routes.
7718 * \see `bgp_route_map_process_update`.
7720 aggregate
->count
= 0;
7721 aggregate
->incomplete_origin_count
= 0;
7722 aggregate
->incomplete_origin_count
= 0;
7723 aggregate
->egp_origin_count
= 0;
7725 /* ORIGIN attribute: If at least one route among routes that are
7726 aggregated has ORIGIN with the value INCOMPLETE, then the
7727 aggregated route must have the ORIGIN attribute with the value
7728 INCOMPLETE. Otherwise, if at least one route among routes that
7729 are aggregated has ORIGIN with the value EGP, then the aggregated
7730 route must have the origin attribute with the value EGP. In all
7731 other case the value of the ORIGIN attribute of the aggregated
7732 route is INTERNAL. */
7733 origin
= BGP_ORIGIN_IGP
;
7735 table
= bgp
->rib
[afi
][safi
];
7737 top
= bgp_node_get(table
, p
);
7738 for (dest
= bgp_node_get(table
, p
); dest
;
7739 dest
= bgp_route_next_until(dest
, top
)) {
7740 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7742 if (dest_p
->prefixlen
<= p
->prefixlen
)
7745 /* If suppress fib is enabled and route not installed
7746 * in FIB, skip the route
7748 if (!bgp_check_advertise(bgp
, dest
))
7753 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7754 if (BGP_PATH_HOLDDOWN(pi
))
7758 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7759 atomic_aggregate
= 1;
7761 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7765 * summary-only aggregate route suppress
7766 * aggregated route announcements.
7769 * Don't create summaries if MED didn't match
7770 * otherwise neither the specific routes and the
7771 * aggregation will be announced.
7773 if (aggregate
->summary_only
7774 && AGGREGATE_MED_VALID(aggregate
)) {
7775 if (aggr_suppress_path(aggregate
, pi
))
7780 * Suppress more specific routes that match the route
7784 * Don't suppress routes if MED matching is enabled and
7785 * it mismatched otherwise we might end up with no
7786 * routes for this path.
7788 if (aggregate
->suppress_map_name
7789 && AGGREGATE_MED_VALID(aggregate
)
7790 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7791 if (aggr_suppress_path(aggregate
, pi
))
7798 * If at least one route among routes that are
7799 * aggregated has ORIGIN with the value INCOMPLETE,
7800 * then the aggregated route MUST have the ORIGIN
7801 * attribute with the value INCOMPLETE. Otherwise, if
7802 * at least one route among routes that are aggregated
7803 * has ORIGIN with the value EGP, then the aggregated
7804 * route MUST have the ORIGIN attribute with the value
7807 switch (pi
->attr
->origin
) {
7808 case BGP_ORIGIN_INCOMPLETE
:
7809 aggregate
->incomplete_origin_count
++;
7811 case BGP_ORIGIN_EGP
:
7812 aggregate
->egp_origin_count
++;
7820 if (!aggregate
->as_set
)
7824 * as-set aggregate route generate origin, as path,
7825 * and community aggregation.
7827 /* Compute aggregate route's as-path.
7829 bgp_compute_aggregate_aspath_hash(aggregate
,
7832 /* Compute aggregate route's community.
7834 if (bgp_attr_get_community(pi
->attr
))
7835 bgp_compute_aggregate_community_hash(
7837 bgp_attr_get_community(pi
->attr
));
7839 /* Compute aggregate route's extended community.
7841 if (bgp_attr_get_ecommunity(pi
->attr
))
7842 bgp_compute_aggregate_ecommunity_hash(
7844 bgp_attr_get_ecommunity(pi
->attr
));
7846 /* Compute aggregate route's large community.
7848 if (bgp_attr_get_lcommunity(pi
->attr
))
7849 bgp_compute_aggregate_lcommunity_hash(
7851 bgp_attr_get_lcommunity(pi
->attr
));
7854 bgp_process(bgp
, dest
, afi
, safi
);
7856 if (aggregate
->as_set
) {
7857 bgp_compute_aggregate_aspath_val(aggregate
);
7858 bgp_compute_aggregate_community_val(aggregate
);
7859 bgp_compute_aggregate_ecommunity_val(aggregate
);
7860 bgp_compute_aggregate_lcommunity_val(aggregate
);
7864 bgp_dest_unlock_node(top
);
7867 if (aggregate
->incomplete_origin_count
> 0)
7868 origin
= BGP_ORIGIN_INCOMPLETE
;
7869 else if (aggregate
->egp_origin_count
> 0)
7870 origin
= BGP_ORIGIN_EGP
;
7872 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7873 origin
= aggregate
->origin
;
7875 if (aggregate
->as_set
) {
7876 if (aggregate
->aspath
)
7877 /* Retrieve aggregate route's as-path.
7879 aspath
= aspath_dup(aggregate
->aspath
);
7881 if (aggregate
->community
)
7882 /* Retrieve aggregate route's community.
7884 community
= community_dup(aggregate
->community
);
7886 if (aggregate
->ecommunity
)
7887 /* Retrieve aggregate route's ecommunity.
7889 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7891 if (aggregate
->lcommunity
)
7892 /* Retrieve aggregate route's lcommunity.
7894 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7897 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7898 ecommunity
, lcommunity
, atomic_aggregate
,
7902 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7903 safi_t safi
, struct bgp_aggregate
*aggregate
)
7905 struct bgp_table
*table
;
7906 struct bgp_dest
*top
;
7907 struct bgp_dest
*dest
;
7908 struct bgp_path_info
*pi
;
7909 unsigned long match
;
7911 table
= bgp
->rib
[afi
][safi
];
7913 /* If routes exists below this node, generate aggregate routes. */
7914 top
= bgp_node_get(table
, p
);
7915 for (dest
= bgp_node_get(table
, p
); dest
;
7916 dest
= bgp_route_next_until(dest
, top
)) {
7917 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7919 if (dest_p
->prefixlen
<= p
->prefixlen
)
7923 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7924 if (BGP_PATH_HOLDDOWN(pi
))
7927 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7931 * This route is suppressed: attempt to unsuppress it.
7933 * `aggr_unsuppress_path` will fail if this particular
7934 * aggregate route was not the suppressor.
7936 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7937 listcount(pi
->extra
->aggr_suppressors
)) {
7938 if (aggr_unsuppress_path(aggregate
, pi
))
7944 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7945 aggregate
->incomplete_origin_count
--;
7946 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7947 aggregate
->egp_origin_count
--;
7949 if (aggregate
->as_set
) {
7950 /* Remove as-path from aggregate.
7952 bgp_remove_aspath_from_aggregate_hash(
7956 if (bgp_attr_get_community(pi
->attr
))
7957 /* Remove community from aggregate.
7959 bgp_remove_comm_from_aggregate_hash(
7961 bgp_attr_get_community(
7964 if (bgp_attr_get_ecommunity(pi
->attr
))
7965 /* Remove ecommunity from aggregate.
7967 bgp_remove_ecomm_from_aggregate_hash(
7969 bgp_attr_get_ecommunity(
7972 if (bgp_attr_get_lcommunity(pi
->attr
))
7973 /* Remove lcommunity from aggregate.
7975 bgp_remove_lcomm_from_aggregate_hash(
7977 bgp_attr_get_lcommunity(
7982 /* If this node was suppressed, process the change. */
7984 bgp_process(bgp
, dest
, afi
, safi
);
7986 if (aggregate
->as_set
) {
7987 aspath_free(aggregate
->aspath
);
7988 aggregate
->aspath
= NULL
;
7989 if (aggregate
->community
)
7990 community_free(&aggregate
->community
);
7991 if (aggregate
->ecommunity
)
7992 ecommunity_free(&aggregate
->ecommunity
);
7993 if (aggregate
->lcommunity
)
7994 lcommunity_free(&aggregate
->lcommunity
);
7997 bgp_dest_unlock_node(top
);
8000 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
8001 const struct prefix
*aggr_p
,
8002 struct bgp_path_info
*pinew
, afi_t afi
,
8004 struct bgp_aggregate
*aggregate
)
8007 struct aspath
*aspath
= NULL
;
8008 uint8_t atomic_aggregate
= 0;
8009 struct community
*community
= NULL
;
8010 struct ecommunity
*ecommunity
= NULL
;
8011 struct lcommunity
*lcommunity
= NULL
;
8013 /* If the bgp instance is being deleted or self peer is deleted
8014 * then do not create aggregate route
8016 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8017 || (bgp
->peer_self
== NULL
))
8020 /* ORIGIN attribute: If at least one route among routes that are
8021 * aggregated has ORIGIN with the value INCOMPLETE, then the
8022 * aggregated route must have the ORIGIN attribute with the value
8023 * INCOMPLETE. Otherwise, if at least one route among routes that
8024 * are aggregated has ORIGIN with the value EGP, then the aggregated
8025 * route must have the origin attribute with the value EGP. In all
8026 * other case the value of the ORIGIN attribute of the aggregated
8027 * route is INTERNAL.
8029 origin
= BGP_ORIGIN_IGP
;
8034 * This must be called before `summary` check to avoid
8035 * "suppressing" twice.
8037 if (aggregate
->match_med
)
8038 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8041 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8042 aggr_suppress_path(aggregate
, pinew
);
8044 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8045 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8046 aggr_suppress_path(aggregate
, pinew
);
8048 switch (pinew
->attr
->origin
) {
8049 case BGP_ORIGIN_INCOMPLETE
:
8050 aggregate
->incomplete_origin_count
++;
8052 case BGP_ORIGIN_EGP
:
8053 aggregate
->egp_origin_count
++;
8061 if (aggregate
->incomplete_origin_count
> 0)
8062 origin
= BGP_ORIGIN_INCOMPLETE
;
8063 else if (aggregate
->egp_origin_count
> 0)
8064 origin
= BGP_ORIGIN_EGP
;
8066 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8067 origin
= aggregate
->origin
;
8069 if (aggregate
->as_set
) {
8070 /* Compute aggregate route's as-path.
8072 bgp_compute_aggregate_aspath(aggregate
,
8073 pinew
->attr
->aspath
);
8075 /* Compute aggregate route's community.
8077 if (bgp_attr_get_community(pinew
->attr
))
8078 bgp_compute_aggregate_community(
8079 aggregate
, bgp_attr_get_community(pinew
->attr
));
8081 /* Compute aggregate route's extended community.
8083 if (bgp_attr_get_ecommunity(pinew
->attr
))
8084 bgp_compute_aggregate_ecommunity(
8086 bgp_attr_get_ecommunity(pinew
->attr
));
8088 /* Compute aggregate route's large community.
8090 if (bgp_attr_get_lcommunity(pinew
->attr
))
8091 bgp_compute_aggregate_lcommunity(
8093 bgp_attr_get_lcommunity(pinew
->attr
));
8095 /* Retrieve aggregate route's as-path.
8097 if (aggregate
->aspath
)
8098 aspath
= aspath_dup(aggregate
->aspath
);
8100 /* Retrieve aggregate route's community.
8102 if (aggregate
->community
)
8103 community
= community_dup(aggregate
->community
);
8105 /* Retrieve aggregate route's ecommunity.
8107 if (aggregate
->ecommunity
)
8108 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8110 /* Retrieve aggregate route's lcommunity.
8112 if (aggregate
->lcommunity
)
8113 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8116 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8117 aspath
, community
, ecommunity
,
8118 lcommunity
, atomic_aggregate
, aggregate
);
8121 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8123 struct bgp_path_info
*pi
,
8124 struct bgp_aggregate
*aggregate
,
8125 const struct prefix
*aggr_p
)
8128 struct aspath
*aspath
= NULL
;
8129 uint8_t atomic_aggregate
= 0;
8130 struct community
*community
= NULL
;
8131 struct ecommunity
*ecommunity
= NULL
;
8132 struct lcommunity
*lcommunity
= NULL
;
8133 unsigned long match
= 0;
8135 /* If the bgp instance is being deleted or self peer is deleted
8136 * then do not create aggregate route
8138 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8139 || (bgp
->peer_self
== NULL
))
8142 if (BGP_PATH_HOLDDOWN(pi
))
8145 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8148 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8149 if (aggr_unsuppress_path(aggregate
, pi
))
8152 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8153 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8154 if (aggr_unsuppress_path(aggregate
, pi
))
8158 * This must be called after `summary`, `suppress-map` check to avoid
8159 * "unsuppressing" twice.
8161 if (aggregate
->match_med
)
8162 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8164 if (aggregate
->count
> 0)
8167 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8168 aggregate
->incomplete_origin_count
--;
8169 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8170 aggregate
->egp_origin_count
--;
8172 if (aggregate
->as_set
) {
8173 /* Remove as-path from aggregate.
8175 bgp_remove_aspath_from_aggregate(aggregate
,
8178 if (bgp_attr_get_community(pi
->attr
))
8179 /* Remove community from aggregate.
8181 bgp_remove_community_from_aggregate(
8182 aggregate
, bgp_attr_get_community(pi
->attr
));
8184 if (bgp_attr_get_ecommunity(pi
->attr
))
8185 /* Remove ecommunity from aggregate.
8187 bgp_remove_ecommunity_from_aggregate(
8188 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8190 if (bgp_attr_get_lcommunity(pi
->attr
))
8191 /* Remove lcommunity from aggregate.
8193 bgp_remove_lcommunity_from_aggregate(
8194 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8197 /* If this node was suppressed, process the change. */
8199 bgp_process(bgp
, pi
->net
, afi
, safi
);
8201 origin
= BGP_ORIGIN_IGP
;
8202 if (aggregate
->incomplete_origin_count
> 0)
8203 origin
= BGP_ORIGIN_INCOMPLETE
;
8204 else if (aggregate
->egp_origin_count
> 0)
8205 origin
= BGP_ORIGIN_EGP
;
8207 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8208 origin
= aggregate
->origin
;
8210 if (aggregate
->as_set
) {
8211 /* Retrieve aggregate route's as-path.
8213 if (aggregate
->aspath
)
8214 aspath
= aspath_dup(aggregate
->aspath
);
8216 /* Retrieve aggregate route's community.
8218 if (aggregate
->community
)
8219 community
= community_dup(aggregate
->community
);
8221 /* Retrieve aggregate route's ecommunity.
8223 if (aggregate
->ecommunity
)
8224 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8226 /* Retrieve aggregate route's lcommunity.
8228 if (aggregate
->lcommunity
)
8229 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8232 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8233 aspath
, community
, ecommunity
,
8234 lcommunity
, atomic_aggregate
, aggregate
);
8237 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8238 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8240 struct bgp_dest
*child
;
8241 struct bgp_dest
*dest
;
8242 struct bgp_aggregate
*aggregate
;
8243 struct bgp_table
*table
;
8245 table
= bgp
->aggregate
[afi
][safi
];
8247 /* No aggregates configured. */
8248 if (bgp_table_top_nolock(table
) == NULL
)
8251 if (p
->prefixlen
== 0)
8254 if (BGP_PATH_HOLDDOWN(pi
))
8257 /* If suppress fib is enabled and route not installed
8258 * in FIB, do not update the aggregate route
8260 if (!bgp_check_advertise(bgp
, pi
->net
))
8263 child
= bgp_node_get(table
, p
);
8265 /* Aggregate address configuration check. */
8266 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8267 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8269 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8270 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8271 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8275 bgp_dest_unlock_node(child
);
8278 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8279 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8281 struct bgp_dest
*child
;
8282 struct bgp_dest
*dest
;
8283 struct bgp_aggregate
*aggregate
;
8284 struct bgp_table
*table
;
8286 table
= bgp
->aggregate
[afi
][safi
];
8288 /* No aggregates configured. */
8289 if (bgp_table_top_nolock(table
) == NULL
)
8292 if (p
->prefixlen
== 0)
8295 child
= bgp_node_get(table
, p
);
8297 /* Aggregate address configuration check. */
8298 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8299 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8301 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8302 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8303 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8307 bgp_dest_unlock_node(child
);
8310 /* Aggregate route attribute. */
8311 #define AGGREGATE_SUMMARY_ONLY 1
8312 #define AGGREGATE_AS_SET 1
8313 #define AGGREGATE_AS_UNSET 0
8315 static const char *bgp_origin2str(uint8_t origin
)
8318 case BGP_ORIGIN_IGP
:
8320 case BGP_ORIGIN_EGP
:
8322 case BGP_ORIGIN_INCOMPLETE
:
8323 return "incomplete";
8328 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8331 case RPKI_NOT_BEING_USED
:
8341 assert(!"We should never get here this is a dev escape");
8345 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8346 afi_t afi
, safi_t safi
)
8348 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8351 struct bgp_dest
*dest
;
8352 struct bgp_aggregate
*aggregate
;
8354 /* Convert string to prefix structure. */
8355 ret
= str2prefix(prefix_str
, &p
);
8357 vty_out(vty
, "Malformed prefix\n");
8358 return CMD_WARNING_CONFIG_FAILED
;
8362 /* Old configuration check. */
8363 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8366 "%% There is no aggregate-address configuration.\n");
8367 return CMD_WARNING_CONFIG_FAILED
;
8370 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8371 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8372 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8373 NULL
, NULL
, 0, aggregate
);
8375 /* Unlock aggregate address configuration. */
8376 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8378 if (aggregate
->community
)
8379 community_free(&aggregate
->community
);
8381 if (aggregate
->community_hash
) {
8382 /* Delete all communities in the hash.
8384 hash_clean(aggregate
->community_hash
,
8385 bgp_aggr_community_remove
);
8386 /* Free up the community_hash.
8388 hash_free(aggregate
->community_hash
);
8391 if (aggregate
->ecommunity
)
8392 ecommunity_free(&aggregate
->ecommunity
);
8394 if (aggregate
->ecommunity_hash
) {
8395 /* Delete all ecommunities in the hash.
8397 hash_clean(aggregate
->ecommunity_hash
,
8398 bgp_aggr_ecommunity_remove
);
8399 /* Free up the ecommunity_hash.
8401 hash_free(aggregate
->ecommunity_hash
);
8404 if (aggregate
->lcommunity
)
8405 lcommunity_free(&aggregate
->lcommunity
);
8407 if (aggregate
->lcommunity_hash
) {
8408 /* Delete all lcommunities in the hash.
8410 hash_clean(aggregate
->lcommunity_hash
,
8411 bgp_aggr_lcommunity_remove
);
8412 /* Free up the lcommunity_hash.
8414 hash_free(aggregate
->lcommunity_hash
);
8417 if (aggregate
->aspath
)
8418 aspath_free(aggregate
->aspath
);
8420 if (aggregate
->aspath_hash
) {
8421 /* Delete all as-paths in the hash.
8423 hash_clean(aggregate
->aspath_hash
,
8424 bgp_aggr_aspath_remove
);
8425 /* Free up the aspath_hash.
8427 hash_free(aggregate
->aspath_hash
);
8430 bgp_aggregate_free(aggregate
);
8431 bgp_dest_unlock_node(dest
);
8432 bgp_dest_unlock_node(dest
);
8437 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8438 safi_t safi
, const char *rmap
,
8439 uint8_t summary_only
, uint8_t as_set
,
8440 uint8_t origin
, bool match_med
,
8441 const char *suppress_map
)
8443 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8446 struct bgp_dest
*dest
;
8447 struct bgp_aggregate
*aggregate
;
8448 uint8_t as_set_new
= as_set
;
8450 if (suppress_map
&& summary_only
) {
8452 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8453 return CMD_WARNING_CONFIG_FAILED
;
8456 /* Convert string to prefix structure. */
8457 ret
= str2prefix(prefix_str
, &p
);
8459 vty_out(vty
, "Malformed prefix\n");
8460 return CMD_WARNING_CONFIG_FAILED
;
8464 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8465 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8466 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8468 return CMD_WARNING_CONFIG_FAILED
;
8471 /* Old configuration check. */
8472 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8473 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8476 vty_out(vty
, "There is already same aggregate network.\n");
8477 /* try to remove the old entry */
8478 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8480 vty_out(vty
, "Error deleting aggregate.\n");
8481 bgp_dest_unlock_node(dest
);
8482 return CMD_WARNING_CONFIG_FAILED
;
8486 /* Make aggregate address structure. */
8487 aggregate
= bgp_aggregate_new();
8488 aggregate
->summary_only
= summary_only
;
8489 aggregate
->match_med
= match_med
;
8491 /* Network operators MUST NOT locally generate any new
8492 * announcements containing AS_SET or AS_CONFED_SET. If they have
8493 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8494 * SHOULD withdraw those routes and re-announce routes for the
8495 * aggregate or component prefixes (i.e., the more-specific routes
8496 * subsumed by the previously aggregated route) without AS_SET
8497 * or AS_CONFED_SET in the updates.
8499 if (bgp
->reject_as_sets
) {
8500 if (as_set
== AGGREGATE_AS_SET
) {
8501 as_set_new
= AGGREGATE_AS_UNSET
;
8503 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8506 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8510 aggregate
->as_set
= as_set_new
;
8511 aggregate
->safi
= safi
;
8512 /* Override ORIGIN attribute if defined.
8513 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8514 * to IGP which is not what rfc4271 says.
8515 * This enables the same behavior, optionally.
8517 aggregate
->origin
= origin
;
8520 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8521 route_map_counter_decrement(aggregate
->rmap
.map
);
8522 aggregate
->rmap
.name
=
8523 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8524 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8525 route_map_counter_increment(aggregate
->rmap
.map
);
8529 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8530 route_map_counter_decrement(aggregate
->suppress_map
);
8532 aggregate
->suppress_map_name
=
8533 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8534 aggregate
->suppress_map
=
8535 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8536 route_map_counter_increment(aggregate
->suppress_map
);
8539 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8541 /* Aggregate address insert into BGP routing table. */
8542 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8547 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8548 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8550 "|summary-only$summary_only"
8551 "|route-map RMAP_NAME$rmap_name"
8552 "|origin <egp|igp|incomplete>$origin_s"
8553 "|matching-MED-only$match_med"
8554 "|suppress-map RMAP_NAME$suppress_map"
8557 "Configure BGP aggregate entries\n"
8558 "Aggregate prefix\n"
8559 "Aggregate address\n"
8561 "Generate AS set path information\n"
8562 "Filter more specific routes from updates\n"
8563 "Apply route map to aggregate network\n"
8568 "Unknown heritage\n"
8569 "Only aggregate routes with matching MED\n"
8570 "Suppress the selected more specific routes\n"
8571 "Route map with the route selectors\n")
8573 const char *prefix_s
= NULL
;
8574 safi_t safi
= bgp_node_safi(vty
);
8575 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8576 int as_set
= AGGREGATE_AS_UNSET
;
8577 char prefix_buf
[PREFIX2STR_BUFFER
];
8580 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8583 vty_out(vty
, "%% Inconsistent address and mask\n");
8584 return CMD_WARNING_CONFIG_FAILED
;
8586 prefix_s
= prefix_buf
;
8588 prefix_s
= prefix_str
;
8591 if (strcmp(origin_s
, "egp") == 0)
8592 origin
= BGP_ORIGIN_EGP
;
8593 else if (strcmp(origin_s
, "igp") == 0)
8594 origin
= BGP_ORIGIN_IGP
;
8595 else if (strcmp(origin_s
, "incomplete") == 0)
8596 origin
= BGP_ORIGIN_INCOMPLETE
;
8600 as_set
= AGGREGATE_AS_SET
;
8602 /* Handle configuration removal, otherwise installation. */
8604 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8606 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8607 summary_only
!= NULL
, as_set
, origin
,
8608 match_med
!= NULL
, suppress_map
);
8611 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8612 "[no] aggregate-address X:X::X:X/M$prefix [{"
8614 "|summary-only$summary_only"
8615 "|route-map RMAP_NAME$rmap_name"
8616 "|origin <egp|igp|incomplete>$origin_s"
8617 "|matching-MED-only$match_med"
8618 "|suppress-map RMAP_NAME$suppress_map"
8621 "Configure BGP aggregate entries\n"
8622 "Aggregate prefix\n"
8623 "Generate AS set path information\n"
8624 "Filter more specific routes from updates\n"
8625 "Apply route map to aggregate network\n"
8630 "Unknown heritage\n"
8631 "Only aggregate routes with matching MED\n"
8632 "Suppress the selected more specific routes\n"
8633 "Route map with the route selectors\n")
8635 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8636 int as_set
= AGGREGATE_AS_UNSET
;
8639 if (strcmp(origin_s
, "egp") == 0)
8640 origin
= BGP_ORIGIN_EGP
;
8641 else if (strcmp(origin_s
, "igp") == 0)
8642 origin
= BGP_ORIGIN_IGP
;
8643 else if (strcmp(origin_s
, "incomplete") == 0)
8644 origin
= BGP_ORIGIN_INCOMPLETE
;
8648 as_set
= AGGREGATE_AS_SET
;
8650 /* Handle configuration removal, otherwise installation. */
8652 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8655 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8656 rmap_name
, summary_only
!= NULL
, as_set
,
8657 origin
, match_med
!= NULL
, suppress_map
);
8660 /* Redistribute route treatment. */
8661 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8662 const union g_addr
*nexthop
, ifindex_t ifindex
,
8663 enum nexthop_types_t nhtype
, uint8_t distance
,
8664 enum blackhole_type bhtype
, uint32_t metric
,
8665 uint8_t type
, unsigned short instance
,
8668 struct bgp_path_info
*new;
8669 struct bgp_path_info
*bpi
;
8670 struct bgp_path_info rmap_path
;
8671 struct bgp_dest
*bn
;
8673 struct attr
*new_attr
;
8675 route_map_result_t ret
;
8676 struct bgp_redist
*red
;
8678 /* Make default attribute. */
8679 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8681 * This must not be NULL to satisfy Coverity SA
8683 assert(attr
.aspath
);
8686 case NEXTHOP_TYPE_IFINDEX
:
8687 switch (p
->family
) {
8689 attr
.nexthop
.s_addr
= INADDR_ANY
;
8690 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8693 memset(&attr
.mp_nexthop_global
, 0,
8694 sizeof(attr
.mp_nexthop_global
));
8695 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8699 case NEXTHOP_TYPE_IPV4
:
8700 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8701 attr
.nexthop
= nexthop
->ipv4
;
8702 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8704 case NEXTHOP_TYPE_IPV6
:
8705 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8706 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8707 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8709 case NEXTHOP_TYPE_BLACKHOLE
:
8710 switch (p
->family
) {
8712 attr
.nexthop
.s_addr
= INADDR_ANY
;
8713 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8716 memset(&attr
.mp_nexthop_global
, 0,
8717 sizeof(attr
.mp_nexthop_global
));
8718 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8721 attr
.bh_type
= bhtype
;
8724 attr
.nh_type
= nhtype
;
8725 attr
.nh_ifindex
= ifindex
;
8728 attr
.distance
= distance
;
8729 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8733 bgp_attr_set_aigp_metric(&attr
, metric
);
8735 afi
= family2afi(p
->family
);
8737 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8739 struct attr attr_new
;
8741 /* Copy attribute for modification. */
8744 if (red
->redist_metric_flag
) {
8745 attr_new
.med
= red
->redist_metric
;
8746 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8749 /* Apply route-map. */
8750 if (red
->rmap
.name
) {
8751 memset(&rmap_path
, 0, sizeof(rmap_path
));
8752 rmap_path
.peer
= bgp
->peer_self
;
8753 rmap_path
.attr
= &attr_new
;
8755 SET_FLAG(bgp
->peer_self
->rmap_type
,
8756 PEER_RMAP_TYPE_REDISTRIBUTE
);
8758 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8760 bgp
->peer_self
->rmap_type
= 0;
8762 if (ret
== RMAP_DENYMATCH
) {
8763 /* Free uninterned attribute. */
8764 bgp_attr_flush(&attr_new
);
8766 /* Unintern original. */
8767 aspath_unintern(&attr
.aspath
);
8768 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8773 if (bgp_in_graceful_shutdown(bgp
))
8774 bgp_attr_add_gshut_community(&attr_new
);
8776 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8777 SAFI_UNICAST
, p
, NULL
);
8779 new_attr
= bgp_attr_intern(&attr_new
);
8781 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8782 if (bpi
->peer
== bgp
->peer_self
8783 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8787 /* Ensure the (source route) type is updated. */
8789 if (attrhash_cmp(bpi
->attr
, new_attr
)
8790 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8791 bgp_attr_unintern(&new_attr
);
8792 aspath_unintern(&attr
.aspath
);
8793 bgp_dest_unlock_node(bn
);
8796 /* The attribute is changed. */
8797 bgp_path_info_set_flag(bn
, bpi
,
8798 BGP_PATH_ATTR_CHANGED
);
8800 /* Rewrite BGP route information. */
8801 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8802 bgp_path_info_restore(bn
, bpi
);
8804 bgp_aggregate_decrement(
8805 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8806 bgp_attr_unintern(&bpi
->attr
);
8807 bpi
->attr
= new_attr
;
8808 bpi
->uptime
= monotime(NULL
);
8810 /* Process change. */
8811 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8813 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8814 bgp_dest_unlock_node(bn
);
8815 aspath_unintern(&attr
.aspath
);
8817 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8819 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8821 vpn_leak_from_vrf_update(
8822 bgp_get_default(), bgp
, bpi
);
8828 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8829 bgp
->peer_self
, new_attr
, bn
);
8830 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8832 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8833 bgp_path_info_add(bn
, new);
8834 bgp_dest_unlock_node(bn
);
8835 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8836 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8838 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8839 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8841 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8845 /* Unintern original. */
8846 aspath_unintern(&attr
.aspath
);
8849 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8850 unsigned short instance
)
8853 struct bgp_dest
*dest
;
8854 struct bgp_path_info
*pi
;
8855 struct bgp_redist
*red
;
8857 afi
= family2afi(p
->family
);
8859 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8861 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8862 SAFI_UNICAST
, p
, NULL
);
8864 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8865 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8869 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8870 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8872 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8875 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8876 bgp_path_info_delete(dest
, pi
);
8877 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8879 bgp_dest_unlock_node(dest
);
8883 /* Withdraw specified route type's route. */
8884 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8885 unsigned short instance
)
8887 struct bgp_dest
*dest
;
8888 struct bgp_path_info
*pi
;
8889 struct bgp_table
*table
;
8891 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8893 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8894 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8895 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8896 && pi
->instance
== instance
)
8900 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8901 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8903 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8906 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8907 pi
, afi
, SAFI_UNICAST
);
8908 bgp_path_info_delete(dest
, pi
);
8909 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8914 /* Static function to display route. */
8915 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8916 struct vty
*vty
, json_object
*json
, bool wide
)
8921 if (p
->family
== AF_INET
) {
8923 len
= vty_out(vty
, "%pFX", p
);
8925 json_object_string_add(json
, "prefix",
8926 inet_ntop(p
->family
,
8929 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8930 json_object_string_addf(json
, "network", "%pFX", p
);
8931 json_object_int_add(json
, "version", dest
->version
);
8933 } else if (p
->family
== AF_ETHERNET
) {
8934 len
= vty_out(vty
, "%pFX", p
);
8935 } else if (p
->family
== AF_EVPN
) {
8937 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8939 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8940 } else if (p
->family
== AF_FLOWSPEC
) {
8941 route_vty_out_flowspec(vty
, p
, NULL
,
8943 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8944 NLRI_STRING_FORMAT_MIN
, json
);
8947 len
= vty_out(vty
, "%pFX", p
);
8949 json_object_string_add(json
, "prefix",
8950 inet_ntop(p
->family
,
8953 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8954 json_object_string_addf(json
, "network", "%pFX", p
);
8955 json_object_int_add(json
, "version", dest
->version
);
8960 len
= wide
? (45 - len
) : (17 - len
);
8962 vty_out(vty
, "\n%*s", 20, " ");
8964 vty_out(vty
, "%*s", len
, " ");
8968 enum bgp_display_type
{
8972 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8975 case bgp_path_selection_none
:
8976 return "Nothing to Select";
8977 case bgp_path_selection_first
:
8978 return "First path received";
8979 case bgp_path_selection_evpn_sticky_mac
:
8980 return "EVPN Sticky Mac";
8981 case bgp_path_selection_evpn_seq
:
8982 return "EVPN sequence number";
8983 case bgp_path_selection_evpn_lower_ip
:
8984 return "EVPN lower IP";
8985 case bgp_path_selection_evpn_local_path
:
8986 return "EVPN local ES path";
8987 case bgp_path_selection_evpn_non_proxy
:
8988 return "EVPN non proxy";
8989 case bgp_path_selection_weight
:
8991 case bgp_path_selection_local_pref
:
8992 return "Local Pref";
8993 case bgp_path_selection_accept_own
:
8994 return "Accept Own";
8995 case bgp_path_selection_local_route
:
8996 return "Local Route";
8997 case bgp_path_selection_aigp
:
8999 case bgp_path_selection_confed_as_path
:
9000 return "Confederation based AS Path";
9001 case bgp_path_selection_as_path
:
9003 case bgp_path_selection_origin
:
9005 case bgp_path_selection_med
:
9007 case bgp_path_selection_peer
:
9009 case bgp_path_selection_confed
:
9010 return "Confed Peer Type";
9011 case bgp_path_selection_igp_metric
:
9012 return "IGP Metric";
9013 case bgp_path_selection_older
:
9014 return "Older Path";
9015 case bgp_path_selection_router_id
:
9017 case bgp_path_selection_cluster_length
:
9018 return "Cluster length";
9019 case bgp_path_selection_stale
:
9020 return "Path Staleness";
9021 case bgp_path_selection_local_configured
:
9022 return "Locally configured route";
9023 case bgp_path_selection_neighbor_ip
:
9024 return "Neighbor IP";
9025 case bgp_path_selection_default
:
9026 return "Nothing left to compare";
9028 return "Invalid (internal error)";
9031 /* Print the short form route status for a bgp_path_info */
9032 static void route_vty_short_status_out(struct vty
*vty
,
9033 struct bgp_path_info
*path
,
9034 const struct prefix
*p
,
9035 json_object
*json_path
)
9037 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
9041 /* Route status display. */
9042 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9043 json_object_boolean_true_add(json_path
, "removed");
9045 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9046 json_object_boolean_true_add(json_path
, "stale");
9048 if (path
->extra
&& bgp_path_suppressed(path
))
9049 json_object_boolean_true_add(json_path
, "suppressed");
9051 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9052 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9053 json_object_boolean_true_add(json_path
, "valid");
9056 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9057 json_object_boolean_true_add(json_path
, "history");
9059 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9060 json_object_boolean_true_add(json_path
, "damped");
9062 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9063 json_object_boolean_true_add(json_path
, "bestpath");
9064 json_object_string_add(json_path
, "selectionReason",
9065 bgp_path_selection_reason2str(
9066 path
->net
->reason
));
9069 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9070 json_object_boolean_true_add(json_path
, "multipath");
9072 /* Internal route. */
9073 if ((path
->peer
->as
)
9074 && (path
->peer
->as
== path
->peer
->local_as
))
9075 json_object_string_add(json_path
, "pathFrom",
9078 json_object_string_add(json_path
, "pathFrom",
9084 /* RPKI validation state */
9086 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9088 if (rpki_state
== RPKI_VALID
)
9090 else if (rpki_state
== RPKI_INVALID
)
9092 else if (rpki_state
== RPKI_NOTFOUND
)
9097 /* Route status display. */
9098 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9100 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9102 else if (bgp_path_suppressed(path
))
9104 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9105 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9111 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9113 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9115 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9117 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9122 /* Internal route. */
9123 if (path
->peer
&& (path
->peer
->as
)
9124 && (path
->peer
->as
== path
->peer
->local_as
))
9130 static char *bgp_nexthop_hostname(struct peer
*peer
,
9131 struct bgp_nexthop_cache
*bnc
)
9134 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9135 return peer
->hostname
;
9139 /* called from terminal list command */
9140 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9141 struct bgp_path_info
*path
, int display
, safi_t safi
,
9142 json_object
*json_paths
, bool wide
)
9145 struct attr
*attr
= path
->attr
;
9146 json_object
*json_path
= NULL
;
9147 json_object
*json_nexthops
= NULL
;
9148 json_object
*json_nexthop_global
= NULL
;
9149 json_object
*json_nexthop_ll
= NULL
;
9150 json_object
*json_ext_community
= NULL
;
9151 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9153 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9154 bool nexthop_othervrf
= false;
9155 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9156 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9157 char *nexthop_hostname
=
9158 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9159 char esi_buf
[ESI_STR_LEN
];
9162 json_path
= json_object_new_object();
9164 /* short status lead text */
9165 route_vty_short_status_out(vty
, path
, p
, json_path
);
9168 /* print prefix and mask */
9170 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9172 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9174 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9178 * If vrf id of nexthop is different from that of prefix,
9179 * set up printable string to append
9181 if (path
->extra
&& path
->extra
->bgp_orig
) {
9182 const char *self
= "";
9187 nexthop_othervrf
= true;
9188 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9190 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9191 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9192 "@%s%s", VRFID_NONE_STR
, self
);
9194 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9195 path
->extra
->bgp_orig
->vrf_id
, self
);
9197 if (path
->extra
->bgp_orig
->inst_type
9198 != BGP_INSTANCE_TYPE_DEFAULT
)
9200 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9202 const char *self
= "";
9207 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9211 * For ENCAP and EVPN routes, nexthop address family is not
9212 * neccessarily the same as the prefix address family.
9213 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9214 * EVPN routes are also exchanged with a MP nexthop. Currently,
9216 * is only IPv4, the value will be present in either
9218 * attr->mp_nexthop_global_in
9220 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9223 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9227 snprintf(nexthop
, sizeof(nexthop
), "%s",
9228 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
9232 snprintf(nexthop
, sizeof(nexthop
), "%s",
9233 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
9237 snprintf(nexthop
, sizeof(nexthop
), "?");
9242 json_nexthop_global
= json_object_new_object();
9244 json_object_string_add(json_nexthop_global
, "ip",
9247 if (path
->peer
->hostname
)
9248 json_object_string_add(json_nexthop_global
,
9250 path
->peer
->hostname
);
9252 json_object_string_add(json_nexthop_global
, "afi",
9253 (af
== AF_INET
) ? "ipv4"
9255 json_object_boolean_true_add(json_nexthop_global
,
9258 if (nexthop_hostname
)
9259 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9260 nexthop_hostname
, vrf_id_str
);
9262 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9264 len
= wide
? (41 - len
) : (16 - len
);
9266 vty_out(vty
, "\n%*s", 36, " ");
9268 vty_out(vty
, "%*s", len
, " ");
9270 } else if (safi
== SAFI_EVPN
) {
9272 json_nexthop_global
= json_object_new_object();
9274 json_object_string_addf(json_nexthop_global
, "ip",
9276 &attr
->mp_nexthop_global_in
);
9278 if (path
->peer
->hostname
)
9279 json_object_string_add(json_nexthop_global
,
9281 path
->peer
->hostname
);
9283 json_object_string_add(json_nexthop_global
, "afi",
9285 json_object_boolean_true_add(json_nexthop_global
,
9288 if (nexthop_hostname
)
9289 len
= vty_out(vty
, "%pI4(%s)%s",
9290 &attr
->mp_nexthop_global_in
,
9291 nexthop_hostname
, vrf_id_str
);
9293 len
= vty_out(vty
, "%pI4%s",
9294 &attr
->mp_nexthop_global_in
,
9297 len
= wide
? (41 - len
) : (16 - len
);
9299 vty_out(vty
, "\n%*s", 36, " ");
9301 vty_out(vty
, "%*s", len
, " ");
9303 } else if (safi
== SAFI_FLOWSPEC
) {
9304 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9306 json_nexthop_global
= json_object_new_object();
9308 json_object_string_add(json_nexthop_global
,
9310 json_object_string_addf(json_nexthop_global
,
9314 if (path
->peer
->hostname
)
9315 json_object_string_add(
9316 json_nexthop_global
, "hostname",
9317 path
->peer
->hostname
);
9319 json_object_boolean_true_add(
9320 json_nexthop_global
,
9323 if (nexthop_hostname
)
9324 len
= vty_out(vty
, "%pI4(%s)%s",
9329 len
= vty_out(vty
, "%pI4%s",
9333 len
= wide
? (41 - len
) : (16 - len
);
9335 vty_out(vty
, "\n%*s", 36, " ");
9337 vty_out(vty
, "%*s", len
, " ");
9340 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9342 json_nexthop_global
= json_object_new_object();
9344 json_object_string_addf(json_nexthop_global
, "ip",
9345 "%pI4", &attr
->nexthop
);
9347 if (path
->peer
->hostname
)
9348 json_object_string_add(json_nexthop_global
,
9350 path
->peer
->hostname
);
9352 json_object_string_add(json_nexthop_global
, "afi",
9354 json_object_boolean_true_add(json_nexthop_global
,
9357 if (nexthop_hostname
)
9358 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9359 nexthop_hostname
, vrf_id_str
);
9361 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9364 len
= wide
? (41 - len
) : (16 - len
);
9366 vty_out(vty
, "\n%*s", 36, " ");
9368 vty_out(vty
, "%*s", len
, " ");
9373 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9375 json_nexthop_global
= json_object_new_object();
9376 json_object_string_addf(json_nexthop_global
, "ip",
9378 &attr
->mp_nexthop_global
);
9380 if (path
->peer
->hostname
)
9381 json_object_string_add(json_nexthop_global
,
9383 path
->peer
->hostname
);
9385 json_object_string_add(json_nexthop_global
, "afi",
9387 json_object_string_add(json_nexthop_global
, "scope",
9390 /* We display both LL & GL if both have been
9392 if ((attr
->mp_nexthop_len
9393 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9394 || (path
->peer
->conf_if
)) {
9395 json_nexthop_ll
= json_object_new_object();
9396 json_object_string_addf(
9397 json_nexthop_ll
, "ip", "%pI6",
9398 &attr
->mp_nexthop_local
);
9400 if (path
->peer
->hostname
)
9401 json_object_string_add(
9402 json_nexthop_ll
, "hostname",
9403 path
->peer
->hostname
);
9405 json_object_string_add(json_nexthop_ll
, "afi",
9407 json_object_string_add(json_nexthop_ll
, "scope",
9410 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9411 &attr
->mp_nexthop_local
)
9413 && !attr
->mp_nexthop_prefer_global
)
9414 json_object_boolean_true_add(
9415 json_nexthop_ll
, "used");
9417 json_object_boolean_true_add(
9418 json_nexthop_global
, "used");
9420 json_object_boolean_true_add(
9421 json_nexthop_global
, "used");
9423 /* Display LL if LL/Global both in table unless
9424 * prefer-global is set */
9425 if (((attr
->mp_nexthop_len
9426 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9427 && !attr
->mp_nexthop_prefer_global
)
9428 || (path
->peer
->conf_if
)) {
9429 if (path
->peer
->conf_if
) {
9430 len
= vty_out(vty
, "%s",
9431 path
->peer
->conf_if
);
9432 /* len of IPv6 addr + max len of def
9434 len
= wide
? (41 - len
) : (16 - len
);
9437 vty_out(vty
, "\n%*s", 36, " ");
9439 vty_out(vty
, "%*s", len
, " ");
9441 if (nexthop_hostname
)
9444 &attr
->mp_nexthop_local
,
9450 &attr
->mp_nexthop_local
,
9453 len
= wide
? (41 - len
) : (16 - len
);
9456 vty_out(vty
, "\n%*s", 36, " ");
9458 vty_out(vty
, "%*s", len
, " ");
9461 if (nexthop_hostname
)
9462 len
= vty_out(vty
, "%pI6(%s)%s",
9463 &attr
->mp_nexthop_global
,
9467 len
= vty_out(vty
, "%pI6%s",
9468 &attr
->mp_nexthop_global
,
9471 len
= wide
? (41 - len
) : (16 - len
);
9474 vty_out(vty
, "\n%*s", 36, " ");
9476 vty_out(vty
, "%*s", len
, " ");
9482 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9484 json_object_int_add(json_path
, "metric", attr
->med
);
9486 vty_out(vty
, "%7u", attr
->med
);
9488 vty_out(vty
, "%10u", attr
->med
);
9489 else if (!json_paths
) {
9491 vty_out(vty
, "%*s", 7, " ");
9493 vty_out(vty
, "%*s", 10, " ");
9497 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9499 json_object_int_add(json_path
, "locPrf",
9502 vty_out(vty
, "%7u", attr
->local_pref
);
9503 else if (!json_paths
)
9507 json_object_int_add(json_path
, "weight", attr
->weight
);
9509 vty_out(vty
, "%7u ", attr
->weight
);
9512 json_object_string_addf(json_path
, "peerId", "%pSU",
9518 json_object_string_add(json_path
, "path",
9521 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9526 json_object_string_add(json_path
, "origin",
9527 bgp_origin_long_str
[attr
->origin
]);
9529 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9532 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9533 json_object_string_add(json_path
, "esi",
9534 esi_to_str(&attr
->esi
,
9535 esi_buf
, sizeof(esi_buf
)));
9537 if (safi
== SAFI_EVPN
&&
9538 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9539 json_ext_community
= json_object_new_object();
9540 json_object_string_add(
9541 json_ext_community
, "string",
9542 bgp_attr_get_ecommunity(attr
)->str
);
9543 json_object_object_add(json_path
,
9544 "extendedCommunity",
9545 json_ext_community
);
9549 json_object_boolean_true_add(json_path
,
9550 "announceNexthopSelf");
9551 if (nexthop_othervrf
) {
9552 json_object_string_add(json_path
, "nhVrfName",
9555 json_object_int_add(json_path
, "nhVrfId",
9556 ((nexthop_vrfid
== VRF_UNKNOWN
)
9558 : (int)nexthop_vrfid
));
9563 if (json_nexthop_global
|| json_nexthop_ll
) {
9564 json_nexthops
= json_object_new_array();
9566 if (json_nexthop_global
)
9567 json_object_array_add(json_nexthops
,
9568 json_nexthop_global
);
9570 if (json_nexthop_ll
)
9571 json_object_array_add(json_nexthops
,
9574 json_object_object_add(json_path
, "nexthops",
9578 json_object_array_add(json_paths
, json_path
);
9582 if (safi
== SAFI_EVPN
) {
9583 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9584 /* XXX - add these params to the json out */
9585 vty_out(vty
, "%*s", 20, " ");
9586 vty_out(vty
, "ESI:%s",
9587 esi_to_str(&attr
->esi
, esi_buf
,
9593 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9594 vty_out(vty
, "%*s", 20, " ");
9595 vty_out(vty
, "%s\n",
9596 bgp_attr_get_ecommunity(attr
)->str
);
9600 #ifdef ENABLE_BGP_VNC
9601 /* prints an additional line, indented, with VNC info, if
9603 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9604 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9609 /* called from terminal list command */
9610 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9611 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9612 bool use_json
, json_object
*json_ar
, bool wide
)
9614 json_object
*json_status
= NULL
;
9615 json_object
*json_net
= NULL
;
9619 /* Route status display. */
9621 json_status
= json_object_new_object();
9622 json_net
= json_object_new_object();
9629 /* print prefix and mask */
9631 if (safi
== SAFI_EVPN
)
9632 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9633 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9634 json_object_string_add(
9635 json_net
, "addrPrefix",
9636 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9638 json_object_int_add(json_net
, "prefixLen",
9640 json_object_string_addf(json_net
, "network", "%pFX", p
);
9643 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9645 /* Print attribute */
9648 if (p
->family
== AF_INET
&&
9649 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9650 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9651 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9652 json_object_string_addf(
9653 json_net
, "nextHop", "%pI4",
9654 &attr
->mp_nexthop_global_in
);
9656 json_object_string_addf(
9657 json_net
, "nextHop", "%pI4",
9659 } else if (p
->family
== AF_INET6
||
9660 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9661 json_object_string_addf(
9662 json_net
, "nextHopGlobal", "%pI6",
9663 &attr
->mp_nexthop_global
);
9664 } else if (p
->family
== AF_EVPN
&&
9665 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9666 json_object_string_addf(
9667 json_net
, "nextHop", "%pI4",
9668 &attr
->mp_nexthop_global_in
);
9672 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9673 json_object_int_add(json_net
, "metric",
9676 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9677 json_object_int_add(json_net
, "locPrf",
9680 json_object_int_add(json_net
, "weight", attr
->weight
);
9684 json_object_string_add(json_net
, "path",
9688 json_object_string_add(json_net
, "bgpOriginCode",
9689 bgp_origin_str
[attr
->origin
]);
9691 if (p
->family
== AF_INET
&&
9692 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9693 safi
== SAFI_EVPN
||
9694 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9695 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9696 || safi
== SAFI_EVPN
)
9697 vty_out(vty
, "%-16pI4",
9698 &attr
->mp_nexthop_global_in
);
9700 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9702 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9703 } else if (p
->family
== AF_INET6
||
9704 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9710 &attr
->mp_nexthop_global
, buf
,
9712 len
= wide
? (41 - len
) : (16 - len
);
9714 vty_out(vty
, "\n%*s", 36, " ");
9716 vty_out(vty
, "%*s", len
, " ");
9719 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9721 vty_out(vty
, "%7u", attr
->med
);
9723 vty_out(vty
, "%10u", attr
->med
);
9729 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9730 vty_out(vty
, "%7u", attr
->local_pref
);
9734 vty_out(vty
, "%7u ", attr
->weight
);
9738 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9741 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9745 json_object_boolean_true_add(json_status
, "*");
9746 json_object_boolean_true_add(json_status
, ">");
9747 json_object_object_add(json_net
, "appliedStatusSymbols",
9749 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9754 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9755 struct bgp_path_info
*path
, int display
, safi_t safi
,
9758 json_object
*json_out
= NULL
;
9760 mpls_label_t label
= MPLS_INVALID_LABEL
;
9766 json_out
= json_object_new_object();
9768 /* short status lead text */
9769 route_vty_short_status_out(vty
, path
, p
, json_out
);
9771 /* print prefix and mask */
9774 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9776 vty_out(vty
, "%*s", 17, " ");
9779 /* Print attribute */
9781 if (((p
->family
== AF_INET
) &&
9782 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9783 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9784 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9785 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9786 || safi
== SAFI_EVPN
) {
9788 json_object_string_addf(
9789 json_out
, "mpNexthopGlobalIn", "%pI4",
9790 &attr
->mp_nexthop_global_in
);
9792 vty_out(vty
, "%-16pI4",
9793 &attr
->mp_nexthop_global_in
);
9796 json_object_string_addf(json_out
, "nexthop",
9797 "%pI4", &attr
->nexthop
);
9799 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9801 } else if (((p
->family
== AF_INET6
) &&
9802 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9803 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9804 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9807 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9809 json_object_string_addf(
9810 json_out
, "mpNexthopGlobalIn", "%pI6",
9811 &attr
->mp_nexthop_global
);
9815 &attr
->mp_nexthop_global
,
9816 buf_a
, sizeof(buf_a
)));
9817 } else if (attr
->mp_nexthop_len
9818 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9819 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9820 &attr
->mp_nexthop_global
,
9821 &attr
->mp_nexthop_local
);
9823 json_object_string_add(json_out
,
9824 "mpNexthopGlobalLocal",
9827 vty_out(vty
, "%s", buf_a
);
9831 label
= decode_label(&path
->extra
->label
[0]);
9833 if (bgp_is_valid_label(&label
)) {
9835 json_object_int_add(json_out
, "notag", label
);
9836 json_object_array_add(json
, json_out
);
9838 vty_out(vty
, "notag/%d", label
);
9845 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9846 struct bgp_path_info
*path
, int display
,
9847 json_object
*json_paths
)
9850 json_object
*json_path
= NULL
;
9851 json_object
*json_nexthop
= NULL
;
9852 json_object
*json_overlay
= NULL
;
9858 json_path
= json_object_new_object();
9859 json_overlay
= json_object_new_object();
9860 json_nexthop
= json_object_new_object();
9863 /* short status lead text */
9864 route_vty_short_status_out(vty
, path
, p
, json_path
);
9866 /* print prefix and mask */
9868 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9870 vty_out(vty
, "%*s", 17, " ");
9872 /* Print attribute */
9874 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9879 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9881 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9882 &attr
->mp_nexthop_global_in
);
9884 json_object_string_add(json_nexthop
, "afi", "ipv4");
9886 json_object_object_add(json_path
, "nexthop",
9892 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9893 &attr
->mp_nexthop_local
);
9895 json_object_string_addf(json_nexthop
, "ipv6Global",
9897 &attr
->mp_nexthop_global
);
9899 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9901 &attr
->mp_nexthop_local
);
9903 json_object_string_add(json_nexthop
, "afi", "ipv6");
9905 json_object_object_add(json_path
, "nexthop",
9913 json_object_string_add(json_nexthop
, "Error",
9914 "Unsupported address-family");
9915 json_object_string_add(json_nexthop
, "error",
9916 "Unsupported address-family");
9920 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9923 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9925 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9927 if (bgp_attr_get_ecommunity(attr
)) {
9929 struct ecommunity_val
*routermac
= ecommunity_lookup(
9930 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9931 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9934 mac
= ecom_mac2str((char *)routermac
->val
);
9937 vty_out(vty
, "/%s", mac
);
9939 json_object_string_add(json_overlay
, "rmac",
9942 XFREE(MTYPE_TMP
, mac
);
9949 json_object_object_add(json_path
, "overlay", json_overlay
);
9951 json_object_array_add(json_paths
, json_path
);
9955 /* dampening route */
9956 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9957 struct bgp_path_info
*path
, int display
,
9958 afi_t afi
, safi_t safi
, bool use_json
,
9959 json_object
*json_paths
)
9961 struct attr
*attr
= path
->attr
;
9963 char timebuf
[BGP_UPTIME_LEN
];
9964 json_object
*json_path
= NULL
;
9967 json_path
= json_object_new_object();
9969 /* short status lead text */
9970 route_vty_short_status_out(vty
, path
, p
, json_path
);
9972 /* print prefix and mask */
9975 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9977 vty_out(vty
, "%*s", 17, " ");
9979 len
= vty_out(vty
, "%s", path
->peer
->host
);
9983 vty_out(vty
, "\n%*s", 34, " ");
9985 vty_out(vty
, "%*s", len
, " ");
9988 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9989 BGP_UPTIME_LEN
, afi
, safi
,
9993 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9995 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9999 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
10000 safi
, use_json
, json_path
);
10003 json_object_string_add(json_path
, "asPath",
10004 attr
->aspath
->str
);
10006 json_object_string_add(json_path
, "origin",
10007 bgp_origin_str
[attr
->origin
]);
10008 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10010 json_object_array_add(json_paths
, json_path
);
10015 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
10016 struct bgp_path_info
*path
, int display
,
10017 afi_t afi
, safi_t safi
, bool use_json
,
10018 json_object
*json_paths
)
10020 struct attr
*attr
= path
->attr
;
10021 struct bgp_damp_info
*bdi
;
10022 char timebuf
[BGP_UPTIME_LEN
];
10024 json_object
*json_path
= NULL
;
10030 json_path
= json_object_new_object();
10032 bdi
= path
->extra
->damp_info
;
10034 /* short status lead text */
10035 route_vty_short_status_out(vty
, path
, p
, json_path
);
10039 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10041 vty_out(vty
, "%*s", 17, " ");
10043 len
= vty_out(vty
, "%s", path
->peer
->host
);
10046 vty_out(vty
, "\n%*s", 33, " ");
10048 vty_out(vty
, "%*s", len
, " ");
10050 len
= vty_out(vty
, "%d", bdi
->flap
);
10055 vty_out(vty
, "%*s", len
, " ");
10057 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10058 BGP_UPTIME_LEN
, 0, NULL
));
10060 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10061 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10062 vty_out(vty
, "%s ",
10063 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10064 BGP_UPTIME_LEN
, afi
,
10065 safi
, use_json
, NULL
));
10067 vty_out(vty
, "%*s ", 8, " ");
10070 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
10072 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10074 vty_out(vty
, "\n");
10076 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10077 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10079 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10082 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10083 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10084 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10085 BGP_UPTIME_LEN
, afi
, safi
,
10086 use_json
, json_path
);
10089 json_object_string_add(json_path
, "asPath",
10090 attr
->aspath
->str
);
10092 json_object_string_add(json_path
, "origin",
10093 bgp_origin_str
[attr
->origin
]);
10095 json_object_array_add(json_paths
, json_path
);
10099 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10100 int *first
, const char *header
,
10101 json_object
*json_adv_to
)
10103 json_object
*json_peer
= NULL
;
10106 /* 'advertised-to' is a dictionary of peers we have advertised
10108 * prefix too. The key is the peer's IP or swpX, the value is
10110 * hostname if we know it and "" if not.
10112 json_peer
= json_object_new_object();
10114 if (peer
->hostname
)
10115 json_object_string_add(json_peer
, "hostname",
10119 json_object_object_add(json_adv_to
, peer
->conf_if
,
10122 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10126 vty_out(vty
, "%s", header
);
10131 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10133 vty_out(vty
, " %s(%s)", peer
->hostname
,
10136 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10140 vty_out(vty
, " %s", peer
->conf_if
);
10142 vty_out(vty
, " %pSU", &peer
->su
);
10147 static void route_vty_out_tx_ids(struct vty
*vty
,
10148 struct bgp_addpath_info_data
*d
)
10152 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10153 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10154 d
->addpath_tx_id
[i
],
10155 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10159 static void route_vty_out_detail_es_info(struct vty
*vty
,
10160 struct bgp_path_info
*pi
,
10162 json_object
*json_path
)
10164 char esi_buf
[ESI_STR_LEN
];
10165 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10166 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10167 ATTR_ES_PEER_ROUTER
);
10168 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10169 ATTR_ES_PEER_ACTIVE
);
10170 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10171 ATTR_ES_PEER_PROXY
);
10172 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10174 json_object
*json_es_info
= NULL
;
10176 json_object_string_add(
10179 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10180 json_es_info
= json_object_new_object();
10182 json_object_boolean_true_add(
10183 json_es_info
, "localEs");
10185 json_object_boolean_true_add(
10186 json_es_info
, "peerActive");
10188 json_object_boolean_true_add(
10189 json_es_info
, "peerProxy");
10191 json_object_boolean_true_add(
10192 json_es_info
, "peerRouter");
10193 if (attr
->mm_sync_seqnum
)
10194 json_object_int_add(
10195 json_es_info
, "peerSeq",
10196 attr
->mm_sync_seqnum
);
10197 json_object_object_add(
10198 json_path
, "es_info",
10202 if (bgp_evpn_attr_is_sync(attr
))
10204 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10206 es_local
? "local-es":"",
10207 peer_proxy
? "proxy " : "",
10208 peer_active
? "active ":"",
10209 peer_router
? "router ":"",
10210 attr
->mm_sync_seqnum
);
10212 vty_out(vty
, " ESI %s %s\n",
10214 es_local
? "local-es":"");
10218 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10219 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
10220 enum rpki_states rpki_curr_state
,
10221 json_object
*json_paths
)
10223 char buf
[INET6_ADDRSTRLEN
];
10225 struct attr
*attr
= path
->attr
;
10227 json_object
*json_bestpath
= NULL
;
10228 json_object
*json_cluster_list
= NULL
;
10229 json_object
*json_cluster_list_list
= NULL
;
10230 json_object
*json_ext_community
= NULL
;
10231 json_object
*json_last_update
= NULL
;
10232 json_object
*json_pmsi
= NULL
;
10233 json_object
*json_nexthop_global
= NULL
;
10234 json_object
*json_nexthop_ll
= NULL
;
10235 json_object
*json_nexthops
= NULL
;
10236 json_object
*json_path
= NULL
;
10237 json_object
*json_peer
= NULL
;
10238 json_object
*json_string
= NULL
;
10239 json_object
*json_adv_to
= NULL
;
10241 struct listnode
*node
, *nnode
;
10243 bool addpath_capable
;
10245 unsigned int first_as
;
10246 bool nexthop_self
=
10247 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10249 char *nexthop_hostname
=
10250 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10254 mpls_label_t label
= MPLS_INVALID_LABEL
;
10257 json_path
= json_object_new_object();
10258 json_peer
= json_object_new_object();
10259 json_nexthop_global
= json_object_new_object();
10262 if (safi
== SAFI_EVPN
) {
10264 vty_out(vty
, " Route %pRN", bn
);
10271 if (path
->extra
&& path
->extra
->num_labels
) {
10272 bgp_evpn_label2str(path
->extra
->label
,
10273 path
->extra
->num_labels
, tag_buf
,
10276 if (safi
== SAFI_EVPN
) {
10278 if (tag_buf
[0] != '\0')
10279 vty_out(vty
, " VNI %s", tag_buf
);
10282 json_object_string_add(json_path
, "VNI",
10284 json_object_string_add(json_path
, "vni",
10290 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10291 struct bgp_path_info
*parent_ri
;
10292 struct bgp_dest
*dest
, *pdest
;
10294 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10295 dest
= parent_ri
->net
;
10296 if (dest
&& dest
->pdest
) {
10297 pdest
= dest
->pdest
;
10298 if (is_pi_family_evpn(parent_ri
)) {
10300 " Imported from %pRD:%pFX, VNI %s",
10301 (struct prefix_rd
*)
10302 bgp_dest_get_prefix(
10304 (struct prefix_evpn
*)
10305 bgp_dest_get_prefix(
10308 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
10309 vty_out(vty
, ", L3NHG %s",
10311 & ATTR_ES_L3_NHG_ACTIVE
)
10314 vty_out(vty
, "\n");
10318 " Imported from %pRD:%pFX\n",
10319 (struct prefix_rd
*)
10320 bgp_dest_get_prefix(
10322 (struct prefix_evpn
*)
10323 bgp_dest_get_prefix(
10329 if (safi
== SAFI_EVPN
10330 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10331 char gwip_buf
[INET6_ADDRSTRLEN
];
10333 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10337 json_object_string_add(json_path
, "gatewayIP",
10340 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10343 if (safi
== SAFI_EVPN
&& !json_path
)
10344 vty_out(vty
, "\n");
10346 /* Line1 display AS-path, Aggregator */
10347 if (attr
->aspath
) {
10349 if (!attr
->aspath
->json
)
10350 aspath_str_update(attr
->aspath
, true);
10351 json_object_lock(attr
->aspath
->json
);
10352 json_object_object_add(json_path
, "aspath",
10353 attr
->aspath
->json
);
10355 if (attr
->aspath
->segments
)
10356 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
10358 vty_out(vty
, " Local");
10362 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10364 json_object_boolean_true_add(json_path
, "removed");
10366 vty_out(vty
, ", (removed)");
10369 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10371 json_object_boolean_true_add(json_path
, "stale");
10373 vty_out(vty
, ", (stale)");
10376 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10378 json_object_int_add(json_path
, "aggregatorAs",
10379 attr
->aggregator_as
);
10380 json_object_string_addf(json_path
, "aggregatorId",
10381 "%pI4", &attr
->aggregator_addr
);
10383 vty_out(vty
, ", (aggregated by %u %pI4)",
10384 attr
->aggregator_as
, &attr
->aggregator_addr
);
10388 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10389 PEER_FLAG_REFLECTOR_CLIENT
)) {
10391 json_object_boolean_true_add(json_path
,
10392 "rxedFromRrClient");
10394 vty_out(vty
, ", (Received from a RR-client)");
10397 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10398 PEER_FLAG_RSERVER_CLIENT
)) {
10400 json_object_boolean_true_add(json_path
,
10401 "rxedFromRsClient");
10403 vty_out(vty
, ", (Received from a RS-client)");
10406 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10408 json_object_boolean_true_add(json_path
,
10409 "dampeningHistoryEntry");
10411 vty_out(vty
, ", (history entry)");
10412 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10414 json_object_boolean_true_add(json_path
,
10415 "dampeningSuppressed");
10417 vty_out(vty
, ", (suppressed due to dampening)");
10421 vty_out(vty
, "\n");
10423 /* Line2 display Next-hop, Neighbor, Router-id */
10424 /* Display the nexthop */
10425 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
10427 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
||
10428 bn_p
->family
== AF_EVPN
) &&
10429 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10430 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10431 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10432 || safi
== SAFI_EVPN
) {
10434 json_object_string_addf(
10435 json_nexthop_global
, "ip", "%pI4",
10436 &attr
->mp_nexthop_global_in
);
10438 if (path
->peer
->hostname
)
10439 json_object_string_add(
10440 json_nexthop_global
, "hostname",
10441 path
->peer
->hostname
);
10443 if (nexthop_hostname
)
10444 vty_out(vty
, " %pI4(%s)",
10445 &attr
->mp_nexthop_global_in
,
10448 vty_out(vty
, " %pI4",
10449 &attr
->mp_nexthop_global_in
);
10453 json_object_string_addf(json_nexthop_global
,
10457 if (path
->peer
->hostname
)
10458 json_object_string_add(
10459 json_nexthop_global
, "hostname",
10460 path
->peer
->hostname
);
10462 if (nexthop_hostname
)
10463 vty_out(vty
, " %pI4(%s)",
10467 vty_out(vty
, " %pI4",
10473 json_object_string_add(json_nexthop_global
, "afi",
10477 json_object_string_addf(json_nexthop_global
, "ip",
10479 &attr
->mp_nexthop_global
);
10481 if (path
->peer
->hostname
)
10482 json_object_string_add(json_nexthop_global
,
10484 path
->peer
->hostname
);
10486 json_object_string_add(json_nexthop_global
, "afi",
10488 json_object_string_add(json_nexthop_global
, "scope",
10491 if (nexthop_hostname
)
10492 vty_out(vty
, " %pI6(%s)",
10493 &attr
->mp_nexthop_global
,
10496 vty_out(vty
, " %pI6",
10497 &attr
->mp_nexthop_global
);
10501 /* Display the IGP cost or 'inaccessible' */
10502 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10503 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10506 json_object_boolean_false_add(json_nexthop_global
,
10508 json_object_boolean_add(json_nexthop_global
,
10509 "importCheckEnabled", import
);
10511 vty_out(vty
, " (inaccessible%s)",
10512 import
? ", import-check enabled" : "");
10515 if (path
->extra
&& path
->extra
->igpmetric
) {
10517 json_object_int_add(json_nexthop_global
,
10519 path
->extra
->igpmetric
);
10521 vty_out(vty
, " (metric %u)",
10522 path
->extra
->igpmetric
);
10525 /* IGP cost is 0, display this only for json */
10528 json_object_int_add(json_nexthop_global
,
10533 json_object_boolean_true_add(json_nexthop_global
,
10537 /* Display peer "from" output */
10538 /* This path was originated locally */
10539 if (path
->peer
== bgp
->peer_self
) {
10541 if (safi
== SAFI_EVPN
|| (bn_p
->family
== AF_INET
&&
10542 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10544 json_object_string_add(json_peer
, "peerId",
10547 vty_out(vty
, " from 0.0.0.0 ");
10550 json_object_string_add(json_peer
, "peerId",
10553 vty_out(vty
, " from :: ");
10557 json_object_string_addf(json_peer
, "routerId", "%pI4",
10560 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10563 /* We RXed this path from one of our peers */
10567 json_object_string_addf(json_peer
, "peerId", "%pSU",
10569 json_object_string_addf(json_peer
, "routerId", "%pI4",
10570 &path
->peer
->remote_id
);
10572 if (path
->peer
->hostname
)
10573 json_object_string_add(json_peer
, "hostname",
10574 path
->peer
->hostname
);
10576 if (path
->peer
->domainname
)
10577 json_object_string_add(json_peer
, "domainname",
10578 path
->peer
->domainname
);
10580 if (path
->peer
->conf_if
)
10581 json_object_string_add(json_peer
, "interface",
10582 path
->peer
->conf_if
);
10584 if (path
->peer
->conf_if
) {
10585 if (path
->peer
->hostname
10586 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10587 BGP_FLAG_SHOW_HOSTNAME
))
10588 vty_out(vty
, " from %s(%s)",
10589 path
->peer
->hostname
,
10590 path
->peer
->conf_if
);
10592 vty_out(vty
, " from %s",
10593 path
->peer
->conf_if
);
10595 if (path
->peer
->hostname
10596 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10597 BGP_FLAG_SHOW_HOSTNAME
))
10598 vty_out(vty
, " from %s(%s)",
10599 path
->peer
->hostname
,
10602 vty_out(vty
, " from %pSU",
10606 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10607 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10609 vty_out(vty
, " (%s)",
10611 &path
->peer
->remote_id
, buf1
,
10617 * Note when vrfid of nexthop is different from that of prefix
10619 if (path
->extra
&& path
->extra
->bgp_orig
) {
10620 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10625 if (path
->extra
->bgp_orig
->inst_type
10626 == BGP_INSTANCE_TYPE_DEFAULT
)
10627 vn
= VRF_DEFAULT_NAME
;
10629 vn
= path
->extra
->bgp_orig
->name
;
10631 json_object_string_add(json_path
, "nhVrfName", vn
);
10633 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10634 json_object_int_add(json_path
, "nhVrfId", -1);
10636 json_object_int_add(json_path
, "nhVrfId",
10637 (int)nexthop_vrfid
);
10640 if (nexthop_vrfid
== VRF_UNKNOWN
)
10641 vty_out(vty
, " vrf ?");
10645 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10646 vty_out(vty
, " vrf %s(%u)",
10647 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10652 if (nexthop_self
) {
10654 json_object_boolean_true_add(json_path
,
10655 "announceNexthopSelf");
10657 vty_out(vty
, " announce-nh-self");
10662 vty_out(vty
, "\n");
10664 /* display the link-local nexthop */
10665 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10667 json_nexthop_ll
= json_object_new_object();
10668 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10669 &attr
->mp_nexthop_local
);
10671 if (path
->peer
->hostname
)
10672 json_object_string_add(json_nexthop_ll
,
10674 path
->peer
->hostname
);
10676 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10677 json_object_string_add(json_nexthop_ll
, "scope",
10680 json_object_boolean_true_add(json_nexthop_ll
,
10683 if (!attr
->mp_nexthop_prefer_global
)
10684 json_object_boolean_true_add(json_nexthop_ll
,
10687 json_object_boolean_true_add(
10688 json_nexthop_global
, "used");
10690 vty_out(vty
, " (%s) %s\n",
10691 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10692 buf
, INET6_ADDRSTRLEN
),
10693 attr
->mp_nexthop_prefer_global
10694 ? "(prefer-global)"
10698 /* If we do not have a link-local nexthop then we must flag the
10699 global as "used" */
10702 json_object_boolean_true_add(json_nexthop_global
,
10706 if (safi
== SAFI_EVPN
&&
10707 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10708 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10711 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10712 * Int/Ext/Local, Atomic, best */
10714 json_object_string_add(json_path
, "origin",
10715 bgp_origin_long_str
[attr
->origin
]);
10717 vty_out(vty
, " Origin %s",
10718 bgp_origin_long_str
[attr
->origin
]);
10720 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10722 json_object_int_add(json_path
, "metric", attr
->med
);
10724 vty_out(vty
, ", metric %u", attr
->med
);
10727 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10729 json_object_int_add(json_path
, "locPrf",
10732 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10735 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10737 json_object_int_add(json_path
, "aigpMetric",
10738 bgp_attr_get_aigp_metric(attr
));
10740 vty_out(vty
, ", aigp-metric %" PRIu64
,
10741 bgp_attr_get_aigp_metric(attr
));
10744 if (attr
->weight
!= 0) {
10746 json_object_int_add(json_path
, "weight", attr
->weight
);
10748 vty_out(vty
, ", weight %u", attr
->weight
);
10751 if (attr
->tag
!= 0) {
10753 json_object_int_add(json_path
, "tag", attr
->tag
);
10755 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10758 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10760 json_object_boolean_false_add(json_path
, "valid");
10762 vty_out(vty
, ", invalid");
10763 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10765 json_object_boolean_true_add(json_path
, "valid");
10767 vty_out(vty
, ", valid");
10771 json_object_int_add(json_path
, "version", bn
->version
);
10773 if (path
->peer
!= bgp
->peer_self
) {
10774 if (path
->peer
->as
== path
->peer
->local_as
) {
10775 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10777 json_object_string_add(
10779 "confed-internal");
10781 vty_out(vty
, ", confed-internal");
10784 json_object_string_add(
10785 json_peer
, "type", "internal");
10787 vty_out(vty
, ", internal");
10790 if (bgp_confederation_peers_check(bgp
,
10793 json_object_string_add(
10795 "confed-external");
10797 vty_out(vty
, ", confed-external");
10800 json_object_string_add(
10801 json_peer
, "type", "external");
10803 vty_out(vty
, ", external");
10806 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10808 json_object_boolean_true_add(json_path
, "aggregated");
10809 json_object_boolean_true_add(json_path
, "local");
10811 vty_out(vty
, ", aggregated, local");
10813 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10815 json_object_boolean_true_add(json_path
, "sourced");
10817 vty_out(vty
, ", sourced");
10820 json_object_boolean_true_add(json_path
, "sourced");
10821 json_object_boolean_true_add(json_path
, "local");
10823 vty_out(vty
, ", sourced, local");
10827 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10829 json_object_boolean_true_add(json_path
,
10830 "atomicAggregate");
10832 vty_out(vty
, ", atomic-aggregate");
10835 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10837 json_object_int_add(json_path
, "otc", attr
->otc
);
10839 vty_out(vty
, ", otc %u", attr
->otc
);
10842 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10843 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10844 && bgp_path_info_mpath_count(path
))) {
10846 json_object_boolean_true_add(json_path
, "multipath");
10848 vty_out(vty
, ", multipath");
10851 // Mark the bestpath(s)
10852 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10853 first_as
= aspath_get_first_as(attr
->aspath
);
10856 if (!json_bestpath
)
10857 json_bestpath
= json_object_new_object();
10858 json_object_int_add(json_bestpath
, "bestpathFromAs",
10862 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10864 vty_out(vty
, ", bestpath-from-AS Local");
10868 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10870 if (!json_bestpath
)
10871 json_bestpath
= json_object_new_object();
10872 json_object_boolean_true_add(json_bestpath
, "overall");
10873 json_object_string_add(
10874 json_bestpath
, "selectionReason",
10875 bgp_path_selection_reason2str(bn
->reason
));
10877 vty_out(vty
, ", best");
10878 vty_out(vty
, " (%s)",
10879 bgp_path_selection_reason2str(bn
->reason
));
10883 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10885 json_object_string_add(
10886 json_path
, "rpkiValidationState",
10887 bgp_rpki_validation2str(rpki_curr_state
));
10889 vty_out(vty
, ", rpki validation-state: %s",
10890 bgp_rpki_validation2str(rpki_curr_state
));
10894 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10897 vty_out(vty
, "\n");
10899 /* Line 4 display Community */
10900 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10902 if (!bgp_attr_get_community(attr
)->json
)
10903 community_str(bgp_attr_get_community(attr
),
10905 json_object_lock(bgp_attr_get_community(attr
)->json
);
10906 json_object_object_add(
10907 json_path
, "community",
10908 bgp_attr_get_community(attr
)->json
);
10910 vty_out(vty
, " Community: %s\n",
10911 bgp_attr_get_community(attr
)->str
);
10915 /* Line 5 display Extended-community */
10916 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10918 json_ext_community
= json_object_new_object();
10919 json_object_string_add(
10920 json_ext_community
, "string",
10921 bgp_attr_get_ecommunity(attr
)->str
);
10922 json_object_object_add(json_path
, "extendedCommunity",
10923 json_ext_community
);
10925 vty_out(vty
, " Extended Community: %s\n",
10926 bgp_attr_get_ecommunity(attr
)->str
);
10930 /* Line 6 display Large community */
10931 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10933 if (!bgp_attr_get_lcommunity(attr
)->json
)
10934 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10936 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10937 json_object_object_add(
10938 json_path
, "largeCommunity",
10939 bgp_attr_get_lcommunity(attr
)->json
);
10941 vty_out(vty
, " Large Community: %s\n",
10942 bgp_attr_get_lcommunity(attr
)->str
);
10946 /* Line 7 display Originator, Cluster-id */
10947 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10948 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10949 char buf
[BUFSIZ
] = {0};
10951 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10953 json_object_string_addf(json_path
,
10954 "originatorId", "%pI4",
10955 &attr
->originator_id
);
10957 vty_out(vty
, " Originator: %pI4",
10958 &attr
->originator_id
);
10961 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10962 struct cluster_list
*cluster
=
10963 bgp_attr_get_cluster(attr
);
10967 json_cluster_list
= json_object_new_object();
10968 json_cluster_list_list
=
10969 json_object_new_array();
10971 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10972 json_string
= json_object_new_string(
10975 buf
, sizeof(buf
)));
10976 json_object_array_add(
10977 json_cluster_list_list
,
10982 * struct cluster_list does not have
10983 * "str" variable like aspath and community
10984 * do. Add this someday if someone asks
10986 * json_object_string_add(json_cluster_list,
10987 * "string", cluster->str);
10989 json_object_object_add(json_cluster_list
,
10991 json_cluster_list_list
);
10992 json_object_object_add(json_path
, "clusterList",
10993 json_cluster_list
);
10995 vty_out(vty
, ", Cluster list: ");
10997 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10998 vty_out(vty
, "%pI4 ",
10999 &cluster
->list
[i
]);
11005 vty_out(vty
, "\n");
11008 if (path
->extra
&& path
->extra
->damp_info
)
11009 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
11012 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
11013 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
11014 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
11018 json_object_int_add(json_path
, "remoteLabel", label
);
11020 vty_out(vty
, " Remote label: %d\n", label
);
11024 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
11025 inet_ntop(AF_INET6
, &path
->extra
->sid
[0].sid
, buf
, sizeof(buf
));
11027 json_object_string_add(json_path
, "remoteSid", buf
);
11029 vty_out(vty
, " Remote SID: %s\n", buf
);
11033 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
11035 json_object_int_add(json_path
, "labelIndex",
11036 attr
->label_index
);
11038 vty_out(vty
, " Label Index: %d\n",
11039 attr
->label_index
);
11042 /* Line 8 display Addpath IDs */
11043 if (path
->addpath_rx_id
11044 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11046 json_object_int_add(json_path
, "addpathRxId",
11047 path
->addpath_rx_id
);
11049 /* Keep backwards compatibility with the old API
11050 * by putting TX All's ID in the old field
11052 json_object_int_add(
11053 json_path
, "addpathTxId",
11055 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11057 /* ... but create a specific field for each
11060 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11061 json_object_int_add(
11063 bgp_addpath_names(i
)->id_json_name
,
11064 path
->tx_addpath
.addpath_tx_id
[i
]);
11067 vty_out(vty
, " AddPath ID: RX %u, ",
11068 path
->addpath_rx_id
);
11070 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11074 /* If we used addpath to TX a non-bestpath we need to display
11075 * "Advertised to" on a path-by-path basis
11077 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11080 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11082 bgp_addpath_encode_tx(peer
, afi
, safi
);
11083 has_adj
= bgp_adj_out_lookup(
11085 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11086 &path
->tx_addpath
));
11088 if ((addpath_capable
&& has_adj
)
11089 || (!addpath_capable
&& has_adj
11090 && CHECK_FLAG(path
->flags
,
11091 BGP_PATH_SELECTED
))) {
11092 if (json_path
&& !json_adv_to
)
11093 json_adv_to
= json_object_new_object();
11095 route_vty_out_advertised_to(
11097 " Advertised to:", json_adv_to
);
11103 json_object_object_add(
11104 json_path
, "advertisedTo", json_adv_to
);
11108 vty_out(vty
, "\n");
11113 /* Line 9 display Uptime */
11114 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11116 json_last_update
= json_object_new_object();
11117 json_object_int_add(json_last_update
, "epoch", tbuf
);
11118 json_object_string_add(json_last_update
, "string",
11120 json_object_object_add(json_path
, "lastUpdate",
11123 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11125 /* Line 10 display PMSI tunnel attribute, if present */
11126 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11127 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11128 bgp_attr_get_pmsi_tnl_type(attr
),
11129 PMSI_TNLTYPE_STR_DEFAULT
);
11132 json_pmsi
= json_object_new_object();
11133 json_object_string_add(json_pmsi
, "tunnelType", str
);
11134 json_object_int_add(json_pmsi
, "label",
11135 label2vni(&attr
->label
));
11136 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11138 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11139 str
, label2vni(&attr
->label
));
11142 if (path
->peer
->t_gr_restart
&&
11143 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11144 unsigned long gr_remaining
=
11145 thread_timer_remain_second(path
->peer
->t_gr_restart
);
11148 json_object_int_add(json_path
,
11149 "gracefulRestartSecondsRemaining",
11153 " Time until Graceful Restart stale route deleted: %lu\n",
11157 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11158 bgp_attr_get_community(attr
) &&
11159 community_include(bgp_attr_get_community(attr
),
11160 COMMUNITY_LLGR_STALE
)) {
11161 unsigned long llgr_remaining
= thread_timer_remain_second(
11162 path
->peer
->t_llgr_stale
[afi
][safi
]);
11165 json_object_int_add(json_path
, "llgrSecondsRemaining",
11169 " Time until Long-lived stale route deleted: %lu\n",
11173 /* Output some debug about internal state of the dest flags */
11175 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11176 json_object_boolean_true_add(json_path
, "processScheduled");
11177 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11178 json_object_boolean_true_add(json_path
, "userCleared");
11179 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11180 json_object_boolean_true_add(json_path
, "labelChanged");
11181 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11182 json_object_boolean_true_add(json_path
, "registeredForLabel");
11183 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11184 json_object_boolean_true_add(json_path
, "selectDefered");
11185 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11186 json_object_boolean_true_add(json_path
, "fibInstalled");
11187 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11188 json_object_boolean_true_add(json_path
, "fibPending");
11190 if (json_nexthop_global
|| json_nexthop_ll
) {
11191 json_nexthops
= json_object_new_array();
11193 if (json_nexthop_global
)
11194 json_object_array_add(json_nexthops
,
11195 json_nexthop_global
);
11197 if (json_nexthop_ll
)
11198 json_object_array_add(json_nexthops
,
11201 json_object_object_add(json_path
, "nexthops",
11205 json_object_object_add(json_path
, "peer", json_peer
);
11206 json_object_array_add(json_paths
, json_path
);
11210 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11211 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11212 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11214 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11215 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11217 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11218 const char *comstr
, int exact
, afi_t afi
,
11219 safi_t safi
, uint16_t show_flags
);
11221 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11222 struct bgp_table
*table
, enum bgp_show_type type
,
11223 void *output_arg
, const char *rd
, int is_last
,
11224 unsigned long *output_cum
, unsigned long *total_cum
,
11225 unsigned long *json_header_depth
, uint16_t show_flags
,
11226 enum rpki_states rpki_target_state
)
11228 struct bgp_path_info
*pi
;
11229 struct bgp_dest
*dest
;
11230 bool header
= true;
11231 bool json_detail_header
= false;
11233 unsigned long output_count
= 0;
11234 unsigned long total_count
= 0;
11236 json_object
*json_paths
= NULL
;
11238 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11239 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11240 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11242 if (output_cum
&& *output_cum
!= 0)
11245 if (use_json
&& !*json_header_depth
) {
11247 *json_header_depth
= 1;
11249 vty_out(vty
, "{\n");
11250 *json_header_depth
= 2;
11254 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11255 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11256 " \"localAS\": %u,\n \"routes\": { ",
11257 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11258 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11261 table
->version
, &bgp
->router_id
,
11262 bgp
->default_local_pref
, bgp
->as
);
11264 vty_out(vty
, " \"routeDistinguishers\" : {");
11265 ++*json_header_depth
;
11269 if (use_json
&& rd
) {
11270 vty_out(vty
, " \"%s\" : { ", rd
);
11273 /* Check for 'json detail', where we need header output once per dest */
11274 if (use_json
&& CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
) &&
11275 type
!= bgp_show_type_dampend_paths
&&
11276 type
!= bgp_show_type_damp_neighbor
&&
11277 type
!= bgp_show_type_flap_statistics
&&
11278 type
!= bgp_show_type_flap_neighbor
)
11279 json_detail_header
= true;
11281 /* Start processing of routes. */
11282 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11283 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11284 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11285 bool json_detail
= json_detail_header
;
11287 pi
= bgp_dest_get_bgp_path_info(dest
);
11293 json_paths
= json_object_new_array();
11297 for (; pi
; pi
= pi
->next
) {
11298 struct community
*picomm
= NULL
;
11300 picomm
= bgp_attr_get_community(pi
->attr
);
11304 if (type
== bgp_show_type_prefix_version
) {
11306 strtoul(output_arg
, NULL
, 10);
11307 if (dest
->version
< version
)
11311 if (type
== bgp_show_type_community_alias
) {
11312 char *alias
= output_arg
;
11313 char **communities
;
11315 bool found
= false;
11318 frrstr_split(picomm
->str
, " ",
11319 &communities
, &num
);
11320 for (int i
= 0; i
< num
; i
++) {
11321 const char *com2alias
=
11322 bgp_community2alias(
11325 && strcmp(alias
, com2alias
)
11331 XFREE(MTYPE_TMP
, communities
);
11335 bgp_attr_get_lcommunity(pi
->attr
)) {
11336 frrstr_split(bgp_attr_get_lcommunity(
11339 " ", &communities
, &num
);
11340 for (int i
= 0; i
< num
; i
++) {
11341 const char *com2alias
=
11342 bgp_community2alias(
11345 && strcmp(alias
, com2alias
)
11351 XFREE(MTYPE_TMP
, communities
);
11358 if (type
== bgp_show_type_rpki
) {
11359 if (dest_p
->family
== AF_INET
11360 || dest_p
->family
== AF_INET6
)
11361 rpki_curr_state
= hook_call(
11362 bgp_rpki_prefix_status
,
11363 pi
->peer
, pi
->attr
, dest_p
);
11364 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11365 && rpki_curr_state
!= rpki_target_state
)
11369 if (type
== bgp_show_type_flap_statistics
11370 || type
== bgp_show_type_flap_neighbor
11371 || type
== bgp_show_type_dampend_paths
11372 || type
== bgp_show_type_damp_neighbor
) {
11373 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11376 if (type
== bgp_show_type_regexp
) {
11377 regex_t
*regex
= output_arg
;
11379 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11383 if (type
== bgp_show_type_prefix_list
) {
11384 struct prefix_list
*plist
= output_arg
;
11386 if (prefix_list_apply(plist
, dest_p
)
11390 if (type
== bgp_show_type_access_list
) {
11391 struct access_list
*alist
= output_arg
;
11393 if (access_list_apply(alist
, dest_p
) !=
11397 if (type
== bgp_show_type_filter_list
) {
11398 struct as_list
*as_list
= output_arg
;
11400 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11401 != AS_FILTER_PERMIT
)
11404 if (type
== bgp_show_type_route_map
) {
11405 struct route_map
*rmap
= output_arg
;
11406 struct bgp_path_info path
;
11407 struct bgp_path_info_extra extra
;
11408 struct attr dummy_attr
= {};
11409 route_map_result_t ret
;
11411 dummy_attr
= *pi
->attr
;
11413 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11414 pi
->peer
, &dummy_attr
);
11416 ret
= route_map_apply(rmap
, dest_p
, &path
);
11417 bgp_attr_flush(&dummy_attr
);
11418 if (ret
== RMAP_DENYMATCH
)
11421 if (type
== bgp_show_type_neighbor
11422 || type
== bgp_show_type_flap_neighbor
11423 || type
== bgp_show_type_damp_neighbor
) {
11424 union sockunion
*su
= output_arg
;
11426 if (pi
->peer
== NULL
11427 || pi
->peer
->su_remote
== NULL
11428 || !sockunion_same(pi
->peer
->su_remote
, su
))
11431 if (type
== bgp_show_type_cidr_only
) {
11432 uint32_t destination
;
11434 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11435 if (IN_CLASSC(destination
)
11436 && dest_p
->prefixlen
== 24)
11438 if (IN_CLASSB(destination
)
11439 && dest_p
->prefixlen
== 16)
11441 if (IN_CLASSA(destination
)
11442 && dest_p
->prefixlen
== 8)
11445 if (type
== bgp_show_type_prefix_longer
) {
11447 if (!prefix_match(p
, dest_p
))
11450 if (type
== bgp_show_type_community_all
) {
11454 if (type
== bgp_show_type_community
) {
11455 struct community
*com
= output_arg
;
11457 if (!picomm
|| !community_match(picomm
, com
))
11460 if (type
== bgp_show_type_community_exact
) {
11461 struct community
*com
= output_arg
;
11463 if (!picomm
|| !community_cmp(picomm
, com
))
11466 if (type
== bgp_show_type_community_list
) {
11467 struct community_list
*list
= output_arg
;
11469 if (!community_list_match(picomm
, list
))
11472 if (type
== bgp_show_type_community_list_exact
) {
11473 struct community_list
*list
= output_arg
;
11475 if (!community_list_exact_match(picomm
, list
))
11478 if (type
== bgp_show_type_lcommunity
) {
11479 struct lcommunity
*lcom
= output_arg
;
11481 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11483 bgp_attr_get_lcommunity(pi
->attr
),
11488 if (type
== bgp_show_type_lcommunity_exact
) {
11489 struct lcommunity
*lcom
= output_arg
;
11491 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11493 bgp_attr_get_lcommunity(pi
->attr
),
11497 if (type
== bgp_show_type_lcommunity_list
) {
11498 struct community_list
*list
= output_arg
;
11500 if (!lcommunity_list_match(
11501 bgp_attr_get_lcommunity(pi
->attr
),
11506 == bgp_show_type_lcommunity_list_exact
) {
11507 struct community_list
*list
= output_arg
;
11509 if (!lcommunity_list_exact_match(
11510 bgp_attr_get_lcommunity(pi
->attr
),
11514 if (type
== bgp_show_type_lcommunity_all
) {
11515 if (!bgp_attr_get_lcommunity(pi
->attr
))
11518 if (type
== bgp_show_type_dampend_paths
11519 || type
== bgp_show_type_damp_neighbor
) {
11520 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11521 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11525 if (!use_json
&& header
) {
11527 "BGP table version is %" PRIu64
11528 ", local router ID is %pI4, vrf id ",
11529 table
->version
, &bgp
->router_id
);
11530 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11531 vty_out(vty
, "%s", VRFID_NONE_STR
);
11533 vty_out(vty
, "%u", bgp
->vrf_id
);
11534 vty_out(vty
, "\n");
11535 vty_out(vty
, "Default local pref %u, ",
11536 bgp
->default_local_pref
);
11537 vty_out(vty
, "local AS %u\n", bgp
->as
);
11538 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11539 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11540 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11541 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11542 if (type
== bgp_show_type_dampend_paths
11543 || type
== bgp_show_type_damp_neighbor
)
11544 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11545 else if (type
== bgp_show_type_flap_statistics
11546 || type
== bgp_show_type_flap_neighbor
)
11547 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11549 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11550 : BGP_SHOW_HEADER
));
11553 } else if (json_detail
&& json_paths
!= NULL
) {
11554 const struct prefix_rd
*prd
;
11555 json_object
*jtemp
;
11557 /* Use common detail header, for most types;
11558 * need a json 'object'.
11561 jtemp
= json_object_new_object();
11562 prd
= bgp_rd_from_dest(dest
, safi
);
11564 route_vty_out_detail_header(
11565 vty
, bgp
, dest
, prd
, table
->afi
,
11568 json_object_array_add(json_paths
, jtemp
);
11570 json_detail
= false;
11573 if (rd
!= NULL
&& !display
&& !output_count
) {
11576 "Route Distinguisher: %s\n",
11579 if (type
== bgp_show_type_dampend_paths
11580 || type
== bgp_show_type_damp_neighbor
)
11581 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11582 AFI_IP
, safi
, use_json
,
11584 else if (type
== bgp_show_type_flap_statistics
11585 || type
== bgp_show_type_flap_neighbor
)
11586 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11587 AFI_IP
, safi
, use_json
,
11590 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
11591 route_vty_out_detail(
11592 vty
, bgp
, dest
, pi
,
11593 family2afi(dest_p
->family
),
11594 safi
, RPKI_NOT_BEING_USED
,
11597 route_vty_out(vty
, dest_p
, pi
, display
,
11598 safi
, json_paths
, wide
);
11608 /* encode prefix */
11609 if (dest_p
->family
== AF_FLOWSPEC
) {
11610 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11613 bgp_fs_nlri_get_string(
11615 dest_p
->u
.prefix_flowspec
.ptr
,
11616 dest_p
->u
.prefix_flowspec
.prefixlen
,
11617 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11618 family2afi(dest_p
->u
11619 .prefix_flowspec
.family
));
11621 vty_out(vty
, "\"%s/%d\": ", retstr
,
11622 dest_p
->u
.prefix_flowspec
11625 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11626 dest_p
->u
.prefix_flowspec
11630 vty_out(vty
, "\"%pFX\": ", dest_p
);
11632 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11634 vty_json(vty
, json_paths
);
11638 json_object_free(json_paths
);
11642 output_count
+= *output_cum
;
11643 *output_cum
= output_count
;
11646 total_count
+= *total_cum
;
11647 *total_cum
= total_count
;
11651 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11655 for (i
= 0; i
< *json_header_depth
; ++i
)
11656 vty_out(vty
, " } ");
11658 vty_out(vty
, "\n");
11662 /* No route is displayed */
11663 if (output_count
== 0) {
11664 if (type
== bgp_show_type_normal
)
11666 "No BGP prefixes displayed, %ld exist\n",
11670 "\nDisplayed %ld routes and %ld total paths\n",
11671 output_count
, total_count
);
11675 return CMD_SUCCESS
;
11678 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11679 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11680 enum bgp_show_type type
, void *output_arg
, bool use_json
)
11682 struct bgp_dest
*dest
, *next
;
11683 unsigned long output_cum
= 0;
11684 unsigned long total_cum
= 0;
11685 unsigned long json_header_depth
= 0;
11686 struct bgp_table
*itable
;
11688 uint16_t show_flags
= 0;
11690 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11693 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11695 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11696 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11698 next
= bgp_route_next(dest
);
11699 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11702 itable
= bgp_dest_get_bgp_table_info(dest
);
11703 if (itable
!= NULL
) {
11704 struct prefix_rd prd
;
11705 char rd
[RD_ADDRSTRLEN
];
11707 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11708 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11709 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11710 rd
, next
== NULL
, &output_cum
,
11711 &total_cum
, &json_header_depth
,
11712 show_flags
, RPKI_NOT_BEING_USED
);
11718 if (output_cum
== 0)
11719 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11723 "\nDisplayed %ld routes and %ld total paths\n",
11724 output_cum
, total_cum
);
11726 return CMD_SUCCESS
;
11729 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11730 enum bgp_show_type type
, void *output_arg
,
11731 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11733 struct bgp_table
*table
;
11734 unsigned long json_header_depth
= 0;
11735 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11738 bgp
= bgp_get_default();
11743 vty_out(vty
, "No BGP process is configured\n");
11745 vty_out(vty
, "{}\n");
11746 return CMD_WARNING
;
11749 /* Labeled-unicast routes live in the unicast table. */
11750 if (safi
== SAFI_LABELED_UNICAST
)
11751 safi
= SAFI_UNICAST
;
11753 table
= bgp
->rib
[afi
][safi
];
11754 /* use MPLS and ENCAP specific shows until they are merged */
11755 if (safi
== SAFI_MPLS_VPN
) {
11756 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11757 output_arg
, use_json
);
11760 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11761 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11762 output_arg
, use_json
,
11766 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11767 NULL
, NULL
, &json_header_depth
, show_flags
,
11768 rpki_target_state
);
11771 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11772 safi_t safi
, uint16_t show_flags
)
11774 struct listnode
*node
, *nnode
;
11777 bool route_output
= false;
11778 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11781 vty_out(vty
, "{\n");
11783 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11784 route_output
= true;
11787 vty_out(vty
, ",\n");
11791 vty_out(vty
, "\"%s\":",
11792 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11796 vty_out(vty
, "\nInstance %s:\n",
11797 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11801 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11802 show_flags
, RPKI_NOT_BEING_USED
);
11806 vty_out(vty
, "}\n");
11807 else if (!route_output
)
11808 vty_out(vty
, "%% BGP instance not found\n");
11811 /* Header of detailed BGP route information */
11812 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11813 struct bgp_dest
*dest
,
11814 const struct prefix_rd
*prd
,
11815 afi_t afi
, safi_t safi
, json_object
*json
)
11817 struct bgp_path_info
*pi
;
11818 const struct prefix
*p
;
11820 struct listnode
*node
, *nnode
;
11821 char buf1
[RD_ADDRSTRLEN
];
11825 int accept_own
= 0;
11826 int route_filter_translated_v4
= 0;
11827 int route_filter_v4
= 0;
11828 int route_filter_translated_v6
= 0;
11829 int route_filter_v6
= 0;
11830 int llgr_stale
= 0;
11832 int accept_own_nexthop
= 0;
11835 int no_advertise
= 0;
11839 int has_valid_label
= 0;
11840 mpls_label_t label
= 0;
11841 json_object
*json_adv_to
= NULL
;
11846 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11848 p
= bgp_dest_get_prefix(dest
);
11849 has_valid_label
= bgp_is_valid_label(&label
);
11851 if (safi
== SAFI_EVPN
) {
11853 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11854 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11856 prd
? ":" : "", (struct prefix_evpn
*)p
);
11858 json_object_string_add(json
, "rd",
11859 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11861 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11866 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11868 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11869 ? prefix_rd2str(prd
, buf1
,
11872 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11876 json_object_string_addf(json
, "prefix", "%pFX", p
);
11877 json_object_int_add(json
, "version", dest
->version
);
11882 if (has_valid_label
) {
11884 json_object_int_add(json
, "localLabel", label
);
11886 vty_out(vty
, "Local label: %d\n", label
);
11890 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11891 vty_out(vty
, "not allocated\n");
11893 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11894 struct community
*picomm
= NULL
;
11896 picomm
= bgp_attr_get_community(pi
->attr
);
11899 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11901 if (bgp_path_suppressed(pi
))
11907 no_advertise
+= community_include(
11908 picomm
, COMMUNITY_NO_ADVERTISE
);
11910 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11912 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11914 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11915 route_filter_translated_v4
+= community_include(
11916 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11917 route_filter_translated_v6
+= community_include(
11918 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11919 route_filter_v4
+= community_include(
11920 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11921 route_filter_v6
+= community_include(
11922 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11924 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11925 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11926 accept_own_nexthop
+= community_include(
11927 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11929 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11930 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11935 vty_out(vty
, "Paths: (%d available", count
);
11937 vty_out(vty
, ", best #%d", best
);
11938 if (safi
== SAFI_UNICAST
) {
11939 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11940 vty_out(vty
, ", table %s",
11943 vty_out(vty
, ", vrf %s",
11947 vty_out(vty
, ", no best path");
11951 ", accept own local route exported and imported in different VRF");
11952 else if (route_filter_translated_v4
)
11954 ", mark translated RTs for VPNv4 route filtering");
11955 else if (route_filter_v4
)
11957 ", attach RT as-is for VPNv4 route filtering");
11958 else if (route_filter_translated_v6
)
11960 ", mark translated RTs for VPNv6 route filtering");
11961 else if (route_filter_v6
)
11963 ", attach RT as-is for VPNv6 route filtering");
11964 else if (llgr_stale
)
11966 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11969 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11970 else if (accept_own_nexthop
)
11972 ", accept local nexthop");
11973 else if (blackhole
)
11974 vty_out(vty
, ", inform peer to blackhole prefix");
11975 else if (no_export
)
11976 vty_out(vty
, ", not advertised to EBGP peer");
11977 else if (no_advertise
)
11978 vty_out(vty
, ", not advertised to any peer");
11980 vty_out(vty
, ", not advertised outside local AS");
11983 ", inform EBGP peer not to advertise to their EBGP peers");
11987 ", Advertisements suppressed by an aggregate.");
11988 vty_out(vty
, ")\n");
11991 /* If we are not using addpath then we can display Advertised to and
11993 * show what peers we advertised the bestpath to. If we are using
11995 * though then we must display Advertised to on a path-by-path basis. */
11996 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11997 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11998 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11999 if (json
&& !json_adv_to
)
12000 json_adv_to
= json_object_new_object();
12002 route_vty_out_advertised_to(
12004 " Advertised to non peer-group peers:\n ",
12011 json_object_object_add(json
, "advertisedTo",
12016 vty_out(vty
, " Not advertised to any peer");
12017 vty_out(vty
, "\n");
12022 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12023 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12024 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12025 json_object
*json
, enum bgp_path_type pathtype
,
12026 int *display
, enum rpki_states rpki_target_state
)
12028 struct bgp_path_info
*pi
;
12030 json_object
*json_header
= NULL
;
12031 json_object
*json_paths
= NULL
;
12032 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12034 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12035 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12037 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12038 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12039 pi
->peer
, pi
->attr
, p
);
12041 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12042 && rpki_curr_state
!= rpki_target_state
)
12045 if (json
&& !json_paths
) {
12046 /* Instantiate json_paths only if path is valid */
12047 json_paths
= json_object_new_array();
12049 json_header
= json_object_new_object();
12051 json_header
= json
;
12055 route_vty_out_detail_header(
12056 vty
, bgp
, bgp_node
, pfx_rd
,
12057 AFI_IP
, safi
, json_header
);
12062 if (pathtype
== BGP_PATH_SHOW_ALL
12063 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12064 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12065 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12066 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12067 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12068 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
12069 safi
, rpki_curr_state
, json_paths
);
12072 if (json
&& json_paths
) {
12073 json_object_object_add(json_header
, "paths", json_paths
);
12076 json_object_object_addf(json
, json_header
, "%pRD",
12082 * Return rd based on safi
12084 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12088 case SAFI_MPLS_VPN
:
12091 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12097 /* Display specified route of BGP table. */
12098 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12099 struct bgp_table
*rib
, const char *ip_str
,
12100 afi_t afi
, safi_t safi
,
12101 enum rpki_states rpki_target_state
,
12102 struct prefix_rd
*prd
, int prefix_check
,
12103 enum bgp_path_type pathtype
, bool use_json
)
12107 struct prefix match
;
12108 struct bgp_dest
*dest
;
12109 struct bgp_dest
*rm
;
12110 struct bgp_table
*table
;
12111 json_object
*json
= NULL
;
12112 json_object
*json_paths
= NULL
;
12114 /* Check IP address argument. */
12115 ret
= str2prefix(ip_str
, &match
);
12117 vty_out(vty
, "address is malformed\n");
12118 return CMD_WARNING
;
12121 match
.family
= afi2family(afi
);
12124 json
= json_object_new_object();
12126 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12127 for (dest
= bgp_table_top(rib
); dest
;
12128 dest
= bgp_route_next(dest
)) {
12129 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12131 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12133 table
= bgp_dest_get_bgp_table_info(dest
);
12137 rm
= bgp_node_match(table
, &match
);
12141 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12143 && rm_p
->prefixlen
!= match
.prefixlen
) {
12144 bgp_dest_unlock_node(rm
);
12148 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12149 bgp
, afi
, safi
, json
, pathtype
,
12150 &display
, rpki_target_state
);
12152 bgp_dest_unlock_node(rm
);
12154 } else if (safi
== SAFI_EVPN
) {
12155 struct bgp_dest
*longest_pfx
;
12156 bool is_exact_pfxlen_match
= false;
12158 for (dest
= bgp_table_top(rib
); dest
;
12159 dest
= bgp_route_next(dest
)) {
12160 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12162 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12164 table
= bgp_dest_get_bgp_table_info(dest
);
12168 longest_pfx
= NULL
;
12169 is_exact_pfxlen_match
= false;
12171 * Search through all the prefixes for a match. The
12172 * pfx's are enumerated in ascending order of pfxlens.
12173 * So, the last pfx match is the longest match. Set
12174 * is_exact_pfxlen_match when we get exact pfxlen match
12176 for (rm
= bgp_table_top(table
); rm
;
12177 rm
= bgp_route_next(rm
)) {
12178 const struct prefix
*rm_p
=
12179 bgp_dest_get_prefix(rm
);
12181 * Get prefixlen of the ip-prefix within type5
12184 if (evpn_type5_prefix_match(rm_p
, &match
)
12188 bgp_evpn_get_type5_prefixlen(
12190 if (type5_pfxlen
== match
.prefixlen
) {
12191 is_exact_pfxlen_match
= true;
12192 bgp_dest_unlock_node(rm
);
12201 if (prefix_check
&& !is_exact_pfxlen_match
)
12205 bgp_dest_lock_node(rm
);
12207 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12208 bgp
, afi
, safi
, json
, pathtype
,
12209 &display
, rpki_target_state
);
12211 bgp_dest_unlock_node(rm
);
12213 } else if (safi
== SAFI_FLOWSPEC
) {
12215 json_paths
= json_object_new_array();
12217 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12218 &match
, prefix_check
,
12224 json_object_object_add(json
, "paths",
12227 json_object_free(json_paths
);
12230 dest
= bgp_node_match(rib
, &match
);
12231 if (dest
!= NULL
) {
12232 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12234 || dest_p
->prefixlen
== match
.prefixlen
) {
12235 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12236 safi
, json
, pathtype
,
12237 &display
, rpki_target_state
);
12240 bgp_dest_unlock_node(dest
);
12245 vty_json(vty
, json
);
12248 vty_out(vty
, "%% Network not in table\n");
12249 return CMD_WARNING
;
12253 return CMD_SUCCESS
;
12256 /* Display specified route of Main RIB */
12257 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12258 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12259 int prefix_check
, enum bgp_path_type pathtype
,
12260 enum rpki_states rpki_target_state
, bool use_json
)
12263 bgp
= bgp_get_default();
12266 vty_out(vty
, "No BGP process is configured\n");
12268 vty_out(vty
, "{}\n");
12269 return CMD_WARNING
;
12273 /* labeled-unicast routes live in the unicast table */
12274 if (safi
== SAFI_LABELED_UNICAST
)
12275 safi
= SAFI_UNICAST
;
12277 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12278 afi
, safi
, rpki_target_state
, prd
,
12279 prefix_check
, pathtype
, use_json
);
12282 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12283 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12284 safi_t safi
, bool uj
)
12286 struct lcommunity
*lcom
;
12291 uint16_t show_flags
= 0;
12295 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12297 b
= buffer_new(1024);
12298 for (i
= 0; i
< argc
; i
++) {
12300 buffer_putc(b
, ' ');
12302 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12304 buffer_putstr(b
, argv
[i
]->arg
);
12308 buffer_putc(b
, '\0');
12310 str
= buffer_getstr(b
);
12313 lcom
= lcommunity_str2com(str
);
12314 XFREE(MTYPE_TMP
, str
);
12316 vty_out(vty
, "%% Large-community malformed\n");
12317 return CMD_WARNING
;
12320 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12321 (exact
? bgp_show_type_lcommunity_exact
12322 : bgp_show_type_lcommunity
),
12323 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12325 lcommunity_free(&lcom
);
12329 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12330 const char *lcom
, bool exact
, afi_t afi
,
12331 safi_t safi
, bool uj
)
12333 struct community_list
*list
;
12334 uint16_t show_flags
= 0;
12337 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12340 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12341 LARGE_COMMUNITY_LIST_MASTER
);
12342 if (list
== NULL
) {
12343 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12345 return CMD_WARNING
;
12348 return bgp_show(vty
, bgp
, afi
, safi
,
12349 (exact
? bgp_show_type_lcommunity_list_exact
12350 : bgp_show_type_lcommunity_list
),
12351 list
, show_flags
, RPKI_NOT_BEING_USED
);
12354 DEFUN (show_ip_bgp_large_community_list
,
12355 show_ip_bgp_large_community_list_cmd
,
12356 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> [exact-match] [json]",
12360 BGP_INSTANCE_HELP_STR
12362 BGP_SAFI_WITH_LABEL_HELP_STR
12363 "Display routes matching the large-community-list\n"
12364 "large-community-list number\n"
12365 "large-community-list name\n"
12366 "Exact match of the large-communities\n"
12369 afi_t afi
= AFI_IP6
;
12370 safi_t safi
= SAFI_UNICAST
;
12372 bool exact_match
= 0;
12373 struct bgp
*bgp
= NULL
;
12374 bool uj
= use_json(argc
, argv
);
12379 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12382 return CMD_WARNING
;
12384 argv_find(argv
, argc
, "large-community-list", &idx
);
12386 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12388 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12391 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12392 exact_match
, afi
, safi
, uj
);
12394 DEFUN (show_ip_bgp_large_community
,
12395 show_ip_bgp_large_community_cmd
,
12396 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12400 BGP_INSTANCE_HELP_STR
12402 BGP_SAFI_WITH_LABEL_HELP_STR
12403 "Display routes matching the large-communities\n"
12404 "List of large-community numbers\n"
12405 "Exact match of the large-communities\n"
12408 afi_t afi
= AFI_IP6
;
12409 safi_t safi
= SAFI_UNICAST
;
12411 bool exact_match
= 0;
12412 struct bgp
*bgp
= NULL
;
12413 bool uj
= use_json(argc
, argv
);
12414 uint16_t show_flags
= 0;
12418 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12421 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12424 return CMD_WARNING
;
12426 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12427 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12431 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12432 exact_match
, afi
, safi
, uj
);
12434 return bgp_show(vty
, bgp
, afi
, safi
,
12435 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12436 RPKI_NOT_BEING_USED
);
12439 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12440 safi_t safi
, struct json_object
*json_array
);
12441 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12442 safi_t safi
, struct json_object
*json
);
12445 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12446 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12447 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12448 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12450 bool uj
= use_json(argc
, argv
);
12451 struct bgp
*bgp
= NULL
;
12452 safi_t safi
= SAFI_UNICAST
;
12453 afi_t afi
= AFI_IP6
;
12455 struct json_object
*json_all
= NULL
;
12456 struct json_object
*json_afi_safi
= NULL
;
12458 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12461 return CMD_WARNING
;
12464 json_all
= json_object_new_object();
12466 FOREACH_AFI_SAFI (afi
, safi
) {
12468 * So limit output to those afi/safi pairs that
12469 * actually have something interesting in them
12471 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12476 json_afi_safi
= json_object_new_array();
12477 json_object_object_add(
12479 get_afi_safi_str(afi
, safi
, true),
12482 json_afi_safi
= NULL
;
12485 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12489 vty_json(vty
, json_all
);
12491 return CMD_SUCCESS
;
12494 /* BGP route print out function without JSON */
12495 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12496 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12497 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12501 BGP_INSTANCE_HELP_STR
12504 "BGP RIB advertisement statistics\n"
12507 afi_t afi
= AFI_IP6
;
12508 safi_t safi
= SAFI_UNICAST
;
12509 struct bgp
*bgp
= NULL
;
12511 bool uj
= use_json(argc
, argv
);
12512 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12514 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12517 return CMD_WARNING
;
12520 json_afi_safi
= json_object_new_array();
12522 json_afi_safi
= NULL
;
12524 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12527 json
= json_object_new_object();
12528 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12530 vty_json(vty
, json
);
12535 /* BGP route print out function without JSON */
12536 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12537 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12538 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12540 statistics [json]",
12541 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12542 BGP_SAFI_WITH_LABEL_HELP_STR
12543 "BGP RIB advertisement statistics\n" JSON_STR
)
12545 afi_t afi
= AFI_IP6
;
12546 safi_t safi
= SAFI_UNICAST
;
12547 struct bgp
*bgp
= NULL
;
12549 bool uj
= use_json(argc
, argv
);
12550 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12552 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12555 return CMD_WARNING
;
12558 json_afi_safi
= json_object_new_array();
12560 json_afi_safi
= NULL
;
12562 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12565 json
= json_object_new_object();
12566 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12568 vty_json(vty
, json
);
12573 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12574 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12575 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12576 "]] [all$all] dampening parameters [json]",
12577 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12578 BGP_SAFI_WITH_LABEL_HELP_STR
12579 "Display the entries for all address families\n"
12580 "Display detailed information about dampening\n"
12581 "Display detail of configured dampening parameters\n"
12584 afi_t afi
= AFI_IP6
;
12585 safi_t safi
= SAFI_UNICAST
;
12586 struct bgp
*bgp
= NULL
;
12588 uint16_t show_flags
= 0;
12589 bool uj
= use_json(argc
, argv
);
12593 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12596 /* [<ipv4|ipv6> [all]] */
12598 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12599 if (argv_find(argv
, argc
, "ipv4", &idx
))
12600 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12602 if (argv_find(argv
, argc
, "ipv6", &idx
))
12603 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12606 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12609 return CMD_WARNING
;
12611 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12614 /* BGP route print out function */
12615 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12616 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12617 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12621 |dampening <flap-statistics|dampened-paths>\
12622 |community [AA:NN|local-AS|no-advertise|no-export\
12623 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12624 |accept-own|accept-own-nexthop|route-filter-v6\
12625 |route-filter-v4|route-filter-translated-v6\
12626 |route-filter-translated-v4] [exact-match]\
12627 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12628 |filter-list AS_PATH_FILTER_NAME\
12630 |access-list ACCESSLIST_NAME\
12631 |route-map RMAP_NAME\
12632 |rpki <invalid|valid|notfound>\
12633 |version (1-4294967295)\
12635 |A.B.C.D/M longer-prefixes\
12636 |X:X::X:X/M longer-prefixes\
12637 |optimal-route-reflection [WORD$orr_group_name]\
12638 ] [json$uj [detail$detail] | wide$wide]",
12639 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12640 BGP_SAFI_WITH_LABEL_HELP_STR
12641 "Display the entries for all address families\n"
12642 "Display only routes with non-natural netmasks\n"
12643 "Display detailed information about dampening\n"
12644 "Display flap statistics of routes\n"
12645 "Display paths suppressed due to dampening\n"
12646 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12647 "Do not send outside local AS (well-known community)\n"
12648 "Do not advertise to any peer (well-known community)\n"
12649 "Do not export to next AS (well-known community)\n"
12650 "Graceful shutdown (well-known community)\n"
12651 "Do not export to any peer (well-known community)\n"
12652 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12653 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12654 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12655 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12656 "Should accept VPN route with local nexthop (well-known community)\n"
12657 "RT VPNv6 route filtering (well-known community)\n"
12658 "RT VPNv4 route filtering (well-known community)\n"
12659 "RT translated VPNv6 route filtering (well-known community)\n"
12660 "RT translated VPNv4 route filtering (well-known community)\n"
12661 "Exact match of the communities\n"
12662 "Community-list number\n"
12663 "Community-list name\n"
12664 "Display routes matching the community-list\n"
12665 "Exact match of the communities\n"
12666 "Display routes conforming to the filter-list\n"
12667 "Regular expression access list name\n"
12668 "Display routes conforming to the prefix-list\n"
12669 "Prefix-list name\n"
12670 "Display routes conforming to the access-list\n"
12671 "Access-list name\n"
12672 "Display routes matching the route-map\n"
12673 "A route-map to match on\n"
12674 "RPKI route types\n"
12675 "A valid path as determined by rpki\n"
12676 "A invalid path as determined by rpki\n"
12677 "A path that has no rpki data\n"
12678 "Display prefixes with matching version numbers\n"
12679 "Version number and above\n"
12680 "Display prefixes with matching BGP community alias\n"
12681 "BGP community alias\n"
12683 "Display route and more specific routes\n"
12685 "Display route and more specific routes\n"
12686 "Display Optimal Route Reflection RR Clients\n"
12689 "Display detailed version of JSON output\n"
12690 "Increase table width for longer prefixes\n")
12692 afi_t afi
= AFI_IP6
;
12693 safi_t safi
= SAFI_UNICAST
;
12694 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12695 void *output_arg
= NULL
;
12696 struct bgp
*bgp
= NULL
;
12698 int exact_match
= 0;
12699 char *community
= NULL
;
12701 uint16_t show_flags
= 0;
12702 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12704 bool orr_group
= false;
12708 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12712 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12714 /* [<ipv4|ipv6> [all]] */
12716 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12718 if (argv_find(argv
, argc
, "ipv4", &idx
))
12719 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12721 if (argv_find(argv
, argc
, "ipv6", &idx
))
12722 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12726 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12728 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12731 return CMD_WARNING
;
12733 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12734 sh_type
= bgp_show_type_cidr_only
;
12736 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12737 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12738 sh_type
= bgp_show_type_dampend_paths
;
12739 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12740 sh_type
= bgp_show_type_flap_statistics
;
12743 if (argv_find(argv
, argc
, "community", &idx
)) {
12744 char *maybecomm
= NULL
;
12746 if (idx
+ 1 < argc
) {
12747 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12748 maybecomm
= argv
[idx
+ 1]->arg
;
12750 maybecomm
= argv
[idx
+ 1]->text
;
12753 if (maybecomm
&& !strmatch(maybecomm
, "json")
12754 && !strmatch(maybecomm
, "exact-match"))
12755 community
= maybecomm
;
12757 if (argv_find(argv
, argc
, "exact-match", &idx
))
12761 sh_type
= bgp_show_type_community_all
;
12764 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12765 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12766 struct community_list
*list
;
12768 if (argv_find(argv
, argc
, "exact-match", &idx
))
12771 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12772 COMMUNITY_LIST_MASTER
);
12773 if (list
== NULL
) {
12774 vty_out(vty
, "%% %s community-list not found\n",
12775 clist_number_or_name
);
12776 return CMD_WARNING
;
12780 sh_type
= bgp_show_type_community_list_exact
;
12782 sh_type
= bgp_show_type_community_list
;
12786 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12787 const char *filter
= argv
[++idx
]->arg
;
12788 struct as_list
*as_list
;
12790 as_list
= as_list_lookup(filter
);
12791 if (as_list
== NULL
) {
12792 vty_out(vty
, "%% %s AS-path access-list not found\n",
12794 return CMD_WARNING
;
12797 sh_type
= bgp_show_type_filter_list
;
12798 output_arg
= as_list
;
12801 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12802 const char *prefix_list_str
= argv
[++idx
]->arg
;
12803 struct prefix_list
*plist
;
12805 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12806 if (plist
== NULL
) {
12807 vty_out(vty
, "%% %s prefix-list not found\n",
12809 return CMD_WARNING
;
12812 sh_type
= bgp_show_type_prefix_list
;
12813 output_arg
= plist
;
12816 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12817 const char *access_list_str
= argv
[++idx
]->arg
;
12818 struct access_list
*alist
;
12820 alist
= access_list_lookup(afi
, access_list_str
);
12822 vty_out(vty
, "%% %s access-list not found\n",
12824 return CMD_WARNING
;
12827 sh_type
= bgp_show_type_access_list
;
12828 output_arg
= alist
;
12831 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12832 const char *rmap_str
= argv
[++idx
]->arg
;
12833 struct route_map
*rmap
;
12835 rmap
= route_map_lookup_by_name(rmap_str
);
12837 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12838 return CMD_WARNING
;
12841 sh_type
= bgp_show_type_route_map
;
12845 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12846 sh_type
= bgp_show_type_rpki
;
12847 if (argv_find(argv
, argc
, "valid", &idx
))
12848 rpki_target_state
= RPKI_VALID
;
12849 else if (argv_find(argv
, argc
, "invalid", &idx
))
12850 rpki_target_state
= RPKI_INVALID
;
12853 /* Display prefixes with matching version numbers */
12854 if (argv_find(argv
, argc
, "version", &idx
)) {
12855 sh_type
= bgp_show_type_prefix_version
;
12856 output_arg
= argv
[idx
+ 1]->arg
;
12859 /* Display prefixes with matching BGP community alias */
12860 if (argv_find(argv
, argc
, "alias", &idx
)) {
12861 sh_type
= bgp_show_type_community_alias
;
12862 output_arg
= argv
[idx
+ 1]->arg
;
12865 /* prefix-longer */
12866 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12867 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12868 const char *prefix_str
= argv
[idx
]->arg
;
12870 if (!str2prefix(prefix_str
, &p
)) {
12871 vty_out(vty
, "%% Malformed Prefix\n");
12872 return CMD_WARNING
;
12875 sh_type
= bgp_show_type_prefix_longer
;
12879 if (argv_find(argv
, argc
, "optimal-route-reflection", &idx
))
12883 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12885 return bgp_show_community(vty
, bgp
, community
,
12886 exact_match
, afi
, safi
,
12888 else if (orr_group
)
12889 return bgp_show_orr(vty
, bgp
, afi
, safi
, orr_group_name
,
12892 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12893 output_arg
, show_flags
,
12894 rpki_target_state
);
12896 struct listnode
*node
;
12898 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12902 vty_out(vty
, "{\n");
12904 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12905 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12906 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12909 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12910 FOREACH_SAFI (safi
) {
12911 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12919 vty_out(vty
, ",\n");
12920 vty_out(vty
, "\"%s\":{\n",
12921 get_afi_safi_str(afi
,
12926 "\nFor address family: %s\n",
12932 bgp_show_community(
12933 vty
, abgp
, community
,
12934 exact_match
, afi
, safi
,
12936 else if (orr_group
)
12937 bgp_show_orr(vty
, bgp
, afi
,
12942 bgp_show(vty
, abgp
, afi
, safi
,
12943 sh_type
, output_arg
,
12945 rpki_target_state
);
12947 vty_out(vty
, "}\n");
12951 /* show <ip> bgp all: for each AFI and SAFI*/
12952 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12953 FOREACH_AFI_SAFI (afi
, safi
) {
12954 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12962 vty_out(vty
, ",\n");
12964 vty_out(vty
, "\"%s\":{\n",
12965 get_afi_safi_str(afi
,
12970 "\nFor address family: %s\n",
12976 bgp_show_community(
12977 vty
, abgp
, community
,
12978 exact_match
, afi
, safi
,
12980 else if (orr_group
)
12981 bgp_show_orr(vty
, bgp
, afi
,
12986 bgp_show(vty
, abgp
, afi
, safi
,
12987 sh_type
, output_arg
,
12989 rpki_target_state
);
12991 vty_out(vty
, "}\n");
12996 vty_out(vty
, "}\n");
12998 return CMD_SUCCESS
;
13001 DEFUN (show_ip_bgp_route
,
13002 show_ip_bgp_route_cmd
,
13003 "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]",
13007 BGP_INSTANCE_HELP_STR
13009 BGP_SAFI_WITH_LABEL_HELP_STR
13010 "Network in the BGP routing table to display\n"
13012 "Network in the BGP routing table to display\n"
13014 "Display only the bestpath\n"
13015 "Display only multipaths\n"
13016 "Display only paths that match the specified rpki state\n"
13017 "A valid path as determined by rpki\n"
13018 "A invalid path as determined by rpki\n"
13019 "A path that has no rpki data\n"
13022 int prefix_check
= 0;
13024 afi_t afi
= AFI_IP6
;
13025 safi_t safi
= SAFI_UNICAST
;
13026 char *prefix
= NULL
;
13027 struct bgp
*bgp
= NULL
;
13028 enum bgp_path_type path_type
;
13029 bool uj
= use_json(argc
, argv
);
13033 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13036 return CMD_WARNING
;
13040 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13041 return CMD_WARNING
;
13044 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13045 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13046 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13048 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13049 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13052 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13053 && afi
!= AFI_IP6
) {
13055 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13056 return CMD_WARNING
;
13058 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13059 && afi
!= AFI_IP
) {
13061 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13062 return CMD_WARNING
;
13065 prefix
= argv
[idx
]->arg
;
13067 /* [<bestpath|multipath>] */
13068 if (argv_find(argv
, argc
, "bestpath", &idx
))
13069 path_type
= BGP_PATH_SHOW_BESTPATH
;
13070 else if (argv_find(argv
, argc
, "multipath", &idx
))
13071 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13073 path_type
= BGP_PATH_SHOW_ALL
;
13075 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13076 path_type
, RPKI_NOT_BEING_USED
, uj
);
13079 DEFUN (show_ip_bgp_regexp
,
13080 show_ip_bgp_regexp_cmd
,
13081 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13085 BGP_INSTANCE_HELP_STR
13087 BGP_SAFI_WITH_LABEL_HELP_STR
13088 "Display routes matching the AS path regular expression\n"
13089 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13092 afi_t afi
= AFI_IP6
;
13093 safi_t safi
= SAFI_UNICAST
;
13094 struct bgp
*bgp
= NULL
;
13095 bool uj
= use_json(argc
, argv
);
13096 char *regstr
= NULL
;
13099 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13102 return CMD_WARNING
;
13104 // get index of regex
13105 if (argv_find(argv
, argc
, "REGEX", &idx
))
13106 regstr
= argv
[idx
]->arg
;
13109 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13110 bgp_show_type_regexp
, uj
);
13113 DEFPY (show_ip_bgp_instance_all
,
13114 show_ip_bgp_instance_all_cmd
,
13115 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13119 BGP_INSTANCE_ALL_HELP_STR
13121 BGP_SAFI_WITH_LABEL_HELP_STR
13123 "Increase table width for longer prefixes\n")
13125 afi_t afi
= AFI_IP6
;
13126 safi_t safi
= SAFI_UNICAST
;
13127 struct bgp
*bgp
= NULL
;
13129 uint16_t show_flags
= 0;
13133 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13137 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13139 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13142 return CMD_WARNING
;
13144 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13145 return CMD_SUCCESS
;
13148 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13149 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13154 uint16_t show_flags
= 0;
13157 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13159 if (!config_bgp_aspath_validate(regstr
)) {
13160 vty_out(vty
, "Invalid character in REGEX %s\n",
13162 return CMD_WARNING_CONFIG_FAILED
;
13165 regex
= bgp_regcomp(regstr
);
13167 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13168 return CMD_WARNING
;
13171 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13172 RPKI_NOT_BEING_USED
);
13173 bgp_regex_free(regex
);
13177 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13178 const char *comstr
, int exact
, afi_t afi
,
13179 safi_t safi
, uint16_t show_flags
)
13181 struct community
*com
;
13184 com
= community_str2com(comstr
);
13186 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13187 return CMD_WARNING
;
13190 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13191 (exact
? bgp_show_type_community_exact
13192 : bgp_show_type_community
),
13193 com
, show_flags
, RPKI_NOT_BEING_USED
);
13194 community_free(&com
);
13200 BGP_STATS_MAXBITLEN
= 0,
13202 BGP_STATS_PREFIXES
,
13204 BGP_STATS_UNAGGREGATEABLE
,
13205 BGP_STATS_MAX_AGGREGATEABLE
,
13206 BGP_STATS_AGGREGATES
,
13208 BGP_STATS_ASPATH_COUNT
,
13209 BGP_STATS_ASPATH_MAXHOPS
,
13210 BGP_STATS_ASPATH_TOTHOPS
,
13211 BGP_STATS_ASPATH_MAXSIZE
,
13212 BGP_STATS_ASPATH_TOTSIZE
,
13213 BGP_STATS_ASN_HIGHEST
,
13217 #define TABLE_STATS_IDX_VTY 0
13218 #define TABLE_STATS_IDX_JSON 1
13220 static const char *table_stats_strs
[][2] = {
13221 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13222 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13223 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13224 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13225 "unaggregateablePrefixes"},
13226 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13227 "maximumAggregateablePrefixes"},
13228 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13229 "bgpAggregateAdvertisements"},
13230 [BGP_STATS_SPACE
] = {"Address space advertised",
13231 "addressSpaceAdvertised"},
13232 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13233 "advertisementsWithPaths"},
13234 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13236 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13238 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13239 "averageAsPathLengthHops"},
13240 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13241 "averageAsPathSizeBytes"},
13242 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13243 [BGP_STATS_MAX
] = {NULL
, NULL
}
13246 struct bgp_table_stats
{
13247 struct bgp_table
*table
;
13248 unsigned long long counts
[BGP_STATS_MAX
];
13251 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13254 double total_space
;
13257 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13258 struct bgp_table_stats
*ts
, unsigned int space
)
13260 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13261 struct bgp_path_info
*pi
;
13262 const struct prefix
*rn_p
;
13264 if (!bgp_dest_has_bgp_path_info_data(dest
))
13267 rn_p
= bgp_dest_get_prefix(dest
);
13268 ts
->counts
[BGP_STATS_PREFIXES
]++;
13269 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13271 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13272 /* check if the prefix is included by any other announcements */
13273 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13274 pdest
= bgp_dest_parent_nolock(pdest
);
13276 if (pdest
== NULL
|| pdest
== top
) {
13277 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13278 /* announced address space */
13280 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13281 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13282 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13285 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13286 ts
->counts
[BGP_STATS_RIB
]++;
13288 if (CHECK_FLAG(pi
->attr
->flag
,
13289 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13290 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13292 /* as-path stats */
13293 if (pi
->attr
->aspath
) {
13294 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13295 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13296 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13298 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13300 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13301 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13303 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13304 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13306 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13307 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13308 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13309 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13314 static void bgp_table_stats_walker(struct thread
*t
)
13316 struct bgp_dest
*dest
, *ndest
;
13317 struct bgp_dest
*top
;
13318 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13319 unsigned int space
= 0;
13321 if (!(top
= bgp_table_top(ts
->table
)))
13324 switch (ts
->table
->afi
) {
13326 space
= IPV4_MAX_BITLEN
;
13329 space
= IPV6_MAX_BITLEN
;
13332 space
= EVPN_ROUTE_PREFIXLEN
;
13338 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13340 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13341 if (ts
->table
->safi
== SAFI_MPLS_VPN
13342 || ts
->table
->safi
== SAFI_ENCAP
13343 || ts
->table
->safi
== SAFI_EVPN
) {
13344 struct bgp_table
*table
;
13346 table
= bgp_dest_get_bgp_table_info(dest
);
13350 top
= bgp_table_top(table
);
13351 for (ndest
= bgp_table_top(table
); ndest
;
13352 ndest
= bgp_route_next(ndest
))
13353 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13355 bgp_table_stats_rn(dest
, top
, ts
, space
);
13360 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13361 struct json_object
*json_array
)
13363 struct listnode
*node
, *nnode
;
13366 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13367 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13370 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13371 safi_t safi
, struct json_object
*json_array
)
13373 struct bgp_table_stats ts
;
13375 int ret
= CMD_SUCCESS
;
13377 struct json_object
*json
= NULL
;
13378 uint32_t bitlen
= 0;
13379 struct json_object
*json_bitlen
;
13382 json
= json_object_new_object();
13384 if (!bgp
->rib
[afi
][safi
]) {
13385 char warning_msg
[50];
13387 snprintf(warning_msg
, sizeof(warning_msg
),
13388 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13392 vty_out(vty
, "%s\n", warning_msg
);
13394 json_object_string_add(json
, "warning", warning_msg
);
13397 goto end_table_stats
;
13401 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13402 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13404 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13406 /* labeled-unicast routes live in the unicast table */
13407 if (safi
== SAFI_LABELED_UNICAST
)
13408 safi
= SAFI_UNICAST
;
13410 memset(&ts
, 0, sizeof(ts
));
13411 ts
.table
= bgp
->rib
[afi
][safi
];
13412 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13414 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13415 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13416 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13420 case BGP_STATS_ASPATH_TOTHOPS
:
13421 case BGP_STATS_ASPATH_TOTSIZE
:
13424 temp_buf
, sizeof(temp_buf
), "%12.2f",
13426 ? (float)ts
.counts
[i
]
13428 [BGP_STATS_ASPATH_COUNT
]
13430 vty_out(vty
, "%-30s: %s",
13431 table_stats_strs
[i
]
13432 [TABLE_STATS_IDX_VTY
],
13435 json_object_double_add(
13437 table_stats_strs
[i
]
13438 [TABLE_STATS_IDX_JSON
],
13440 ? (double)ts
.counts
[i
]
13441 / (double)ts
.counts
13442 [BGP_STATS_ASPATH_COUNT
]
13446 case BGP_STATS_TOTPLEN
:
13449 temp_buf
, sizeof(temp_buf
), "%12.2f",
13451 ? (float)ts
.counts
[i
]
13453 [BGP_STATS_PREFIXES
]
13455 vty_out(vty
, "%-30s: %s",
13456 table_stats_strs
[i
]
13457 [TABLE_STATS_IDX_VTY
],
13460 json_object_double_add(
13462 table_stats_strs
[i
]
13463 [TABLE_STATS_IDX_JSON
],
13465 ? (double)ts
.counts
[i
]
13466 / (double)ts
.counts
13467 [BGP_STATS_PREFIXES
]
13471 case BGP_STATS_SPACE
:
13473 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13475 vty_out(vty
, "%-30s: %s\n",
13476 table_stats_strs
[i
]
13477 [TABLE_STATS_IDX_VTY
],
13480 json_object_double_add(
13482 table_stats_strs
[i
]
13483 [TABLE_STATS_IDX_JSON
],
13484 (double)ts
.total_space
);
13486 if (afi
== AFI_IP6
) {
13488 snprintf(temp_buf
, sizeof(temp_buf
),
13491 * pow(2.0, -128 + 32));
13492 vty_out(vty
, "%30s: %s\n",
13493 "/32 equivalent %s\n",
13496 json_object_double_add(
13497 json
, "/32equivalent",
13498 (double)(ts
.total_space
13503 snprintf(temp_buf
, sizeof(temp_buf
),
13506 * pow(2.0, -128 + 48));
13507 vty_out(vty
, "%30s: %s\n",
13508 "/48 equivalent %s\n",
13511 json_object_double_add(
13512 json
, "/48equivalent",
13513 (double)(ts
.total_space
13519 snprintf(temp_buf
, sizeof(temp_buf
),
13521 ts
.total_space
* 100.
13523 vty_out(vty
, "%30s: %s\n",
13524 "% announced ", temp_buf
);
13526 json_object_double_add(
13527 json
, "%announced",
13528 (double)(ts
.total_space
* 100.
13532 snprintf(temp_buf
, sizeof(temp_buf
),
13535 * pow(2.0, -32 + 8));
13536 vty_out(vty
, "%30s: %s\n",
13537 "/8 equivalent ", temp_buf
);
13539 json_object_double_add(
13540 json
, "/8equivalent",
13541 (double)(ts
.total_space
13542 * pow(2.0, -32 + 8)));
13545 snprintf(temp_buf
, sizeof(temp_buf
),
13548 * pow(2.0, -32 + 24));
13549 vty_out(vty
, "%30s: %s\n",
13550 "/24 equivalent ", temp_buf
);
13552 json_object_double_add(
13553 json
, "/24equivalent",
13554 (double)(ts
.total_space
13555 * pow(2.0, -32 + 24)));
13561 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13563 vty_out(vty
, "%-30s: %s",
13564 table_stats_strs
[i
]
13565 [TABLE_STATS_IDX_VTY
],
13568 json_object_int_add(
13570 table_stats_strs
[i
]
13571 [TABLE_STATS_IDX_JSON
],
13576 vty_out(vty
, "\n");
13581 bitlen
= IPV4_MAX_BITLEN
;
13584 bitlen
= IPV6_MAX_BITLEN
;
13587 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13594 json_bitlen
= json_object_new_array();
13596 for (i
= 0; i
<= bitlen
; i
++) {
13597 struct json_object
*ind_bit
= json_object_new_object();
13599 if (!ts
.prefix_len_count
[i
])
13602 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13603 json_object_int_add(ind_bit
, temp_buf
,
13604 ts
.prefix_len_count
[i
]);
13605 json_object_array_add(json_bitlen
, ind_bit
);
13607 json_object_object_add(json
, "prefixLength", json_bitlen
);
13612 json_object_array_add(json_array
, json
);
13616 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13617 safi_t safi
, struct json_object
*json_array
)
13620 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13621 return CMD_SUCCESS
;
13624 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13636 PCOUNT_BPATH_SELECTED
,
13637 PCOUNT_PFCNT
, /* the figure we display to users */
13641 static const char *const pcount_strs
[] = {
13642 [PCOUNT_ADJ_IN
] = "Adj-in",
13643 [PCOUNT_DAMPED
] = "Damped",
13644 [PCOUNT_REMOVED
] = "Removed",
13645 [PCOUNT_HISTORY
] = "History",
13646 [PCOUNT_STALE
] = "Stale",
13647 [PCOUNT_VALID
] = "Valid",
13648 [PCOUNT_ALL
] = "All RIB",
13649 [PCOUNT_COUNTED
] = "PfxCt counted",
13650 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13651 [PCOUNT_PFCNT
] = "Useable",
13652 [PCOUNT_MAX
] = NULL
,
13655 struct peer_pcounts
{
13656 unsigned int count
[PCOUNT_MAX
];
13657 const struct peer
*peer
;
13658 const struct bgp_table
*table
;
13662 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13664 const struct bgp_adj_in
*ain
;
13665 const struct bgp_path_info
*pi
;
13666 const struct peer
*peer
= pc
->peer
;
13668 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13669 if (ain
->peer
== peer
)
13670 pc
->count
[PCOUNT_ADJ_IN
]++;
13672 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13674 if (pi
->peer
!= peer
)
13677 pc
->count
[PCOUNT_ALL
]++;
13679 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13680 pc
->count
[PCOUNT_DAMPED
]++;
13681 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13682 pc
->count
[PCOUNT_HISTORY
]++;
13683 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13684 pc
->count
[PCOUNT_REMOVED
]++;
13685 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13686 pc
->count
[PCOUNT_STALE
]++;
13687 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13688 pc
->count
[PCOUNT_VALID
]++;
13689 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13690 pc
->count
[PCOUNT_PFCNT
]++;
13691 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13692 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13694 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13695 pc
->count
[PCOUNT_COUNTED
]++;
13696 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13698 EC_LIB_DEVELOPMENT
,
13699 "Attempting to count but flags say it is unusable");
13701 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13703 EC_LIB_DEVELOPMENT
,
13704 "Not counted but flags say we should");
13709 static void bgp_peer_count_walker(struct thread
*t
)
13711 struct bgp_dest
*rn
, *rm
;
13712 const struct bgp_table
*table
;
13713 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13715 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13716 || pc
->safi
== SAFI_EVPN
) {
13717 /* Special handling for 2-level routing tables. */
13718 for (rn
= bgp_table_top(pc
->table
); rn
;
13719 rn
= bgp_route_next(rn
)) {
13720 table
= bgp_dest_get_bgp_table_info(rn
);
13722 for (rm
= bgp_table_top(table
); rm
;
13723 rm
= bgp_route_next(rm
))
13724 bgp_peer_count_proc(rm
, pc
);
13727 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13728 bgp_peer_count_proc(rn
, pc
);
13731 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13732 safi_t safi
, bool use_json
)
13734 struct peer_pcounts pcounts
= {.peer
= peer
};
13736 json_object
*json
= NULL
;
13737 json_object
*json_loop
= NULL
;
13740 json
= json_object_new_object();
13741 json_loop
= json_object_new_object();
13744 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13745 || !peer
->bgp
->rib
[afi
][safi
]) {
13747 json_object_string_add(
13749 "No such neighbor or address family");
13750 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13751 json_object_free(json
);
13752 json_object_free(json_loop
);
13754 vty_out(vty
, "%% No such neighbor or address family\n");
13756 return CMD_WARNING
;
13759 memset(&pcounts
, 0, sizeof(pcounts
));
13760 pcounts
.peer
= peer
;
13761 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13762 pcounts
.safi
= safi
;
13764 /* in-place call via thread subsystem so as to record execution time
13765 * stats for the thread-walk (i.e. ensure this can't be blamed on
13766 * on just vty_read()).
13768 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13771 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13772 json_object_string_add(json
, "multiProtocol",
13773 get_afi_safi_str(afi
, safi
, true));
13774 json_object_int_add(json
, "pfxCounter",
13775 peer
->pcount
[afi
][safi
]);
13777 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13778 json_object_int_add(json_loop
, pcount_strs
[i
],
13781 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13783 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13784 json_object_string_add(json
, "pfxctDriftFor",
13786 json_object_string_add(
13787 json
, "recommended",
13788 "Please report this bug, with the above command output");
13790 vty_json(vty
, json
);
13794 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13795 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13796 peer
->hostname
, peer
->host
,
13797 get_afi_safi_str(afi
, safi
, false));
13799 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13800 get_afi_safi_str(afi
, safi
, false));
13803 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13804 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13806 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13807 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13810 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13811 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13813 "Please report this bug, with the above command output\n");
13817 return CMD_SUCCESS
;
13820 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13821 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13822 "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]",
13826 BGP_INSTANCE_HELP_STR
13829 "Detailed information on TCP and BGP neighbor connections\n"
13830 "Neighbor to display information about\n"
13831 "Neighbor to display information about\n"
13832 "Neighbor on BGP configured interface\n"
13833 "Display detailed prefix count information\n"
13836 afi_t afi
= AFI_IP6
;
13837 safi_t safi
= SAFI_UNICAST
;
13840 struct bgp
*bgp
= NULL
;
13841 bool uj
= use_json(argc
, argv
);
13846 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13849 return CMD_WARNING
;
13851 argv_find(argv
, argc
, "neighbors", &idx
);
13852 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13854 return CMD_WARNING
;
13856 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13859 #ifdef KEEP_OLD_VPN_COMMANDS
13860 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13861 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13862 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13867 "Display information about all VPNv4 NLRIs\n"
13868 "Detailed information on TCP and BGP neighbor connections\n"
13869 "Neighbor to display information about\n"
13870 "Neighbor to display information about\n"
13871 "Neighbor on BGP configured interface\n"
13872 "Display detailed prefix count information\n"
13877 bool uj
= use_json(argc
, argv
);
13879 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13881 return CMD_WARNING
;
13883 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13886 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13887 show_ip_bgp_vpn_all_route_prefix_cmd
,
13888 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13893 "Display information about all VPNv4 NLRIs\n"
13894 "Network in the BGP routing table to display\n"
13895 "Network in the BGP routing table to display\n"
13899 char *network
= NULL
;
13900 struct bgp
*bgp
= bgp_get_default();
13902 vty_out(vty
, "Can't find default instance\n");
13903 return CMD_WARNING
;
13906 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13907 network
= argv
[idx
]->arg
;
13908 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13909 network
= argv
[idx
]->arg
;
13911 vty_out(vty
, "Unable to figure out Network\n");
13912 return CMD_WARNING
;
13915 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13916 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13917 use_json(argc
, argv
));
13919 #endif /* KEEP_OLD_VPN_COMMANDS */
13921 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13922 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13923 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13928 "Network in the BGP routing table to display\n"
13929 "Network in the BGP routing table to display\n"
13930 "Network in the BGP routing table to display\n"
13931 "Network in the BGP routing table to display\n"
13935 char *network
= NULL
;
13936 int prefix_check
= 0;
13938 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13939 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13940 network
= argv
[idx
]->arg
;
13941 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13942 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13943 network
= argv
[idx
]->arg
;
13946 vty_out(vty
, "Unable to figure out Network\n");
13947 return CMD_WARNING
;
13949 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13950 prefix_check
, BGP_PATH_SHOW_ALL
,
13951 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13954 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13955 struct bgp_table
*table
, int *header1
,
13956 int *header2
, json_object
*json
,
13957 json_object
*json_scode
,
13958 json_object
*json_ocode
, bool wide
)
13960 uint64_t version
= table
? table
->version
: 0;
13964 json_object_int_add(json
, "bgpTableVersion", version
);
13965 json_object_string_addf(json
, "bgpLocalRouterId",
13966 "%pI4", &peer
->bgp
->router_id
);
13967 json_object_int_add(json
, "defaultLocPrf",
13968 peer
->bgp
->default_local_pref
);
13969 json_object_int_add(json
, "localAS",
13970 peer
->change_local_as
13971 ? peer
->change_local_as
13973 json_object_object_add(json
, "bgpStatusCodes",
13975 json_object_object_add(json
, "bgpOriginCodes",
13979 "BGP table version is %" PRIu64
13980 ", local router ID is %pI4, vrf id ",
13981 version
, &peer
->bgp
->router_id
);
13982 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
13983 vty_out(vty
, "%s", VRFID_NONE_STR
);
13985 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
13986 vty_out(vty
, "\n");
13987 vty_out(vty
, "Default local pref %u, ",
13988 peer
->bgp
->default_local_pref
);
13989 vty_out(vty
, "local AS %u\n",
13990 peer
->change_local_as
? peer
->change_local_as
13992 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13993 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13994 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13995 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14001 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14002 : BGP_SHOW_HEADER
));
14008 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14009 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14010 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14011 json_object
*json_scode
, json_object
*json_ocode
,
14012 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14013 unsigned long *output_count
, unsigned long *filtered_count
)
14015 struct bgp_adj_in
*ain
;
14016 struct bgp_adj_out
*adj
;
14017 struct bgp_dest
*dest
;
14021 struct update_subgroup
*subgrp
;
14022 struct peer_af
*paf
;
14023 bool route_filtered
;
14024 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14025 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14026 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14027 || (safi
== SAFI_EVPN
))
14033 subgrp
= peer_subgroup(peer
, afi
, safi
);
14035 if (type
== bgp_show_adj_route_advertised
&& subgrp
14036 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14038 json_object_int_add(json
, "bgpTableVersion",
14040 json_object_string_addf(json
, "bgpLocalRouterId",
14041 "%pI4", &bgp
->router_id
);
14042 json_object_int_add(json
, "defaultLocPrf",
14043 bgp
->default_local_pref
);
14044 json_object_int_add(json
, "localAS",
14045 peer
->change_local_as
14046 ? peer
->change_local_as
14048 json_object_object_add(json
, "bgpStatusCodes",
14050 json_object_object_add(json
, "bgpOriginCodes",
14052 json_object_string_add(
14053 json
, "bgpOriginatingDefaultNetwork",
14054 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14057 "BGP table version is %" PRIu64
14058 ", local router ID is %pI4, vrf id ",
14059 table
->version
, &bgp
->router_id
);
14060 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14061 vty_out(vty
, "%s", VRFID_NONE_STR
);
14063 vty_out(vty
, "%u", bgp
->vrf_id
);
14064 vty_out(vty
, "\n");
14065 vty_out(vty
, "Default local pref %u, ",
14066 bgp
->default_local_pref
);
14067 vty_out(vty
, "local AS %u\n",
14068 peer
->change_local_as
? peer
->change_local_as
14070 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14071 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14072 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14073 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14075 vty_out(vty
, "Originating default network %s\n\n",
14076 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14081 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14082 if (type
== bgp_show_adj_route_received
14083 || type
== bgp_show_adj_route_filtered
) {
14084 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14085 if (ain
->peer
!= peer
)
14088 show_adj_route_header(vty
, peer
, table
, header1
,
14089 header2
, json
, json_scode
,
14092 if ((safi
== SAFI_MPLS_VPN
)
14093 || (safi
== SAFI_ENCAP
)
14094 || (safi
== SAFI_EVPN
)) {
14096 json_object_string_add(
14097 json_ar
, "rd", rd_str
);
14098 else if (show_rd
&& rd_str
) {
14100 "Route Distinguisher: %s\n",
14107 route_filtered
= false;
14109 /* Filter prefix using distribute list,
14110 * filter list or prefix list
14112 const struct prefix
*rn_p
=
14113 bgp_dest_get_prefix(dest
);
14114 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14117 route_filtered
= true;
14119 /* Filter prefix using route-map */
14120 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14121 safi
, rmap_name
, NULL
,
14124 if (type
== bgp_show_adj_route_filtered
&&
14125 !route_filtered
&& ret
!= RMAP_DENY
) {
14126 bgp_attr_flush(&attr
);
14130 if (type
== bgp_show_adj_route_received
14131 && (route_filtered
|| ret
== RMAP_DENY
))
14132 (*filtered_count
)++;
14134 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
14135 use_json
, json_ar
, wide
);
14136 bgp_attr_flush(&attr
);
14139 } else if (type
== bgp_show_adj_route_advertised
) {
14140 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14141 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14142 if (paf
->peer
!= peer
|| !adj
->attr
)
14145 show_adj_route_header(vty
, peer
, table
,
14150 const struct prefix
*rn_p
=
14151 bgp_dest_get_prefix(dest
);
14154 ret
= bgp_output_modifier(
14155 peer
, rn_p
, &attr
, afi
, safi
,
14158 if (ret
!= RMAP_DENY
) {
14159 if ((safi
== SAFI_MPLS_VPN
)
14160 || (safi
== SAFI_ENCAP
)
14161 || (safi
== SAFI_EVPN
)) {
14163 json_object_string_add(
14170 "Route Distinguisher: %s\n",
14176 vty
, dest
, rn_p
, &attr
,
14177 safi
, use_json
, json_ar
,
14181 (*filtered_count
)++;
14184 bgp_attr_flush(&attr
);
14186 } else if (type
== bgp_show_adj_route_bestpath
) {
14187 struct bgp_path_info
*pi
;
14189 show_adj_route_header(vty
, peer
, table
, header1
,
14190 header2
, json
, json_scode
,
14193 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14195 if (pi
->peer
!= peer
)
14198 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14201 route_vty_out_tmp(vty
, dest
,
14202 bgp_dest_get_prefix(dest
),
14203 pi
->attr
, safi
, use_json
,
14211 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14212 safi_t safi
, enum bgp_show_adj_route_type type
,
14213 const char *rmap_name
, uint16_t show_flags
)
14216 struct bgp_table
*table
;
14217 json_object
*json
= NULL
;
14218 json_object
*json_scode
= NULL
;
14219 json_object
*json_ocode
= NULL
;
14220 json_object
*json_ar
= NULL
;
14221 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14223 /* Init BGP headers here so they're only displayed once
14224 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14230 * Initialize variables for each RD
14231 * All prefixes under an RD is aggregated within "json_routes"
14233 char rd_str
[BUFSIZ
] = {0};
14234 json_object
*json_routes
= NULL
;
14237 /* For 2-tier tables, prefix counts need to be
14238 * maintained across multiple runs of show_adj_route()
14240 unsigned long output_count_per_rd
;
14241 unsigned long filtered_count_per_rd
;
14242 unsigned long output_count
= 0;
14243 unsigned long filtered_count
= 0;
14246 json
= json_object_new_object();
14247 json_ar
= json_object_new_object();
14248 json_scode
= json_object_new_object();
14249 json_ocode
= json_object_new_object();
14251 json_object_string_add(json_scode
, "suppressed", "s");
14252 json_object_string_add(json_scode
, "damped", "d");
14253 json_object_string_add(json_scode
, "history", "h");
14254 json_object_string_add(json_scode
, "valid", "*");
14255 json_object_string_add(json_scode
, "best", ">");
14256 json_object_string_add(json_scode
, "multipath", "=");
14257 json_object_string_add(json_scode
, "internal", "i");
14258 json_object_string_add(json_scode
, "ribFailure", "r");
14259 json_object_string_add(json_scode
, "stale", "S");
14260 json_object_string_add(json_scode
, "removed", "R");
14262 json_object_string_add(json_ocode
, "igp", "i");
14263 json_object_string_add(json_ocode
, "egp", "e");
14264 json_object_string_add(json_ocode
, "incomplete", "?");
14267 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14269 json_object_string_add(
14271 "No such neighbor or address family");
14272 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14273 json_object_free(json
);
14274 json_object_free(json_ar
);
14275 json_object_free(json_scode
);
14276 json_object_free(json_ocode
);
14278 vty_out(vty
, "%% No such neighbor or address family\n");
14280 return CMD_WARNING
;
14283 if ((type
== bgp_show_adj_route_received
14284 || type
== bgp_show_adj_route_filtered
)
14285 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14286 PEER_FLAG_SOFT_RECONFIG
)) {
14288 json_object_string_add(
14290 "Inbound soft reconfiguration not enabled");
14291 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14292 json_object_free(json
);
14293 json_object_free(json_ar
);
14294 json_object_free(json_scode
);
14295 json_object_free(json_ocode
);
14298 "%% Inbound soft reconfiguration not enabled\n");
14300 return CMD_WARNING
;
14305 /* labeled-unicast routes live in the unicast table */
14306 if (safi
== SAFI_LABELED_UNICAST
)
14307 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14309 table
= bgp
->rib
[afi
][safi
];
14311 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14312 || (safi
== SAFI_EVPN
)) {
14314 struct bgp_dest
*dest
;
14316 for (dest
= bgp_table_top(table
); dest
;
14317 dest
= bgp_route_next(dest
)) {
14318 table
= bgp_dest_get_bgp_table_info(dest
);
14322 output_count_per_rd
= 0;
14323 filtered_count_per_rd
= 0;
14326 json_routes
= json_object_new_object();
14328 const struct prefix_rd
*prd
;
14329 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14332 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
14334 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
14335 rmap_name
, json
, json_routes
, json_scode
,
14336 json_ocode
, show_flags
, &header1
,
14337 &header2
, rd_str
, &output_count_per_rd
,
14338 &filtered_count_per_rd
);
14340 /* Don't include an empty RD in the output! */
14341 if (json_routes
&& (output_count_per_rd
> 0))
14342 json_object_object_add(json_ar
, rd_str
,
14345 output_count
+= output_count_per_rd
;
14346 filtered_count
+= filtered_count_per_rd
;
14349 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14350 json
, json_ar
, json_scode
, json_ocode
,
14351 show_flags
, &header1
, &header2
, rd_str
,
14352 &output_count
, &filtered_count
);
14355 if (type
== bgp_show_adj_route_advertised
)
14356 json_object_object_add(json
, "advertisedRoutes",
14359 json_object_object_add(json
, "receivedRoutes", json_ar
);
14360 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14361 json_object_int_add(json
, "filteredPrefixCounter",
14365 * These fields only give up ownership to `json` when `header1`
14366 * is used (set to zero). See code in `show_adj_route` and
14367 * `show_adj_route_header`.
14369 if (header1
== 1) {
14370 json_object_free(json_scode
);
14371 json_object_free(json_ocode
);
14374 vty_json(vty
, json
);
14375 } else if (output_count
> 0) {
14376 if (filtered_count
> 0)
14378 "\nTotal number of prefixes %ld (%ld filtered)\n",
14379 output_count
, filtered_count
);
14381 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14385 return CMD_SUCCESS
;
14388 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14389 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14390 "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]",
14394 BGP_INSTANCE_HELP_STR
14396 BGP_SAFI_WITH_LABEL_HELP_STR
14397 "Detailed information on TCP and BGP neighbor connections\n"
14398 "Neighbor to display information about\n"
14399 "Neighbor to display information about\n"
14400 "Neighbor on BGP configured interface\n"
14401 "Display the routes selected by best path\n"
14403 "Increase table width for longer prefixes\n")
14405 afi_t afi
= AFI_IP6
;
14406 safi_t safi
= SAFI_UNICAST
;
14407 char *rmap_name
= NULL
;
14408 char *peerstr
= NULL
;
14409 struct bgp
*bgp
= NULL
;
14411 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14413 uint16_t show_flags
= 0;
14416 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14419 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14421 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14425 return CMD_WARNING
;
14427 argv_find(argv
, argc
, "neighbors", &idx
);
14428 peerstr
= argv
[++idx
]->arg
;
14430 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14432 return CMD_WARNING
;
14434 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14438 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
14439 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14440 "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 RMAP_NAME$route_map] [json$uj | wide$wide]",
14444 BGP_INSTANCE_HELP_STR
14446 BGP_SAFI_WITH_LABEL_HELP_STR
14447 "Display the entries for all address families\n"
14448 "Detailed information on TCP and BGP neighbor connections\n"
14449 "Neighbor to display information about\n"
14450 "Neighbor to display information about\n"
14451 "Neighbor on BGP configured interface\n"
14452 "Display the routes advertised to a BGP neighbor\n"
14453 "Display the received routes from neighbor\n"
14454 "Display the filtered routes received from neighbor\n"
14455 "Route-map to modify the attributes\n"
14456 "Name of the route map\n"
14458 "Increase table width for longer prefixes\n")
14460 afi_t afi
= AFI_IP6
;
14461 safi_t safi
= SAFI_UNICAST
;
14462 char *peerstr
= NULL
;
14463 struct bgp
*bgp
= NULL
;
14465 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14468 uint16_t show_flags
= 0;
14469 struct listnode
*node
;
14474 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14478 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14479 if (argv_find(argv
, argc
, "ipv4", &idx
))
14480 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14482 if (argv_find(argv
, argc
, "ipv6", &idx
))
14483 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14487 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14489 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14492 return CMD_WARNING
;
14494 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14495 argv_find(argv
, argc
, "neighbors", &idx
);
14496 peerstr
= argv
[++idx
]->arg
;
14498 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14500 return CMD_WARNING
;
14502 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14503 type
= bgp_show_adj_route_advertised
;
14504 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14505 type
= bgp_show_adj_route_received
;
14506 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14507 type
= bgp_show_adj_route_filtered
;
14510 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14513 vty_out(vty
, "{\n");
14515 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14516 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14517 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14519 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14520 FOREACH_SAFI (safi
) {
14521 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14528 vty_out(vty
, ",\n");
14529 vty_out(vty
, "\"%s\":",
14530 get_afi_safi_str(afi
, safi
,
14534 "\nFor address family: %s\n",
14535 get_afi_safi_str(afi
, safi
,
14538 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14539 route_map
, show_flags
);
14543 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14544 FOREACH_AFI_SAFI (afi
, safi
) {
14545 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14552 vty_out(vty
, ",\n");
14553 vty_out(vty
, "\"%s\":",
14554 get_afi_safi_str(afi
, safi
,
14558 "\nFor address family: %s\n",
14559 get_afi_safi_str(afi
, safi
,
14562 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14563 route_map
, show_flags
);
14568 vty_out(vty
, "}\n");
14570 return CMD_SUCCESS
;
14573 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14574 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14575 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14579 BGP_INSTANCE_HELP_STR
14582 BGP_AF_MODIFIER_STR
14583 "Detailed information on TCP and BGP neighbor connections\n"
14584 "Neighbor to display information about\n"
14585 "Neighbor to display information about\n"
14586 "Neighbor on BGP configured interface\n"
14587 "Display information received from a BGP neighbor\n"
14588 "Display the prefixlist filter\n"
14591 afi_t afi
= AFI_IP6
;
14592 safi_t safi
= SAFI_UNICAST
;
14593 char *peerstr
= NULL
;
14598 struct bgp
*bgp
= NULL
;
14599 bool uj
= use_json(argc
, argv
);
14604 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14607 return CMD_WARNING
;
14609 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14610 argv_find(argv
, argc
, "neighbors", &idx
);
14611 peerstr
= argv
[++idx
]->arg
;
14613 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14615 return CMD_WARNING
;
14617 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14618 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14621 vty_out(vty
, "Address Family: %s\n",
14622 get_afi_safi_str(afi
, safi
, false));
14623 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14626 vty_out(vty
, "{}\n");
14628 vty_out(vty
, "No functional output\n");
14631 return CMD_SUCCESS
;
14634 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14635 afi_t afi
, safi_t safi
,
14636 enum bgp_show_type type
, bool use_json
)
14638 uint16_t show_flags
= 0;
14641 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14643 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14645 json_object
*json_no
= NULL
;
14646 json_no
= json_object_new_object();
14647 json_object_string_add(
14648 json_no
, "warning",
14649 "No such neighbor or address family");
14650 vty_out(vty
, "%s\n",
14651 json_object_to_json_string(json_no
));
14652 json_object_free(json_no
);
14654 vty_out(vty
, "%% No such neighbor or address family\n");
14655 return CMD_WARNING
;
14658 /* labeled-unicast routes live in the unicast table */
14659 if (safi
== SAFI_LABELED_UNICAST
)
14660 safi
= SAFI_UNICAST
;
14662 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14663 RPKI_NOT_BEING_USED
);
14666 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14667 show_ip_bgp_flowspec_routes_detailed_cmd
,
14668 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14672 BGP_INSTANCE_HELP_STR
14675 "Detailed information on flowspec entries\n"
14678 afi_t afi
= AFI_IP6
;
14679 safi_t safi
= SAFI_UNICAST
;
14680 struct bgp
*bgp
= NULL
;
14682 bool uj
= use_json(argc
, argv
);
14683 uint16_t show_flags
= BGP_SHOW_OPT_DETAIL
;
14687 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14690 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14693 return CMD_WARNING
;
14695 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14696 show_flags
, RPKI_NOT_BEING_USED
);
14699 DEFUN (show_ip_bgp_neighbor_routes
,
14700 show_ip_bgp_neighbor_routes_cmd
,
14701 "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]",
14705 BGP_INSTANCE_HELP_STR
14707 BGP_SAFI_WITH_LABEL_HELP_STR
14708 "Detailed information on TCP and BGP neighbor connections\n"
14709 "Neighbor to display information about\n"
14710 "Neighbor to display information about\n"
14711 "Neighbor on BGP configured interface\n"
14712 "Display flap statistics of the routes learned from neighbor\n"
14713 "Display the dampened routes received from neighbor\n"
14714 "Display routes learned from neighbor\n"
14717 char *peerstr
= NULL
;
14718 struct bgp
*bgp
= NULL
;
14719 afi_t afi
= AFI_IP6
;
14720 safi_t safi
= SAFI_UNICAST
;
14722 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14724 bool uj
= use_json(argc
, argv
);
14729 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14732 return CMD_WARNING
;
14734 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14735 argv_find(argv
, argc
, "neighbors", &idx
);
14736 peerstr
= argv
[++idx
]->arg
;
14738 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14740 return CMD_WARNING
;
14742 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14743 sh_type
= bgp_show_type_flap_neighbor
;
14744 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14745 sh_type
= bgp_show_type_damp_neighbor
;
14746 else if (argv_find(argv
, argc
, "routes", &idx
))
14747 sh_type
= bgp_show_type_neighbor
;
14749 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14752 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14754 struct bgp_distance
{
14755 /* Distance value for the IP source prefix. */
14758 /* Name of the access-list to be matched. */
14762 DEFUN (show_bgp_afi_vpn_rd_route
,
14763 show_bgp_afi_vpn_rd_route_cmd
,
14764 "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]",
14768 BGP_AF_MODIFIER_STR
14769 "Display information for a route distinguisher\n"
14770 "Route Distinguisher\n"
14771 "All Route Distinguishers\n"
14772 "Network in the BGP routing table to display\n"
14773 "Network in the BGP routing table to display\n"
14777 struct prefix_rd prd
;
14778 afi_t afi
= AFI_MAX
;
14781 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14782 vty_out(vty
, "%% Malformed Address Family\n");
14783 return CMD_WARNING
;
14786 if (!strcmp(argv
[5]->arg
, "all"))
14787 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14788 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14789 RPKI_NOT_BEING_USED
,
14790 use_json(argc
, argv
));
14792 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14794 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14795 return CMD_WARNING
;
14798 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14799 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14800 use_json(argc
, argv
));
14803 static struct bgp_distance
*bgp_distance_new(void)
14805 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14808 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14810 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14813 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14814 const char *ip_str
, const char *access_list_str
)
14821 struct bgp_dest
*dest
;
14822 struct bgp_distance
*bdistance
;
14824 afi
= bgp_node_afi(vty
);
14825 safi
= bgp_node_safi(vty
);
14827 ret
= str2prefix(ip_str
, &p
);
14829 vty_out(vty
, "Malformed prefix\n");
14830 return CMD_WARNING_CONFIG_FAILED
;
14833 distance
= atoi(distance_str
);
14835 /* Get BGP distance node. */
14836 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14837 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14839 bgp_dest_unlock_node(dest
);
14841 bdistance
= bgp_distance_new();
14842 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14845 /* Set distance value. */
14846 bdistance
->distance
= distance
;
14848 /* Reset access-list configuration. */
14849 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14850 if (access_list_str
)
14851 bdistance
->access_list
=
14852 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14854 return CMD_SUCCESS
;
14857 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14858 const char *ip_str
, const char *access_list_str
)
14865 struct bgp_dest
*dest
;
14866 struct bgp_distance
*bdistance
;
14868 afi
= bgp_node_afi(vty
);
14869 safi
= bgp_node_safi(vty
);
14871 ret
= str2prefix(ip_str
, &p
);
14873 vty_out(vty
, "Malformed prefix\n");
14874 return CMD_WARNING_CONFIG_FAILED
;
14877 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14879 vty_out(vty
, "Can't find specified prefix\n");
14880 return CMD_WARNING_CONFIG_FAILED
;
14883 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14884 distance
= atoi(distance_str
);
14886 if (bdistance
->distance
!= distance
) {
14887 vty_out(vty
, "Distance does not match configured\n");
14888 bgp_dest_unlock_node(dest
);
14889 return CMD_WARNING_CONFIG_FAILED
;
14892 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14893 bgp_distance_free(bdistance
);
14895 bgp_dest_set_bgp_path_info(dest
, NULL
);
14896 bgp_dest_unlock_node(dest
);
14897 bgp_dest_unlock_node(dest
);
14899 return CMD_SUCCESS
;
14902 /* Apply BGP information to distance method. */
14903 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14904 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14906 struct bgp_dest
*dest
;
14907 struct prefix q
= {0};
14909 struct bgp_distance
*bdistance
;
14910 struct access_list
*alist
;
14911 struct bgp_static
*bgp_static
;
14916 peer
= pinfo
->peer
;
14918 if (pinfo
->attr
->distance
)
14919 return pinfo
->attr
->distance
;
14921 /* Check source address.
14922 * Note: for aggregate route, peer can have unspec af type.
14924 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14925 && !sockunion2hostprefix(&peer
->su
, &q
))
14928 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14930 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14931 bgp_dest_unlock_node(dest
);
14933 if (bdistance
->access_list
) {
14934 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14936 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14937 return bdistance
->distance
;
14939 return bdistance
->distance
;
14942 /* Backdoor check. */
14943 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14945 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14946 bgp_dest_unlock_node(dest
);
14948 if (bgp_static
->backdoor
) {
14949 if (bgp
->distance_local
[afi
][safi
])
14950 return bgp
->distance_local
[afi
][safi
];
14952 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14956 if (peer
->sort
== BGP_PEER_EBGP
) {
14957 if (bgp
->distance_ebgp
[afi
][safi
])
14958 return bgp
->distance_ebgp
[afi
][safi
];
14959 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14960 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14961 if (bgp
->distance_ibgp
[afi
][safi
])
14962 return bgp
->distance_ibgp
[afi
][safi
];
14963 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14965 if (bgp
->distance_local
[afi
][safi
])
14966 return bgp
->distance_local
[afi
][safi
];
14967 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14971 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14972 * we should tell ZEBRA update the routes for a specific
14973 * AFI/SAFI to reflect changes in RIB.
14975 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
14977 safi_t update_safi
)
14982 FOREACH_AFI_SAFI (afi
, safi
) {
14983 if (!bgp_fibupd_safi(safi
))
14986 if (afi
!= update_afi
&& safi
!= update_safi
)
14989 if (BGP_DEBUG(zebra
, ZEBRA
))
14991 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14992 __func__
, afi
, safi
);
14993 bgp_zebra_announce_table(bgp
, afi
, safi
);
14997 DEFUN (bgp_distance
,
14999 "distance bgp (1-255) (1-255) (1-255)",
15000 "Define an administrative distance\n"
15002 "Distance for routes external to the AS\n"
15003 "Distance for routes internal to the AS\n"
15004 "Distance for local routes\n")
15006 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15007 int idx_number
= 2;
15008 int idx_number_2
= 3;
15009 int idx_number_3
= 4;
15010 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15011 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15012 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15016 afi
= bgp_node_afi(vty
);
15017 safi
= bgp_node_safi(vty
);
15019 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15020 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15021 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15022 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15023 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15024 bgp
->distance_local
[afi
][safi
] = distance_local
;
15025 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15027 return CMD_SUCCESS
;
15030 DEFUN (no_bgp_distance
,
15031 no_bgp_distance_cmd
,
15032 "no distance bgp [(1-255) (1-255) (1-255)]",
15034 "Define an administrative distance\n"
15036 "Distance for routes external to the AS\n"
15037 "Distance for routes internal to the AS\n"
15038 "Distance for local routes\n")
15040 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15044 afi
= bgp_node_afi(vty
);
15045 safi
= bgp_node_safi(vty
);
15047 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15048 || bgp
->distance_ibgp
[afi
][safi
] != 0
15049 || bgp
->distance_local
[afi
][safi
] != 0) {
15050 bgp
->distance_ebgp
[afi
][safi
] = 0;
15051 bgp
->distance_ibgp
[afi
][safi
] = 0;
15052 bgp
->distance_local
[afi
][safi
] = 0;
15053 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15055 return CMD_SUCCESS
;
15059 DEFUN (bgp_distance_source
,
15060 bgp_distance_source_cmd
,
15061 "distance (1-255) A.B.C.D/M",
15062 "Define an administrative distance\n"
15063 "Administrative distance\n"
15064 "IP source prefix\n")
15066 int idx_number
= 1;
15067 int idx_ipv4_prefixlen
= 2;
15068 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15069 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15070 return CMD_SUCCESS
;
15073 DEFUN (no_bgp_distance_source
,
15074 no_bgp_distance_source_cmd
,
15075 "no distance (1-255) A.B.C.D/M",
15077 "Define an administrative distance\n"
15078 "Administrative distance\n"
15079 "IP source prefix\n")
15081 int idx_number
= 2;
15082 int idx_ipv4_prefixlen
= 3;
15083 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15084 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15085 return CMD_SUCCESS
;
15088 DEFUN (bgp_distance_source_access_list
,
15089 bgp_distance_source_access_list_cmd
,
15090 "distance (1-255) A.B.C.D/M WORD",
15091 "Define an administrative distance\n"
15092 "Administrative distance\n"
15093 "IP source prefix\n"
15094 "Access list name\n")
15096 int idx_number
= 1;
15097 int idx_ipv4_prefixlen
= 2;
15099 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15100 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15101 return CMD_SUCCESS
;
15104 DEFUN (no_bgp_distance_source_access_list
,
15105 no_bgp_distance_source_access_list_cmd
,
15106 "no distance (1-255) A.B.C.D/M WORD",
15108 "Define an administrative distance\n"
15109 "Administrative distance\n"
15110 "IP source prefix\n"
15111 "Access list name\n")
15113 int idx_number
= 2;
15114 int idx_ipv4_prefixlen
= 3;
15116 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15117 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15118 return CMD_SUCCESS
;
15121 DEFUN (ipv6_bgp_distance_source
,
15122 ipv6_bgp_distance_source_cmd
,
15123 "distance (1-255) X:X::X:X/M",
15124 "Define an administrative distance\n"
15125 "Administrative distance\n"
15126 "IP source prefix\n")
15128 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15129 return CMD_SUCCESS
;
15132 DEFUN (no_ipv6_bgp_distance_source
,
15133 no_ipv6_bgp_distance_source_cmd
,
15134 "no distance (1-255) X:X::X:X/M",
15136 "Define an administrative distance\n"
15137 "Administrative distance\n"
15138 "IP source prefix\n")
15140 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15141 return CMD_SUCCESS
;
15144 DEFUN (ipv6_bgp_distance_source_access_list
,
15145 ipv6_bgp_distance_source_access_list_cmd
,
15146 "distance (1-255) X:X::X:X/M WORD",
15147 "Define an administrative distance\n"
15148 "Administrative distance\n"
15149 "IP source prefix\n"
15150 "Access list name\n")
15152 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15153 return CMD_SUCCESS
;
15156 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15157 no_ipv6_bgp_distance_source_access_list_cmd
,
15158 "no distance (1-255) X:X::X:X/M WORD",
15160 "Define an administrative distance\n"
15161 "Administrative distance\n"
15162 "IP source prefix\n"
15163 "Access list name\n")
15165 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15166 return CMD_SUCCESS
;
15169 DEFUN (bgp_damp_set
,
15171 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15172 "BGP Specific commands\n"
15173 "Enable route-flap dampening\n"
15174 "Half-life time for the penalty\n"
15175 "Value to start reusing a route\n"
15176 "Value to start suppressing a route\n"
15177 "Maximum duration to suppress a stable route\n")
15179 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15180 int idx_half_life
= 2;
15182 int idx_suppress
= 4;
15183 int idx_max_suppress
= 5;
15184 int half
= DEFAULT_HALF_LIFE
* 60;
15185 int reuse
= DEFAULT_REUSE
;
15186 int suppress
= DEFAULT_SUPPRESS
;
15187 int max
= 4 * half
;
15190 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15191 reuse
= atoi(argv
[idx_reuse
]->arg
);
15192 suppress
= atoi(argv
[idx_suppress
]->arg
);
15193 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15194 } else if (argc
== 3) {
15195 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15200 * These can't be 0 but our SA doesn't understand the
15201 * way our cli is constructed
15205 if (suppress
< reuse
) {
15207 "Suppress value cannot be less than reuse value \n");
15211 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15212 reuse
, suppress
, max
);
15215 DEFUN (bgp_damp_unset
,
15216 bgp_damp_unset_cmd
,
15217 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15219 "BGP Specific commands\n"
15220 "Enable route-flap dampening\n"
15221 "Half-life time for the penalty\n"
15222 "Value to start reusing a route\n"
15223 "Value to start suppressing a route\n"
15224 "Maximum duration to suppress a stable route\n")
15226 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15227 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15230 /* Display specified route of BGP table. */
15231 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15232 const char *ip_str
, afi_t afi
, safi_t safi
,
15233 struct prefix_rd
*prd
, int prefix_check
)
15236 struct prefix match
;
15237 struct bgp_dest
*dest
;
15238 struct bgp_dest
*rm
;
15239 struct bgp_path_info
*pi
;
15240 struct bgp_path_info
*pi_temp
;
15242 struct bgp_table
*table
;
15244 /* BGP structure lookup. */
15246 bgp
= bgp_lookup_by_name(view_name
);
15248 vty_out(vty
, "%% Can't find BGP instance %s\n",
15250 return CMD_WARNING
;
15253 bgp
= bgp_get_default();
15255 vty_out(vty
, "%% No BGP process is configured\n");
15256 return CMD_WARNING
;
15260 /* Check IP address argument. */
15261 ret
= str2prefix(ip_str
, &match
);
15263 vty_out(vty
, "%% address is malformed\n");
15264 return CMD_WARNING
;
15267 match
.family
= afi2family(afi
);
15269 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15270 || (safi
== SAFI_EVPN
)) {
15271 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15272 dest
= bgp_route_next(dest
)) {
15273 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15275 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15277 table
= bgp_dest_get_bgp_table_info(dest
);
15280 rm
= bgp_node_match(table
, &match
);
15284 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15287 || rm_p
->prefixlen
== match
.prefixlen
) {
15288 pi
= bgp_dest_get_bgp_path_info(rm
);
15290 if (pi
->extra
&& pi
->extra
->damp_info
) {
15291 pi_temp
= pi
->next
;
15292 bgp_damp_info_free(
15293 pi
->extra
->damp_info
,
15301 bgp_dest_unlock_node(rm
);
15304 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15305 if (dest
!= NULL
) {
15306 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15309 || dest_p
->prefixlen
== match
.prefixlen
) {
15310 pi
= bgp_dest_get_bgp_path_info(dest
);
15312 if (pi
->extra
&& pi
->extra
->damp_info
) {
15313 pi_temp
= pi
->next
;
15314 bgp_damp_info_free(
15315 pi
->extra
->damp_info
,
15323 bgp_dest_unlock_node(dest
);
15327 return CMD_SUCCESS
;
15330 DEFUN (clear_ip_bgp_dampening
,
15331 clear_ip_bgp_dampening_cmd
,
15332 "clear ip bgp dampening",
15336 "Clear route flap dampening information\n")
15338 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15339 return CMD_SUCCESS
;
15342 DEFUN (clear_ip_bgp_dampening_prefix
,
15343 clear_ip_bgp_dampening_prefix_cmd
,
15344 "clear ip bgp dampening A.B.C.D/M",
15348 "Clear route flap dampening information\n"
15351 int idx_ipv4_prefixlen
= 4;
15352 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15353 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15356 DEFUN (clear_ip_bgp_dampening_address
,
15357 clear_ip_bgp_dampening_address_cmd
,
15358 "clear ip bgp dampening A.B.C.D",
15362 "Clear route flap dampening information\n"
15363 "Network to clear damping information\n")
15366 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15367 SAFI_UNICAST
, NULL
, 0);
15370 DEFUN (clear_ip_bgp_dampening_address_mask
,
15371 clear_ip_bgp_dampening_address_mask_cmd
,
15372 "clear ip bgp dampening A.B.C.D A.B.C.D",
15376 "Clear route flap dampening information\n"
15377 "Network to clear damping information\n"
15381 int idx_ipv4_2
= 5;
15383 char prefix_str
[BUFSIZ
];
15385 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15386 prefix_str
, sizeof(prefix_str
));
15388 vty_out(vty
, "%% Inconsistent address and mask\n");
15389 return CMD_WARNING
;
15392 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15396 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15398 struct vty
*vty
= arg
;
15399 struct peer
*peer
= bucket
->data
;
15401 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15404 DEFUN (show_bgp_listeners
,
15405 show_bgp_listeners_cmd
,
15406 "show bgp listeners",
15409 "Display Listen Sockets and who created them\n")
15411 bgp_dump_listener_info(vty
);
15413 return CMD_SUCCESS
;
15416 DEFUN (show_bgp_peerhash
,
15417 show_bgp_peerhash_cmd
,
15418 "show bgp peerhash",
15421 "Display information about the BGP peerhash\n")
15423 struct list
*instances
= bm
->bgp
;
15424 struct listnode
*node
;
15427 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15428 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15429 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15433 return CMD_SUCCESS
;
15436 /* also used for encap safi */
15437 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15438 afi_t afi
, safi_t safi
)
15440 struct bgp_dest
*pdest
;
15441 struct bgp_dest
*dest
;
15442 struct bgp_table
*table
;
15443 const struct prefix
*p
;
15444 const struct prefix_rd
*prd
;
15445 struct bgp_static
*bgp_static
;
15446 mpls_label_t label
;
15448 /* Network configuration. */
15449 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15450 pdest
= bgp_route_next(pdest
)) {
15451 table
= bgp_dest_get_bgp_table_info(pdest
);
15455 for (dest
= bgp_table_top(table
); dest
;
15456 dest
= bgp_route_next(dest
)) {
15457 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15458 if (bgp_static
== NULL
)
15461 p
= bgp_dest_get_prefix(dest
);
15462 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
15465 /* "network" configuration display. */
15466 label
= decode_label(&bgp_static
->label
);
15468 vty_out(vty
, " network %pFX rd %pRD", p
, prd
);
15469 if (safi
== SAFI_MPLS_VPN
)
15470 vty_out(vty
, " label %u", label
);
15472 if (bgp_static
->rmap
.name
)
15473 vty_out(vty
, " route-map %s",
15474 bgp_static
->rmap
.name
);
15476 if (bgp_static
->backdoor
)
15477 vty_out(vty
, " backdoor");
15479 vty_out(vty
, "\n");
15484 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15485 afi_t afi
, safi_t safi
)
15487 struct bgp_dest
*pdest
;
15488 struct bgp_dest
*dest
;
15489 struct bgp_table
*table
;
15490 const struct prefix
*p
;
15491 const struct prefix_rd
*prd
;
15492 struct bgp_static
*bgp_static
;
15493 char buf
[PREFIX_STRLEN
* 2];
15494 char buf2
[SU_ADDRSTRLEN
];
15495 char esi_buf
[ESI_STR_LEN
];
15497 /* Network configuration. */
15498 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15499 pdest
= bgp_route_next(pdest
)) {
15500 table
= bgp_dest_get_bgp_table_info(pdest
);
15504 for (dest
= bgp_table_top(table
); dest
;
15505 dest
= bgp_route_next(dest
)) {
15506 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15507 if (bgp_static
== NULL
)
15510 char *macrouter
= NULL
;
15512 if (bgp_static
->router_mac
)
15513 macrouter
= prefix_mac2str(
15514 bgp_static
->router_mac
, NULL
, 0);
15515 if (bgp_static
->eth_s_id
)
15516 esi_to_str(bgp_static
->eth_s_id
,
15517 esi_buf
, sizeof(esi_buf
));
15518 p
= bgp_dest_get_prefix(dest
);
15519 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15521 /* "network" configuration display. */
15522 if (p
->u
.prefix_evpn
.route_type
== 5) {
15523 char local_buf
[PREFIX_STRLEN
];
15524 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15525 struct prefix_evpn
*)p
)
15529 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
15530 local_buf
, PREFIX_STRLEN
);
15531 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15532 p
->u
.prefix_evpn
.prefix_addr
15533 .ip_prefix_length
);
15535 prefix2str(p
, buf
, sizeof(buf
));
15538 if (bgp_static
->gatewayIp
.family
== AF_INET
15539 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15540 inet_ntop(bgp_static
->gatewayIp
.family
,
15541 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15544 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15545 buf
, prd
, p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15546 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15549 XFREE(MTYPE_TMP
, macrouter
);
15554 /* Configuration of static route announcement and aggregate
15556 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15559 struct bgp_dest
*dest
;
15560 const struct prefix
*p
;
15561 struct bgp_static
*bgp_static
;
15562 struct bgp_aggregate
*bgp_aggregate
;
15564 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15565 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15569 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15570 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15574 /* Network configuration. */
15575 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15576 dest
= bgp_route_next(dest
)) {
15577 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15578 if (bgp_static
== NULL
)
15581 p
= bgp_dest_get_prefix(dest
);
15583 vty_out(vty
, " network %pFX", p
);
15585 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15586 vty_out(vty
, " label-index %u",
15587 bgp_static
->label_index
);
15589 if (bgp_static
->rmap
.name
)
15590 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15592 if (bgp_static
->backdoor
)
15593 vty_out(vty
, " backdoor");
15595 vty_out(vty
, "\n");
15598 /* Aggregate-address configuration. */
15599 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15600 dest
= bgp_route_next(dest
)) {
15601 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15602 if (bgp_aggregate
== NULL
)
15605 p
= bgp_dest_get_prefix(dest
);
15607 vty_out(vty
, " aggregate-address %pFX", p
);
15609 if (bgp_aggregate
->as_set
)
15610 vty_out(vty
, " as-set");
15612 if (bgp_aggregate
->summary_only
)
15613 vty_out(vty
, " summary-only");
15615 if (bgp_aggregate
->rmap
.name
)
15616 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15618 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15619 vty_out(vty
, " origin %s",
15620 bgp_origin2str(bgp_aggregate
->origin
));
15622 if (bgp_aggregate
->match_med
)
15623 vty_out(vty
, " matching-MED-only");
15625 if (bgp_aggregate
->suppress_map_name
)
15626 vty_out(vty
, " suppress-map %s",
15627 bgp_aggregate
->suppress_map_name
);
15629 vty_out(vty
, "\n");
15633 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15636 struct bgp_dest
*dest
;
15637 struct bgp_distance
*bdistance
;
15639 /* Distance configuration. */
15640 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15641 && bgp
->distance_local
[afi
][safi
]
15642 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15643 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15644 || bgp
->distance_local
[afi
][safi
]
15645 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15646 vty_out(vty
, " distance bgp %d %d %d\n",
15647 bgp
->distance_ebgp
[afi
][safi
],
15648 bgp
->distance_ibgp
[afi
][safi
],
15649 bgp
->distance_local
[afi
][safi
]);
15652 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15653 dest
= bgp_route_next(dest
)) {
15654 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15655 if (bdistance
!= NULL
)
15656 vty_out(vty
, " distance %d %pBD %s\n",
15657 bdistance
->distance
, dest
,
15658 bdistance
->access_list
? bdistance
->access_list
15663 /* Allocate routing table structure and install commands. */
15664 void bgp_route_init(void)
15669 /* Init BGP distance table. */
15670 FOREACH_AFI_SAFI (afi
, safi
)
15671 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15673 /* IPv4 BGP commands. */
15674 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15675 install_element(BGP_NODE
, &bgp_network_cmd
);
15676 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15678 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15680 /* IPv4 unicast configuration. */
15681 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15682 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15683 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15685 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15687 /* IPv4 multicast configuration. */
15688 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15689 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15690 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15691 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15693 /* IPv4 labeled-unicast configuration. */
15694 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15695 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15697 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15698 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15699 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15700 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15701 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15702 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15703 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15704 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15706 install_element(VIEW_NODE
,
15707 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15708 install_element(VIEW_NODE
,
15709 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15710 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15711 install_element(VIEW_NODE
,
15712 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15713 #ifdef KEEP_OLD_VPN_COMMANDS
15714 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15715 #endif /* KEEP_OLD_VPN_COMMANDS */
15716 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15717 install_element(VIEW_NODE
,
15718 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15720 /* BGP dampening clear commands */
15721 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15722 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15724 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15725 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15728 install_element(ENABLE_NODE
,
15729 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15730 #ifdef KEEP_OLD_VPN_COMMANDS
15731 install_element(ENABLE_NODE
,
15732 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15733 #endif /* KEEP_OLD_VPN_COMMANDS */
15735 /* New config IPv6 BGP commands. */
15736 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15737 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15738 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15740 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15742 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15744 /* IPv6 labeled unicast address family. */
15745 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15746 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15748 install_element(BGP_NODE
, &bgp_distance_cmd
);
15749 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15750 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15751 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15752 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15753 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15754 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15755 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15756 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15757 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15758 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15759 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15760 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15761 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15762 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15763 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15764 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15765 install_element(BGP_IPV4M_NODE
,
15766 &no_bgp_distance_source_access_list_cmd
);
15767 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15768 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15769 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15770 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15771 install_element(BGP_IPV6_NODE
,
15772 &ipv6_bgp_distance_source_access_list_cmd
);
15773 install_element(BGP_IPV6_NODE
,
15774 &no_ipv6_bgp_distance_source_access_list_cmd
);
15775 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15776 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15777 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15778 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15779 install_element(BGP_IPV6M_NODE
,
15780 &ipv6_bgp_distance_source_access_list_cmd
);
15781 install_element(BGP_IPV6M_NODE
,
15782 &no_ipv6_bgp_distance_source_access_list_cmd
);
15784 /* BGP dampening */
15785 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15786 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15787 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15788 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15789 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15790 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15791 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15792 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15793 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15794 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15795 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15796 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15797 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15798 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15800 /* Large Communities */
15801 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15802 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15804 /* show bgp ipv4 flowspec detailed */
15805 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15807 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15808 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15811 void bgp_route_finish(void)
15816 FOREACH_AFI_SAFI (afi
, safi
) {
15817 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15818 bgp_distance_table
[afi
][safi
] = NULL
;