1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "sockunion.h"
39 #include "workqueue.h"
44 #include "lib_errors.h"
46 #include "bgpd/bgpd.h"
47 #include "bgpd/bgp_table.h"
48 #include "bgpd/bgp_route.h"
49 #include "bgpd/bgp_attr.h"
50 #include "bgpd/bgp_debug.h"
51 #include "bgpd/bgp_errors.h"
52 #include "bgpd/bgp_aspath.h"
53 #include "bgpd/bgp_regex.h"
54 #include "bgpd/bgp_community.h"
55 #include "bgpd/bgp_community_alias.h"
56 #include "bgpd/bgp_ecommunity.h"
57 #include "bgpd/bgp_lcommunity.h"
58 #include "bgpd/bgp_clist.h"
59 #include "bgpd/bgp_packet.h"
60 #include "bgpd/bgp_filter.h"
61 #include "bgpd/bgp_fsm.h"
62 #include "bgpd/bgp_mplsvpn.h"
63 #include "bgpd/bgp_nexthop.h"
64 #include "bgpd/bgp_damp.h"
65 #include "bgpd/bgp_advertise.h"
66 #include "bgpd/bgp_zebra.h"
67 #include "bgpd/bgp_vty.h"
68 #include "bgpd/bgp_mpath.h"
69 #include "bgpd/bgp_nht.h"
70 #include "bgpd/bgp_updgrp.h"
71 #include "bgpd/bgp_label.h"
72 #include "bgpd/bgp_addpath.h"
73 #include "bgpd/bgp_mac.h"
74 #include "bgpd/bgp_network.h"
75 #include "bgpd/bgp_trace.h"
76 #include "bgpd/bgp_rpki.h"
79 #include "bgpd/rfapi/rfapi_backend.h"
80 #include "bgpd/rfapi/vnc_import_bgp.h"
81 #include "bgpd/rfapi/vnc_export_bgp.h"
83 #include "bgpd/bgp_encap_types.h"
84 #include "bgpd/bgp_encap_tlv.h"
85 #include "bgpd/bgp_evpn.h"
86 #include "bgpd/bgp_evpn_mh.h"
87 #include "bgpd/bgp_evpn_vty.h"
88 #include "bgpd/bgp_flowspec.h"
89 #include "bgpd/bgp_flowspec_util.h"
90 #include "bgpd/bgp_pbr.h"
92 #ifndef VTYSH_EXTRACT_PL
93 #include "bgpd/bgp_route_clippy.c"
96 DEFINE_HOOK(bgp_snmp_update_stats
,
97 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
100 DEFINE_HOOK(bgp_rpki_prefix_status
,
101 (struct peer
*peer
, struct attr
*attr
,
102 const struct prefix
*prefix
),
103 (peer
, attr
, prefix
));
105 /* Render dest to prefix_rd based on safi */
106 static const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
109 /* Extern from bgp_dump.c */
110 extern const char *bgp_origin_str
[];
111 extern const char *bgp_origin_long_str
[];
114 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
115 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
116 static const struct message bgp_pmsi_tnltype_str
[] = {
117 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
118 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
119 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
120 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
121 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
122 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
123 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
124 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
128 #define VRFID_NONE_STR "-"
129 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
131 DEFINE_HOOK(bgp_process
,
132 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
133 struct peer
*peer
, bool withdraw
),
134 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
136 /** Test if path is suppressed. */
137 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
139 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
142 return listcount(pi
->extra
->aggr_suppressors
) > 0;
145 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
146 safi_t safi
, const struct prefix
*p
,
147 struct prefix_rd
*prd
)
149 struct bgp_dest
*dest
;
150 struct bgp_dest
*pdest
= NULL
;
154 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
155 || (safi
== SAFI_EVPN
)) {
156 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
158 if (!bgp_dest_has_bgp_path_info_data(pdest
))
159 bgp_dest_set_bgp_table_info(
160 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
162 bgp_dest_unlock_node(pdest
);
163 table
= bgp_dest_get_bgp_table_info(pdest
);
166 dest
= bgp_node_get(table
, p
);
168 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
169 || (safi
== SAFI_EVPN
))
175 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
176 safi_t safi
, const struct prefix
*p
,
177 struct prefix_rd
*prd
)
179 struct bgp_dest
*dest
;
180 struct bgp_dest
*pdest
= NULL
;
185 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
186 || (safi
== SAFI_EVPN
)) {
187 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
191 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
192 bgp_dest_unlock_node(pdest
);
196 table
= bgp_dest_get_bgp_table_info(pdest
);
199 dest
= bgp_node_lookup(table
, p
);
204 /* Allocate bgp_path_info_extra */
205 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
207 struct bgp_path_info_extra
*new;
208 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
209 sizeof(struct bgp_path_info_extra
));
210 new->label
[0] = MPLS_INVALID_LABEL
;
212 new->bgp_fs_pbr
= NULL
;
213 new->bgp_fs_iprule
= NULL
;
217 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
219 struct bgp_path_info_extra
*e
;
221 if (!extra
|| !*extra
)
226 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
231 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
234 /* FIXME: since multiple e may have the same e->parent
235 * and e->parent->net is holding a refcount for each
236 * of them, we need to do some fudging here.
238 * WARNING: if bpi->net->lock drops to 0, bpi may be
239 * freed as well (because bpi->net was holding the
240 * last reference to bpi) => write after free!
244 bpi
= bgp_path_info_lock(bpi
);
245 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
246 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
249 bgp_path_info_unlock(bpi
);
251 bgp_path_info_unlock(e
->parent
);
256 bgp_unlock(e
->bgp_orig
);
259 peer_unlock(e
->peer_orig
);
261 if (e
->aggr_suppressors
)
262 list_delete(&e
->aggr_suppressors
);
265 bgp_evpn_path_mh_info_free(e
->mh_info
);
267 if ((*extra
)->bgp_fs_iprule
)
268 list_delete(&((*extra
)->bgp_fs_iprule
));
269 if ((*extra
)->bgp_fs_pbr
)
270 list_delete(&((*extra
)->bgp_fs_pbr
));
271 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
274 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
275 * allocated if required.
277 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
280 pi
->extra
= bgp_path_info_extra_new();
284 /* Free bgp route information. */
285 static void bgp_path_info_free(struct bgp_path_info
*path
)
287 bgp_attr_unintern(&path
->attr
);
289 bgp_unlink_nexthop(path
);
290 bgp_path_info_extra_free(&path
->extra
);
291 bgp_path_info_mpath_free(&path
->mpath
);
293 bgp_addpath_free_info_data(&path
->tx_addpath
,
294 &path
->net
->tx_addpath
);
296 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
298 XFREE(MTYPE_BGP_ROUTE
, path
);
301 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
307 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
309 assert(path
&& path
->lock
> 0);
312 if (path
->lock
== 0) {
313 bgp_path_info_free(path
);
320 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
321 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
324 struct bgp_path_info
*old_pi
, *nextpi
;
325 bool set_flag
= false;
326 struct bgp
*bgp
= NULL
;
327 struct bgp_table
*table
= NULL
;
331 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
332 * then the route selection is deferred
334 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
337 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
338 if (BGP_DEBUG(update
, UPDATE_OUT
))
340 "Route %pBD is in workqueue and being processed, not deferred.",
346 table
= bgp_dest_table(dest
);
353 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
354 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
355 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
358 /* Route selection is deferred if there is a stale path which
359 * which indicates peer is in restart mode
361 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
362 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
365 /* If the peer is graceful restart capable and peer is
366 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
369 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
370 && BGP_PEER_RESTARTING_MODE(peer
)
372 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
380 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
383 if (set_flag
&& table
) {
384 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
385 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
386 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
387 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
388 if (BGP_DEBUG(update
, UPDATE_OUT
))
389 zlog_debug("DEFER route %pBD, dest %p", dest
,
397 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
399 struct bgp_path_info
*top
;
401 top
= bgp_dest_get_bgp_path_info(dest
);
407 bgp_dest_set_bgp_path_info(dest
, pi
);
409 bgp_path_info_lock(pi
);
410 bgp_dest_lock_node(dest
);
411 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
412 bgp_dest_set_defer_flag(dest
, false);
413 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
416 /* Do the actual removal of info from RIB, for use by bgp_process
417 completion callback *only* */
418 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
421 pi
->next
->prev
= pi
->prev
;
423 pi
->prev
->next
= pi
->next
;
425 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
427 bgp_path_info_mpath_dequeue(pi
);
428 bgp_path_info_unlock(pi
);
429 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
430 bgp_dest_unlock_node(dest
);
433 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
435 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
436 /* set of previous already took care of pcount */
437 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
440 /* undo the effects of a previous call to bgp_path_info_delete; typically
441 called when a route is deleted and then quickly re-added before the
442 deletion has been processed */
443 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
445 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
446 /* unset of previous already took care of pcount */
447 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
450 /* Adjust pcount as required */
451 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
453 struct bgp_table
*table
;
455 assert(dest
&& bgp_dest_table(dest
));
456 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
458 table
= bgp_dest_table(dest
);
460 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
463 if (!BGP_PATH_COUNTABLE(pi
)
464 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
466 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
468 /* slight hack, but more robust against errors. */
469 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
470 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
472 flog_err(EC_LIB_DEVELOPMENT
,
473 "Asked to decrement 0 prefix count for peer");
474 } else if (BGP_PATH_COUNTABLE(pi
)
475 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
476 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
477 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
481 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
482 struct bgp_path_info
*pi2
)
484 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
487 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
488 * This is here primarily to keep prefix-count in check.
490 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
493 SET_FLAG(pi
->flags
, flag
);
495 /* early bath if we know it's not a flag that changes countability state
497 if (!CHECK_FLAG(flag
,
498 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
501 bgp_pcount_adjust(dest
, pi
);
504 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
507 UNSET_FLAG(pi
->flags
, flag
);
509 /* early bath if we know it's not a flag that changes countability state
511 if (!CHECK_FLAG(flag
,
512 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
515 bgp_pcount_adjust(dest
, pi
);
518 /* Get MED value. If MED value is missing and "bgp bestpath
519 missing-as-worst" is specified, treat it as the worst value. */
520 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
522 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
525 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
532 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
535 if (pi
->addpath_rx_id
)
536 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
537 pi
->peer
->host
, pi
->addpath_rx_id
);
539 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
544 * Get the ultimate path info.
546 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
548 struct bgp_path_info
*bpi_ultimate
;
550 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
553 for (bpi_ultimate
= info
;
554 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
555 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
561 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
563 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
564 struct bgp_path_info
*exist
, int *paths_eq
,
565 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
566 char *pfx_buf
, afi_t afi
, safi_t safi
,
567 enum bgp_path_selection_reason
*reason
)
569 const struct prefix
*new_p
;
570 struct attr
*newattr
, *existattr
;
571 enum bgp_peer_sort new_sort
;
572 enum bgp_peer_sort exist_sort
;
578 uint32_t exist_weight
;
579 uint32_t newm
, existm
;
580 struct in_addr new_id
;
581 struct in_addr exist_id
;
584 int internal_as_route
;
587 int igp_metric_ret
= 0;
588 int peer_sort_ret
= -1;
589 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
590 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
592 uint32_t exist_mm_seq
;
599 bool new_origin
, exist_origin
;
600 struct bgp_path_info
*bpi_ultimate
;
606 *reason
= bgp_path_selection_none
;
608 zlog_debug("%s: new is NULL", pfx_buf
);
613 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
614 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
619 *reason
= bgp_path_selection_first
;
621 zlog_debug("%s(%s): %s is the initial bestpath",
622 pfx_buf
, bgp
->name_pretty
, new_buf
);
627 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
628 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
630 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
631 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
632 exist_buf
, exist
->flags
);
636 existattr
= exist
->attr
;
638 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
639 * Capability" to a neighbor MUST perform the following upon receiving
640 * a route from that neighbor with the "LLGR_STALE" community, or upon
641 * attaching the "LLGR_STALE" community itself per Section 4.2:
643 * Treat the route as the least-preferred in route selection (see
644 * below). See the Risks of Depreferencing Routes section (Section 5.2)
645 * for a discussion of potential risks inherent in doing this.
647 if (bgp_attr_get_community(newattr
) &&
648 community_include(bgp_attr_get_community(newattr
),
649 COMMUNITY_LLGR_STALE
)) {
652 "%s: %s wins over %s due to LLGR_STALE community",
653 pfx_buf
, new_buf
, exist_buf
);
657 if (bgp_attr_get_community(existattr
) &&
658 community_include(bgp_attr_get_community(existattr
),
659 COMMUNITY_LLGR_STALE
)) {
662 "%s: %s loses to %s due to LLGR_STALE community",
663 pfx_buf
, new_buf
, exist_buf
);
667 new_p
= bgp_dest_get_prefix(new->net
);
669 /* For EVPN routes, we cannot just go by local vs remote, we have to
670 * look at the MAC mobility sequence number, if present.
672 if ((safi
== SAFI_EVPN
)
673 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
674 /* This is an error condition described in RFC 7432 Section
676 * states that in this scenario "the PE MUST alert the operator"
678 * does not state what other action to take. In order to provide
680 * consistency in this scenario we are going to prefer the path
684 if (newattr
->sticky
!= existattr
->sticky
) {
686 prefix2str(new_p
, pfx_buf
,
688 * PREFIX2STR_BUFFER
);
689 bgp_path_info_path_with_addpath_rx_str(
690 new, new_buf
, sizeof(new_buf
));
691 bgp_path_info_path_with_addpath_rx_str(
692 exist
, exist_buf
, sizeof(exist_buf
));
695 if (newattr
->sticky
&& !existattr
->sticky
) {
696 *reason
= bgp_path_selection_evpn_sticky_mac
;
699 "%s: %s wins over %s due to sticky MAC flag",
700 pfx_buf
, new_buf
, exist_buf
);
704 if (!newattr
->sticky
&& existattr
->sticky
) {
705 *reason
= bgp_path_selection_evpn_sticky_mac
;
708 "%s: %s loses to %s due to sticky MAC flag",
709 pfx_buf
, new_buf
, exist_buf
);
714 new_esi
= bgp_evpn_attr_get_esi(newattr
);
715 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
716 if (bgp_evpn_is_esi_valid(new_esi
) &&
717 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
723 /* If both paths have the same non-zero ES and
724 * one path is local it wins.
725 * PS: Note the local path wins even if the remote
726 * has the higher MM seq. The local path's
727 * MM seq will be fixed up to match the highest
728 * rem seq, subsequently.
731 char esi_buf
[ESI_STR_LEN
];
733 if (bgp_evpn_is_path_local(bgp
, new)) {
734 *reason
= bgp_path_selection_evpn_local_path
;
737 "%s: %s wins over %s as ES %s is same and local",
738 pfx_buf
, new_buf
, exist_buf
,
739 esi_to_str(new_esi
, esi_buf
,
743 if (bgp_evpn_is_path_local(bgp
, exist
)) {
744 *reason
= bgp_path_selection_evpn_local_path
;
747 "%s: %s loses to %s as ES %s is same and local",
748 pfx_buf
, new_buf
, exist_buf
,
749 esi_to_str(new_esi
, esi_buf
,
755 new_mm_seq
= mac_mobility_seqnum(newattr
);
756 exist_mm_seq
= mac_mobility_seqnum(existattr
);
758 if (new_mm_seq
> exist_mm_seq
) {
759 *reason
= bgp_path_selection_evpn_seq
;
762 "%s: %s wins over %s due to MM seq %u > %u",
763 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
768 if (new_mm_seq
< exist_mm_seq
) {
769 *reason
= bgp_path_selection_evpn_seq
;
772 "%s: %s loses to %s due to MM seq %u < %u",
773 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
778 /* if the sequence numbers and ESI are the same and one path
779 * is non-proxy it wins (over proxy)
781 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
782 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
783 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
784 old_proxy
!= new_proxy
) {
786 *reason
= bgp_path_selection_evpn_non_proxy
;
789 "%s: %s wins over %s, same seq/es and non-proxy",
790 pfx_buf
, new_buf
, exist_buf
);
794 *reason
= bgp_path_selection_evpn_non_proxy
;
797 "%s: %s loses to %s, same seq/es and non-proxy",
798 pfx_buf
, new_buf
, exist_buf
);
803 * if sequence numbers are the same path with the lowest IP
806 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
808 *reason
= bgp_path_selection_evpn_lower_ip
;
811 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
812 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
813 &new->attr
->nexthop
);
817 *reason
= bgp_path_selection_evpn_lower_ip
;
820 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
821 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
822 &new->attr
->nexthop
);
827 /* 1. Weight check. */
828 new_weight
= newattr
->weight
;
829 exist_weight
= existattr
->weight
;
831 if (new_weight
> exist_weight
) {
832 *reason
= bgp_path_selection_weight
;
834 zlog_debug("%s: %s wins over %s due to weight %d > %d",
835 pfx_buf
, new_buf
, exist_buf
, new_weight
,
840 if (new_weight
< exist_weight
) {
841 *reason
= bgp_path_selection_weight
;
843 zlog_debug("%s: %s loses to %s due to weight %d < %d",
844 pfx_buf
, new_buf
, exist_buf
, new_weight
,
849 /* 2. Local preference check. */
850 new_pref
= exist_pref
= bgp
->default_local_pref
;
852 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
853 new_pref
= newattr
->local_pref
;
854 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
855 exist_pref
= existattr
->local_pref
;
857 if (new_pref
> exist_pref
) {
858 *reason
= bgp_path_selection_local_pref
;
861 "%s: %s wins over %s due to localpref %d > %d",
862 pfx_buf
, new_buf
, exist_buf
, new_pref
,
867 if (new_pref
< exist_pref
) {
868 *reason
= bgp_path_selection_local_pref
;
871 "%s: %s loses to %s due to localpref %d < %d",
872 pfx_buf
, new_buf
, exist_buf
, new_pref
,
877 /* 3. Local route check. We prefer:
879 * - BGP_ROUTE_AGGREGATE
880 * - BGP_ROUTE_REDISTRIBUTE
882 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
883 new->sub_type
== BGP_ROUTE_IMPORTED
);
884 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
885 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
887 if (new_origin
&& !exist_origin
) {
888 *reason
= bgp_path_selection_local_route
;
891 "%s: %s wins over %s due to preferred BGP_ROUTE type",
892 pfx_buf
, new_buf
, exist_buf
);
896 if (!new_origin
&& exist_origin
) {
897 *reason
= bgp_path_selection_local_route
;
900 "%s: %s loses to %s due to preferred BGP_ROUTE type",
901 pfx_buf
, new_buf
, exist_buf
);
905 /* Here if these are imported routes then get ultimate pi for
908 new = bgp_get_imported_bpi_ultimate(new);
909 exist
= bgp_get_imported_bpi_ultimate(exist
);
911 existattr
= exist
->attr
;
913 /* 4. AS path length check. */
914 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
915 int exist_hops
= aspath_count_hops(existattr
->aspath
);
916 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
918 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
921 aspath_hops
= aspath_count_hops(newattr
->aspath
);
922 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
924 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
925 *reason
= bgp_path_selection_confed_as_path
;
928 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
929 pfx_buf
, new_buf
, exist_buf
,
931 (exist_hops
+ exist_confeds
));
935 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
936 *reason
= bgp_path_selection_confed_as_path
;
939 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
940 pfx_buf
, new_buf
, exist_buf
,
942 (exist_hops
+ exist_confeds
));
946 int newhops
= aspath_count_hops(newattr
->aspath
);
948 if (newhops
< exist_hops
) {
949 *reason
= bgp_path_selection_as_path
;
952 "%s: %s wins over %s due to aspath hopcount %d < %d",
953 pfx_buf
, new_buf
, exist_buf
,
954 newhops
, exist_hops
);
958 if (newhops
> exist_hops
) {
959 *reason
= bgp_path_selection_as_path
;
962 "%s: %s loses to %s due to aspath hopcount %d > %d",
963 pfx_buf
, new_buf
, exist_buf
,
964 newhops
, exist_hops
);
970 /* 5. Origin check. */
971 if (newattr
->origin
< existattr
->origin
) {
972 *reason
= bgp_path_selection_origin
;
974 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
975 pfx_buf
, new_buf
, exist_buf
,
976 bgp_origin_long_str
[newattr
->origin
],
977 bgp_origin_long_str
[existattr
->origin
]);
981 if (newattr
->origin
> existattr
->origin
) {
982 *reason
= bgp_path_selection_origin
;
984 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
985 pfx_buf
, new_buf
, exist_buf
,
986 bgp_origin_long_str
[newattr
->origin
],
987 bgp_origin_long_str
[existattr
->origin
]);
992 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
993 && aspath_count_hops(existattr
->aspath
) == 0);
994 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
995 && aspath_count_confeds(existattr
->aspath
) > 0
996 && aspath_count_hops(newattr
->aspath
) == 0
997 && aspath_count_hops(existattr
->aspath
) == 0);
999 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1000 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1001 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1002 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1003 || internal_as_route
) {
1004 new_med
= bgp_med_value(new->attr
, bgp
);
1005 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1007 if (new_med
< exist_med
) {
1008 *reason
= bgp_path_selection_med
;
1011 "%s: %s wins over %s due to MED %d < %d",
1012 pfx_buf
, new_buf
, exist_buf
, new_med
,
1017 if (new_med
> exist_med
) {
1018 *reason
= bgp_path_selection_med
;
1021 "%s: %s loses to %s due to MED %d > %d",
1022 pfx_buf
, new_buf
, exist_buf
, new_med
,
1028 /* 7. Peer type check. */
1029 new_sort
= new->peer
->sort
;
1030 exist_sort
= exist
->peer
->sort
;
1032 if (new_sort
== BGP_PEER_EBGP
1033 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1034 *reason
= bgp_path_selection_peer
;
1037 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1038 pfx_buf
, new_buf
, exist_buf
);
1039 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1044 if (exist_sort
== BGP_PEER_EBGP
1045 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1046 *reason
= bgp_path_selection_peer
;
1049 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1050 pfx_buf
, new_buf
, exist_buf
);
1051 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1056 /* 8. IGP metric check. */
1060 newm
= new->extra
->igpmetric
;
1062 existm
= exist
->extra
->igpmetric
;
1064 if (newm
< existm
) {
1065 if (debug
&& peer_sort_ret
< 0)
1067 "%s: %s wins over %s due to IGP metric %u < %u",
1068 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1072 if (newm
> existm
) {
1073 if (debug
&& peer_sort_ret
< 0)
1075 "%s: %s loses to %s due to IGP metric %u > %u",
1076 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1080 /* 9. Same IGP metric. Compare the cluster list length as
1081 representative of IGP hops metric. Rewrite the metric value
1082 pair (newm, existm) with the cluster list length. Prefer the
1083 path with smaller cluster list length. */
1084 if (newm
== existm
) {
1085 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
&&
1086 peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
&&
1087 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1088 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1089 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1091 if (newm
< existm
) {
1092 if (debug
&& peer_sort_ret
< 0)
1094 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1095 pfx_buf
, new_buf
, exist_buf
,
1100 if (newm
> existm
) {
1101 if (debug
&& peer_sort_ret
< 0)
1103 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1104 pfx_buf
, new_buf
, exist_buf
,
1111 /* 10. confed-external vs. confed-internal */
1112 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1113 if (new_sort
== BGP_PEER_CONFED
1114 && exist_sort
== BGP_PEER_IBGP
) {
1115 *reason
= bgp_path_selection_confed
;
1118 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1119 pfx_buf
, new_buf
, exist_buf
);
1120 if (!CHECK_FLAG(bgp
->flags
,
1121 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1126 if (exist_sort
== BGP_PEER_CONFED
1127 && new_sort
== BGP_PEER_IBGP
) {
1128 *reason
= bgp_path_selection_confed
;
1131 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1132 pfx_buf
, new_buf
, exist_buf
);
1133 if (!CHECK_FLAG(bgp
->flags
,
1134 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1140 /* 11. Maximum path check. */
1141 if (newm
== existm
) {
1142 /* If one path has a label but the other does not, do not treat
1143 * them as equals for multipath
1145 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1147 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1150 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1151 pfx_buf
, new_buf
, exist_buf
);
1152 } else if (CHECK_FLAG(bgp
->flags
,
1153 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1156 * For the two paths, all comparison steps till IGP
1158 * have succeeded - including AS_PATH hop count. Since
1160 * bestpath as-path multipath-relax' knob is on, we
1162 * an exact match of AS_PATH. Thus, mark the paths are
1164 * That will trigger both these paths to get into the
1172 "%s: %s and %s are equal via multipath-relax",
1173 pfx_buf
, new_buf
, exist_buf
);
1174 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1175 if (aspath_cmp(new->attr
->aspath
,
1176 exist
->attr
->aspath
)) {
1181 "%s: %s and %s are equal via matching aspaths",
1182 pfx_buf
, new_buf
, exist_buf
);
1184 } else if (new->peer
->as
== exist
->peer
->as
) {
1189 "%s: %s and %s are equal via same remote-as",
1190 pfx_buf
, new_buf
, exist_buf
);
1194 * TODO: If unequal cost ibgp multipath is enabled we can
1195 * mark the paths as equal here instead of returning
1198 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1199 * if either step 7 or 10 (peer type checks) yielded a winner,
1200 * that result was returned immediately. Returning from step 10
1201 * ignored the return value computed in steps 8 and 9 (IGP
1202 * metric checks). In order to preserve that behavior, if
1203 * peer_sort_ret is set, return that rather than igp_metric_ret.
1205 ret
= peer_sort_ret
;
1206 if (peer_sort_ret
< 0) {
1207 ret
= igp_metric_ret
;
1211 "%s: %s wins over %s after IGP metric comparison",
1212 pfx_buf
, new_buf
, exist_buf
);
1215 "%s: %s loses to %s after IGP metric comparison",
1216 pfx_buf
, new_buf
, exist_buf
);
1218 *reason
= bgp_path_selection_igp_metric
;
1224 * At this point, the decision whether to set *paths_eq = 1 has been
1225 * completed. If we deferred returning because of bestpath peer-type
1226 * relax configuration, return now.
1228 if (peer_sort_ret
>= 0)
1229 return peer_sort_ret
;
1231 /* 12. If both paths are external, prefer the path that was received
1232 first (the oldest one). This step minimizes route-flap, since a
1233 newer path won't displace an older one, even if it was the
1234 preferred route based on the additional decision criteria below. */
1235 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1236 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1237 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1238 *reason
= bgp_path_selection_older
;
1241 "%s: %s wins over %s due to oldest external",
1242 pfx_buf
, new_buf
, exist_buf
);
1246 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1247 *reason
= bgp_path_selection_older
;
1250 "%s: %s loses to %s due to oldest external",
1251 pfx_buf
, new_buf
, exist_buf
);
1256 /* 13. Router-ID comparison. */
1257 /* If one of the paths is "stale", the corresponding peer router-id will
1258 * be 0 and would always win over the other path. If originator id is
1259 * used for the comparison, it will decide which path is better.
1261 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1262 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1264 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1265 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1266 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1268 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1270 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1271 *reason
= bgp_path_selection_router_id
;
1274 "%s: %s wins over %s due to Router-ID comparison",
1275 pfx_buf
, new_buf
, exist_buf
);
1279 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1280 *reason
= bgp_path_selection_router_id
;
1283 "%s: %s loses to %s due to Router-ID comparison",
1284 pfx_buf
, new_buf
, exist_buf
);
1288 /* 14. Cluster length comparison. */
1289 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1290 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1292 if (new_cluster
< exist_cluster
) {
1293 *reason
= bgp_path_selection_cluster_length
;
1296 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1297 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1302 if (new_cluster
> exist_cluster
) {
1303 *reason
= bgp_path_selection_cluster_length
;
1306 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1307 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1312 /* 15. Neighbor address comparison. */
1313 /* Do this only if neither path is "stale" as stale paths do not have
1314 * valid peer information (as the connection may or may not be up).
1316 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1317 *reason
= bgp_path_selection_stale
;
1320 "%s: %s wins over %s due to latter path being STALE",
1321 pfx_buf
, new_buf
, exist_buf
);
1325 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1326 *reason
= bgp_path_selection_stale
;
1329 "%s: %s loses to %s due to former path being STALE",
1330 pfx_buf
, new_buf
, exist_buf
);
1334 /* locally configured routes to advertise do not have su_remote */
1335 if (new->peer
->su_remote
== NULL
) {
1336 *reason
= bgp_path_selection_local_configured
;
1339 if (exist
->peer
->su_remote
== NULL
) {
1340 *reason
= bgp_path_selection_local_configured
;
1344 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1347 *reason
= bgp_path_selection_neighbor_ip
;
1350 "%s: %s loses to %s due to Neighor IP comparison",
1351 pfx_buf
, new_buf
, exist_buf
);
1356 *reason
= bgp_path_selection_neighbor_ip
;
1359 "%s: %s wins over %s due to Neighor IP comparison",
1360 pfx_buf
, new_buf
, exist_buf
);
1364 *reason
= bgp_path_selection_default
;
1366 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1367 pfx_buf
, new_buf
, exist_buf
);
1373 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1374 struct bgp_path_info
*exist
, int *paths_eq
)
1376 enum bgp_path_selection_reason reason
;
1377 char pfx_buf
[PREFIX2STR_BUFFER
];
1379 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1380 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1383 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1384 * is preferred, or 0 if they are the same (usually will only occur if
1385 * multipath is enabled
1386 * This version is compatible with */
1387 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1388 struct bgp_path_info
*exist
, char *pfx_buf
,
1389 afi_t afi
, safi_t safi
,
1390 enum bgp_path_selection_reason
*reason
)
1394 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1408 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1409 const struct prefix
*p
,
1410 struct attr
*attr
, afi_t afi
,
1413 struct bgp_filter
*filter
;
1414 enum filter_type ret
= FILTER_PERMIT
;
1416 filter
= &peer
->filter
[afi
][safi
];
1418 #define FILTER_EXIST_WARN(F, f, filter) \
1419 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1420 zlog_debug("%s: Could not find configured input %s-list %s!", \
1421 peer->host, #f, F##_IN_NAME(filter));
1423 if (DISTRIBUTE_IN_NAME(filter
)) {
1424 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1426 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1433 if (PREFIX_LIST_IN_NAME(filter
)) {
1434 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1436 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1443 if (FILTER_LIST_IN_NAME(filter
)) {
1444 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1446 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1447 == AS_FILTER_DENY
) {
1454 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1455 char pfxprint
[PREFIX2STR_BUFFER
];
1457 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1458 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1459 ret
== FILTER_PERMIT
? "permit" : "deny");
1463 #undef FILTER_EXIST_WARN
1466 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1467 const struct prefix
*p
,
1468 struct attr
*attr
, afi_t afi
,
1471 struct bgp_filter
*filter
;
1472 enum filter_type ret
= FILTER_PERMIT
;
1474 filter
= &peer
->filter
[afi
][safi
];
1476 #define FILTER_EXIST_WARN(F, f, filter) \
1477 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1478 zlog_debug("%s: Could not find configured output %s-list %s!", \
1479 peer->host, #f, F##_OUT_NAME(filter));
1481 if (DISTRIBUTE_OUT_NAME(filter
)) {
1482 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1484 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1491 if (PREFIX_LIST_OUT_NAME(filter
)) {
1492 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1494 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1501 if (FILTER_LIST_OUT_NAME(filter
)) {
1502 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1504 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1505 == AS_FILTER_DENY
) {
1511 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1512 char pfxprint
[PREFIX2STR_BUFFER
];
1514 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1515 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1516 ret
== FILTER_PERMIT
? "permit" : "deny");
1521 #undef FILTER_EXIST_WARN
1524 /* If community attribute includes no_export then return 1. */
1525 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1527 if (bgp_attr_get_community(attr
)) {
1528 /* NO_ADVERTISE check. */
1529 if (community_include(bgp_attr_get_community(attr
),
1530 COMMUNITY_NO_ADVERTISE
))
1533 /* NO_EXPORT check. */
1534 if (peer
->sort
== BGP_PEER_EBGP
&&
1535 community_include(bgp_attr_get_community(attr
),
1536 COMMUNITY_NO_EXPORT
))
1539 /* NO_EXPORT_SUBCONFED check. */
1540 if (peer
->sort
== BGP_PEER_EBGP
1541 || peer
->sort
== BGP_PEER_CONFED
)
1542 if (community_include(bgp_attr_get_community(attr
),
1543 COMMUNITY_NO_EXPORT_SUBCONFED
))
1549 /* Route reflection loop check. */
1550 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1552 struct in_addr cluster_id
;
1553 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1556 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1557 cluster_id
= peer
->bgp
->cluster_id
;
1559 cluster_id
= peer
->bgp
->router_id
;
1561 if (cluster_loop_check(cluster
, cluster_id
))
1567 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1569 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1570 if (peer
->local_role
== ROLE_PROVIDER
||
1571 peer
->local_role
== ROLE_RS_SERVER
)
1573 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1577 if (peer
->local_role
== ROLE_CUSTOMER
||
1578 peer
->local_role
== ROLE_PEER
||
1579 peer
->local_role
== ROLE_RS_CLIENT
) {
1580 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1581 attr
->otc
= peer
->as
;
1586 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1588 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1589 if (peer
->local_role
== ROLE_CUSTOMER
||
1590 peer
->local_role
== ROLE_RS_CLIENT
||
1591 peer
->local_role
== ROLE_PEER
)
1595 if (peer
->local_role
== ROLE_PROVIDER
||
1596 peer
->local_role
== ROLE_PEER
||
1597 peer
->local_role
== ROLE_RS_SERVER
) {
1598 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1599 attr
->otc
= peer
->bgp
->as
;
1604 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1606 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1609 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1610 struct attr
*attr
, afi_t afi
, safi_t safi
,
1611 const char *rmap_name
, mpls_label_t
*label
,
1612 uint32_t num_labels
, struct bgp_dest
*dest
)
1614 struct bgp_filter
*filter
;
1615 struct bgp_path_info rmap_path
= { 0 };
1616 struct bgp_path_info_extra extra
= { 0 };
1617 route_map_result_t ret
;
1618 struct route_map
*rmap
= NULL
;
1620 filter
= &peer
->filter
[afi
][safi
];
1622 /* Apply default weight value. */
1623 if (peer
->weight
[afi
][safi
])
1624 attr
->weight
= peer
->weight
[afi
][safi
];
1627 rmap
= route_map_lookup_by_name(rmap_name
);
1632 if (ROUTE_MAP_IN_NAME(filter
)) {
1633 rmap
= ROUTE_MAP_IN(filter
);
1640 /* Route map apply. */
1642 memset(&rmap_path
, 0, sizeof(rmap_path
));
1643 /* Duplicate current value to new structure for modification. */
1644 rmap_path
.peer
= peer
;
1645 rmap_path
.attr
= attr
;
1646 rmap_path
.extra
= &extra
;
1647 rmap_path
.net
= dest
;
1649 extra
.num_labels
= num_labels
;
1650 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1651 memcpy(extra
.label
, label
,
1652 num_labels
* sizeof(mpls_label_t
));
1654 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1656 /* Apply BGP route map to the attribute. */
1657 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1659 peer
->rmap_type
= 0;
1661 if (ret
== RMAP_DENYMATCH
)
1667 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1668 struct attr
*attr
, afi_t afi
, safi_t safi
,
1669 const char *rmap_name
)
1671 struct bgp_path_info rmap_path
;
1672 route_map_result_t ret
;
1673 struct route_map
*rmap
= NULL
;
1677 * So if we get to this point and have no rmap_name
1678 * we want to just show the output as it currently
1684 /* Apply default weight value. */
1685 if (peer
->weight
[afi
][safi
])
1686 attr
->weight
= peer
->weight
[afi
][safi
];
1688 rmap
= route_map_lookup_by_name(rmap_name
);
1691 * If we have a route map name and we do not find
1692 * the routemap that means we have an implicit
1698 memset(&rmap_path
, 0, sizeof(rmap_path
));
1699 /* Route map apply. */
1700 /* Duplicate current value to new structure for modification. */
1701 rmap_path
.peer
= peer
;
1702 rmap_path
.attr
= attr
;
1704 rmap_type
= peer
->rmap_type
;
1705 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1707 /* Apply BGP route map to the attribute. */
1708 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1710 peer
->rmap_type
= rmap_type
;
1712 if (ret
== RMAP_DENYMATCH
)
1714 * caller has multiple error paths with bgp_attr_flush()
1721 /* If this is an EBGP peer with remove-private-AS */
1722 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1723 struct peer
*peer
, struct attr
*attr
)
1725 if (peer
->sort
== BGP_PEER_EBGP
1726 && (peer_af_flag_check(peer
, afi
, safi
,
1727 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1728 || peer_af_flag_check(peer
, afi
, safi
,
1729 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1730 || peer_af_flag_check(peer
, afi
, safi
,
1731 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1732 || peer_af_flag_check(peer
, afi
, safi
,
1733 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1734 // Take action on the entire aspath
1735 if (peer_af_flag_check(peer
, afi
, safi
,
1736 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1737 || peer_af_flag_check(peer
, afi
, safi
,
1738 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1739 if (peer_af_flag_check(
1741 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1742 attr
->aspath
= aspath_replace_private_asns(
1743 attr
->aspath
, bgp
->as
, peer
->as
);
1746 * Even if the aspath consists of just private ASNs we
1747 * need to walk the AS-Path to maintain all instances
1748 * of the peer's ASN to break possible loops.
1751 attr
->aspath
= aspath_remove_private_asns(
1752 attr
->aspath
, peer
->as
);
1755 // 'all' was not specified so the entire aspath must be private
1757 // for us to do anything
1758 else if (aspath_private_as_check(attr
->aspath
)) {
1759 if (peer_af_flag_check(
1761 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1762 attr
->aspath
= aspath_replace_private_asns(
1763 attr
->aspath
, bgp
->as
, peer
->as
);
1766 * Walk the aspath to retain any instances of
1769 attr
->aspath
= aspath_remove_private_asns(
1770 attr
->aspath
, peer
->as
);
1775 /* If this is an EBGP peer with as-override */
1776 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1777 struct peer
*peer
, struct attr
*attr
)
1779 struct aspath
*aspath
;
1781 if (peer
->sort
== BGP_PEER_EBGP
&&
1782 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1783 if (attr
->aspath
->refcnt
)
1784 aspath
= aspath_dup(attr
->aspath
);
1786 aspath
= attr
->aspath
;
1788 attr
->aspath
= aspath_intern(
1789 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1791 aspath_free(aspath
);
1795 void bgp_attr_add_llgr_community(struct attr
*attr
)
1797 struct community
*old
;
1798 struct community
*new;
1799 struct community
*merge
;
1800 struct community
*llgr
;
1802 old
= bgp_attr_get_community(attr
);
1803 llgr
= community_str2com("llgr-stale");
1808 merge
= community_merge(community_dup(old
), llgr
);
1810 if (old
->refcnt
== 0)
1811 community_free(&old
);
1813 new = community_uniq_sort(merge
);
1814 community_free(&merge
);
1816 new = community_dup(llgr
);
1819 community_free(&llgr
);
1821 bgp_attr_set_community(attr
, new);
1824 void bgp_attr_add_gshut_community(struct attr
*attr
)
1826 struct community
*old
;
1827 struct community
*new;
1828 struct community
*merge
;
1829 struct community
*gshut
;
1831 old
= bgp_attr_get_community(attr
);
1832 gshut
= community_str2com("graceful-shutdown");
1837 merge
= community_merge(community_dup(old
), gshut
);
1839 if (old
->refcnt
== 0)
1840 community_free(&old
);
1842 new = community_uniq_sort(merge
);
1843 community_free(&merge
);
1845 new = community_dup(gshut
);
1848 community_free(&gshut
);
1849 bgp_attr_set_community(attr
, new);
1851 /* When we add the graceful-shutdown community we must also
1852 * lower the local-preference */
1853 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1854 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1858 /* Notify BGP Conditional advertisement scanner process. */
1859 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1861 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1862 afi_t afi
= SUBGRP_AFI(subgrp
);
1863 safi_t safi
= SUBGRP_SAFI(subgrp
);
1864 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1866 if (!ADVERTISE_MAP_NAME(filter
))
1869 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1872 peer
->advmap_table_change
= true;
1876 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1878 if (family
== AF_INET
) {
1879 attr
->nexthop
.s_addr
= INADDR_ANY
;
1880 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1882 if (family
== AF_INET6
)
1883 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1884 if (family
== AF_EVPN
)
1885 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1888 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1889 struct update_subgroup
*subgrp
,
1890 const struct prefix
*p
, struct attr
*attr
,
1891 struct attr
*post_attr
)
1893 struct bgp_filter
*filter
;
1896 struct peer
*onlypeer
;
1898 struct attr
*piattr
;
1899 route_map_result_t ret
;
1904 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1905 bool nh_reset
= false;
1908 if (DISABLE_BGP_ANNOUNCE
)
1911 afi
= SUBGRP_AFI(subgrp
);
1912 safi
= SUBGRP_SAFI(subgrp
);
1913 peer
= SUBGRP_PEER(subgrp
);
1915 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1916 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1919 filter
= &peer
->filter
[afi
][safi
];
1920 bgp
= SUBGRP_INST(subgrp
);
1921 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1924 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
1925 peer
->pmax_out
[afi
][safi
] != 0 &&
1926 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
1927 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
1928 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
1929 zlog_debug("%s reached maximum prefix to be send (%u)",
1930 peer
->host
, peer
->pmax_out
[afi
][safi
]);
1935 #ifdef ENABLE_BGP_VNC
1936 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1937 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1938 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1941 * direct and direct_ext type routes originate internally even
1942 * though they can have peer pointers that reference other
1945 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1951 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1952 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1953 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1954 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1956 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1961 /* With addpath we may be asked to TX all kinds of paths so make sure
1963 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1964 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1965 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1969 /* If this is not the bestpath then check to see if there is an enabled
1971 * feature that requires us to advertise it */
1972 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1973 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1978 /* Aggregate-address suppress check. */
1979 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
1983 * If we are doing VRF 2 VRF leaking via the import
1984 * statement, we want to prevent the route going
1985 * off box as that the RT and RD created are localy
1986 * significant and globaly useless.
1988 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1989 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1992 /* If it's labeled safi, make sure the route has a valid label. */
1993 if (safi
== SAFI_LABELED_UNICAST
) {
1994 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1995 if (!bgp_is_valid_label(&label
)) {
1996 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1997 zlog_debug("u%" PRIu64
":s%" PRIu64
1998 " %pFX is filtered - no label (%p)",
1999 subgrp
->update_group
->id
, subgrp
->id
,
2005 /* Do not send back route to sender. */
2006 if (onlypeer
&& from
== onlypeer
) {
2010 /* Do not send the default route in the BGP table if the neighbor is
2011 * configured for default-originate */
2012 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2013 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2014 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2016 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2020 /* Transparency check. */
2021 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2022 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2027 /* If community is not disabled check the no-export and local. */
2028 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2029 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2030 zlog_debug("%s: community filter check fail for %pFX",
2035 /* If the attribute has originator-id and it is same as remote
2037 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2038 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2039 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2041 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2046 /* ORF prefix-list filter check */
2047 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2048 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2049 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2050 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2051 if (peer
->orf_plist
[afi
][safi
]) {
2052 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2054 if (bgp_debug_update(NULL
, p
,
2055 subgrp
->update_group
, 0))
2057 "%pBP [Update:SEND] %pFX is filtered via ORF",
2063 /* Output filter check. */
2064 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2065 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2066 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2071 /* AS path loop check. */
2072 if (onlypeer
&& onlypeer
->as_path_loop_detection
2073 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
2074 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2076 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2077 onlypeer
, onlypeer
->as
);
2081 /* If we're a CONFED we need to loop check the CONFED ID too */
2082 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2083 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
2084 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2086 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2087 peer
, bgp
->confed_id
);
2092 /* Route-Reflect check. */
2093 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2098 /* IBGP reflection check. */
2099 if (reflect
&& !samepeer_safe
) {
2100 /* A route from a Client peer. */
2101 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2102 PEER_FLAG_REFLECTOR_CLIENT
)) {
2103 /* Reflect to all the Non-Client peers and also to the
2104 Client peers other than the originator. Originator
2106 is already done. So there is noting to do. */
2107 /* no bgp client-to-client reflection check. */
2108 if (CHECK_FLAG(bgp
->flags
,
2109 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2110 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2111 PEER_FLAG_REFLECTOR_CLIENT
))
2114 /* A route from a Non-client peer. Reflect to all other
2116 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2117 PEER_FLAG_REFLECTOR_CLIENT
))
2122 /* For modify attribute, copy it to temporary structure.
2123 * post_attr comes from BGP conditional advertisements, where
2124 * attributes are already processed by advertise-map route-map,
2125 * and this needs to be saved instead of overwriting from the
2133 /* If local-preference is not set. */
2134 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2135 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2136 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2137 attr
->local_pref
= bgp
->default_local_pref
;
2140 /* If originator-id is not set and the route is to be reflected,
2141 set the originator id */
2143 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2144 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2145 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2148 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2150 if (peer
->sort
== BGP_PEER_EBGP
2151 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2152 if (from
!= bgp
->peer_self
&& !transparent
2153 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2154 PEER_FLAG_MED_UNCHANGED
))
2156 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2159 /* Since the nexthop attribute can vary per peer, it is not explicitly
2161 * in announce check, only certain flags and length (or number of
2163 * -- for IPv6/MP_REACH) are set here in order to guide the update
2165 * code in setting the nexthop(s) on a per peer basis in
2167 * Typically, the source nexthop in the attribute is preserved but in
2169 * scenarios where we know it will always be overwritten, we reset the
2170 * nexthop to "0" in an attempt to achieve better Update packing. An
2171 * example of this is when a prefix from each of 2 IBGP peers needs to
2173 * announced to an EBGP peer (and they have the same attributes barring
2177 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2179 #define NEXTHOP_IS_V6 \
2180 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2181 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2182 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2183 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2185 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2187 * the peer (group) is configured to receive link-local nexthop
2189 * and it is available in the prefix OR we're not reflecting the route,
2190 * link-local nexthop address is valid and
2191 * the peer (group) to whom we're going to announce is on a shared
2193 * and this is either a self-originated route or the peer is EBGP.
2194 * By checking if nexthop LL address is valid we are sure that
2195 * we do not announce LL address as `::`.
2197 if (NEXTHOP_IS_V6
) {
2198 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2199 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2200 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2201 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2202 || (!reflect
&& !transparent
2203 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2204 && peer
->shared_network
2205 && (from
== bgp
->peer_self
2206 || peer
->sort
== BGP_PEER_EBGP
))) {
2207 attr
->mp_nexthop_len
=
2208 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2211 /* Clear off link-local nexthop in source, whenever it is not
2213 * ensure more prefixes share the same attribute for
2216 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2217 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2218 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2221 if (bgp_check_role_applicability(afi
, safi
) &&
2222 bgp_otc_egress(peer
, attr
))
2225 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2226 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2228 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2229 filter
->advmap
.aname
&&
2230 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2231 struct bgp_path_info rmap_path
= {0};
2232 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2233 struct attr dummy_attr
= *attr
;
2235 /* Fill temp path_info */
2236 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2237 pi
, peer
, &dummy_attr
);
2239 struct route_map
*amap
=
2240 route_map_lookup_by_name(filter
->advmap
.aname
);
2242 ret
= route_map_apply(amap
, p
, &rmap_path
);
2244 bgp_attr_flush(&dummy_attr
);
2247 * The conditional advertisement mode is Withdraw and this
2248 * prefix is a conditional prefix. Don't advertise it
2250 if (ret
== RMAP_PERMITMATCH
)
2254 /* Route map & unsuppress-map apply. */
2256 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2257 struct bgp_path_info rmap_path
= {0};
2258 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2259 struct attr dummy_attr
= {0};
2261 /* Fill temp path_info */
2262 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2265 /* don't confuse inbound and outbound setting */
2266 RESET_FLAG(attr
->rmap_change_flags
);
2269 * The route reflector is not allowed to modify the attributes
2270 * of the reflected IBGP routes unless explicitly allowed.
2272 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2273 && !CHECK_FLAG(bgp
->flags
,
2274 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2276 rmap_path
.attr
= &dummy_attr
;
2279 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2281 if (bgp_path_suppressed(pi
))
2282 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2285 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2288 bgp_attr_flush(&dummy_attr
);
2289 peer
->rmap_type
= 0;
2291 if (ret
== RMAP_DENYMATCH
) {
2292 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2294 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2295 peer
, p
, ROUTE_MAP_OUT_NAME(filter
));
2296 bgp_attr_flush(rmap_path
.attr
);
2301 /* RFC 8212 to prevent route leaks.
2302 * This specification intends to improve this situation by requiring the
2303 * explicit configuration of both BGP Import and Export Policies for any
2304 * External BGP (EBGP) session such as customers, peers, or
2305 * confederation boundaries for all enabled address families. Through
2306 * codification of the aforementioned requirement, operators will
2307 * benefit from consistent behavior across different BGP
2310 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2311 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2312 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2313 NULL
) > FIFTEENMINUTE2USEC
||
2314 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2316 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2317 monotime(&bgp
->ebgprequirespolicywarning
);
2322 /* draft-ietf-idr-deprecate-as-set-confed-set
2323 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2324 * Eventually, This document (if approved) updates RFC 4271
2325 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2326 * and obsoletes RFC 6472.
2328 if (peer
->bgp
->reject_as_sets
)
2329 if (aspath_check_as_sets(attr
->aspath
))
2332 /* If neighbor sso is configured, then check if the route has
2333 * SoO extended community and validate against the configured
2334 * one. If they match, do not announce, to prevent routing
2337 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2338 peer
->soo
[afi
][safi
]) {
2339 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2340 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2342 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2343 ECOMMUNITY_SITE_ORIGIN
) ||
2344 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2345 ECOMMUNITY_SITE_ORIGIN
)) &&
2346 ecommunity_include(ecomm
, ecomm_soo
)) {
2347 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2349 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2350 peer
, p
, ecommunity_str(ecomm_soo
));
2355 /* Codification of AS 0 Processing */
2356 if (aspath_check_as_zero(attr
->aspath
))
2359 if (bgp_in_graceful_shutdown(bgp
)) {
2360 if (peer
->sort
== BGP_PEER_IBGP
2361 || peer
->sort
== BGP_PEER_CONFED
) {
2362 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2363 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2365 bgp_attr_add_gshut_community(attr
);
2369 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2370 * Capability" to a neighbor MUST perform the following upon receiving
2371 * a route from that neighbor with the "LLGR_STALE" community, or upon
2372 * attaching the "LLGR_STALE" community itself per Section 4.2:
2374 * The route SHOULD NOT be advertised to any neighbor from which the
2375 * Long-lived Graceful Restart Capability has not been received.
2377 if (bgp_attr_get_community(attr
) &&
2378 community_include(bgp_attr_get_community(attr
),
2379 COMMUNITY_LLGR_STALE
) &&
2380 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2381 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2384 /* After route-map has been applied, we check to see if the nexthop to
2385 * be carried in the attribute (that is used for the announcement) can
2386 * be cleared off or not. We do this in all cases where we would be
2387 * setting the nexthop to "ourselves". For IPv6, we only need to
2389 * the global nexthop here; the link-local nexthop would have been
2391 * already, and if not, it is required by the update formation code.
2392 * Also see earlier comments in this function.
2395 * If route-map has performed some operation on the nexthop or the peer
2396 * configuration says to pass it unchanged, we cannot reset the nexthop
2397 * here, so only attempt to do it if these aren't true. Note that the
2398 * route-map handler itself might have cleared the nexthop, if for
2400 * it is configured as 'peer-address'.
2402 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2403 piattr
->rmap_change_flags
)
2405 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2406 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2407 /* We can reset the nexthop, if setting (or forcing) it to
2409 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2410 PEER_FLAG_NEXTHOP_SELF
)
2411 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2412 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2414 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2415 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2416 subgroup_announce_reset_nhop(
2417 (peer_cap_enhe(peer
, afi
, safi
)
2423 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2424 /* Can also reset the nexthop if announcing to EBGP, but
2426 * no peer in the subgroup is on a shared subnet.
2427 * Note: 3rd party nexthop currently implemented for
2430 if ((p
->family
== AF_INET
) &&
2431 (!bgp_subgrp_multiaccess_check_v4(
2434 subgroup_announce_reset_nhop(
2435 (peer_cap_enhe(peer
, afi
, safi
)
2442 if ((p
->family
== AF_INET6
) &&
2443 (!bgp_subgrp_multiaccess_check_v6(
2444 piattr
->mp_nexthop_global
,
2446 subgroup_announce_reset_nhop(
2447 (peer_cap_enhe(peer
, afi
, safi
)
2456 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2458 * This flag is used for leaked vpn-vrf routes
2460 int family
= p
->family
;
2462 if (peer_cap_enhe(peer
, afi
, safi
))
2465 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2467 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2468 __func__
, family2str(family
));
2469 subgroup_announce_reset_nhop(family
, attr
);
2474 /* If IPv6/MP and nexthop does not have any override and happens
2476 * be a link-local address, reset it so that we don't pass along
2478 * source's link-local IPv6 address to recipients who may not be
2480 * the same interface.
2482 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2483 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2484 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2489 /* If this is an iBGP, send Origin Validation State (OVS)
2490 * extended community (rfc8097).
2492 if (peer
->sort
== BGP_PEER_IBGP
) {
2493 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2495 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2497 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2498 bgp_attr_set_ecommunity(
2499 attr
, ecommunity_add_origin_validation_state(
2501 bgp_attr_get_ecommunity(attr
)));
2505 * When the next hop is set to ourselves, if all multipaths have
2506 * link-bandwidth announce the cumulative bandwidth as that makes
2507 * the most sense. However, don't modify if the link-bandwidth has
2508 * been explicitly set by user policy.
2511 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2512 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2513 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2514 bgp_attr_set_ecommunity(
2516 ecommunity_replace_linkbw(
2517 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2520 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2525 static void bgp_route_select_timer_expire(struct thread
*thread
)
2527 struct afi_safi_info
*info
;
2532 info
= THREAD_ARG(thread
);
2537 if (BGP_DEBUG(update
, UPDATE_OUT
))
2538 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2541 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2543 XFREE(MTYPE_TMP
, info
);
2545 /* Best path selection */
2546 bgp_best_path_select_defer(bgp
, afi
, safi
);
2549 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2550 struct bgp_maxpaths_cfg
*mpath_cfg
,
2551 struct bgp_path_info_pair
*result
, afi_t afi
,
2554 struct bgp_path_info
*new_select
;
2555 struct bgp_path_info
*old_select
;
2556 struct bgp_path_info
*pi
;
2557 struct bgp_path_info
*pi1
;
2558 struct bgp_path_info
*pi2
;
2559 struct bgp_path_info
*nextpi
= NULL
;
2560 int paths_eq
, do_mpath
, debug
;
2561 struct list mp_list
;
2562 char pfx_buf
[PREFIX2STR_BUFFER
];
2563 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2565 bgp_mp_list_init(&mp_list
);
2567 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2569 debug
= bgp_debug_bestpath(dest
);
2572 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2574 dest
->reason
= bgp_path_selection_none
;
2575 /* bgp deterministic-med */
2577 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2579 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2580 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2582 bgp_path_info_unset_flag(dest
, pi1
,
2583 BGP_PATH_DMED_SELECTED
);
2585 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2587 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2589 if (BGP_PATH_HOLDDOWN(pi1
))
2591 if (pi1
->peer
!= bgp
->peer_self
)
2592 if (!peer_established(pi1
->peer
))
2597 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2598 if (CHECK_FLAG(pi2
->flags
,
2599 BGP_PATH_DMED_CHECK
))
2601 if (BGP_PATH_HOLDDOWN(pi2
))
2603 if (pi2
->peer
!= bgp
->peer_self
2606 PEER_STATUS_NSF_WAIT
))
2607 if (pi2
->peer
->status
2611 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2613 && !aspath_cmp_left_confed(
2618 if (bgp_path_info_cmp(
2619 bgp
, pi2
, new_select
,
2620 &paths_eq
, mpath_cfg
, debug
,
2623 bgp_path_info_unset_flag(
2625 BGP_PATH_DMED_SELECTED
);
2629 bgp_path_info_set_flag(
2630 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2633 bgp_path_info_set_flag(dest
, new_select
,
2634 BGP_PATH_DMED_CHECK
);
2635 bgp_path_info_set_flag(dest
, new_select
,
2636 BGP_PATH_DMED_SELECTED
);
2639 bgp_path_info_path_with_addpath_rx_str(
2640 new_select
, path_buf
, sizeof(path_buf
));
2642 "%pBD(%s): %s is the bestpath from AS %u",
2643 dest
, bgp
->name_pretty
, path_buf
,
2644 aspath_get_first_as(
2645 new_select
->attr
->aspath
));
2650 /* Check old selected route and new selected route. */
2653 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2654 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2655 enum bgp_path_selection_reason reason
;
2657 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2660 if (BGP_PATH_HOLDDOWN(pi
)) {
2661 /* reap REMOVED routes, if needs be
2662 * selected route must stay for a while longer though
2664 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2665 && (pi
!= old_select
))
2666 bgp_path_info_reap(dest
, pi
);
2669 zlog_debug("%s: pi %p in holddown", __func__
,
2675 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2676 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2677 if (!peer_established(pi
->peer
)) {
2681 "%s: pi %p non self peer %s not estab state",
2682 __func__
, pi
, pi
->peer
->host
);
2687 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2688 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2689 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2691 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2695 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2697 reason
= dest
->reason
;
2698 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2699 debug
, pfx_buf
, afi
, safi
,
2701 if (new_select
== NULL
&&
2702 reason
!= bgp_path_selection_none
)
2703 dest
->reason
= reason
;
2708 /* Now that we know which path is the bestpath see if any of the other
2710 * qualify as multipaths
2714 bgp_path_info_path_with_addpath_rx_str(
2715 new_select
, path_buf
, sizeof(path_buf
));
2717 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2719 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2720 dest
, bgp
->name_pretty
, path_buf
,
2721 old_select
? old_select
->peer
->host
: "NONE");
2724 if (do_mpath
&& new_select
) {
2725 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2726 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2729 bgp_path_info_path_with_addpath_rx_str(
2730 pi
, path_buf
, sizeof(path_buf
));
2732 if (pi
== new_select
) {
2735 "%pBD(%s): %s is the bestpath, add to the multipath list",
2736 dest
, bgp
->name_pretty
,
2738 bgp_mp_list_add(&mp_list
, pi
);
2742 if (BGP_PATH_HOLDDOWN(pi
))
2745 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2746 && !CHECK_FLAG(pi
->peer
->sflags
,
2747 PEER_STATUS_NSF_WAIT
))
2748 if (!peer_established(pi
->peer
))
2751 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2754 "%pBD: %s has the same nexthop as the bestpath, skip it",
2759 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2760 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2766 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2768 bgp_mp_list_add(&mp_list
, pi
);
2773 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2775 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2776 bgp_mp_list_clear(&mp_list
);
2778 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2780 result
->old
= old_select
;
2781 result
->new = new_select
;
2787 * A new route/change in bestpath of an existing route. Evaluate the path
2788 * for advertisement to the subgroup.
2790 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2791 struct bgp_path_info
*selected
,
2792 struct bgp_dest
*dest
,
2793 uint32_t addpath_tx_id
)
2795 const struct prefix
*p
;
2796 struct peer
*onlypeer
;
2803 p
= bgp_dest_get_prefix(dest
);
2804 afi
= SUBGRP_AFI(subgrp
);
2805 safi
= SUBGRP_SAFI(subgrp
);
2806 bgp
= SUBGRP_INST(subgrp
);
2807 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2810 if (BGP_DEBUG(update
, UPDATE_OUT
))
2811 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2813 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2814 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2815 PEER_STATUS_ORF_WAIT_REFRESH
))
2818 memset(&attr
, 0, sizeof(attr
));
2819 /* It's initialized in bgp_announce_check() */
2821 /* Announcement to the subgroup. If the route is filtered withdraw it.
2822 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2823 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2826 advertise
= bgp_check_advertise(bgp
, dest
);
2829 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2831 /* Route is selected, if the route is already installed
2832 * in FIB, then it is advertised
2835 if (!bgp_check_withdrawal(bgp
, dest
))
2836 bgp_adj_out_set_subgroup(
2837 dest
, subgrp
, &attr
, selected
);
2839 bgp_adj_out_unset_subgroup(
2840 dest
, subgrp
, 1, addpath_tx_id
);
2843 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2847 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2849 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2854 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2855 * This is called at the end of route processing.
2857 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2859 struct bgp_path_info
*pi
;
2861 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2862 if (BGP_PATH_HOLDDOWN(pi
))
2864 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2865 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2870 * Has the route changed from the RIB's perspective? This is invoked only
2871 * if the route selection returns the same best route as earlier - to
2872 * determine if we need to update zebra or not.
2874 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2876 struct bgp_path_info
*mpinfo
;
2878 /* If this is multipath, check all selected paths for any nexthop
2879 * change or attribute change. Some attribute changes (e.g., community)
2880 * aren't of relevance to the RIB, but we'll update zebra to ensure
2881 * we handle the case of BGP nexthop change. This is the behavior
2882 * when the best path has an attribute change anyway.
2884 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2885 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2886 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2890 * If this is multipath, check all selected paths for any nexthop change
2892 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2893 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2894 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2895 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2899 /* Nothing has changed from the RIB's perspective. */
2903 struct bgp_process_queue
{
2905 STAILQ_HEAD(, bgp_dest
) pqueue
;
2906 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2908 unsigned int queued
;
2911 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2912 safi_t safi
, struct bgp_dest
*dest
,
2913 struct bgp_path_info
*new_select
,
2914 struct bgp_path_info
*old_select
)
2916 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2918 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2921 if (advertise_type5_routes(bgp
, afi
) && new_select
2922 && is_route_injectable_into_evpn(new_select
)) {
2924 /* apply the route-map */
2925 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2926 route_map_result_t ret
;
2927 struct bgp_path_info rmap_path
;
2928 struct bgp_path_info_extra rmap_path_extra
;
2929 struct attr dummy_attr
;
2931 dummy_attr
= *new_select
->attr
;
2933 /* Fill temp path_info */
2934 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2935 new_select
, new_select
->peer
,
2938 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2940 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2943 if (ret
== RMAP_DENYMATCH
) {
2944 bgp_attr_flush(&dummy_attr
);
2945 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2948 bgp_evpn_advertise_type5_route(
2949 bgp
, p
, &dummy_attr
, afi
, safi
);
2951 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2954 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2955 && is_route_injectable_into_evpn(old_select
))
2956 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2960 * Utility to determine whether a particular path_info should use
2961 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2962 * in a path where we basically _know_ this is a BGP-LU route.
2964 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
2966 /* Certain types get imp null; so do paths where the nexthop is
2969 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2970 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2971 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
2973 else if (new_select
->extra
== NULL
||
2974 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
2975 /* TODO -- should be configurable? */
2982 * old_select = The old best path
2983 * new_select = the new best path
2985 * if (!old_select && new_select)
2986 * We are sending new information on.
2988 * if (old_select && new_select) {
2989 * if (new_select != old_select)
2990 * We have a new best path send a change
2992 * We've received a update with new attributes that needs
2996 * if (old_select && !new_select)
2997 * We have no eligible route that we can announce or the rn
3000 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3001 afi_t afi
, safi_t safi
)
3003 struct bgp_path_info
*new_select
;
3004 struct bgp_path_info
*old_select
;
3005 struct bgp_path_info_pair old_and_new
;
3008 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3010 debug
= bgp_debug_bestpath(dest
);
3013 "%s: bgp delete in progress, ignoring event, p=%pBD",
3017 /* Is it end of initial update? (after startup) */
3019 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3020 sizeof(bgp
->update_delay_zebra_resume_time
));
3022 bgp
->main_zebra_update_hold
= 0;
3023 FOREACH_AFI_SAFI (afi
, safi
) {
3024 if (bgp_fibupd_safi(safi
))
3025 bgp_zebra_announce_table(bgp
, afi
, safi
);
3027 bgp
->main_peers_update_hold
= 0;
3029 bgp_start_routeadv(bgp
);
3033 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3035 debug
= bgp_debug_bestpath(dest
);
3037 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__
,
3038 dest
, bgp
->name_pretty
, afi2str(afi
),
3041 /* The best path calculation for the route is deferred if
3042 * BGP_NODE_SELECT_DEFER is set
3044 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3045 if (BGP_DEBUG(update
, UPDATE_OUT
))
3046 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
3050 /* Best path selection. */
3051 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3053 old_select
= old_and_new
.old
;
3054 new_select
= old_and_new
.new;
3056 /* Do we need to allocate or free labels?
3057 * Right now, since we only deal with per-prefix labels, it is not
3058 * necessary to do this upon changes to best path. Exceptions:
3059 * - label index has changed -> recalculate resulting label
3060 * - path_info sub_type changed -> switch to/from implicit-null
3061 * - no valid label (due to removed static label binding) -> get new one
3063 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3066 || bgp_label_index_differs(new_select
, old_select
)
3067 || new_select
->sub_type
!= old_select
->sub_type
3068 || !bgp_is_valid_label(&dest
->local_label
)) {
3069 /* Enforced penultimate hop popping:
3070 * implicit-null for local routes, aggregate
3071 * and redistributed routes
3073 if (bgp_lu_need_imp_null(new_select
)) {
3076 BGP_NODE_REGISTERED_FOR_LABEL
)
3079 BGP_NODE_LABEL_REQUESTED
))
3080 bgp_unregister_for_label(dest
);
3081 dest
->local_label
= mpls_lse_encode(
3082 MPLS_LABEL_IMPLICIT_NULL
, 0, 0,
3084 bgp_set_valid_label(&dest
->local_label
);
3086 bgp_register_for_label(dest
,
3089 } else if (CHECK_FLAG(dest
->flags
,
3090 BGP_NODE_REGISTERED_FOR_LABEL
)
3091 || CHECK_FLAG(dest
->flags
,
3092 BGP_NODE_LABEL_REQUESTED
)) {
3093 bgp_unregister_for_label(dest
);
3095 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3096 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3097 bgp_unregister_for_label(dest
);
3102 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3103 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3104 safi2str(safi
), old_select
, new_select
);
3106 /* If best route remains the same and this is not due to user-initiated
3107 * clear, see exactly what needs to be done.
3109 if (old_select
&& old_select
== new_select
3110 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3111 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3112 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3113 if (bgp_zebra_has_route_changed(old_select
)) {
3114 #ifdef ENABLE_BGP_VNC
3115 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3116 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3118 if (bgp_fibupd_safi(safi
)
3119 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3121 if (BGP_SUPPRESS_FIB_ENABLED(bgp
)
3122 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
3123 SET_FLAG(dest
->flags
,
3124 BGP_NODE_FIB_INSTALL_PENDING
);
3126 if (new_select
->type
== ZEBRA_ROUTE_BGP
3127 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3128 || new_select
->sub_type
3129 == BGP_ROUTE_IMPORTED
))
3131 bgp_zebra_announce(dest
, p
, old_select
,
3136 /* If there is a change of interest to peers, reannounce the
3138 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3139 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3140 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3141 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3143 /* unicast routes must also be annouced to
3144 * labeled-unicast update-groups */
3145 if (safi
== SAFI_UNICAST
)
3146 group_announce_route(bgp
, afi
,
3147 SAFI_LABELED_UNICAST
, dest
,
3150 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3151 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3154 /* advertise/withdraw type-5 routes */
3155 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3156 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3157 bgp_process_evpn_route_injection(
3158 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3160 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3161 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3162 bgp_zebra_clear_route_change_flags(dest
);
3163 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3167 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3169 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3171 /* bestpath has changed; bump version */
3172 if (old_select
|| new_select
) {
3173 bgp_bump_version(dest
);
3175 if (!bgp
->t_rmap_def_originate_eval
) {
3179 update_group_refresh_default_originate_route_map
,
3180 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3181 &bgp
->t_rmap_def_originate_eval
);
3186 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3189 zlog_debug("%s: setting SELECTED flag", __func__
);
3190 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3191 bgp_path_info_unset_flag(dest
, new_select
,
3192 BGP_PATH_ATTR_CHANGED
);
3193 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3194 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3197 #ifdef ENABLE_BGP_VNC
3198 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3199 if (old_select
!= new_select
) {
3201 vnc_import_bgp_exterior_del_route(bgp
, p
,
3203 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3206 vnc_import_bgp_exterior_add_route(bgp
, p
,
3208 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3214 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3216 /* unicast routes must also be annouced to labeled-unicast update-groups
3218 if (safi
== SAFI_UNICAST
)
3219 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3223 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3224 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3226 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3227 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3228 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3229 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3231 if (BGP_SUPPRESS_FIB_ENABLED(bgp
))
3232 SET_FLAG(dest
->flags
,
3233 BGP_NODE_FIB_INSTALL_PENDING
);
3235 /* if this is an evpn imported type-5 prefix,
3236 * we need to withdraw the route first to clear
3237 * the nh neigh and the RMAC entry.
3240 is_route_parent_evpn(old_select
))
3241 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3243 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3245 /* Withdraw the route from the kernel. */
3246 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3247 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3248 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3249 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3251 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3255 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3258 /* Clear any route change flags. */
3259 bgp_zebra_clear_route_change_flags(dest
);
3261 /* Reap old select bgp_path_info, if it has been removed */
3262 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3263 bgp_path_info_reap(dest
, old_select
);
3265 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3269 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3270 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3272 struct bgp_dest
*dest
;
3274 struct afi_safi_info
*thread_info
;
3276 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3277 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3279 thread_info
= THREAD_ARG(t
);
3280 XFREE(MTYPE_TMP
, thread_info
);
3281 THREAD_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3284 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3285 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3286 get_afi_safi_str(afi
, safi
, false),
3287 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3290 /* Process the route list */
3291 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3292 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3293 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3294 dest
= bgp_route_next(dest
)) {
3295 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3298 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3299 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3300 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3303 /* If iteration stopped before the entire table was traversed then the
3304 * node needs to be unlocked.
3307 bgp_dest_unlock_node(dest
);
3311 /* Send EOR message when all routes are processed */
3312 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3313 bgp_send_delayed_eor(bgp
);
3314 /* Send route processing complete message to RIB */
3315 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3316 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3320 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3322 thread_info
->afi
= afi
;
3323 thread_info
->safi
= safi
;
3324 thread_info
->bgp
= bgp
;
3326 /* If there are more routes to be processed, start the
3329 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3330 BGP_ROUTE_SELECT_DELAY
,
3331 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3334 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3336 struct bgp_process_queue
*pqnode
= data
;
3337 struct bgp
*bgp
= pqnode
->bgp
;
3338 struct bgp_table
*table
;
3339 struct bgp_dest
*dest
;
3342 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3343 bgp_process_main_one(bgp
, NULL
, 0, 0);
3344 /* should always have dedicated wq call */
3345 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3349 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3350 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3351 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3352 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3353 table
= bgp_dest_table(dest
);
3354 /* note, new DESTs may be added as part of processing */
3355 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3357 bgp_dest_unlock_node(dest
);
3358 bgp_table_unlock(table
);
3364 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3366 struct bgp_process_queue
*pqnode
= data
;
3368 bgp_unlock(pqnode
->bgp
);
3370 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3373 void bgp_process_queue_init(struct bgp
*bgp
)
3375 if (!bgp
->process_queue
) {
3378 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3379 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3382 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3383 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3384 bgp
->process_queue
->spec
.max_retries
= 0;
3385 bgp
->process_queue
->spec
.hold
= 50;
3386 /* Use a higher yield value of 50ms for main queue processing */
3387 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3390 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3392 struct bgp_process_queue
*pqnode
;
3394 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3395 sizeof(struct bgp_process_queue
));
3397 /* unlocked in bgp_processq_del */
3398 pqnode
->bgp
= bgp_lock(bgp
);
3399 STAILQ_INIT(&pqnode
->pqueue
);
3404 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3406 #define ARBITRARY_PROCESS_QLEN 10000
3407 struct work_queue
*wq
= bgp
->process_queue
;
3408 struct bgp_process_queue
*pqnode
;
3409 int pqnode_reuse
= 0;
3411 /* already scheduled for processing? */
3412 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3415 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3418 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3419 if (BGP_DEBUG(update
, UPDATE_OUT
))
3420 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3425 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3426 if (BGP_DEBUG(update
, UPDATE_OUT
))
3428 "Soft reconfigure table in progress for route %p",
3436 /* Add route nodes to an existing work queue item until reaching the
3437 limit only if is from the same BGP view and it's not an EOIU marker
3439 if (work_queue_item_count(wq
)) {
3440 struct work_queue_item
*item
= work_queue_last_item(wq
);
3441 pqnode
= item
->data
;
3443 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3444 || pqnode
->bgp
!= bgp
3445 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3446 pqnode
= bgp_processq_alloc(bgp
);
3450 pqnode
= bgp_processq_alloc(bgp
);
3451 /* all unlocked in bgp_process_wq */
3452 bgp_table_lock(bgp_dest_table(dest
));
3454 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3455 bgp_dest_lock_node(dest
);
3457 /* can't be enqueued twice */
3458 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3459 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3463 work_queue_add(wq
, pqnode
);
3468 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3470 struct bgp_process_queue
*pqnode
;
3472 if (bgp
->process_queue
== NULL
)
3475 pqnode
= bgp_processq_alloc(bgp
);
3477 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3478 work_queue_add(bgp
->process_queue
, pqnode
);
3481 static void bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3485 peer
= THREAD_ARG(thread
);
3486 peer
->t_pmax_restart
= NULL
;
3488 if (bgp_debug_neighbor_events(peer
))
3490 "%s Maximum-prefix restart timer expired, restore peering",
3493 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3494 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3497 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3501 bool filtered
= false;
3502 struct bgp_dest
*dest
;
3503 struct bgp_adj_in
*ain
;
3504 struct attr attr
= {};
3505 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3507 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3508 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3509 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3513 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3517 if (bgp_input_modifier(
3518 peer
, rn_p
, &attr
, afi
, safi
,
3519 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3527 bgp_attr_flush(&attr
);
3534 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3538 iana_safi_t pkt_safi
;
3539 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3540 PEER_FLAG_MAX_PREFIX_FORCE
))
3541 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3542 + peer
->pcount
[afi
][safi
]
3543 : peer
->pcount
[afi
][safi
];
3545 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3548 if (pcount
> peer
->pmax
[afi
][safi
]) {
3549 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3550 PEER_STATUS_PREFIX_LIMIT
)
3555 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3556 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3557 peer
->pmax
[afi
][safi
]);
3558 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3560 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3561 PEER_FLAG_MAX_PREFIX_WARNING
))
3564 /* Convert AFI, SAFI to values for packet. */
3565 pkt_afi
= afi_int2iana(afi
);
3566 pkt_safi
= safi_int2iana(safi
);
3570 ndata
[0] = (pkt_afi
>> 8);
3572 ndata
[2] = pkt_safi
;
3573 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3574 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3575 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3576 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3578 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3579 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3580 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3584 /* Dynamic peers will just close their connection. */
3585 if (peer_dynamic_neighbor(peer
))
3588 /* restart timer start */
3589 if (peer
->pmax_restart
[afi
][safi
]) {
3590 peer
->v_pmax_restart
=
3591 peer
->pmax_restart
[afi
][safi
] * 60;
3593 if (bgp_debug_neighbor_events(peer
))
3595 "%pBP Maximum-prefix restart timer started for %d secs",
3596 peer
, peer
->v_pmax_restart
);
3598 BGP_TIMER_ON(peer
->t_pmax_restart
,
3599 bgp_maximum_prefix_restart_timer
,
3600 peer
->v_pmax_restart
);
3605 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3606 PEER_STATUS_PREFIX_LIMIT
);
3609 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3610 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3611 PEER_STATUS_PREFIX_THRESHOLD
)
3616 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3617 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3618 peer
->pmax
[afi
][safi
]);
3619 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3620 PEER_STATUS_PREFIX_THRESHOLD
);
3622 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3623 PEER_STATUS_PREFIX_THRESHOLD
);
3627 /* Unconditionally remove the route from the RIB, without taking
3628 * damping into consideration (eg, because the session went down)
3630 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3631 struct peer
*peer
, afi_t afi
, safi_t safi
)
3634 struct bgp
*bgp
= NULL
;
3635 bool delete_route
= false;
3637 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3640 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3641 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3643 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3646 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3647 delete_route
= true;
3648 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3649 delete_route
= true;
3651 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3652 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3653 bgp
= pi
->peer
->bgp
;
3654 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3659 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3660 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3663 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3664 struct peer
*peer
, afi_t afi
, safi_t safi
,
3665 struct prefix_rd
*prd
)
3667 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3669 /* apply dampening, if result is suppressed, we'll be retaining
3670 * the bgp_path_info in the RIB for historical reference.
3672 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3673 && peer
->sort
== BGP_PEER_EBGP
)
3674 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3675 == BGP_DAMP_SUPPRESSED
) {
3676 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3681 #ifdef ENABLE_BGP_VNC
3682 if (safi
== SAFI_MPLS_VPN
) {
3683 struct bgp_dest
*pdest
= NULL
;
3684 struct bgp_table
*table
= NULL
;
3686 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3687 (struct prefix
*)prd
);
3688 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3689 table
= bgp_dest_get_bgp_table_info(pdest
);
3691 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3692 peer
->bgp
, prd
, table
, p
, pi
);
3694 bgp_dest_unlock_node(pdest
);
3696 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3697 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3699 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3700 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3705 /* If this is an EVPN route, process for un-import. */
3706 if (safi
== SAFI_EVPN
)
3707 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3709 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3712 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3713 struct peer
*peer
, struct attr
*attr
,
3714 struct bgp_dest
*dest
)
3716 struct bgp_path_info
*new;
3718 /* Make new BGP info. */
3719 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3721 new->instance
= instance
;
3722 new->sub_type
= sub_type
;
3725 new->uptime
= monotime(NULL
);
3730 /* Check if received nexthop is valid or not. */
3731 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3732 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3733 struct bgp_dest
*dest
)
3736 bool is_bgp_static_route
=
3737 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3741 * Only validated for unicast and multicast currently.
3742 * Also valid for EVPN where the nexthop is an IP address.
3743 * If we are a bgp static route being checked then there is
3744 * no need to check to see if the nexthop is martian as
3745 * that it should be ok.
3747 if (is_bgp_static_route
||
3748 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3751 /* If NEXT_HOP is present, validate it. */
3752 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3753 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3754 !ipv4_unicast_valid(&attr
->nexthop
) ||
3755 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3759 /* If MP_NEXTHOP is present, validate it. */
3760 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3761 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3762 * it is not an IPv6 link-local address.
3764 * If we receive an UPDATE with nexthop length set to 32 bytes
3765 * we shouldn't discard an UPDATE if it's set to (::).
3766 * The link-local (2st) is validated along the code path later.
3768 if (attr
->mp_nexthop_len
) {
3769 switch (attr
->mp_nexthop_len
) {
3770 case BGP_ATTR_NHLEN_IPV4
:
3771 case BGP_ATTR_NHLEN_VPNV4
:
3772 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3774 !ipv4_unicast_valid(
3775 &attr
->mp_nexthop_global_in
) ||
3776 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3780 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3781 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3782 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3783 &attr
->mp_nexthop_global
)
3784 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3785 || IN6_IS_ADDR_MULTICAST(
3786 &attr
->mp_nexthop_global
)
3787 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3790 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3791 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3792 || IN6_IS_ADDR_MULTICAST(
3793 &attr
->mp_nexthop_global
)
3794 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3807 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3809 struct community
*old
;
3810 struct community
*new;
3811 struct community
*merge
;
3812 struct community
*no_export
;
3814 old
= bgp_attr_get_community(attr
);
3815 no_export
= community_str2com("no-export");
3820 merge
= community_merge(community_dup(old
), no_export
);
3823 community_free(&old
);
3825 new = community_uniq_sort(merge
);
3826 community_free(&merge
);
3828 new = community_dup(no_export
);
3831 community_free(&no_export
);
3833 bgp_attr_set_community(attr
, new);
3836 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3837 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3838 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3839 uint32_t num_labels
, int soft_reconfig
,
3840 struct bgp_route_evpn
*evpn
)
3843 int aspath_loop_count
= 0;
3844 struct bgp_dest
*dest
;
3846 struct attr new_attr
;
3847 struct attr
*attr_new
;
3848 struct bgp_path_info
*pi
;
3849 struct bgp_path_info
*new;
3850 struct bgp_path_info_extra
*extra
;
3852 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3854 int do_loop_check
= 1;
3855 int has_valid_label
= 0;
3857 uint8_t pi_type
= 0;
3858 uint8_t pi_sub_type
= 0;
3859 bool force_evpn_import
= false;
3860 safi_t orig_safi
= safi
;
3861 bool leak_success
= true;
3863 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3864 char pfxprint
[PREFIX2STR_BUFFER
];
3866 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3867 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3871 #ifdef ENABLE_BGP_VNC
3872 int vnc_implicit_withdraw
= 0;
3876 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3877 if (orig_safi
== SAFI_LABELED_UNICAST
)
3878 safi
= SAFI_UNICAST
;
3880 memset(&new_attr
, 0, sizeof(new_attr
));
3881 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3882 new_attr
.label
= MPLS_INVALID_LABEL
;
3885 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3886 /* TODO: Check to see if we can get rid of "is_valid_label" */
3887 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3888 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3890 has_valid_label
= bgp_is_valid_label(label
);
3892 if (has_valid_label
)
3893 assert(label
!= NULL
);
3895 /* Update overlay index of the attribute */
3896 if (afi
== AFI_L2VPN
&& evpn
)
3897 memcpy(&attr
->evpn_overlay
, evpn
,
3898 sizeof(struct bgp_route_evpn
));
3900 /* When peer's soft reconfiguration enabled. Record input packet in
3903 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3904 && peer
!= bgp
->peer_self
)
3905 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3907 /* Check previously received route. */
3908 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3909 if (pi
->peer
== peer
&& pi
->type
== type
3910 && pi
->sub_type
== sub_type
3911 && pi
->addpath_rx_id
== addpath_id
)
3914 /* AS path local-as loop check. */
3915 if (peer
->change_local_as
) {
3916 if (peer
->allowas_in
[afi
][safi
])
3917 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3918 else if (!CHECK_FLAG(peer
->flags
,
3919 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3920 aspath_loop_count
= 1;
3922 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3923 > aspath_loop_count
) {
3924 peer
->stat_pfx_aspath_loop
++;
3925 reason
= "as-path contains our own AS;";
3930 /* If the peer is configured for "allowas-in origin" and the last ASN in
3932 * as-path is our ASN then we do not need to call aspath_loop_check
3934 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3935 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3938 /* AS path loop check. */
3939 if (do_loop_check
) {
3940 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3941 > peer
->allowas_in
[afi
][safi
]
3942 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3943 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3944 > peer
->allowas_in
[afi
][safi
])) {
3945 peer
->stat_pfx_aspath_loop
++;
3946 reason
= "as-path contains our own AS;";
3951 /* Route reflector originator ID check. */
3952 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3953 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3954 peer
->stat_pfx_originator_loop
++;
3955 reason
= "originator is us;";
3959 /* Route reflector cluster ID check. */
3960 if (bgp_cluster_filter(peer
, attr
)) {
3961 peer
->stat_pfx_cluster_loop
++;
3962 reason
= "reflected from the same cluster;";
3966 /* Apply incoming filter. */
3967 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
3968 peer
->stat_pfx_filter
++;
3973 /* RFC 8212 to prevent route leaks.
3974 * This specification intends to improve this situation by requiring the
3975 * explicit configuration of both BGP Import and Export Policies for any
3976 * External BGP (EBGP) session such as customers, peers, or
3977 * confederation boundaries for all enabled address families. Through
3978 * codification of the aforementioned requirement, operators will
3979 * benefit from consistent behavior across different BGP
3982 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3983 if (!bgp_inbound_policy_exists(peer
,
3984 &peer
->filter
[afi
][safi
])) {
3985 reason
= "inbound policy missing";
3986 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
3987 NULL
) > FIFTEENMINUTE2USEC
||
3988 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
3990 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3991 monotime(&bgp
->ebgprequirespolicywarning
);
3996 /* draft-ietf-idr-deprecate-as-set-confed-set
3997 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3998 * Eventually, This document (if approved) updates RFC 4271
3999 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4000 * and obsoletes RFC 6472.
4002 if (peer
->bgp
->reject_as_sets
)
4003 if (aspath_check_as_sets(attr
->aspath
)) {
4005 "as-path contains AS_SET or AS_CONFED_SET type;";
4011 /* Apply incoming route-map.
4012 * NB: new_attr may now contain newly allocated values from route-map
4014 * commands, so we need bgp_attr_flush in the error paths, until we
4016 * the attr (which takes over the memory references) */
4017 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4020 peer
->stat_pfx_filter
++;
4021 reason
= "route-map;";
4022 bgp_attr_flush(&new_attr
);
4026 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4027 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4028 /* remove from RIB previous entry */
4029 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4032 if (peer
->sort
== BGP_PEER_EBGP
) {
4035 * A BGP speaker receiving an announcement tagged with the
4036 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4037 * NO_EXPORT community as defined in RFC1997, or a
4038 * similar community, to prevent propagation of the
4039 * prefix outside the local AS. The community to prevent
4040 * propagation SHOULD be chosen according to the operator's
4043 if (bgp_attr_get_community(&new_attr
) &&
4044 community_include(bgp_attr_get_community(&new_attr
),
4045 COMMUNITY_BLACKHOLE
))
4046 bgp_attr_add_no_export_community(&new_attr
);
4048 /* If we receive the graceful-shutdown community from an eBGP
4049 * peer we must lower local-preference */
4050 if (bgp_attr_get_community(&new_attr
) &&
4051 community_include(bgp_attr_get_community(&new_attr
),
4053 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4054 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4056 /* If graceful-shutdown is configured then add the GSHUT
4057 * community to all paths received from eBGP peers */
4058 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
4059 bgp_attr_add_gshut_community(&new_attr
);
4064 pi_sub_type
= pi
->sub_type
;
4067 /* next hop check. */
4068 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
4069 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
4071 peer
->stat_pfx_nh_invalid
++;
4072 reason
= "martian or self next-hop;";
4073 bgp_attr_flush(&new_attr
);
4077 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4078 peer
->stat_pfx_nh_invalid
++;
4079 reason
= "self mac;";
4080 bgp_attr_flush(&new_attr
);
4084 if (bgp_check_role_applicability(afi
, safi
) &&
4085 bgp_otc_filter(peer
, &new_attr
)) {
4086 reason
= "failing otc validation";
4087 bgp_attr_flush(&new_attr
);
4090 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4092 * Suppress fib is enabled
4093 * BGP_OPT_NO_FIB is not enabled
4094 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4095 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4097 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
4098 && (sub_type
== BGP_ROUTE_NORMAL
)
4099 && (!bgp_option_check(BGP_OPT_NO_FIB
))
4100 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
4101 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
4103 /* If maximum prefix count is configured and current prefix
4106 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4107 bgp_attr_flush(&new_attr
);
4111 /* If neighbor soo is configured, tag all incoming routes with
4112 * this SoO tag and then filter out advertisements in
4113 * subgroup_announce_check() if it matches the configured SoO
4114 * on the other peer.
4116 if (peer
->soo
[afi
][safi
]) {
4117 struct ecommunity
*old_ecomm
=
4118 bgp_attr_get_ecommunity(&new_attr
);
4119 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4120 struct ecommunity
*new_ecomm
;
4123 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4126 if (!old_ecomm
->refcnt
)
4127 ecommunity_free(&old_ecomm
);
4129 new_ecomm
= ecommunity_dup(ecomm_soo
);
4132 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4135 attr_new
= bgp_attr_intern(&new_attr
);
4137 /* If the update is implicit withdraw. */
4139 pi
->uptime
= monotime(NULL
);
4140 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4142 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4144 /* Same attribute comes in. */
4145 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4147 && (!has_valid_label
4148 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4149 num_labels
* sizeof(mpls_label_t
))
4151 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4152 BGP_CONFIG_DAMPENING
)
4153 && peer
->sort
== BGP_PEER_EBGP
4154 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4155 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4156 bgp_debug_rdpfxpath2str(
4157 afi
, safi
, prd
, p
, label
,
4158 num_labels
, addpath_id
? 1 : 0,
4159 addpath_id
, evpn
, pfx_buf
,
4161 zlog_debug("%pBP rcvd %s", peer
,
4165 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4166 != BGP_DAMP_SUPPRESSED
) {
4167 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4169 bgp_process(bgp
, dest
, afi
, safi
);
4171 } else /* Duplicate - odd */
4173 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4174 if (!peer
->rcvd_attr_printed
) {
4176 "%pBP rcvd UPDATE w/ attr: %s",
4178 peer
->rcvd_attr_str
);
4179 peer
->rcvd_attr_printed
= 1;
4182 bgp_debug_rdpfxpath2str(
4183 afi
, safi
, prd
, p
, label
,
4184 num_labels
, addpath_id
? 1 : 0,
4185 addpath_id
, evpn
, pfx_buf
,
4188 "%pBP rcvd %s...duplicate ignored",
4192 /* graceful restart STALE flag unset. */
4193 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4194 bgp_path_info_unset_flag(
4195 dest
, pi
, BGP_PATH_STALE
);
4196 bgp_dest_set_defer_flag(dest
, false);
4197 bgp_process(bgp
, dest
, afi
, safi
);
4201 bgp_dest_unlock_node(dest
);
4202 bgp_attr_unintern(&attr_new
);
4207 /* Withdraw/Announce before we fully processed the withdraw */
4208 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4209 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4210 bgp_debug_rdpfxpath2str(
4211 afi
, safi
, prd
, p
, label
, num_labels
,
4212 addpath_id
? 1 : 0, addpath_id
, evpn
,
4213 pfx_buf
, sizeof(pfx_buf
));
4215 "%pBP rcvd %s, flapped quicker than processing",
4219 bgp_path_info_restore(dest
, pi
);
4222 * If the BGP_PATH_REMOVED flag is set, then EVPN
4223 * routes would have been unimported already when a
4224 * prior BGP withdraw processing happened. Such routes
4225 * need to be imported again, so flag accordingly.
4227 force_evpn_import
= true;
4230 /* Received Logging. */
4231 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4232 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4233 num_labels
, addpath_id
? 1 : 0,
4234 addpath_id
, evpn
, pfx_buf
,
4236 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4239 /* graceful restart STALE flag unset. */
4240 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4241 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4242 bgp_dest_set_defer_flag(dest
, false);
4245 /* The attribute is changed. */
4246 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4248 /* implicit withdraw, decrement aggregate and pcount here.
4249 * only if update is accepted, they'll increment below.
4251 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4253 /* Update bgp route dampening information. */
4254 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4255 && peer
->sort
== BGP_PEER_EBGP
) {
4256 /* This is implicit withdraw so we should update
4259 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4260 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4262 #ifdef ENABLE_BGP_VNC
4263 if (safi
== SAFI_MPLS_VPN
) {
4264 struct bgp_dest
*pdest
= NULL
;
4265 struct bgp_table
*table
= NULL
;
4267 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4268 (struct prefix
*)prd
);
4269 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4270 table
= bgp_dest_get_bgp_table_info(pdest
);
4272 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4273 bgp
, prd
, table
, p
, pi
);
4275 bgp_dest_unlock_node(pdest
);
4277 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4278 && (safi
== SAFI_UNICAST
)) {
4279 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4281 * Implicit withdraw case.
4283 ++vnc_implicit_withdraw
;
4284 vnc_import_bgp_del_route(bgp
, p
, pi
);
4285 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4290 /* Special handling for EVPN update of an existing route. If the
4291 * extended community attribute has changed, we need to
4293 * the route using its existing extended community. It will be
4294 * subsequently processed for import with the new extended
4297 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4300 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4302 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4305 cmp
= ecommunity_cmp(
4306 bgp_attr_get_ecommunity(pi
->attr
),
4307 bgp_attr_get_ecommunity(attr_new
));
4309 if (bgp_debug_update(peer
, p
, NULL
, 1))
4311 "Change in EXT-COMM, existing %s new %s",
4313 bgp_attr_get_ecommunity(
4316 bgp_attr_get_ecommunity(
4318 if (safi
== SAFI_EVPN
)
4319 bgp_evpn_unimport_route(
4320 bgp
, afi
, safi
, p
, pi
);
4321 else /* SAFI_MPLS_VPN */
4322 vpn_leak_to_vrf_withdraw(bgp
,
4328 /* Update to new attribute. */
4329 bgp_attr_unintern(&pi
->attr
);
4330 pi
->attr
= attr_new
;
4332 /* Update MPLS label */
4333 if (has_valid_label
) {
4334 extra
= bgp_path_info_extra_get(pi
);
4335 if (extra
->label
!= label
) {
4336 memcpy(&extra
->label
, label
,
4337 num_labels
* sizeof(mpls_label_t
));
4338 extra
->num_labels
= num_labels
;
4340 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4341 bgp_set_valid_label(&extra
->label
[0]);
4344 /* Update SRv6 SID */
4345 if (attr
->srv6_l3vpn
) {
4346 extra
= bgp_path_info_extra_get(pi
);
4347 if (sid_diff(&extra
->sid
[0].sid
,
4348 &attr
->srv6_l3vpn
->sid
)) {
4349 sid_copy(&extra
->sid
[0].sid
,
4350 &attr
->srv6_l3vpn
->sid
);
4351 extra
->num_sids
= 1;
4353 extra
->sid
[0].loc_block_len
= 0;
4354 extra
->sid
[0].loc_node_len
= 0;
4355 extra
->sid
[0].func_len
= 0;
4356 extra
->sid
[0].arg_len
= 0;
4357 extra
->sid
[0].transposition_len
= 0;
4358 extra
->sid
[0].transposition_offset
= 0;
4360 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4361 extra
->sid
[0].loc_block_len
=
4362 attr
->srv6_l3vpn
->loc_block_len
;
4363 extra
->sid
[0].loc_node_len
=
4364 attr
->srv6_l3vpn
->loc_node_len
;
4365 extra
->sid
[0].func_len
=
4366 attr
->srv6_l3vpn
->func_len
;
4367 extra
->sid
[0].arg_len
=
4368 attr
->srv6_l3vpn
->arg_len
;
4369 extra
->sid
[0].transposition_len
=
4371 ->transposition_len
;
4372 extra
->sid
[0].transposition_offset
=
4374 ->transposition_offset
;
4377 } else if (attr
->srv6_vpn
) {
4378 extra
= bgp_path_info_extra_get(pi
);
4379 if (sid_diff(&extra
->sid
[0].sid
,
4380 &attr
->srv6_vpn
->sid
)) {
4381 sid_copy(&extra
->sid
[0].sid
,
4382 &attr
->srv6_vpn
->sid
);
4383 extra
->num_sids
= 1;
4387 #ifdef ENABLE_BGP_VNC
4388 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4389 && (safi
== SAFI_UNICAST
)) {
4390 if (vnc_implicit_withdraw
) {
4392 * Add back the route with its new attributes
4394 * The route is still selected, until the route
4396 * queued by bgp_process actually runs. We have
4398 * update to the VNC side immediately to avoid
4400 * configuration changes (e.g., route-map
4402 * trigger re-importation of the entire RIB.
4404 vnc_import_bgp_add_route(bgp
, p
, pi
);
4405 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4410 /* Update bgp route dampening information. */
4411 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4412 && peer
->sort
== BGP_PEER_EBGP
) {
4413 /* Now we do normal update dampening. */
4414 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4415 if (ret
== BGP_DAMP_SUPPRESSED
) {
4416 bgp_dest_unlock_node(dest
);
4421 /* Nexthop reachability check - for unicast and
4422 * labeled-unicast.. */
4423 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4424 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4425 || (safi
== SAFI_EVPN
&&
4426 bgp_evpn_is_prefix_nht_supported(p
))) {
4427 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4428 && peer
->ttl
== BGP_DEFAULT_TTL
4429 && !CHECK_FLAG(peer
->flags
,
4430 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4431 && !CHECK_FLAG(bgp
->flags
,
4432 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4437 struct bgp
*bgp_nexthop
= bgp
;
4439 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4440 bgp_nexthop
= pi
->extra
->bgp_orig
;
4442 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4444 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4445 safi
, pi
, NULL
, connected
,
4447 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4448 bgp_path_info_set_flag(dest
, pi
,
4451 if (BGP_DEBUG(nht
, NHT
)) {
4452 zlog_debug("%s(%pI4): NH unresolved",
4454 (in_addr_t
*)&attr_new
->nexthop
);
4456 bgp_path_info_unset_flag(dest
, pi
,
4460 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4462 #ifdef ENABLE_BGP_VNC
4463 if (safi
== SAFI_MPLS_VPN
) {
4464 struct bgp_dest
*pdest
= NULL
;
4465 struct bgp_table
*table
= NULL
;
4467 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4468 (struct prefix
*)prd
);
4469 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4470 table
= bgp_dest_get_bgp_table_info(pdest
);
4472 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4473 bgp
, prd
, table
, p
, pi
);
4475 bgp_dest_unlock_node(pdest
);
4479 /* If this is an EVPN route and some attribute has changed,
4480 * or we are explicitly told to perform a route import, process
4481 * route for import. If the extended community has changed, we
4483 * have done the un-import earlier and the import would result
4485 * route getting injected into appropriate L2 VNIs. If it is
4487 * some other attribute change, the import will result in
4489 * the attributes for the route in the VNI(s).
4491 if (safi
== SAFI_EVPN
&&
4492 (!same_attr
|| force_evpn_import
) &&
4493 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4494 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4496 /* Process change. */
4497 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4499 bgp_process(bgp
, dest
, afi
, safi
);
4500 bgp_dest_unlock_node(dest
);
4502 if (SAFI_UNICAST
== safi
4503 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4504 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4506 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4508 if ((SAFI_MPLS_VPN
== safi
)
4509 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4511 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
);
4514 #ifdef ENABLE_BGP_VNC
4515 if (SAFI_MPLS_VPN
== safi
) {
4516 mpls_label_t label_decoded
= decode_label(label
);
4518 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4519 type
, sub_type
, &label_decoded
);
4521 if (SAFI_ENCAP
== safi
) {
4522 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4523 type
, sub_type
, NULL
);
4526 if ((safi
== SAFI_MPLS_VPN
) &&
4527 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4528 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4530 bgp_unlink_nexthop(pi
);
4531 bgp_path_info_delete(dest
, pi
);
4534 } // End of implicit withdraw
4536 /* Received Logging. */
4537 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4538 if (!peer
->rcvd_attr_printed
) {
4539 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4540 peer
->rcvd_attr_str
);
4541 peer
->rcvd_attr_printed
= 1;
4544 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4545 addpath_id
? 1 : 0, addpath_id
, evpn
,
4546 pfx_buf
, sizeof(pfx_buf
));
4547 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4550 /* Make new BGP info. */
4551 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4553 /* Update MPLS label */
4554 if (has_valid_label
) {
4555 extra
= bgp_path_info_extra_get(new);
4556 if (extra
->label
!= label
) {
4557 memcpy(&extra
->label
, label
,
4558 num_labels
* sizeof(mpls_label_t
));
4559 extra
->num_labels
= num_labels
;
4561 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4562 bgp_set_valid_label(&extra
->label
[0]);
4565 /* Update SRv6 SID */
4566 if (safi
== SAFI_MPLS_VPN
) {
4567 extra
= bgp_path_info_extra_get(new);
4568 if (attr
->srv6_l3vpn
) {
4569 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4570 extra
->num_sids
= 1;
4572 extra
->sid
[0].loc_block_len
=
4573 attr
->srv6_l3vpn
->loc_block_len
;
4574 extra
->sid
[0].loc_node_len
=
4575 attr
->srv6_l3vpn
->loc_node_len
;
4576 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4577 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4578 extra
->sid
[0].transposition_len
=
4579 attr
->srv6_l3vpn
->transposition_len
;
4580 extra
->sid
[0].transposition_offset
=
4581 attr
->srv6_l3vpn
->transposition_offset
;
4582 } else if (attr
->srv6_vpn
) {
4583 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4584 extra
->num_sids
= 1;
4588 /* Nexthop reachability check. */
4589 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4590 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4591 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4592 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4593 && peer
->ttl
== BGP_DEFAULT_TTL
4594 && !CHECK_FLAG(peer
->flags
,
4595 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4596 && !CHECK_FLAG(bgp
->flags
,
4597 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4602 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4604 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4606 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4607 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4609 if (BGP_DEBUG(nht
, NHT
)) {
4610 char buf1
[INET6_ADDRSTRLEN
];
4612 (const void *)&attr_new
->nexthop
,
4613 buf1
, INET6_ADDRSTRLEN
);
4614 zlog_debug("%s(%s): NH unresolved", __func__
,
4617 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4620 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4623 new->addpath_rx_id
= addpath_id
;
4625 /* Increment prefix */
4626 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4628 /* Register new BGP information. */
4629 bgp_path_info_add(dest
, new);
4631 /* route_node_get lock */
4632 bgp_dest_unlock_node(dest
);
4634 #ifdef ENABLE_BGP_VNC
4635 if (safi
== SAFI_MPLS_VPN
) {
4636 struct bgp_dest
*pdest
= NULL
;
4637 struct bgp_table
*table
= NULL
;
4639 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4640 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4641 table
= bgp_dest_get_bgp_table_info(pdest
);
4643 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4644 bgp
, prd
, table
, p
, new);
4646 bgp_dest_unlock_node(pdest
);
4650 /* If this is an EVPN route, process for import. */
4651 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4652 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4654 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4656 /* Process change. */
4657 bgp_process(bgp
, dest
, afi
, safi
);
4659 if (SAFI_UNICAST
== safi
4660 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4661 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4662 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4664 if ((SAFI_MPLS_VPN
== safi
)
4665 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4666 leak_success
= vpn_leak_to_vrf_update(bgp
, new);
4668 #ifdef ENABLE_BGP_VNC
4669 if (SAFI_MPLS_VPN
== safi
) {
4670 mpls_label_t label_decoded
= decode_label(label
);
4672 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4673 sub_type
, &label_decoded
);
4675 if (SAFI_ENCAP
== safi
) {
4676 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4680 if ((safi
== SAFI_MPLS_VPN
) &&
4681 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4682 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4684 bgp_unlink_nexthop(new);
4685 bgp_path_info_delete(dest
, new);
4690 /* This BGP update is filtered. Log the reason then update BGP
4693 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4695 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4696 if (!peer
->rcvd_attr_printed
) {
4697 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4698 peer
->rcvd_attr_str
);
4699 peer
->rcvd_attr_printed
= 1;
4702 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4703 addpath_id
? 1 : 0, addpath_id
, evpn
,
4704 pfx_buf
, sizeof(pfx_buf
));
4705 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4706 peer
, pfx_buf
, reason
);
4710 /* If this is an EVPN route, un-import it as it is now filtered.
4712 if (safi
== SAFI_EVPN
)
4713 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4715 if (SAFI_UNICAST
== safi
4716 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4717 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4719 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4721 if ((SAFI_MPLS_VPN
== safi
)
4722 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4724 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4727 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4730 bgp_dest_unlock_node(dest
);
4732 #ifdef ENABLE_BGP_VNC
4734 * Filtered update is treated as an implicit withdrawal (see
4736 * a few lines above)
4738 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4739 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4747 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4748 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4749 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4750 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4753 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4754 struct bgp_dest
*dest
;
4755 struct bgp_path_info
*pi
;
4757 #ifdef ENABLE_BGP_VNC
4758 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4759 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4767 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4769 /* If peer is soft reconfiguration enabled. Record input packet for
4770 * further calculation.
4772 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4773 * routes that are filtered. This tanks out Quagga RS pretty badly due
4775 * the iteration over all RS clients.
4776 * Since we need to remove the entry from adj_in anyway, do that first
4778 * if there was no entry, we don't need to do anything more.
4780 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4781 && peer
!= bgp
->peer_self
)
4782 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4783 peer
->stat_pfx_dup_withdraw
++;
4785 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4786 bgp_debug_rdpfxpath2str(
4787 afi
, safi
, prd
, p
, label
, num_labels
,
4788 addpath_id
? 1 : 0, addpath_id
, NULL
,
4789 pfx_buf
, sizeof(pfx_buf
));
4791 "%s withdrawing route %s not in adj-in",
4792 peer
->host
, pfx_buf
);
4794 bgp_dest_unlock_node(dest
);
4798 /* Lookup withdrawn route. */
4799 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4800 if (pi
->peer
== peer
&& pi
->type
== type
4801 && pi
->sub_type
== sub_type
4802 && pi
->addpath_rx_id
== addpath_id
)
4806 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4807 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4808 addpath_id
? 1 : 0, addpath_id
, NULL
,
4809 pfx_buf
, sizeof(pfx_buf
));
4810 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
4814 /* Withdraw specified route from routing table. */
4815 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4816 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4817 if (SAFI_UNICAST
== safi
4818 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4819 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4820 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4822 if ((SAFI_MPLS_VPN
== safi
)
4823 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4825 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4827 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4828 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4829 addpath_id
? 1 : 0, addpath_id
, NULL
,
4830 pfx_buf
, sizeof(pfx_buf
));
4831 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4834 /* Unlock bgp_node_get() lock. */
4835 bgp_dest_unlock_node(dest
);
4840 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4843 struct update_subgroup
*subgrp
;
4844 subgrp
= peer_subgroup(peer
, afi
, safi
);
4845 subgroup_default_originate(subgrp
, withdraw
);
4850 * bgp_stop_announce_route_timer
4852 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4854 if (!paf
->t_announce_route
)
4857 THREAD_OFF(paf
->t_announce_route
);
4861 * bgp_announce_route_timer_expired
4863 * Callback that is invoked when the route announcement timer for a
4866 static void bgp_announce_route_timer_expired(struct thread
*t
)
4868 struct peer_af
*paf
;
4871 paf
= THREAD_ARG(t
);
4874 if (!peer_established(peer
))
4877 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4880 peer_af_announce_route(paf
, 1);
4882 /* Notify BGP conditional advertisement scanner percess */
4883 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
4887 * bgp_announce_route
4889 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4891 * if force is true we will force an update even if the update
4892 * limiting code is attempted to kick in.
4894 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
4896 struct peer_af
*paf
;
4897 struct update_subgroup
*subgrp
;
4899 paf
= peer_af_find(peer
, afi
, safi
);
4902 subgrp
= PAF_SUBGRP(paf
);
4905 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4906 * or a refresh has already been triggered.
4908 if (!subgrp
|| paf
->t_announce_route
)
4912 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
4915 * Start a timer to stagger/delay the announce. This serves
4916 * two purposes - announcement can potentially be combined for
4917 * multiple peers and the announcement doesn't happen in the
4920 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4921 (subgrp
->peer_count
== 1)
4922 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4923 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4924 &paf
->t_announce_route
);
4928 * Announce routes from all AF tables to a peer.
4930 * This should ONLY be called when there is a need to refresh the
4931 * routes to the peer based on a policy change for this peer alone
4932 * or a route refresh request received from the peer.
4933 * The operation will result in splitting the peer from its existing
4934 * subgroups and putting it in new subgroups.
4936 void bgp_announce_route_all(struct peer
*peer
)
4941 FOREACH_AFI_SAFI (afi
, safi
)
4942 bgp_announce_route(peer
, afi
, safi
, false);
4945 /* Flag or unflag bgp_dest to determine whether it should be treated by
4946 * bgp_soft_reconfig_table_task.
4947 * Flag if flag is true. Unflag if flag is false.
4949 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
4951 struct bgp_dest
*dest
;
4952 struct bgp_adj_in
*ain
;
4957 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4958 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4959 if (ain
->peer
!= NULL
)
4962 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
4963 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4965 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
4969 static int bgp_soft_reconfig_table_update(struct peer
*peer
,
4970 struct bgp_dest
*dest
,
4971 struct bgp_adj_in
*ain
, afi_t afi
,
4972 safi_t safi
, struct prefix_rd
*prd
)
4974 struct bgp_path_info
*pi
;
4975 uint32_t num_labels
= 0;
4976 mpls_label_t
*label_pnt
= NULL
;
4977 struct bgp_route_evpn evpn
;
4979 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4980 if (pi
->peer
== peer
)
4983 if (pi
&& pi
->extra
)
4984 num_labels
= pi
->extra
->num_labels
;
4986 label_pnt
= &pi
->extra
->label
[0];
4988 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
4991 memset(&evpn
, 0, sizeof(evpn
));
4993 return bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
4994 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
4995 BGP_ROUTE_NORMAL
, prd
, label_pnt
, num_labels
, 1,
4999 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5000 struct bgp_table
*table
,
5001 struct prefix_rd
*prd
)
5004 struct bgp_dest
*dest
;
5005 struct bgp_adj_in
*ain
;
5008 table
= peer
->bgp
->rib
[afi
][safi
];
5010 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5011 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5012 if (ain
->peer
!= peer
)
5015 ret
= bgp_soft_reconfig_table_update(peer
, dest
, ain
,
5019 bgp_dest_unlock_node(dest
);
5025 /* Do soft reconfig table per bgp table.
5026 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5027 * when BGP_NODE_SOFT_RECONFIG is set,
5028 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5029 * Schedule a new thread to continue the job.
5030 * Without splitting the full job into several part,
5031 * vtysh waits for the job to finish before responding to a BGP command
5033 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
5035 uint32_t iter
, max_iter
;
5037 struct bgp_dest
*dest
;
5038 struct bgp_adj_in
*ain
;
5040 struct bgp_table
*table
;
5041 struct prefix_rd
*prd
;
5042 struct listnode
*node
, *nnode
;
5044 table
= THREAD_ARG(thread
);
5047 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5048 if (table
->soft_reconfig_init
) {
5049 /* first call of the function with a new srta structure.
5050 * Don't do any treatment this time on nodes
5051 * in order vtysh to respond quickly
5056 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5057 dest
= bgp_route_next(dest
)) {
5058 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5061 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5063 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5064 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5066 if (ain
->peer
!= peer
)
5069 ret
= bgp_soft_reconfig_table_update(
5070 peer
, dest
, ain
, table
->afi
,
5075 bgp_dest_unlock_node(dest
);
5077 table
->soft_reconfig_peers
,
5079 bgp_announce_route(peer
, table
->afi
,
5080 table
->safi
, false);
5082 table
->soft_reconfig_peers
)) {
5084 &table
->soft_reconfig_peers
);
5085 bgp_soft_reconfig_table_flag(
5094 /* we're either starting the initial iteration,
5095 * or we're going to continue an ongoing iteration
5097 if (dest
|| table
->soft_reconfig_init
) {
5098 table
->soft_reconfig_init
= false;
5099 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
5100 table
, 0, &table
->soft_reconfig_thread
);
5103 /* we're done, clean up the background iteration context info and
5104 schedule route annoucement
5106 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5107 listnode_delete(table
->soft_reconfig_peers
, peer
);
5108 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5111 list_delete(&table
->soft_reconfig_peers
);
5115 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5117 * - bgp cannot be NULL
5118 * - if table and peer are NULL, cancel all threads within the bgp instance
5119 * - if table is NULL and peer is not,
5120 * remove peer in all threads within the bgp instance
5121 * - if peer is NULL, cancel all threads matching table within the bgp instance
5123 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5124 const struct bgp_table
*table
,
5125 const struct peer
*peer
)
5128 struct listnode
*node
, *nnode
;
5130 struct bgp_table
*ntable
;
5135 FOREACH_AFI_SAFI (afi
, safi
) {
5136 ntable
= bgp
->rib
[afi
][safi
];
5139 if (table
&& table
!= ntable
)
5142 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5144 if (peer
&& peer
!= npeer
)
5146 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5149 if (!ntable
->soft_reconfig_peers
5150 || !list_isempty(ntable
->soft_reconfig_peers
))
5153 list_delete(&ntable
->soft_reconfig_peers
);
5154 bgp_soft_reconfig_table_flag(ntable
, false);
5155 THREAD_OFF(ntable
->soft_reconfig_thread
);
5159 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5161 struct bgp_dest
*dest
;
5162 struct bgp_table
*table
;
5163 struct listnode
*node
, *nnode
;
5165 struct peer_af
*paf
;
5167 if (!peer_established(peer
))
5170 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5171 && (safi
!= SAFI_EVPN
)) {
5172 table
= peer
->bgp
->rib
[afi
][safi
];
5176 table
->soft_reconfig_init
= true;
5178 if (!table
->soft_reconfig_peers
)
5179 table
->soft_reconfig_peers
= list_new();
5181 /* add peer to the table soft_reconfig_peers if not already
5184 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5190 listnode_add(table
->soft_reconfig_peers
, peer
);
5192 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5193 * on table would start back at the beginning.
5195 bgp_soft_reconfig_table_flag(table
, true);
5197 if (!table
->soft_reconfig_thread
)
5198 thread_add_event(bm
->master
,
5199 bgp_soft_reconfig_table_task
, table
, 0,
5200 &table
->soft_reconfig_thread
);
5201 /* Cancel bgp_announce_route_timer_expired threads.
5202 * bgp_announce_route_timer_expired threads have been scheduled
5203 * to announce routes as soon as the soft_reconfigure process
5205 * In this case, soft_reconfigure is also scheduled by using
5206 * a thread but is planned after the
5207 * bgp_announce_route_timer_expired threads. It means that,
5208 * without cancelling the threads, the route announcement task
5209 * would run before the soft reconfiguration one. That would
5210 * useless and would block vtysh during several seconds. Route
5211 * announcements are rescheduled as soon as the soft_reconfigure
5214 paf
= peer_af_find(peer
, afi
, safi
);
5216 bgp_stop_announce_route_timer(paf
);
5218 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5219 dest
= bgp_route_next(dest
)) {
5220 table
= bgp_dest_get_bgp_table_info(dest
);
5225 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5226 struct prefix_rd prd
;
5228 prd
.family
= AF_UNSPEC
;
5230 memcpy(&prd
.val
, p
->u
.val
, 8);
5232 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5237 struct bgp_clear_node_queue
{
5238 struct bgp_dest
*dest
;
5241 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5243 struct bgp_clear_node_queue
*cnq
= data
;
5244 struct bgp_dest
*dest
= cnq
->dest
;
5245 struct peer
*peer
= wq
->spec
.data
;
5246 struct bgp_path_info
*pi
;
5248 afi_t afi
= bgp_dest_table(dest
)->afi
;
5249 safi_t safi
= bgp_dest_table(dest
)->safi
;
5251 assert(dest
&& peer
);
5254 /* It is possible that we have multiple paths for a prefix from a peer
5255 * if that peer is using AddPath.
5257 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5258 if (pi
->peer
!= peer
)
5261 /* graceful restart STALE flag set. */
5262 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5263 && peer
->nsf
[afi
][safi
])
5264 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5265 PEER_STATUS_ENHANCED_REFRESH
))
5266 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5267 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5268 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5270 /* If this is an EVPN route, process for
5272 if (safi
== SAFI_EVPN
)
5273 bgp_evpn_unimport_route(
5275 bgp_dest_get_prefix(dest
), pi
);
5276 /* Handle withdraw for VRF route-leaking and L3VPN */
5277 if (SAFI_UNICAST
== safi
5278 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5279 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5280 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5283 if (SAFI_MPLS_VPN
== safi
&&
5284 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5285 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5288 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5294 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5296 struct bgp_clear_node_queue
*cnq
= data
;
5297 struct bgp_dest
*dest
= cnq
->dest
;
5298 struct bgp_table
*table
= bgp_dest_table(dest
);
5300 bgp_dest_unlock_node(dest
);
5301 bgp_table_unlock(table
);
5302 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5305 static void bgp_clear_node_complete(struct work_queue
*wq
)
5307 struct peer
*peer
= wq
->spec
.data
;
5309 /* Tickle FSM to start moving again */
5310 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5312 peer_unlock(peer
); /* bgp_clear_route */
5315 static void bgp_clear_node_queue_init(struct peer
*peer
)
5317 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5319 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5320 #undef CLEAR_QUEUE_NAME_LEN
5322 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5323 peer
->clear_node_queue
->spec
.hold
= 10;
5324 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5325 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5326 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5327 peer
->clear_node_queue
->spec
.max_retries
= 0;
5329 /* we only 'lock' this peer reference when the queue is actually active
5331 peer
->clear_node_queue
->spec
.data
= peer
;
5334 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5335 struct bgp_table
*table
)
5337 struct bgp_dest
*dest
;
5338 int force
= peer
->bgp
->process_queue
? 0 : 1;
5341 table
= peer
->bgp
->rib
[afi
][safi
];
5343 /* If still no table => afi/safi isn't configured at all or smth. */
5347 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5348 struct bgp_path_info
*pi
, *next
;
5349 struct bgp_adj_in
*ain
;
5350 struct bgp_adj_in
*ain_next
;
5352 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5353 * queued for every clearing peer, regardless of whether it is
5354 * relevant to the peer at hand.
5356 * Overview: There are 3 different indices which need to be
5357 * scrubbed, potentially, when a peer is removed:
5359 * 1 peer's routes visible via the RIB (ie accepted routes)
5360 * 2 peer's routes visible by the (optional) peer's adj-in index
5361 * 3 other routes visible by the peer's adj-out index
5363 * 3 there is no hurry in scrubbing, once the struct peer is
5364 * removed from bgp->peer, we could just GC such deleted peer's
5365 * adj-outs at our leisure.
5367 * 1 and 2 must be 'scrubbed' in some way, at least made
5368 * invisible via RIB index before peer session is allowed to be
5369 * brought back up. So one needs to know when such a 'search' is
5374 * - there'd be a single global queue or a single RIB walker
5375 * - rather than tracking which route_nodes still need to be
5376 * examined on a peer basis, we'd track which peers still
5379 * Given that our per-peer prefix-counts now should be reliable,
5380 * this may actually be achievable. It doesn't seem to be a huge
5381 * problem at this time,
5383 * It is possible that we have multiple paths for a prefix from
5385 * if that peer is using AddPath.
5389 ain_next
= ain
->next
;
5391 if (ain
->peer
== peer
)
5392 bgp_adj_in_remove(dest
, ain
);
5397 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5399 if (pi
->peer
!= peer
)
5403 bgp_path_info_reap(dest
, pi
);
5405 struct bgp_clear_node_queue
*cnq
;
5407 /* both unlocked in bgp_clear_node_queue_del */
5408 bgp_table_lock(bgp_dest_table(dest
));
5409 bgp_dest_lock_node(dest
);
5411 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5412 sizeof(struct bgp_clear_node_queue
));
5414 work_queue_add(peer
->clear_node_queue
, cnq
);
5422 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5424 struct bgp_dest
*dest
;
5425 struct bgp_table
*table
;
5427 if (peer
->clear_node_queue
== NULL
)
5428 bgp_clear_node_queue_init(peer
);
5430 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5431 * Idle until it receives a Clearing_Completed event. This protects
5432 * against peers which flap faster than we can we clear, which could
5435 * a) race with routes from the new session being installed before
5436 * clear_route_node visits the node (to delete the route of that
5438 * b) resource exhaustion, clear_route_node likely leads to an entry
5439 * on the process_main queue. Fast-flapping could cause that queue
5443 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5444 * the unlock will happen upon work-queue completion; other wise, the
5445 * unlock happens at the end of this function.
5447 if (!peer
->clear_node_queue
->thread
)
5450 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5451 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5453 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5454 dest
= bgp_route_next(dest
)) {
5455 table
= bgp_dest_get_bgp_table_info(dest
);
5459 bgp_clear_route_table(peer
, afi
, safi
, table
);
5462 /* unlock if no nodes got added to the clear-node-queue. */
5463 if (!peer
->clear_node_queue
->thread
)
5467 void bgp_clear_route_all(struct peer
*peer
)
5472 FOREACH_AFI_SAFI (afi
, safi
)
5473 bgp_clear_route(peer
, afi
, safi
);
5475 #ifdef ENABLE_BGP_VNC
5476 rfapiProcessPeerDown(peer
);
5480 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5482 struct bgp_table
*table
;
5483 struct bgp_dest
*dest
;
5484 struct bgp_adj_in
*ain
;
5485 struct bgp_adj_in
*ain_next
;
5487 table
= peer
->bgp
->rib
[afi
][safi
];
5489 /* It is possible that we have multiple paths for a prefix from a peer
5490 * if that peer is using AddPath.
5492 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5496 ain_next
= ain
->next
;
5498 if (ain
->peer
== peer
)
5499 bgp_adj_in_remove(dest
, ain
);
5506 /* If any of the routes from the peer have been marked with the NO_LLGR
5507 * community, either as sent by the peer, or as the result of a configured
5508 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5509 * operation of [RFC4271].
5511 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5513 struct bgp_dest
*dest
;
5514 struct bgp_path_info
*pi
;
5515 struct bgp_table
*table
;
5517 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5518 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5519 dest
= bgp_route_next(dest
)) {
5520 struct bgp_dest
*rm
;
5522 /* look for neighbor in tables */
5523 table
= bgp_dest_get_bgp_table_info(dest
);
5527 for (rm
= bgp_table_top(table
); rm
;
5528 rm
= bgp_route_next(rm
))
5529 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5531 if (pi
->peer
!= peer
)
5534 peer
->af_sflags
[afi
][safi
],
5535 PEER_STATUS_LLGR_WAIT
) &&
5536 bgp_attr_get_community(pi
->attr
) &&
5538 bgp_attr_get_community(
5542 if (!CHECK_FLAG(pi
->flags
,
5547 * If this is VRF leaked route
5548 * process for withdraw.
5551 BGP_ROUTE_IMPORTED
&&
5552 peer
->bgp
->inst_type
==
5553 BGP_INSTANCE_TYPE_DEFAULT
)
5554 vpn_leak_to_vrf_withdraw(
5557 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5562 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5563 dest
= bgp_route_next(dest
))
5564 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5566 if (pi
->peer
!= peer
)
5568 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5569 PEER_STATUS_LLGR_WAIT
) &&
5570 bgp_attr_get_community(pi
->attr
) &&
5572 bgp_attr_get_community(pi
->attr
),
5575 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5577 if (safi
== SAFI_UNICAST
&&
5578 (peer
->bgp
->inst_type
==
5579 BGP_INSTANCE_TYPE_VRF
||
5580 peer
->bgp
->inst_type
==
5581 BGP_INSTANCE_TYPE_DEFAULT
))
5582 vpn_leak_from_vrf_withdraw(
5583 bgp_get_default(), peer
->bgp
,
5586 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5592 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5594 struct bgp_dest
*dest
, *ndest
;
5595 struct bgp_path_info
*pi
;
5596 struct bgp_table
*table
;
5598 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5599 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5600 dest
= bgp_route_next(dest
)) {
5601 table
= bgp_dest_get_bgp_table_info(dest
);
5605 for (ndest
= bgp_table_top(table
); ndest
;
5606 ndest
= bgp_route_next(ndest
)) {
5607 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5609 if (pi
->peer
!= peer
)
5613 peer
->af_sflags
[afi
][safi
],
5614 PEER_STATUS_ENHANCED_REFRESH
))
5615 && !CHECK_FLAG(pi
->flags
,
5619 BGP_PATH_UNUSEABLE
)) {
5620 if (bgp_debug_neighbor_events(
5623 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5627 bgp_dest_get_prefix(
5630 bgp_path_info_set_flag(
5638 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5639 dest
= bgp_route_next(dest
)) {
5640 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5642 if (pi
->peer
!= peer
)
5645 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5646 PEER_STATUS_ENHANCED_REFRESH
))
5647 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5648 && !CHECK_FLAG(pi
->flags
,
5649 BGP_PATH_UNUSEABLE
)) {
5650 if (bgp_debug_neighbor_events(peer
))
5652 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5655 bgp_dest_get_prefix(
5658 bgp_path_info_set_flag(dest
, pi
,
5666 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5668 if (peer
->sort
== BGP_PEER_IBGP
)
5671 if (peer
->sort
== BGP_PEER_EBGP
5672 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5673 || FILTER_LIST_OUT_NAME(filter
)
5674 || DISTRIBUTE_OUT_NAME(filter
)))
5679 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5681 if (peer
->sort
== BGP_PEER_IBGP
)
5684 if (peer
->sort
== BGP_PEER_EBGP
5685 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5686 || FILTER_LIST_IN_NAME(filter
)
5687 || DISTRIBUTE_IN_NAME(filter
)))
5692 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5695 struct bgp_dest
*dest
;
5696 struct bgp_path_info
*pi
;
5697 struct bgp_path_info
*next
;
5699 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5700 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5701 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5705 /* Unimport EVPN routes from VRFs */
5706 if (safi
== SAFI_EVPN
)
5707 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5710 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5711 && pi
->type
== ZEBRA_ROUTE_BGP
5712 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5713 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5714 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5716 if (bgp_fibupd_safi(safi
))
5717 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5720 bgp_path_info_reap(dest
, pi
);
5724 /* Delete all kernel routes. */
5725 void bgp_cleanup_routes(struct bgp
*bgp
)
5728 struct bgp_dest
*dest
;
5729 struct bgp_table
*table
;
5731 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5732 if (afi
== AFI_L2VPN
)
5734 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5737 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5739 if (afi
!= AFI_L2VPN
) {
5741 safi
= SAFI_MPLS_VPN
;
5742 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5743 dest
= bgp_route_next(dest
)) {
5744 table
= bgp_dest_get_bgp_table_info(dest
);
5745 if (table
!= NULL
) {
5746 bgp_cleanup_table(bgp
, table
, safi
);
5747 bgp_table_finish(&table
);
5748 bgp_dest_set_bgp_table_info(dest
, NULL
);
5749 bgp_dest_unlock_node(dest
);
5753 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5754 dest
= bgp_route_next(dest
)) {
5755 table
= bgp_dest_get_bgp_table_info(dest
);
5756 if (table
!= NULL
) {
5757 bgp_cleanup_table(bgp
, table
, safi
);
5758 bgp_table_finish(&table
);
5759 bgp_dest_set_bgp_table_info(dest
, NULL
);
5760 bgp_dest_unlock_node(dest
);
5765 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5766 dest
= bgp_route_next(dest
)) {
5767 table
= bgp_dest_get_bgp_table_info(dest
);
5768 if (table
!= NULL
) {
5769 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5770 bgp_table_finish(&table
);
5771 bgp_dest_set_bgp_table_info(dest
, NULL
);
5772 bgp_dest_unlock_node(dest
);
5777 void bgp_reset(void)
5780 bgp_zclient_reset();
5781 access_list_reset();
5782 prefix_list_reset();
5785 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5787 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5788 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5789 PEER_CAP_ADDPATH_AF_TX_RCV
));
5792 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5794 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5795 struct bgp_nlri
*packet
)
5804 bool addpath_capable
;
5805 uint32_t addpath_id
;
5808 lim
= pnt
+ packet
->length
;
5810 safi
= packet
->safi
;
5812 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5814 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5815 syntactic validity. If the field is syntactically incorrect,
5816 then the Error Subcode is set to Invalid Network Field. */
5817 for (; pnt
< lim
; pnt
+= psize
) {
5818 /* Clear prefix structure. */
5819 memset(&p
, 0, sizeof(p
));
5821 if (addpath_capable
) {
5823 /* When packet overflow occurs return immediately. */
5824 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5825 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5827 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5828 addpath_id
= ntohl(addpath_id
);
5829 pnt
+= BGP_ADDPATH_ID_LEN
;
5832 /* Fetch prefix length. */
5833 p
.prefixlen
= *pnt
++;
5834 /* afi/safi validity already verified by caller,
5835 * bgp_update_receive */
5836 p
.family
= afi2family(afi
);
5838 /* Prefix length check. */
5839 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5842 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5843 peer
->host
, p
.prefixlen
, packet
->afi
);
5844 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5847 /* Packet size overflow check. */
5848 psize
= PSIZE(p
.prefixlen
);
5850 /* When packet overflow occur return immediately. */
5851 if (pnt
+ psize
> lim
) {
5854 "%s [Error] Update packet error (prefix length %d overflows packet)",
5855 peer
->host
, p
.prefixlen
);
5856 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5859 /* Defensive coding, double-check the psize fits in a struct
5860 * prefix for the v4 and v6 afi's and unicast/multicast */
5861 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
5864 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5865 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
5866 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5869 /* Fetch prefix from NLRI packet. */
5870 memcpy(p
.u
.val
, pnt
, psize
);
5872 /* Check address. */
5873 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5874 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5875 /* From RFC4271 Section 6.3:
5877 * If a prefix in the NLRI field is semantically
5879 * (e.g., an unexpected multicast IP address),
5881 * be logged locally, and the prefix SHOULD be
5886 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5887 peer
->host
, &p
.u
.prefix4
);
5892 /* Check address. */
5893 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5894 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5897 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5898 peer
->host
, &p
.u
.prefix6
);
5902 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5905 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5906 peer
->host
, &p
.u
.prefix6
);
5912 /* Normal process. */
5914 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5915 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5916 NULL
, NULL
, 0, 0, NULL
);
5918 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5919 safi
, ZEBRA_ROUTE_BGP
,
5920 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5923 /* Do not send BGP notification twice when maximum-prefix count
5925 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5926 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5928 /* Address family configuration mismatch. */
5930 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5933 /* Packet length consistency check. */
5937 "%s [Error] Update packet error (prefix length mismatch with total length)",
5939 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5942 return BGP_NLRI_PARSE_OK
;
5945 static struct bgp_static
*bgp_static_new(void)
5947 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5950 static void bgp_static_free(struct bgp_static
*bgp_static
)
5952 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5953 route_map_counter_decrement(bgp_static
->rmap
.map
);
5955 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5956 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5959 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5960 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5962 struct bgp_dest
*dest
;
5963 struct bgp_path_info
*pi
;
5964 struct bgp_path_info
*new;
5965 struct bgp_path_info rmap_path
;
5967 struct attr
*attr_new
;
5968 route_map_result_t ret
;
5969 #ifdef ENABLE_BGP_VNC
5970 int vnc_implicit_withdraw
= 0;
5975 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5977 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
5979 attr
.nexthop
= bgp_static
->igpnexthop
;
5980 attr
.med
= bgp_static
->igpmetric
;
5981 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5984 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
5986 if (bgp_static
->atomic
)
5987 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5989 /* Store label index, if required. */
5990 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5991 attr
.label_index
= bgp_static
->label_index
;
5992 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5995 /* Apply route-map. */
5996 if (bgp_static
->rmap
.name
) {
5997 struct attr attr_tmp
= attr
;
5999 memset(&rmap_path
, 0, sizeof(rmap_path
));
6000 rmap_path
.peer
= bgp
->peer_self
;
6001 rmap_path
.attr
= &attr_tmp
;
6003 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6005 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6007 bgp
->peer_self
->rmap_type
= 0;
6009 if (ret
== RMAP_DENYMATCH
) {
6010 /* Free uninterned attribute. */
6011 bgp_attr_flush(&attr_tmp
);
6013 /* Unintern original. */
6014 aspath_unintern(&attr
.aspath
);
6015 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6016 bgp_dest_unlock_node(dest
);
6020 if (bgp_in_graceful_shutdown(bgp
))
6021 bgp_attr_add_gshut_community(&attr_tmp
);
6023 attr_new
= bgp_attr_intern(&attr_tmp
);
6026 if (bgp_in_graceful_shutdown(bgp
))
6027 bgp_attr_add_gshut_community(&attr
);
6029 attr_new
= bgp_attr_intern(&attr
);
6032 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6033 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6034 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6038 if (attrhash_cmp(pi
->attr
, attr_new
)
6039 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6040 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6041 bgp_dest_unlock_node(dest
);
6042 bgp_attr_unintern(&attr_new
);
6043 aspath_unintern(&attr
.aspath
);
6046 /* The attribute is changed. */
6047 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6049 /* Rewrite BGP route information. */
6050 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6051 bgp_path_info_restore(dest
, pi
);
6053 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6054 #ifdef ENABLE_BGP_VNC
6055 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6056 && (safi
== SAFI_UNICAST
)) {
6057 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6059 * Implicit withdraw case.
6060 * We have to do this before pi is
6063 ++vnc_implicit_withdraw
;
6064 vnc_import_bgp_del_route(bgp
, p
, pi
);
6065 vnc_import_bgp_exterior_del_route(
6070 bgp_attr_unintern(&pi
->attr
);
6071 pi
->attr
= attr_new
;
6072 pi
->uptime
= monotime(NULL
);
6073 #ifdef ENABLE_BGP_VNC
6074 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6075 && (safi
== SAFI_UNICAST
)) {
6076 if (vnc_implicit_withdraw
) {
6077 vnc_import_bgp_add_route(bgp
, p
, pi
);
6078 vnc_import_bgp_exterior_add_route(
6084 /* Nexthop reachability check. */
6085 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6086 && (safi
== SAFI_UNICAST
6087 || safi
== SAFI_LABELED_UNICAST
)) {
6089 struct bgp
*bgp_nexthop
= bgp
;
6091 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6092 bgp_nexthop
= pi
->extra
->bgp_orig
;
6094 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6095 afi
, safi
, pi
, NULL
,
6097 bgp_path_info_set_flag(dest
, pi
,
6100 if (BGP_DEBUG(nht
, NHT
)) {
6101 char buf1
[INET6_ADDRSTRLEN
];
6102 inet_ntop(p
->family
,
6106 "%s(%s): Route not in table, not advertising",
6109 bgp_path_info_unset_flag(
6110 dest
, pi
, BGP_PATH_VALID
);
6113 /* Delete the NHT structure if any, if we're
6115 * enabling/disabling import check. We
6116 * deregister the route
6117 * from NHT to avoid overloading NHT and the
6118 * process interaction
6120 bgp_unlink_nexthop(pi
);
6121 bgp_path_info_set_flag(dest
, pi
,
6124 /* Process change. */
6125 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6126 bgp_process(bgp
, dest
, afi
, safi
);
6128 if (SAFI_UNICAST
== safi
6129 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6131 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6132 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6136 bgp_dest_unlock_node(dest
);
6137 aspath_unintern(&attr
.aspath
);
6142 /* Make new BGP info. */
6143 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6145 /* Nexthop reachability check. */
6146 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6147 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6148 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6150 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6152 if (BGP_DEBUG(nht
, NHT
)) {
6153 char buf1
[INET6_ADDRSTRLEN
];
6154 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6157 "%s(%s): Route not in table, not advertising",
6160 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6163 /* Delete the NHT structure if any, if we're toggling between
6164 * enabling/disabling import check. We deregister the route
6165 * from NHT to avoid overloading NHT and the process interaction
6167 bgp_unlink_nexthop(new);
6169 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6172 /* Aggregate address increment. */
6173 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6175 /* Register new BGP information. */
6176 bgp_path_info_add(dest
, new);
6178 /* route_node_get lock */
6179 bgp_dest_unlock_node(dest
);
6181 /* Process change. */
6182 bgp_process(bgp
, dest
, afi
, safi
);
6184 if (SAFI_UNICAST
== safi
6185 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6186 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6187 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6190 /* Unintern original. */
6191 aspath_unintern(&attr
.aspath
);
6194 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6197 struct bgp_dest
*dest
;
6198 struct bgp_path_info
*pi
;
6200 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6202 /* Check selected route and self inserted route. */
6203 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6204 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6205 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6208 /* Withdraw static BGP route from routing table. */
6210 if (SAFI_UNICAST
== safi
6211 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6212 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6213 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6215 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6216 bgp_unlink_nexthop(pi
);
6217 bgp_path_info_delete(dest
, pi
);
6218 bgp_process(bgp
, dest
, afi
, safi
);
6221 /* Unlock bgp_node_lookup. */
6222 bgp_dest_unlock_node(dest
);
6226 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6228 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6229 afi_t afi
, safi_t safi
,
6230 struct prefix_rd
*prd
)
6232 struct bgp_dest
*dest
;
6233 struct bgp_path_info
*pi
;
6235 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6237 /* Check selected route and self inserted route. */
6238 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6239 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6240 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6243 /* Withdraw static BGP route from routing table. */
6245 #ifdef ENABLE_BGP_VNC
6246 rfapiProcessWithdraw(
6247 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6248 1); /* Kill, since it is an administrative change */
6250 if (SAFI_MPLS_VPN
== safi
6251 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6252 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6254 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6255 bgp_path_info_delete(dest
, pi
);
6256 bgp_process(bgp
, dest
, afi
, safi
);
6259 /* Unlock bgp_node_lookup. */
6260 bgp_dest_unlock_node(dest
);
6263 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6264 struct bgp_static
*bgp_static
, afi_t afi
,
6267 struct bgp_dest
*dest
;
6268 struct bgp_path_info
*new;
6269 struct attr
*attr_new
;
6270 struct attr attr
= {0};
6271 struct bgp_path_info
*pi
;
6272 #ifdef ENABLE_BGP_VNC
6273 mpls_label_t label
= 0;
6275 uint32_t num_labels
= 0;
6279 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6281 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6284 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6286 attr
.nexthop
= bgp_static
->igpnexthop
;
6287 attr
.med
= bgp_static
->igpmetric
;
6288 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6290 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6291 || (safi
== SAFI_ENCAP
)) {
6292 if (afi
== AFI_IP
) {
6293 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6294 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6297 if (afi
== AFI_L2VPN
) {
6298 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6299 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6300 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6301 &bgp_static
->gatewayIp
.u
.prefix4
,
6303 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6304 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6305 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6306 &bgp_static
->gatewayIp
.u
.prefix6
,
6309 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6310 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6311 struct bgp_encap_type_vxlan bet
;
6312 memset(&bet
, 0, sizeof(bet
));
6313 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6314 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6316 if (bgp_static
->router_mac
) {
6317 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6320 /* Apply route-map. */
6321 if (bgp_static
->rmap
.name
) {
6322 struct attr attr_tmp
= attr
;
6323 struct bgp_path_info rmap_path
;
6324 route_map_result_t ret
;
6326 rmap_path
.peer
= bgp
->peer_self
;
6327 rmap_path
.attr
= &attr_tmp
;
6329 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6331 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6333 bgp
->peer_self
->rmap_type
= 0;
6335 if (ret
== RMAP_DENYMATCH
) {
6336 /* Free uninterned attribute. */
6337 bgp_attr_flush(&attr_tmp
);
6339 /* Unintern original. */
6340 aspath_unintern(&attr
.aspath
);
6341 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6343 bgp_dest_unlock_node(dest
);
6347 attr_new
= bgp_attr_intern(&attr_tmp
);
6349 attr_new
= bgp_attr_intern(&attr
);
6352 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6353 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6354 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6358 if (attrhash_cmp(pi
->attr
, attr_new
)
6359 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6360 bgp_dest_unlock_node(dest
);
6361 bgp_attr_unintern(&attr_new
);
6362 aspath_unintern(&attr
.aspath
);
6365 /* The attribute is changed. */
6366 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6368 /* Rewrite BGP route information. */
6369 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6370 bgp_path_info_restore(dest
, pi
);
6372 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6373 bgp_attr_unintern(&pi
->attr
);
6374 pi
->attr
= attr_new
;
6375 pi
->uptime
= monotime(NULL
);
6376 #ifdef ENABLE_BGP_VNC
6378 label
= decode_label(&pi
->extra
->label
[0]);
6381 /* Process change. */
6382 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6383 bgp_process(bgp
, dest
, afi
, safi
);
6385 if (SAFI_MPLS_VPN
== safi
6386 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6387 vpn_leak_to_vrf_update(bgp
, pi
);
6389 #ifdef ENABLE_BGP_VNC
6390 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6391 pi
->attr
, afi
, safi
, pi
->type
,
6392 pi
->sub_type
, &label
);
6394 bgp_dest_unlock_node(dest
);
6395 aspath_unintern(&attr
.aspath
);
6401 /* Make new BGP info. */
6402 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6404 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6405 bgp_path_info_extra_get(new);
6407 new->extra
->label
[0] = bgp_static
->label
;
6408 new->extra
->num_labels
= num_labels
;
6410 #ifdef ENABLE_BGP_VNC
6411 label
= decode_label(&bgp_static
->label
);
6414 /* Aggregate address increment. */
6415 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6417 /* Register new BGP information. */
6418 bgp_path_info_add(dest
, new);
6419 /* route_node_get lock */
6420 bgp_dest_unlock_node(dest
);
6422 /* Process change. */
6423 bgp_process(bgp
, dest
, afi
, safi
);
6425 if (SAFI_MPLS_VPN
== safi
6426 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6427 vpn_leak_to_vrf_update(bgp
, new);
6429 #ifdef ENABLE_BGP_VNC
6430 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6431 safi
, new->type
, new->sub_type
, &label
);
6434 /* Unintern original. */
6435 aspath_unintern(&attr
.aspath
);
6438 /* Configure static BGP network. When user don't run zebra, static
6439 route should be installed as valid. */
6440 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6441 const char *ip_str
, afi_t afi
, safi_t safi
,
6442 const char *rmap
, int backdoor
, uint32_t label_index
)
6444 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6447 struct bgp_static
*bgp_static
;
6448 struct bgp_dest
*dest
;
6449 uint8_t need_update
= 0;
6451 /* Convert IP prefix string to struct prefix. */
6452 ret
= str2prefix(ip_str
, &p
);
6454 vty_out(vty
, "%% Malformed prefix\n");
6455 return CMD_WARNING_CONFIG_FAILED
;
6457 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6458 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6459 return CMD_WARNING_CONFIG_FAILED
;
6466 /* Set BGP static route configuration. */
6467 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6470 vty_out(vty
, "%% Can't find static route specified\n");
6471 return CMD_WARNING_CONFIG_FAILED
;
6474 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6476 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6477 && (label_index
!= bgp_static
->label_index
)) {
6479 "%% label-index doesn't match static route\n");
6480 bgp_dest_unlock_node(dest
);
6481 return CMD_WARNING_CONFIG_FAILED
;
6484 if ((rmap
&& bgp_static
->rmap
.name
)
6485 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6487 "%% route-map name doesn't match static route\n");
6488 bgp_dest_unlock_node(dest
);
6489 return CMD_WARNING_CONFIG_FAILED
;
6492 /* Update BGP RIB. */
6493 if (!bgp_static
->backdoor
)
6494 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6496 /* Clear configuration. */
6497 bgp_static_free(bgp_static
);
6498 bgp_dest_set_bgp_static_info(dest
, NULL
);
6499 bgp_dest_unlock_node(dest
);
6500 bgp_dest_unlock_node(dest
);
6503 /* Set BGP static route configuration. */
6504 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6505 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6507 /* Configuration change. */
6508 /* Label index cannot be changed. */
6509 if (bgp_static
->label_index
!= label_index
) {
6510 vty_out(vty
, "%% cannot change label-index\n");
6511 bgp_dest_unlock_node(dest
);
6512 return CMD_WARNING_CONFIG_FAILED
;
6515 /* Check previous routes are installed into BGP. */
6516 if (bgp_static
->valid
6517 && bgp_static
->backdoor
!= backdoor
)
6520 bgp_static
->backdoor
= backdoor
;
6523 XFREE(MTYPE_ROUTE_MAP_NAME
,
6524 bgp_static
->rmap
.name
);
6525 route_map_counter_decrement(
6526 bgp_static
->rmap
.map
);
6527 bgp_static
->rmap
.name
=
6528 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6529 bgp_static
->rmap
.map
=
6530 route_map_lookup_by_name(rmap
);
6531 route_map_counter_increment(
6532 bgp_static
->rmap
.map
);
6534 XFREE(MTYPE_ROUTE_MAP_NAME
,
6535 bgp_static
->rmap
.name
);
6536 route_map_counter_decrement(
6537 bgp_static
->rmap
.map
);
6538 bgp_static
->rmap
.map
= NULL
;
6539 bgp_static
->valid
= 0;
6541 bgp_dest_unlock_node(dest
);
6543 /* New configuration. */
6544 bgp_static
= bgp_static_new();
6545 bgp_static
->backdoor
= backdoor
;
6546 bgp_static
->valid
= 0;
6547 bgp_static
->igpmetric
= 0;
6548 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6549 bgp_static
->label_index
= label_index
;
6552 XFREE(MTYPE_ROUTE_MAP_NAME
,
6553 bgp_static
->rmap
.name
);
6554 route_map_counter_decrement(
6555 bgp_static
->rmap
.map
);
6556 bgp_static
->rmap
.name
=
6557 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6558 bgp_static
->rmap
.map
=
6559 route_map_lookup_by_name(rmap
);
6560 route_map_counter_increment(
6561 bgp_static
->rmap
.map
);
6563 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6566 bgp_static
->valid
= 1;
6568 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6570 if (!bgp_static
->backdoor
)
6571 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6577 void bgp_static_add(struct bgp
*bgp
)
6581 struct bgp_dest
*dest
;
6582 struct bgp_dest
*rm
;
6583 struct bgp_table
*table
;
6584 struct bgp_static
*bgp_static
;
6586 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6587 FOREACH_AFI_SAFI (afi
, safi
)
6588 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6589 dest
= bgp_route_next(dest
)) {
6590 if (!bgp_dest_has_bgp_path_info_data(dest
))
6593 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6594 || (safi
== SAFI_EVPN
)) {
6595 table
= bgp_dest_get_bgp_table_info(dest
);
6597 for (rm
= bgp_table_top(table
); rm
;
6598 rm
= bgp_route_next(rm
)) {
6600 bgp_dest_get_bgp_static_info(
6602 bgp_static_update_safi(
6603 bgp
, bgp_dest_get_prefix(rm
),
6604 bgp_static
, afi
, safi
);
6608 bgp
, bgp_dest_get_prefix(dest
),
6609 bgp_dest_get_bgp_static_info(dest
), afi
,
6613 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6616 /* Called from bgp_delete(). Delete all static routes from the BGP
6618 void bgp_static_delete(struct bgp
*bgp
)
6622 struct bgp_dest
*dest
;
6623 struct bgp_dest
*rm
;
6624 struct bgp_table
*table
;
6625 struct bgp_static
*bgp_static
;
6627 FOREACH_AFI_SAFI (afi
, safi
)
6628 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6629 dest
= bgp_route_next(dest
)) {
6630 if (!bgp_dest_has_bgp_path_info_data(dest
))
6633 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6634 || (safi
== SAFI_EVPN
)) {
6635 table
= bgp_dest_get_bgp_table_info(dest
);
6637 for (rm
= bgp_table_top(table
); rm
;
6638 rm
= bgp_route_next(rm
)) {
6640 bgp_dest_get_bgp_static_info(
6645 bgp_static_withdraw_safi(
6646 bgp
, bgp_dest_get_prefix(rm
),
6648 (struct prefix_rd
*)
6649 bgp_dest_get_prefix(
6651 bgp_static_free(bgp_static
);
6652 bgp_dest_set_bgp_static_info(rm
,
6654 bgp_dest_unlock_node(rm
);
6657 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6658 bgp_static_withdraw(bgp
,
6659 bgp_dest_get_prefix(dest
),
6661 bgp_static_free(bgp_static
);
6662 bgp_dest_set_bgp_static_info(dest
, NULL
);
6663 bgp_dest_unlock_node(dest
);
6668 void bgp_static_redo_import_check(struct bgp
*bgp
)
6672 struct bgp_dest
*dest
;
6673 struct bgp_dest
*rm
;
6674 struct bgp_table
*table
;
6675 struct bgp_static
*bgp_static
;
6677 /* Use this flag to force reprocessing of the route */
6678 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6679 FOREACH_AFI_SAFI (afi
, safi
) {
6680 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6681 dest
= bgp_route_next(dest
)) {
6682 if (!bgp_dest_has_bgp_path_info_data(dest
))
6685 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6686 || (safi
== SAFI_EVPN
)) {
6687 table
= bgp_dest_get_bgp_table_info(dest
);
6689 for (rm
= bgp_table_top(table
); rm
;
6690 rm
= bgp_route_next(rm
)) {
6692 bgp_dest_get_bgp_static_info(
6694 bgp_static_update_safi(
6695 bgp
, bgp_dest_get_prefix(rm
),
6696 bgp_static
, afi
, safi
);
6699 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6700 bgp_static_update(bgp
,
6701 bgp_dest_get_prefix(dest
),
6702 bgp_static
, afi
, safi
);
6706 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6709 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6712 struct bgp_table
*table
;
6713 struct bgp_dest
*dest
;
6714 struct bgp_path_info
*pi
;
6716 /* Do not install the aggregate route if BGP is in the
6717 * process of termination.
6719 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6720 || (bgp
->peer_self
== NULL
))
6723 table
= bgp
->rib
[afi
][safi
];
6724 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6725 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6726 if (pi
->peer
== bgp
->peer_self
6727 && ((pi
->type
== ZEBRA_ROUTE_BGP
6728 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6729 || (pi
->type
!= ZEBRA_ROUTE_BGP
6731 == BGP_ROUTE_REDISTRIBUTE
))) {
6732 bgp_aggregate_decrement(
6733 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6735 bgp_unlink_nexthop(pi
);
6736 bgp_path_info_delete(dest
, pi
);
6737 bgp_process(bgp
, dest
, afi
, safi
);
6744 * Purge all networks and redistributed routes from routing table.
6745 * Invoked upon the instance going down.
6747 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6752 FOREACH_AFI_SAFI (afi
, safi
)
6753 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6758 * Currently this is used to set static routes for VPN and ENCAP.
6759 * I think it can probably be factored with bgp_static_set.
6761 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6762 const char *ip_str
, const char *rd_str
,
6763 const char *label_str
, const char *rmap_str
,
6764 int evpn_type
, const char *esi
, const char *gwip
,
6765 const char *ethtag
, const char *routermac
)
6767 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6770 struct prefix_rd prd
;
6771 struct bgp_dest
*pdest
;
6772 struct bgp_dest
*dest
;
6773 struct bgp_table
*table
;
6774 struct bgp_static
*bgp_static
;
6775 mpls_label_t label
= MPLS_INVALID_LABEL
;
6776 struct prefix gw_ip
;
6778 /* validate ip prefix */
6779 ret
= str2prefix(ip_str
, &p
);
6781 vty_out(vty
, "%% Malformed prefix\n");
6782 return CMD_WARNING_CONFIG_FAILED
;
6785 if ((afi
== AFI_L2VPN
)
6786 && (bgp_build_evpn_prefix(evpn_type
,
6787 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6788 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6789 return CMD_WARNING_CONFIG_FAILED
;
6792 ret
= str2prefix_rd(rd_str
, &prd
);
6794 vty_out(vty
, "%% Malformed rd\n");
6795 return CMD_WARNING_CONFIG_FAILED
;
6799 unsigned long label_val
;
6800 label_val
= strtoul(label_str
, NULL
, 10);
6801 encode_label(label_val
, &label
);
6804 if (safi
== SAFI_EVPN
) {
6805 if (esi
&& str2esi(esi
, NULL
) == 0) {
6806 vty_out(vty
, "%% Malformed ESI\n");
6807 return CMD_WARNING_CONFIG_FAILED
;
6809 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6810 vty_out(vty
, "%% Malformed Router MAC\n");
6811 return CMD_WARNING_CONFIG_FAILED
;
6814 memset(&gw_ip
, 0, sizeof(gw_ip
));
6815 ret
= str2prefix(gwip
, &gw_ip
);
6817 vty_out(vty
, "%% Malformed GatewayIp\n");
6818 return CMD_WARNING_CONFIG_FAILED
;
6820 if ((gw_ip
.family
== AF_INET
6821 && is_evpn_prefix_ipaddr_v6(
6822 (struct prefix_evpn
*)&p
))
6823 || (gw_ip
.family
== AF_INET6
6824 && is_evpn_prefix_ipaddr_v4(
6825 (struct prefix_evpn
*)&p
))) {
6827 "%% GatewayIp family differs with IP prefix\n");
6828 return CMD_WARNING_CONFIG_FAILED
;
6832 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6833 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6834 bgp_dest_set_bgp_table_info(pdest
,
6835 bgp_table_init(bgp
, afi
, safi
));
6836 table
= bgp_dest_get_bgp_table_info(pdest
);
6838 dest
= bgp_node_get(table
, &p
);
6840 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6841 vty_out(vty
, "%% Same network configuration exists\n");
6842 bgp_dest_unlock_node(dest
);
6844 /* New configuration. */
6845 bgp_static
= bgp_static_new();
6846 bgp_static
->backdoor
= 0;
6847 bgp_static
->valid
= 0;
6848 bgp_static
->igpmetric
= 0;
6849 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6850 bgp_static
->label
= label
;
6851 bgp_static
->prd
= prd
;
6854 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6855 route_map_counter_decrement(bgp_static
->rmap
.map
);
6856 bgp_static
->rmap
.name
=
6857 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6858 bgp_static
->rmap
.map
=
6859 route_map_lookup_by_name(rmap_str
);
6860 route_map_counter_increment(bgp_static
->rmap
.map
);
6863 if (safi
== SAFI_EVPN
) {
6865 bgp_static
->eth_s_id
=
6868 str2esi(esi
, bgp_static
->eth_s_id
);
6871 bgp_static
->router_mac
=
6872 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
6873 (void)prefix_str2mac(routermac
,
6874 bgp_static
->router_mac
);
6877 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
6879 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6881 bgp_static
->valid
= 1;
6882 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
6888 /* Configure static BGP network. */
6889 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6890 const char *ip_str
, const char *rd_str
,
6891 const char *label_str
, int evpn_type
, const char *esi
,
6892 const char *gwip
, const char *ethtag
)
6894 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6897 struct prefix_rd prd
;
6898 struct bgp_dest
*pdest
;
6899 struct bgp_dest
*dest
;
6900 struct bgp_table
*table
;
6901 struct bgp_static
*bgp_static
;
6902 mpls_label_t label
= MPLS_INVALID_LABEL
;
6904 /* Convert IP prefix string to struct prefix. */
6905 ret
= str2prefix(ip_str
, &p
);
6907 vty_out(vty
, "%% Malformed prefix\n");
6908 return CMD_WARNING_CONFIG_FAILED
;
6911 if ((afi
== AFI_L2VPN
)
6912 && (bgp_build_evpn_prefix(evpn_type
,
6913 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6914 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6915 return CMD_WARNING_CONFIG_FAILED
;
6917 ret
= str2prefix_rd(rd_str
, &prd
);
6919 vty_out(vty
, "%% Malformed rd\n");
6920 return CMD_WARNING_CONFIG_FAILED
;
6924 unsigned long label_val
;
6925 label_val
= strtoul(label_str
, NULL
, 10);
6926 encode_label(label_val
, &label
);
6929 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6930 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6931 bgp_dest_set_bgp_table_info(pdest
,
6932 bgp_table_init(bgp
, afi
, safi
));
6934 bgp_dest_unlock_node(pdest
);
6935 table
= bgp_dest_get_bgp_table_info(pdest
);
6937 dest
= bgp_node_lookup(table
, &p
);
6940 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6942 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6943 bgp_static_free(bgp_static
);
6944 bgp_dest_set_bgp_static_info(dest
, NULL
);
6945 bgp_dest_unlock_node(dest
);
6946 bgp_dest_unlock_node(dest
);
6948 vty_out(vty
, "%% Can't find the route\n");
6953 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6954 const char *rmap_name
)
6956 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6957 struct bgp_rmap
*rmap
;
6959 rmap
= &bgp
->table_map
[afi
][safi
];
6961 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6962 route_map_counter_decrement(rmap
->map
);
6963 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6964 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6965 route_map_counter_increment(rmap
->map
);
6967 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6968 route_map_counter_decrement(rmap
->map
);
6972 if (bgp_fibupd_safi(safi
))
6973 bgp_zebra_announce_table(bgp
, afi
, safi
);
6978 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6979 const char *rmap_name
)
6981 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6982 struct bgp_rmap
*rmap
;
6984 rmap
= &bgp
->table_map
[afi
][safi
];
6985 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6986 route_map_counter_decrement(rmap
->map
);
6989 if (bgp_fibupd_safi(safi
))
6990 bgp_zebra_announce_table(bgp
, afi
, safi
);
6995 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6998 if (bgp
->table_map
[afi
][safi
].name
) {
6999 vty_out(vty
, " table-map %s\n",
7000 bgp
->table_map
[afi
][safi
].name
);
7004 DEFUN (bgp_table_map
,
7007 "BGP table to RIB route download filter\n"
7008 "Name of the route map\n")
7011 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7012 argv
[idx_word
]->arg
);
7014 DEFUN (no_bgp_table_map
,
7015 no_bgp_table_map_cmd
,
7016 "no table-map WORD",
7018 "BGP table to RIB route download filter\n"
7019 "Name of the route map\n")
7022 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7023 argv
[idx_word
]->arg
);
7029 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7030 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7031 backdoor$backdoor}]",
7033 "Specify a network to announce via BGP\n"
7038 "Route-map to modify the attributes\n"
7039 "Name of the route map\n"
7040 "Label index to associate with the prefix\n"
7041 "Label index value\n"
7042 "Specify a BGP backdoor route\n")
7044 char addr_prefix_str
[BUFSIZ
];
7049 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7051 sizeof(addr_prefix_str
));
7053 vty_out(vty
, "%% Inconsistent address and mask\n");
7054 return CMD_WARNING_CONFIG_FAILED
;
7058 return bgp_static_set(
7059 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7060 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7061 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7064 DEFPY(ipv6_bgp_network
,
7065 ipv6_bgp_network_cmd
,
7066 "[no] network X:X::X:X/M$prefix \
7067 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7069 "Specify a network to announce via BGP\n"
7071 "Route-map to modify the attributes\n"
7072 "Name of the route map\n"
7073 "Label index to associate with the prefix\n"
7074 "Label index value\n")
7076 return bgp_static_set(
7077 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7078 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7081 static struct bgp_aggregate
*bgp_aggregate_new(void)
7083 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7086 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7088 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7089 route_map_counter_decrement(aggregate
->suppress_map
);
7090 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7091 route_map_counter_decrement(aggregate
->rmap
.map
);
7092 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7096 * Helper function to avoid repeated code: prepare variables for a
7097 * `route_map_apply` call.
7099 * \returns `true` on route map match, otherwise `false`.
7101 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7102 struct bgp_aggregate
*aggregate
,
7103 struct bgp_path_info
*pi
)
7105 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7106 route_map_result_t rmr
= RMAP_DENYMATCH
;
7107 struct bgp_path_info rmap_path
= {};
7108 struct attr attr
= {};
7110 /* No route map entries created, just don't match. */
7111 if (aggregate
->suppress_map
== NULL
)
7114 /* Call route map matching and return result. */
7115 attr
.aspath
= aspath_empty();
7116 rmap_path
.peer
= bgp
->peer_self
;
7117 rmap_path
.attr
= &attr
;
7119 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7120 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7121 bgp
->peer_self
->rmap_type
= 0;
7123 bgp_attr_flush(&attr
);
7124 aspath_unintern(&attr
.aspath
);
7126 return rmr
== RMAP_PERMITMATCH
;
7129 /** Test whether the aggregation has suppressed this path or not. */
7130 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7131 struct bgp_path_info
*pi
)
7133 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7136 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7140 * Suppress this path and keep the reference.
7142 * \returns `true` if needs processing otherwise `false`.
7144 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7145 struct bgp_path_info
*pi
)
7147 struct bgp_path_info_extra
*pie
;
7149 /* Path is already suppressed by this aggregation. */
7150 if (aggr_suppress_exists(aggregate
, pi
))
7153 pie
= bgp_path_info_extra_get(pi
);
7155 /* This is the first suppression, allocate memory and list it. */
7156 if (pie
->aggr_suppressors
== NULL
)
7157 pie
->aggr_suppressors
= list_new();
7159 listnode_add(pie
->aggr_suppressors
, aggregate
);
7161 /* Only mark for processing if suppressed. */
7162 if (listcount(pie
->aggr_suppressors
) == 1) {
7163 if (BGP_DEBUG(update
, UPDATE_OUT
))
7164 zlog_debug("aggregate-address suppressing: %pFX",
7165 bgp_dest_get_prefix(pi
->net
));
7167 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7175 * Unsuppress this path and remove the reference.
7177 * \returns `true` if needs processing otherwise `false`.
7179 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7180 struct bgp_path_info
*pi
)
7182 /* Path wasn't suppressed. */
7183 if (!aggr_suppress_exists(aggregate
, pi
))
7186 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7188 /* Unsuppress and free extra memory if last item. */
7189 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7190 if (BGP_DEBUG(update
, UPDATE_OUT
))
7191 zlog_debug("aggregate-address unsuppressing: %pFX",
7192 bgp_dest_get_prefix(pi
->net
));
7194 list_delete(&pi
->extra
->aggr_suppressors
);
7195 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7202 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7203 struct aspath
*aspath
,
7204 struct community
*comm
,
7205 struct ecommunity
*ecomm
,
7206 struct lcommunity
*lcomm
)
7208 static struct aspath
*ae
= NULL
;
7211 ae
= aspath_empty();
7216 if (origin
!= pi
->attr
->origin
)
7219 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7222 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7225 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7228 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7231 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7237 static void bgp_aggregate_install(
7238 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7239 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7240 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7241 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7243 struct bgp_dest
*dest
;
7244 struct bgp_table
*table
;
7245 struct bgp_path_info
*pi
, *orig
, *new;
7248 table
= bgp
->rib
[afi
][safi
];
7250 dest
= bgp_node_get(table
, p
);
7252 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7253 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7254 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7258 * If we have paths with different MEDs, then don't install
7259 * (or uninstall) the aggregate route.
7261 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7262 goto uninstall_aggregate_route
;
7264 if (aggregate
->count
> 0) {
7266 * If the aggregate information has not changed
7267 * no need to re-install it again.
7269 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7270 ecommunity
, lcommunity
)) {
7271 bgp_dest_unlock_node(dest
);
7274 aspath_free(aspath
);
7276 community_free(&community
);
7278 ecommunity_free(&ecommunity
);
7280 lcommunity_free(&lcommunity
);
7286 * Mark the old as unusable
7289 bgp_path_info_delete(dest
, pi
);
7291 attr
= bgp_attr_aggregate_intern(
7292 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7293 aggregate
, atomic_aggregate
, p
);
7296 bgp_dest_unlock_node(dest
);
7297 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7298 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7299 zlog_debug("%s: %pFX null attribute", __func__
,
7304 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7305 bgp
->peer_self
, attr
, dest
);
7307 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7309 bgp_path_info_add(dest
, new);
7310 bgp_process(bgp
, dest
, afi
, safi
);
7312 uninstall_aggregate_route
:
7313 for (pi
= orig
; pi
; pi
= pi
->next
)
7314 if (pi
->peer
== bgp
->peer_self
7315 && pi
->type
== ZEBRA_ROUTE_BGP
7316 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7319 /* Withdraw static BGP route from routing table. */
7321 bgp_path_info_delete(dest
, pi
);
7322 bgp_process(bgp
, dest
, afi
, safi
);
7326 bgp_dest_unlock_node(dest
);
7330 * Check if the current path has different MED than other known paths.
7332 * \returns `true` if the MED matched the others else `false`.
7334 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7335 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7337 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7339 /* This is the first route being analyzed. */
7340 if (!aggregate
->med_initialized
) {
7341 aggregate
->med_initialized
= true;
7342 aggregate
->med_mismatched
= false;
7343 aggregate
->med_matched_value
= cur_med
;
7345 /* Check if routes with different MED showed up. */
7346 if (cur_med
!= aggregate
->med_matched_value
)
7347 aggregate
->med_mismatched
= true;
7350 return !aggregate
->med_mismatched
;
7354 * Initializes and tests all routes in the aggregate address path for MED
7357 * \returns `true` if all MEDs are the same otherwise `false`.
7359 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7360 struct bgp
*bgp
, const struct prefix
*p
,
7361 afi_t afi
, safi_t safi
)
7363 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7364 const struct prefix
*dest_p
;
7365 struct bgp_dest
*dest
, *top
;
7366 struct bgp_path_info
*pi
;
7367 bool med_matched
= true;
7369 aggregate
->med_initialized
= false;
7371 top
= bgp_node_get(table
, p
);
7372 for (dest
= bgp_node_get(table
, p
); dest
;
7373 dest
= bgp_route_next_until(dest
, top
)) {
7374 dest_p
= bgp_dest_get_prefix(dest
);
7375 if (dest_p
->prefixlen
<= p
->prefixlen
)
7378 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7379 if (BGP_PATH_HOLDDOWN(pi
))
7381 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7383 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7384 med_matched
= false;
7391 bgp_dest_unlock_node(top
);
7397 * Toggles the route suppression status for this aggregate address
7400 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7401 struct bgp
*bgp
, const struct prefix
*p
,
7402 afi_t afi
, safi_t safi
, bool suppress
)
7404 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7405 const struct prefix
*dest_p
;
7406 struct bgp_dest
*dest
, *top
;
7407 struct bgp_path_info
*pi
;
7408 bool toggle_suppression
;
7410 /* We've found a different MED we must revert any suppressed routes. */
7411 top
= bgp_node_get(table
, p
);
7412 for (dest
= bgp_node_get(table
, p
); dest
;
7413 dest
= bgp_route_next_until(dest
, top
)) {
7414 dest_p
= bgp_dest_get_prefix(dest
);
7415 if (dest_p
->prefixlen
<= p
->prefixlen
)
7418 toggle_suppression
= false;
7419 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7420 if (BGP_PATH_HOLDDOWN(pi
))
7422 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7425 /* We are toggling suppression back. */
7427 /* Suppress route if not suppressed already. */
7428 if (aggr_suppress_path(aggregate
, pi
))
7429 toggle_suppression
= true;
7433 /* Install route if there is no more suppression. */
7434 if (aggr_unsuppress_path(aggregate
, pi
))
7435 toggle_suppression
= true;
7438 if (toggle_suppression
)
7439 bgp_process(bgp
, dest
, afi
, safi
);
7441 bgp_dest_unlock_node(top
);
7445 * Aggregate address MED matching incremental test: this function is called
7446 * when the initial aggregation occurred and we are only testing a single
7449 * In addition to testing and setting the MED validity it also installs back
7450 * suppressed routes (if summary is configured).
7452 * Must not be called in `bgp_aggregate_route`.
7454 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7455 struct bgp
*bgp
, const struct prefix
*p
,
7456 afi_t afi
, safi_t safi
,
7457 struct bgp_path_info
*pi
)
7459 /* MED matching disabled. */
7460 if (!aggregate
->match_med
)
7463 /* Aggregation with different MED, recheck if we have got equal MEDs
7466 if (aggregate
->med_mismatched
&&
7467 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7468 aggregate
->summary_only
)
7469 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7472 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7474 /* No mismatches, just quit. */
7475 if (!aggregate
->med_mismatched
)
7478 /* Route summarization is disabled. */
7479 if (!aggregate
->summary_only
)
7482 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7485 /* Update an aggregate as routes are added/removed from the BGP table */
7486 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7487 safi_t safi
, struct bgp_aggregate
*aggregate
)
7489 struct bgp_table
*table
;
7490 struct bgp_dest
*top
;
7491 struct bgp_dest
*dest
;
7493 struct aspath
*aspath
= NULL
;
7494 struct community
*community
= NULL
;
7495 struct ecommunity
*ecommunity
= NULL
;
7496 struct lcommunity
*lcommunity
= NULL
;
7497 struct bgp_path_info
*pi
;
7498 unsigned long match
= 0;
7499 uint8_t atomic_aggregate
= 0;
7501 /* If the bgp instance is being deleted or self peer is deleted
7502 * then do not create aggregate route
7504 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7505 || (bgp
->peer_self
== NULL
))
7508 /* Initialize and test routes for MED difference. */
7509 if (aggregate
->match_med
)
7510 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7513 * Reset aggregate count: we might've been called from route map
7514 * update so in that case we must retest all more specific routes.
7516 * \see `bgp_route_map_process_update`.
7518 aggregate
->count
= 0;
7519 aggregate
->incomplete_origin_count
= 0;
7520 aggregate
->incomplete_origin_count
= 0;
7521 aggregate
->egp_origin_count
= 0;
7523 /* ORIGIN attribute: If at least one route among routes that are
7524 aggregated has ORIGIN with the value INCOMPLETE, then the
7525 aggregated route must have the ORIGIN attribute with the value
7526 INCOMPLETE. Otherwise, if at least one route among routes that
7527 are aggregated has ORIGIN with the value EGP, then the aggregated
7528 route must have the origin attribute with the value EGP. In all
7529 other case the value of the ORIGIN attribute of the aggregated
7530 route is INTERNAL. */
7531 origin
= BGP_ORIGIN_IGP
;
7533 table
= bgp
->rib
[afi
][safi
];
7535 top
= bgp_node_get(table
, p
);
7536 for (dest
= bgp_node_get(table
, p
); dest
;
7537 dest
= bgp_route_next_until(dest
, top
)) {
7538 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7540 if (dest_p
->prefixlen
<= p
->prefixlen
)
7543 /* If suppress fib is enabled and route not installed
7544 * in FIB, skip the route
7546 if (!bgp_check_advertise(bgp
, dest
))
7551 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7552 if (BGP_PATH_HOLDDOWN(pi
))
7556 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7557 atomic_aggregate
= 1;
7559 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7563 * summary-only aggregate route suppress
7564 * aggregated route announcements.
7567 * Don't create summaries if MED didn't match
7568 * otherwise neither the specific routes and the
7569 * aggregation will be announced.
7571 if (aggregate
->summary_only
7572 && AGGREGATE_MED_VALID(aggregate
)) {
7573 if (aggr_suppress_path(aggregate
, pi
))
7578 * Suppress more specific routes that match the route
7582 * Don't suppress routes if MED matching is enabled and
7583 * it mismatched otherwise we might end up with no
7584 * routes for this path.
7586 if (aggregate
->suppress_map_name
7587 && AGGREGATE_MED_VALID(aggregate
)
7588 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7589 if (aggr_suppress_path(aggregate
, pi
))
7596 * If at least one route among routes that are
7597 * aggregated has ORIGIN with the value INCOMPLETE,
7598 * then the aggregated route MUST have the ORIGIN
7599 * attribute with the value INCOMPLETE. Otherwise, if
7600 * at least one route among routes that are aggregated
7601 * has ORIGIN with the value EGP, then the aggregated
7602 * route MUST have the ORIGIN attribute with the value
7605 switch (pi
->attr
->origin
) {
7606 case BGP_ORIGIN_INCOMPLETE
:
7607 aggregate
->incomplete_origin_count
++;
7609 case BGP_ORIGIN_EGP
:
7610 aggregate
->egp_origin_count
++;
7618 if (!aggregate
->as_set
)
7622 * as-set aggregate route generate origin, as path,
7623 * and community aggregation.
7625 /* Compute aggregate route's as-path.
7627 bgp_compute_aggregate_aspath_hash(aggregate
,
7630 /* Compute aggregate route's community.
7632 if (bgp_attr_get_community(pi
->attr
))
7633 bgp_compute_aggregate_community_hash(
7635 bgp_attr_get_community(pi
->attr
));
7637 /* Compute aggregate route's extended community.
7639 if (bgp_attr_get_ecommunity(pi
->attr
))
7640 bgp_compute_aggregate_ecommunity_hash(
7642 bgp_attr_get_ecommunity(pi
->attr
));
7644 /* Compute aggregate route's large community.
7646 if (bgp_attr_get_lcommunity(pi
->attr
))
7647 bgp_compute_aggregate_lcommunity_hash(
7649 bgp_attr_get_lcommunity(pi
->attr
));
7652 bgp_process(bgp
, dest
, afi
, safi
);
7654 if (aggregate
->as_set
) {
7655 bgp_compute_aggregate_aspath_val(aggregate
);
7656 bgp_compute_aggregate_community_val(aggregate
);
7657 bgp_compute_aggregate_ecommunity_val(aggregate
);
7658 bgp_compute_aggregate_lcommunity_val(aggregate
);
7662 bgp_dest_unlock_node(top
);
7665 if (aggregate
->incomplete_origin_count
> 0)
7666 origin
= BGP_ORIGIN_INCOMPLETE
;
7667 else if (aggregate
->egp_origin_count
> 0)
7668 origin
= BGP_ORIGIN_EGP
;
7670 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7671 origin
= aggregate
->origin
;
7673 if (aggregate
->as_set
) {
7674 if (aggregate
->aspath
)
7675 /* Retrieve aggregate route's as-path.
7677 aspath
= aspath_dup(aggregate
->aspath
);
7679 if (aggregate
->community
)
7680 /* Retrieve aggregate route's community.
7682 community
= community_dup(aggregate
->community
);
7684 if (aggregate
->ecommunity
)
7685 /* Retrieve aggregate route's ecommunity.
7687 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7689 if (aggregate
->lcommunity
)
7690 /* Retrieve aggregate route's lcommunity.
7692 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7695 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7696 ecommunity
, lcommunity
, atomic_aggregate
,
7700 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7701 safi_t safi
, struct bgp_aggregate
*aggregate
)
7703 struct bgp_table
*table
;
7704 struct bgp_dest
*top
;
7705 struct bgp_dest
*dest
;
7706 struct bgp_path_info
*pi
;
7707 unsigned long match
;
7709 table
= bgp
->rib
[afi
][safi
];
7711 /* If routes exists below this node, generate aggregate routes. */
7712 top
= bgp_node_get(table
, p
);
7713 for (dest
= bgp_node_get(table
, p
); dest
;
7714 dest
= bgp_route_next_until(dest
, top
)) {
7715 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7717 if (dest_p
->prefixlen
<= p
->prefixlen
)
7721 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7722 if (BGP_PATH_HOLDDOWN(pi
))
7725 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7729 * This route is suppressed: attempt to unsuppress it.
7731 * `aggr_unsuppress_path` will fail if this particular
7732 * aggregate route was not the suppressor.
7734 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7735 listcount(pi
->extra
->aggr_suppressors
)) {
7736 if (aggr_unsuppress_path(aggregate
, pi
))
7742 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7743 aggregate
->incomplete_origin_count
--;
7744 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7745 aggregate
->egp_origin_count
--;
7747 if (aggregate
->as_set
) {
7748 /* Remove as-path from aggregate.
7750 bgp_remove_aspath_from_aggregate_hash(
7754 if (bgp_attr_get_community(pi
->attr
))
7755 /* Remove community from aggregate.
7757 bgp_remove_comm_from_aggregate_hash(
7759 bgp_attr_get_community(
7762 if (bgp_attr_get_ecommunity(pi
->attr
))
7763 /* Remove ecommunity from aggregate.
7765 bgp_remove_ecomm_from_aggregate_hash(
7767 bgp_attr_get_ecommunity(
7770 if (bgp_attr_get_lcommunity(pi
->attr
))
7771 /* Remove lcommunity from aggregate.
7773 bgp_remove_lcomm_from_aggregate_hash(
7775 bgp_attr_get_lcommunity(
7780 /* If this node was suppressed, process the change. */
7782 bgp_process(bgp
, dest
, afi
, safi
);
7784 if (aggregate
->as_set
) {
7785 aspath_free(aggregate
->aspath
);
7786 aggregate
->aspath
= NULL
;
7787 if (aggregate
->community
)
7788 community_free(&aggregate
->community
);
7789 if (aggregate
->ecommunity
)
7790 ecommunity_free(&aggregate
->ecommunity
);
7791 if (aggregate
->lcommunity
)
7792 lcommunity_free(&aggregate
->lcommunity
);
7795 bgp_dest_unlock_node(top
);
7798 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7799 const struct prefix
*aggr_p
,
7800 struct bgp_path_info
*pinew
, afi_t afi
,
7802 struct bgp_aggregate
*aggregate
)
7805 struct aspath
*aspath
= NULL
;
7806 uint8_t atomic_aggregate
= 0;
7807 struct community
*community
= NULL
;
7808 struct ecommunity
*ecommunity
= NULL
;
7809 struct lcommunity
*lcommunity
= NULL
;
7811 /* If the bgp instance is being deleted or self peer is deleted
7812 * then do not create aggregate route
7814 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7815 || (bgp
->peer_self
== NULL
))
7818 /* ORIGIN attribute: If at least one route among routes that are
7819 * aggregated has ORIGIN with the value INCOMPLETE, then the
7820 * aggregated route must have the ORIGIN attribute with the value
7821 * INCOMPLETE. Otherwise, if at least one route among routes that
7822 * are aggregated has ORIGIN with the value EGP, then the aggregated
7823 * route must have the origin attribute with the value EGP. In all
7824 * other case the value of the ORIGIN attribute of the aggregated
7825 * route is INTERNAL.
7827 origin
= BGP_ORIGIN_IGP
;
7832 * This must be called before `summary` check to avoid
7833 * "suppressing" twice.
7835 if (aggregate
->match_med
)
7836 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7839 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7840 aggr_suppress_path(aggregate
, pinew
);
7842 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7843 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7844 aggr_suppress_path(aggregate
, pinew
);
7846 switch (pinew
->attr
->origin
) {
7847 case BGP_ORIGIN_INCOMPLETE
:
7848 aggregate
->incomplete_origin_count
++;
7850 case BGP_ORIGIN_EGP
:
7851 aggregate
->egp_origin_count
++;
7859 if (aggregate
->incomplete_origin_count
> 0)
7860 origin
= BGP_ORIGIN_INCOMPLETE
;
7861 else if (aggregate
->egp_origin_count
> 0)
7862 origin
= BGP_ORIGIN_EGP
;
7864 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7865 origin
= aggregate
->origin
;
7867 if (aggregate
->as_set
) {
7868 /* Compute aggregate route's as-path.
7870 bgp_compute_aggregate_aspath(aggregate
,
7871 pinew
->attr
->aspath
);
7873 /* Compute aggregate route's community.
7875 if (bgp_attr_get_community(pinew
->attr
))
7876 bgp_compute_aggregate_community(
7877 aggregate
, bgp_attr_get_community(pinew
->attr
));
7879 /* Compute aggregate route's extended community.
7881 if (bgp_attr_get_ecommunity(pinew
->attr
))
7882 bgp_compute_aggregate_ecommunity(
7884 bgp_attr_get_ecommunity(pinew
->attr
));
7886 /* Compute aggregate route's large community.
7888 if (bgp_attr_get_lcommunity(pinew
->attr
))
7889 bgp_compute_aggregate_lcommunity(
7891 bgp_attr_get_lcommunity(pinew
->attr
));
7893 /* Retrieve aggregate route's as-path.
7895 if (aggregate
->aspath
)
7896 aspath
= aspath_dup(aggregate
->aspath
);
7898 /* Retrieve aggregate route's community.
7900 if (aggregate
->community
)
7901 community
= community_dup(aggregate
->community
);
7903 /* Retrieve aggregate route's ecommunity.
7905 if (aggregate
->ecommunity
)
7906 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7908 /* Retrieve aggregate route's lcommunity.
7910 if (aggregate
->lcommunity
)
7911 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7914 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7915 aspath
, community
, ecommunity
,
7916 lcommunity
, atomic_aggregate
, aggregate
);
7919 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7921 struct bgp_path_info
*pi
,
7922 struct bgp_aggregate
*aggregate
,
7923 const struct prefix
*aggr_p
)
7926 struct aspath
*aspath
= NULL
;
7927 uint8_t atomic_aggregate
= 0;
7928 struct community
*community
= NULL
;
7929 struct ecommunity
*ecommunity
= NULL
;
7930 struct lcommunity
*lcommunity
= NULL
;
7931 unsigned long match
= 0;
7933 /* If the bgp instance is being deleted or self peer is deleted
7934 * then do not create aggregate route
7936 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7937 || (bgp
->peer_self
== NULL
))
7940 if (BGP_PATH_HOLDDOWN(pi
))
7943 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7946 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7947 if (aggr_unsuppress_path(aggregate
, pi
))
7950 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7951 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7952 if (aggr_unsuppress_path(aggregate
, pi
))
7956 * This must be called after `summary`, `suppress-map` check to avoid
7957 * "unsuppressing" twice.
7959 if (aggregate
->match_med
)
7960 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
7962 if (aggregate
->count
> 0)
7965 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7966 aggregate
->incomplete_origin_count
--;
7967 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7968 aggregate
->egp_origin_count
--;
7970 if (aggregate
->as_set
) {
7971 /* Remove as-path from aggregate.
7973 bgp_remove_aspath_from_aggregate(aggregate
,
7976 if (bgp_attr_get_community(pi
->attr
))
7977 /* Remove community from aggregate.
7979 bgp_remove_community_from_aggregate(
7980 aggregate
, bgp_attr_get_community(pi
->attr
));
7982 if (bgp_attr_get_ecommunity(pi
->attr
))
7983 /* Remove ecommunity from aggregate.
7985 bgp_remove_ecommunity_from_aggregate(
7986 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
7988 if (bgp_attr_get_lcommunity(pi
->attr
))
7989 /* Remove lcommunity from aggregate.
7991 bgp_remove_lcommunity_from_aggregate(
7992 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
7995 /* If this node was suppressed, process the change. */
7997 bgp_process(bgp
, pi
->net
, afi
, safi
);
7999 origin
= BGP_ORIGIN_IGP
;
8000 if (aggregate
->incomplete_origin_count
> 0)
8001 origin
= BGP_ORIGIN_INCOMPLETE
;
8002 else if (aggregate
->egp_origin_count
> 0)
8003 origin
= BGP_ORIGIN_EGP
;
8005 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8006 origin
= aggregate
->origin
;
8008 if (aggregate
->as_set
) {
8009 /* Retrieve aggregate route's as-path.
8011 if (aggregate
->aspath
)
8012 aspath
= aspath_dup(aggregate
->aspath
);
8014 /* Retrieve aggregate route's community.
8016 if (aggregate
->community
)
8017 community
= community_dup(aggregate
->community
);
8019 /* Retrieve aggregate route's ecommunity.
8021 if (aggregate
->ecommunity
)
8022 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8024 /* Retrieve aggregate route's lcommunity.
8026 if (aggregate
->lcommunity
)
8027 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8030 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8031 aspath
, community
, ecommunity
,
8032 lcommunity
, atomic_aggregate
, aggregate
);
8035 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8036 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8038 struct bgp_dest
*child
;
8039 struct bgp_dest
*dest
;
8040 struct bgp_aggregate
*aggregate
;
8041 struct bgp_table
*table
;
8043 table
= bgp
->aggregate
[afi
][safi
];
8045 /* No aggregates configured. */
8046 if (bgp_table_top_nolock(table
) == NULL
)
8049 if (p
->prefixlen
== 0)
8052 if (BGP_PATH_HOLDDOWN(pi
))
8055 /* If suppress fib is enabled and route not installed
8056 * in FIB, do not update the aggregate route
8058 if (!bgp_check_advertise(bgp
, pi
->net
))
8061 child
= bgp_node_get(table
, p
);
8063 /* Aggregate address configuration check. */
8064 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8065 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8067 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8068 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8069 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8073 bgp_dest_unlock_node(child
);
8076 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8077 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8079 struct bgp_dest
*child
;
8080 struct bgp_dest
*dest
;
8081 struct bgp_aggregate
*aggregate
;
8082 struct bgp_table
*table
;
8084 table
= bgp
->aggregate
[afi
][safi
];
8086 /* No aggregates configured. */
8087 if (bgp_table_top_nolock(table
) == NULL
)
8090 if (p
->prefixlen
== 0)
8093 child
= bgp_node_get(table
, p
);
8095 /* Aggregate address configuration check. */
8096 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8097 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8099 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8100 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8101 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8105 bgp_dest_unlock_node(child
);
8108 /* Aggregate route attribute. */
8109 #define AGGREGATE_SUMMARY_ONLY 1
8110 #define AGGREGATE_AS_SET 1
8111 #define AGGREGATE_AS_UNSET 0
8113 static const char *bgp_origin2str(uint8_t origin
)
8116 case BGP_ORIGIN_IGP
:
8118 case BGP_ORIGIN_EGP
:
8120 case BGP_ORIGIN_INCOMPLETE
:
8121 return "incomplete";
8126 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8129 case RPKI_NOT_BEING_USED
:
8139 assert(!"We should never get here this is a dev escape");
8143 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8144 afi_t afi
, safi_t safi
)
8146 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8149 struct bgp_dest
*dest
;
8150 struct bgp_aggregate
*aggregate
;
8152 /* Convert string to prefix structure. */
8153 ret
= str2prefix(prefix_str
, &p
);
8155 vty_out(vty
, "Malformed prefix\n");
8156 return CMD_WARNING_CONFIG_FAILED
;
8160 /* Old configuration check. */
8161 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8164 "%% There is no aggregate-address configuration.\n");
8165 return CMD_WARNING_CONFIG_FAILED
;
8168 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8169 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8170 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8171 NULL
, NULL
, 0, aggregate
);
8173 /* Unlock aggregate address configuration. */
8174 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8176 if (aggregate
->community
)
8177 community_free(&aggregate
->community
);
8179 if (aggregate
->community_hash
) {
8180 /* Delete all communities in the hash.
8182 hash_clean(aggregate
->community_hash
,
8183 bgp_aggr_community_remove
);
8184 /* Free up the community_hash.
8186 hash_free(aggregate
->community_hash
);
8189 if (aggregate
->ecommunity
)
8190 ecommunity_free(&aggregate
->ecommunity
);
8192 if (aggregate
->ecommunity_hash
) {
8193 /* Delete all ecommunities in the hash.
8195 hash_clean(aggregate
->ecommunity_hash
,
8196 bgp_aggr_ecommunity_remove
);
8197 /* Free up the ecommunity_hash.
8199 hash_free(aggregate
->ecommunity_hash
);
8202 if (aggregate
->lcommunity
)
8203 lcommunity_free(&aggregate
->lcommunity
);
8205 if (aggregate
->lcommunity_hash
) {
8206 /* Delete all lcommunities in the hash.
8208 hash_clean(aggregate
->lcommunity_hash
,
8209 bgp_aggr_lcommunity_remove
);
8210 /* Free up the lcommunity_hash.
8212 hash_free(aggregate
->lcommunity_hash
);
8215 if (aggregate
->aspath
)
8216 aspath_free(aggregate
->aspath
);
8218 if (aggregate
->aspath_hash
) {
8219 /* Delete all as-paths in the hash.
8221 hash_clean(aggregate
->aspath_hash
,
8222 bgp_aggr_aspath_remove
);
8223 /* Free up the aspath_hash.
8225 hash_free(aggregate
->aspath_hash
);
8228 bgp_aggregate_free(aggregate
);
8229 bgp_dest_unlock_node(dest
);
8230 bgp_dest_unlock_node(dest
);
8235 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8236 safi_t safi
, const char *rmap
,
8237 uint8_t summary_only
, uint8_t as_set
,
8238 uint8_t origin
, bool match_med
,
8239 const char *suppress_map
)
8241 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8244 struct bgp_dest
*dest
;
8245 struct bgp_aggregate
*aggregate
;
8246 uint8_t as_set_new
= as_set
;
8248 if (suppress_map
&& summary_only
) {
8250 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8251 return CMD_WARNING_CONFIG_FAILED
;
8254 /* Convert string to prefix structure. */
8255 ret
= str2prefix(prefix_str
, &p
);
8257 vty_out(vty
, "Malformed prefix\n");
8258 return CMD_WARNING_CONFIG_FAILED
;
8262 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8263 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8264 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8266 return CMD_WARNING_CONFIG_FAILED
;
8269 /* Old configuration check. */
8270 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8271 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8274 vty_out(vty
, "There is already same aggregate network.\n");
8275 /* try to remove the old entry */
8276 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8278 vty_out(vty
, "Error deleting aggregate.\n");
8279 bgp_dest_unlock_node(dest
);
8280 return CMD_WARNING_CONFIG_FAILED
;
8284 /* Make aggregate address structure. */
8285 aggregate
= bgp_aggregate_new();
8286 aggregate
->summary_only
= summary_only
;
8287 aggregate
->match_med
= match_med
;
8289 /* Network operators MUST NOT locally generate any new
8290 * announcements containing AS_SET or AS_CONFED_SET. If they have
8291 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8292 * SHOULD withdraw those routes and re-announce routes for the
8293 * aggregate or component prefixes (i.e., the more-specific routes
8294 * subsumed by the previously aggregated route) without AS_SET
8295 * or AS_CONFED_SET in the updates.
8297 if (bgp
->reject_as_sets
) {
8298 if (as_set
== AGGREGATE_AS_SET
) {
8299 as_set_new
= AGGREGATE_AS_UNSET
;
8301 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8304 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8308 aggregate
->as_set
= as_set_new
;
8309 aggregate
->safi
= safi
;
8310 /* Override ORIGIN attribute if defined.
8311 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8312 * to IGP which is not what rfc4271 says.
8313 * This enables the same behavior, optionally.
8315 aggregate
->origin
= origin
;
8318 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8319 route_map_counter_decrement(aggregate
->rmap
.map
);
8320 aggregate
->rmap
.name
=
8321 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8322 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8323 route_map_counter_increment(aggregate
->rmap
.map
);
8327 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8328 route_map_counter_decrement(aggregate
->suppress_map
);
8330 aggregate
->suppress_map_name
=
8331 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8332 aggregate
->suppress_map
=
8333 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8334 route_map_counter_increment(aggregate
->suppress_map
);
8337 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8339 /* Aggregate address insert into BGP routing table. */
8340 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8345 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8346 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8348 "|summary-only$summary_only"
8349 "|route-map RMAP_NAME$rmap_name"
8350 "|origin <egp|igp|incomplete>$origin_s"
8351 "|matching-MED-only$match_med"
8352 "|suppress-map RMAP_NAME$suppress_map"
8355 "Configure BGP aggregate entries\n"
8356 "Aggregate prefix\n"
8357 "Aggregate address\n"
8359 "Generate AS set path information\n"
8360 "Filter more specific routes from updates\n"
8361 "Apply route map to aggregate network\n"
8366 "Unknown heritage\n"
8367 "Only aggregate routes with matching MED\n"
8368 "Suppress the selected more specific routes\n"
8369 "Route map with the route selectors\n")
8371 const char *prefix_s
= NULL
;
8372 safi_t safi
= bgp_node_safi(vty
);
8373 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8374 int as_set
= AGGREGATE_AS_UNSET
;
8375 char prefix_buf
[PREFIX2STR_BUFFER
];
8378 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8381 vty_out(vty
, "%% Inconsistent address and mask\n");
8382 return CMD_WARNING_CONFIG_FAILED
;
8384 prefix_s
= prefix_buf
;
8386 prefix_s
= prefix_str
;
8389 if (strcmp(origin_s
, "egp") == 0)
8390 origin
= BGP_ORIGIN_EGP
;
8391 else if (strcmp(origin_s
, "igp") == 0)
8392 origin
= BGP_ORIGIN_IGP
;
8393 else if (strcmp(origin_s
, "incomplete") == 0)
8394 origin
= BGP_ORIGIN_INCOMPLETE
;
8398 as_set
= AGGREGATE_AS_SET
;
8400 /* Handle configuration removal, otherwise installation. */
8402 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8404 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8405 summary_only
!= NULL
, as_set
, origin
,
8406 match_med
!= NULL
, suppress_map
);
8409 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8410 "[no] aggregate-address X:X::X:X/M$prefix [{"
8412 "|summary-only$summary_only"
8413 "|route-map RMAP_NAME$rmap_name"
8414 "|origin <egp|igp|incomplete>$origin_s"
8415 "|matching-MED-only$match_med"
8416 "|suppress-map RMAP_NAME$suppress_map"
8419 "Configure BGP aggregate entries\n"
8420 "Aggregate prefix\n"
8421 "Generate AS set path information\n"
8422 "Filter more specific routes from updates\n"
8423 "Apply route map to aggregate network\n"
8428 "Unknown heritage\n"
8429 "Only aggregate routes with matching MED\n"
8430 "Suppress the selected more specific routes\n"
8431 "Route map with the route selectors\n")
8433 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8434 int as_set
= AGGREGATE_AS_UNSET
;
8437 if (strcmp(origin_s
, "egp") == 0)
8438 origin
= BGP_ORIGIN_EGP
;
8439 else if (strcmp(origin_s
, "igp") == 0)
8440 origin
= BGP_ORIGIN_IGP
;
8441 else if (strcmp(origin_s
, "incomplete") == 0)
8442 origin
= BGP_ORIGIN_INCOMPLETE
;
8446 as_set
= AGGREGATE_AS_SET
;
8448 /* Handle configuration removal, otherwise installation. */
8450 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8453 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8454 rmap_name
, summary_only
!= NULL
, as_set
,
8455 origin
, match_med
!= NULL
, suppress_map
);
8458 /* Redistribute route treatment. */
8459 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8460 const union g_addr
*nexthop
, ifindex_t ifindex
,
8461 enum nexthop_types_t nhtype
, uint8_t distance
,
8462 enum blackhole_type bhtype
, uint32_t metric
,
8463 uint8_t type
, unsigned short instance
,
8466 struct bgp_path_info
*new;
8467 struct bgp_path_info
*bpi
;
8468 struct bgp_path_info rmap_path
;
8469 struct bgp_dest
*bn
;
8471 struct attr
*new_attr
;
8473 route_map_result_t ret
;
8474 struct bgp_redist
*red
;
8476 /* Make default attribute. */
8477 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8479 * This must not be NULL to satisfy Coverity SA
8481 assert(attr
.aspath
);
8484 case NEXTHOP_TYPE_IFINDEX
:
8485 switch (p
->family
) {
8487 attr
.nexthop
.s_addr
= INADDR_ANY
;
8488 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8491 memset(&attr
.mp_nexthop_global
, 0,
8492 sizeof(attr
.mp_nexthop_global
));
8493 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8497 case NEXTHOP_TYPE_IPV4
:
8498 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8499 attr
.nexthop
= nexthop
->ipv4
;
8500 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8502 case NEXTHOP_TYPE_IPV6
:
8503 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8504 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8505 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8507 case NEXTHOP_TYPE_BLACKHOLE
:
8508 switch (p
->family
) {
8510 attr
.nexthop
.s_addr
= INADDR_ANY
;
8511 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8514 memset(&attr
.mp_nexthop_global
, 0,
8515 sizeof(attr
.mp_nexthop_global
));
8516 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8519 attr
.bh_type
= bhtype
;
8522 attr
.nh_type
= nhtype
;
8523 attr
.nh_ifindex
= ifindex
;
8526 attr
.distance
= distance
;
8527 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8530 afi
= family2afi(p
->family
);
8532 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8534 struct attr attr_new
;
8536 /* Copy attribute for modification. */
8539 if (red
->redist_metric_flag
)
8540 attr_new
.med
= red
->redist_metric
;
8542 /* Apply route-map. */
8543 if (red
->rmap
.name
) {
8544 memset(&rmap_path
, 0, sizeof(rmap_path
));
8545 rmap_path
.peer
= bgp
->peer_self
;
8546 rmap_path
.attr
= &attr_new
;
8548 SET_FLAG(bgp
->peer_self
->rmap_type
,
8549 PEER_RMAP_TYPE_REDISTRIBUTE
);
8551 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8553 bgp
->peer_self
->rmap_type
= 0;
8555 if (ret
== RMAP_DENYMATCH
) {
8556 /* Free uninterned attribute. */
8557 bgp_attr_flush(&attr_new
);
8559 /* Unintern original. */
8560 aspath_unintern(&attr
.aspath
);
8561 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8566 if (bgp_in_graceful_shutdown(bgp
))
8567 bgp_attr_add_gshut_community(&attr_new
);
8569 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8570 SAFI_UNICAST
, p
, NULL
);
8572 new_attr
= bgp_attr_intern(&attr_new
);
8574 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8575 if (bpi
->peer
== bgp
->peer_self
8576 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8580 /* Ensure the (source route) type is updated. */
8582 if (attrhash_cmp(bpi
->attr
, new_attr
)
8583 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8584 bgp_attr_unintern(&new_attr
);
8585 aspath_unintern(&attr
.aspath
);
8586 bgp_dest_unlock_node(bn
);
8589 /* The attribute is changed. */
8590 bgp_path_info_set_flag(bn
, bpi
,
8591 BGP_PATH_ATTR_CHANGED
);
8593 /* Rewrite BGP route information. */
8594 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8595 bgp_path_info_restore(bn
, bpi
);
8597 bgp_aggregate_decrement(
8598 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8599 bgp_attr_unintern(&bpi
->attr
);
8600 bpi
->attr
= new_attr
;
8601 bpi
->uptime
= monotime(NULL
);
8603 /* Process change. */
8604 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8606 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8607 bgp_dest_unlock_node(bn
);
8608 aspath_unintern(&attr
.aspath
);
8610 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8612 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8614 vpn_leak_from_vrf_update(
8615 bgp_get_default(), bgp
, bpi
);
8621 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8622 bgp
->peer_self
, new_attr
, bn
);
8623 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8625 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8626 bgp_path_info_add(bn
, new);
8627 bgp_dest_unlock_node(bn
);
8628 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8629 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8631 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8632 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8634 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8638 /* Unintern original. */
8639 aspath_unintern(&attr
.aspath
);
8642 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8643 unsigned short instance
)
8646 struct bgp_dest
*dest
;
8647 struct bgp_path_info
*pi
;
8648 struct bgp_redist
*red
;
8650 afi
= family2afi(p
->family
);
8652 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8654 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8655 SAFI_UNICAST
, p
, NULL
);
8657 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8658 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8662 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8663 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8665 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8668 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8669 bgp_path_info_delete(dest
, pi
);
8670 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8672 bgp_dest_unlock_node(dest
);
8676 /* Withdraw specified route type's route. */
8677 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8678 unsigned short instance
)
8680 struct bgp_dest
*dest
;
8681 struct bgp_path_info
*pi
;
8682 struct bgp_table
*table
;
8684 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8686 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8687 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8688 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8689 && pi
->instance
== instance
)
8693 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8694 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8696 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8699 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8700 pi
, afi
, SAFI_UNICAST
);
8701 bgp_path_info_delete(dest
, pi
);
8702 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8707 /* Static function to display route. */
8708 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8709 struct vty
*vty
, json_object
*json
, bool wide
)
8714 if (p
->family
== AF_INET
) {
8716 len
= vty_out(vty
, "%pFX", p
);
8718 json_object_string_add(json
, "prefix",
8719 inet_ntop(p
->family
,
8722 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8723 json_object_string_addf(json
, "network", "%pFX", p
);
8724 json_object_int_add(json
, "version", dest
->version
);
8726 } else if (p
->family
== AF_ETHERNET
) {
8727 len
= vty_out(vty
, "%pFX", p
);
8728 } else if (p
->family
== AF_EVPN
) {
8730 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8732 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8733 } else if (p
->family
== AF_FLOWSPEC
) {
8734 route_vty_out_flowspec(vty
, p
, NULL
,
8736 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8737 NLRI_STRING_FORMAT_MIN
, json
);
8740 len
= vty_out(vty
, "%pFX", p
);
8742 json_object_string_add(json
, "prefix",
8743 inet_ntop(p
->family
,
8746 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8747 json_object_string_addf(json
, "network", "%pFX", p
);
8748 json_object_int_add(json
, "version", dest
->version
);
8753 len
= wide
? (45 - len
) : (17 - len
);
8755 vty_out(vty
, "\n%*s", 20, " ");
8757 vty_out(vty
, "%*s", len
, " ");
8761 enum bgp_display_type
{
8765 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8768 case bgp_path_selection_none
:
8769 return "Nothing to Select";
8770 case bgp_path_selection_first
:
8771 return "First path received";
8772 case bgp_path_selection_evpn_sticky_mac
:
8773 return "EVPN Sticky Mac";
8774 case bgp_path_selection_evpn_seq
:
8775 return "EVPN sequence number";
8776 case bgp_path_selection_evpn_lower_ip
:
8777 return "EVPN lower IP";
8778 case bgp_path_selection_evpn_local_path
:
8779 return "EVPN local ES path";
8780 case bgp_path_selection_evpn_non_proxy
:
8781 return "EVPN non proxy";
8782 case bgp_path_selection_weight
:
8784 case bgp_path_selection_local_pref
:
8785 return "Local Pref";
8786 case bgp_path_selection_local_route
:
8787 return "Local Route";
8788 case bgp_path_selection_confed_as_path
:
8789 return "Confederation based AS Path";
8790 case bgp_path_selection_as_path
:
8792 case bgp_path_selection_origin
:
8794 case bgp_path_selection_med
:
8796 case bgp_path_selection_peer
:
8798 case bgp_path_selection_confed
:
8799 return "Confed Peer Type";
8800 case bgp_path_selection_igp_metric
:
8801 return "IGP Metric";
8802 case bgp_path_selection_older
:
8803 return "Older Path";
8804 case bgp_path_selection_router_id
:
8806 case bgp_path_selection_cluster_length
:
8807 return "Cluster length";
8808 case bgp_path_selection_stale
:
8809 return "Path Staleness";
8810 case bgp_path_selection_local_configured
:
8811 return "Locally configured route";
8812 case bgp_path_selection_neighbor_ip
:
8813 return "Neighbor IP";
8814 case bgp_path_selection_default
:
8815 return "Nothing left to compare";
8817 return "Invalid (internal error)";
8820 /* Print the short form route status for a bgp_path_info */
8821 static void route_vty_short_status_out(struct vty
*vty
,
8822 struct bgp_path_info
*path
,
8823 const struct prefix
*p
,
8824 json_object
*json_path
)
8826 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8830 /* Route status display. */
8831 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8832 json_object_boolean_true_add(json_path
, "removed");
8834 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8835 json_object_boolean_true_add(json_path
, "stale");
8837 if (path
->extra
&& bgp_path_suppressed(path
))
8838 json_object_boolean_true_add(json_path
, "suppressed");
8840 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8841 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8842 json_object_boolean_true_add(json_path
, "valid");
8845 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8846 json_object_boolean_true_add(json_path
, "history");
8848 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8849 json_object_boolean_true_add(json_path
, "damped");
8851 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8852 json_object_boolean_true_add(json_path
, "bestpath");
8853 json_object_string_add(json_path
, "selectionReason",
8854 bgp_path_selection_reason2str(
8855 path
->net
->reason
));
8858 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8859 json_object_boolean_true_add(json_path
, "multipath");
8861 /* Internal route. */
8862 if ((path
->peer
->as
)
8863 && (path
->peer
->as
== path
->peer
->local_as
))
8864 json_object_string_add(json_path
, "pathFrom",
8867 json_object_string_add(json_path
, "pathFrom",
8873 /* RPKI validation state */
8875 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
8877 if (rpki_state
== RPKI_VALID
)
8879 else if (rpki_state
== RPKI_INVALID
)
8881 else if (rpki_state
== RPKI_NOTFOUND
)
8884 /* Route status display. */
8885 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8887 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8889 else if (bgp_path_suppressed(path
))
8891 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8892 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8898 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8900 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8902 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8904 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8909 /* Internal route. */
8910 if (path
->peer
&& (path
->peer
->as
)
8911 && (path
->peer
->as
== path
->peer
->local_as
))
8917 static char *bgp_nexthop_hostname(struct peer
*peer
,
8918 struct bgp_nexthop_cache
*bnc
)
8921 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8922 return peer
->hostname
;
8926 /* called from terminal list command */
8927 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8928 struct bgp_path_info
*path
, int display
, safi_t safi
,
8929 json_object
*json_paths
, bool wide
)
8932 struct attr
*attr
= path
->attr
;
8933 json_object
*json_path
= NULL
;
8934 json_object
*json_nexthops
= NULL
;
8935 json_object
*json_nexthop_global
= NULL
;
8936 json_object
*json_nexthop_ll
= NULL
;
8937 json_object
*json_ext_community
= NULL
;
8938 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8940 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8941 bool nexthop_othervrf
= false;
8942 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8943 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8944 char *nexthop_hostname
=
8945 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8946 char esi_buf
[ESI_STR_LEN
];
8949 json_path
= json_object_new_object();
8951 /* short status lead text */
8952 route_vty_short_status_out(vty
, path
, p
, json_path
);
8955 /* print prefix and mask */
8957 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8959 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8961 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8965 * If vrf id of nexthop is different from that of prefix,
8966 * set up printable string to append
8968 if (path
->extra
&& path
->extra
->bgp_orig
) {
8969 const char *self
= "";
8974 nexthop_othervrf
= true;
8975 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8977 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8978 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8979 "@%s%s", VRFID_NONE_STR
, self
);
8981 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8982 path
->extra
->bgp_orig
->vrf_id
, self
);
8984 if (path
->extra
->bgp_orig
->inst_type
8985 != BGP_INSTANCE_TYPE_DEFAULT
)
8987 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8989 const char *self
= "";
8994 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8998 * For ENCAP and EVPN routes, nexthop address family is not
8999 * neccessarily the same as the prefix address family.
9000 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9001 * EVPN routes are also exchanged with a MP nexthop. Currently,
9003 * is only IPv4, the value will be present in either
9005 * attr->mp_nexthop_global_in
9007 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9010 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9014 snprintf(nexthop
, sizeof(nexthop
), "%s",
9015 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
9019 snprintf(nexthop
, sizeof(nexthop
), "%s",
9020 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
9024 snprintf(nexthop
, sizeof(nexthop
), "?");
9029 json_nexthop_global
= json_object_new_object();
9031 json_object_string_add(json_nexthop_global
, "ip",
9034 if (path
->peer
->hostname
)
9035 json_object_string_add(json_nexthop_global
,
9037 path
->peer
->hostname
);
9039 json_object_string_add(json_nexthop_global
, "afi",
9040 (af
== AF_INET
) ? "ipv4"
9042 json_object_boolean_true_add(json_nexthop_global
,
9045 if (nexthop_hostname
)
9046 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9047 nexthop_hostname
, vrf_id_str
);
9049 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9051 len
= wide
? (41 - len
) : (16 - len
);
9053 vty_out(vty
, "\n%*s", 36, " ");
9055 vty_out(vty
, "%*s", len
, " ");
9057 } else if (safi
== SAFI_EVPN
) {
9059 json_nexthop_global
= json_object_new_object();
9061 json_object_string_addf(json_nexthop_global
, "ip",
9063 &attr
->mp_nexthop_global_in
);
9065 if (path
->peer
->hostname
)
9066 json_object_string_add(json_nexthop_global
,
9068 path
->peer
->hostname
);
9070 json_object_string_add(json_nexthop_global
, "afi",
9072 json_object_boolean_true_add(json_nexthop_global
,
9075 if (nexthop_hostname
)
9076 len
= vty_out(vty
, "%pI4(%s)%s",
9077 &attr
->mp_nexthop_global_in
,
9078 nexthop_hostname
, vrf_id_str
);
9080 len
= vty_out(vty
, "%pI4%s",
9081 &attr
->mp_nexthop_global_in
,
9084 len
= wide
? (41 - len
) : (16 - len
);
9086 vty_out(vty
, "\n%*s", 36, " ");
9088 vty_out(vty
, "%*s", len
, " ");
9090 } else if (safi
== SAFI_FLOWSPEC
) {
9091 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9093 json_nexthop_global
= json_object_new_object();
9095 json_object_string_add(json_nexthop_global
,
9097 json_object_string_addf(json_nexthop_global
,
9101 if (path
->peer
->hostname
)
9102 json_object_string_add(
9103 json_nexthop_global
, "hostname",
9104 path
->peer
->hostname
);
9106 json_object_boolean_true_add(
9107 json_nexthop_global
,
9110 if (nexthop_hostname
)
9111 len
= vty_out(vty
, "%pI4(%s)%s",
9116 len
= vty_out(vty
, "%pI4%s",
9120 len
= wide
? (41 - len
) : (16 - len
);
9122 vty_out(vty
, "\n%*s", 36, " ");
9124 vty_out(vty
, "%*s", len
, " ");
9127 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9129 json_nexthop_global
= json_object_new_object();
9131 json_object_string_addf(json_nexthop_global
, "ip",
9132 "%pI4", &attr
->nexthop
);
9134 if (path
->peer
->hostname
)
9135 json_object_string_add(json_nexthop_global
,
9137 path
->peer
->hostname
);
9139 json_object_string_add(json_nexthop_global
, "afi",
9141 json_object_boolean_true_add(json_nexthop_global
,
9144 if (nexthop_hostname
)
9145 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9146 nexthop_hostname
, vrf_id_str
);
9148 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9151 len
= wide
? (41 - len
) : (16 - len
);
9153 vty_out(vty
, "\n%*s", 36, " ");
9155 vty_out(vty
, "%*s", len
, " ");
9160 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9162 json_nexthop_global
= json_object_new_object();
9163 json_object_string_addf(json_nexthop_global
, "ip",
9165 &attr
->mp_nexthop_global
);
9167 if (path
->peer
->hostname
)
9168 json_object_string_add(json_nexthop_global
,
9170 path
->peer
->hostname
);
9172 json_object_string_add(json_nexthop_global
, "afi",
9174 json_object_string_add(json_nexthop_global
, "scope",
9177 /* We display both LL & GL if both have been
9179 if ((attr
->mp_nexthop_len
9180 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9181 || (path
->peer
->conf_if
)) {
9182 json_nexthop_ll
= json_object_new_object();
9183 json_object_string_addf(
9184 json_nexthop_ll
, "ip", "%pI6",
9185 &attr
->mp_nexthop_local
);
9187 if (path
->peer
->hostname
)
9188 json_object_string_add(
9189 json_nexthop_ll
, "hostname",
9190 path
->peer
->hostname
);
9192 json_object_string_add(json_nexthop_ll
, "afi",
9194 json_object_string_add(json_nexthop_ll
, "scope",
9197 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9198 &attr
->mp_nexthop_local
)
9200 && !attr
->mp_nexthop_prefer_global
)
9201 json_object_boolean_true_add(
9202 json_nexthop_ll
, "used");
9204 json_object_boolean_true_add(
9205 json_nexthop_global
, "used");
9207 json_object_boolean_true_add(
9208 json_nexthop_global
, "used");
9210 /* Display LL if LL/Global both in table unless
9211 * prefer-global is set */
9212 if (((attr
->mp_nexthop_len
9213 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9214 && !attr
->mp_nexthop_prefer_global
)
9215 || (path
->peer
->conf_if
)) {
9216 if (path
->peer
->conf_if
) {
9217 len
= vty_out(vty
, "%s",
9218 path
->peer
->conf_if
);
9219 /* len of IPv6 addr + max len of def
9221 len
= wide
? (41 - len
) : (16 - len
);
9224 vty_out(vty
, "\n%*s", 36, " ");
9226 vty_out(vty
, "%*s", len
, " ");
9228 if (nexthop_hostname
)
9231 &attr
->mp_nexthop_local
,
9237 &attr
->mp_nexthop_local
,
9240 len
= wide
? (41 - len
) : (16 - len
);
9243 vty_out(vty
, "\n%*s", 36, " ");
9245 vty_out(vty
, "%*s", len
, " ");
9248 if (nexthop_hostname
)
9249 len
= vty_out(vty
, "%pI6(%s)%s",
9250 &attr
->mp_nexthop_global
,
9254 len
= vty_out(vty
, "%pI6%s",
9255 &attr
->mp_nexthop_global
,
9258 len
= wide
? (41 - len
) : (16 - len
);
9261 vty_out(vty
, "\n%*s", 36, " ");
9263 vty_out(vty
, "%*s", len
, " ");
9269 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9271 json_object_int_add(json_path
, "metric", attr
->med
);
9273 vty_out(vty
, "%7u", attr
->med
);
9275 vty_out(vty
, "%10u", attr
->med
);
9276 else if (!json_paths
) {
9278 vty_out(vty
, "%*s", 7, " ");
9280 vty_out(vty
, "%*s", 10, " ");
9284 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9286 json_object_int_add(json_path
, "locPrf",
9289 vty_out(vty
, "%7u", attr
->local_pref
);
9290 else if (!json_paths
)
9294 json_object_int_add(json_path
, "weight", attr
->weight
);
9296 vty_out(vty
, "%7u ", attr
->weight
);
9299 json_object_string_addf(json_path
, "peerId", "%pSU",
9305 json_object_string_add(json_path
, "path",
9308 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9313 json_object_string_add(json_path
, "origin",
9314 bgp_origin_long_str
[attr
->origin
]);
9316 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9319 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9320 json_object_string_add(json_path
, "esi",
9321 esi_to_str(&attr
->esi
,
9322 esi_buf
, sizeof(esi_buf
)));
9324 if (safi
== SAFI_EVPN
&&
9325 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9326 json_ext_community
= json_object_new_object();
9327 json_object_string_add(
9328 json_ext_community
, "string",
9329 bgp_attr_get_ecommunity(attr
)->str
);
9330 json_object_object_add(json_path
,
9331 "extendedCommunity",
9332 json_ext_community
);
9336 json_object_boolean_true_add(json_path
,
9337 "announceNexthopSelf");
9338 if (nexthop_othervrf
) {
9339 json_object_string_add(json_path
, "nhVrfName",
9342 json_object_int_add(json_path
, "nhVrfId",
9343 ((nexthop_vrfid
== VRF_UNKNOWN
)
9345 : (int)nexthop_vrfid
));
9350 if (json_nexthop_global
|| json_nexthop_ll
) {
9351 json_nexthops
= json_object_new_array();
9353 if (json_nexthop_global
)
9354 json_object_array_add(json_nexthops
,
9355 json_nexthop_global
);
9357 if (json_nexthop_ll
)
9358 json_object_array_add(json_nexthops
,
9361 json_object_object_add(json_path
, "nexthops",
9365 json_object_array_add(json_paths
, json_path
);
9369 if (safi
== SAFI_EVPN
) {
9370 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9371 /* XXX - add these params to the json out */
9372 vty_out(vty
, "%*s", 20, " ");
9373 vty_out(vty
, "ESI:%s",
9374 esi_to_str(&attr
->esi
, esi_buf
,
9380 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9381 vty_out(vty
, "%*s", 20, " ");
9382 vty_out(vty
, "%s\n",
9383 bgp_attr_get_ecommunity(attr
)->str
);
9387 #ifdef ENABLE_BGP_VNC
9388 /* prints an additional line, indented, with VNC info, if
9390 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9391 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9396 /* called from terminal list command */
9397 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9398 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9399 bool use_json
, json_object
*json_ar
, bool wide
)
9401 json_object
*json_status
= NULL
;
9402 json_object
*json_net
= NULL
;
9406 /* Route status display. */
9408 json_status
= json_object_new_object();
9409 json_net
= json_object_new_object();
9416 /* print prefix and mask */
9418 if (safi
== SAFI_EVPN
)
9419 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9420 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9421 json_object_string_add(
9422 json_net
, "addrPrefix",
9423 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9425 json_object_int_add(json_net
, "prefixLen",
9427 json_object_string_addf(json_net
, "network", "%pFX", p
);
9430 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9432 /* Print attribute */
9435 if (p
->family
== AF_INET
&&
9436 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9437 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9438 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9439 json_object_string_addf(
9440 json_net
, "nextHop", "%pI4",
9441 &attr
->mp_nexthop_global_in
);
9443 json_object_string_addf(
9444 json_net
, "nextHop", "%pI4",
9446 } else if (p
->family
== AF_INET6
||
9447 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9448 json_object_string_addf(
9449 json_net
, "nextHopGlobal", "%pI6",
9450 &attr
->mp_nexthop_global
);
9451 } else if (p
->family
== AF_EVPN
&&
9452 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9453 json_object_string_addf(
9454 json_net
, "nextHop", "%pI4",
9455 &attr
->mp_nexthop_global_in
);
9459 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9460 json_object_int_add(json_net
, "metric",
9463 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9464 json_object_int_add(json_net
, "locPrf",
9467 json_object_int_add(json_net
, "weight", attr
->weight
);
9471 json_object_string_add(json_net
, "path",
9475 json_object_string_add(json_net
, "bgpOriginCode",
9476 bgp_origin_str
[attr
->origin
]);
9478 if (p
->family
== AF_INET
&&
9479 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9480 safi
== SAFI_EVPN
||
9481 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9482 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9483 || safi
== SAFI_EVPN
)
9484 vty_out(vty
, "%-16pI4",
9485 &attr
->mp_nexthop_global_in
);
9487 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9489 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9490 } else if (p
->family
== AF_INET6
||
9491 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9497 &attr
->mp_nexthop_global
, buf
,
9499 len
= wide
? (41 - len
) : (16 - len
);
9501 vty_out(vty
, "\n%*s", 36, " ");
9503 vty_out(vty
, "%*s", len
, " ");
9506 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9508 vty_out(vty
, "%7u", attr
->med
);
9510 vty_out(vty
, "%10u", attr
->med
);
9516 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9517 vty_out(vty
, "%7u", attr
->local_pref
);
9521 vty_out(vty
, "%7u ", attr
->weight
);
9525 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9528 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9532 json_object_boolean_true_add(json_status
, "*");
9533 json_object_boolean_true_add(json_status
, ">");
9534 json_object_object_add(json_net
, "appliedStatusSymbols",
9536 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9541 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9542 struct bgp_path_info
*path
, int display
, safi_t safi
,
9545 json_object
*json_out
= NULL
;
9547 mpls_label_t label
= MPLS_INVALID_LABEL
;
9553 json_out
= json_object_new_object();
9555 /* short status lead text */
9556 route_vty_short_status_out(vty
, path
, p
, json_out
);
9558 /* print prefix and mask */
9561 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9563 vty_out(vty
, "%*s", 17, " ");
9566 /* Print attribute */
9568 if (((p
->family
== AF_INET
) &&
9569 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9570 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9571 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9572 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9573 || safi
== SAFI_EVPN
) {
9575 json_object_string_addf(
9576 json_out
, "mpNexthopGlobalIn", "%pI4",
9577 &attr
->mp_nexthop_global_in
);
9579 vty_out(vty
, "%-16pI4",
9580 &attr
->mp_nexthop_global_in
);
9583 json_object_string_addf(json_out
, "nexthop",
9584 "%pI4", &attr
->nexthop
);
9586 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9588 } else if (((p
->family
== AF_INET6
) &&
9589 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9590 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9591 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9594 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9596 json_object_string_addf(
9597 json_out
, "mpNexthopGlobalIn", "%pI6",
9598 &attr
->mp_nexthop_global
);
9602 &attr
->mp_nexthop_global
,
9603 buf_a
, sizeof(buf_a
)));
9604 } else if (attr
->mp_nexthop_len
9605 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9606 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9607 &attr
->mp_nexthop_global
,
9608 &attr
->mp_nexthop_local
);
9610 json_object_string_add(json_out
,
9611 "mpNexthopGlobalLocal",
9614 vty_out(vty
, "%s", buf_a
);
9618 label
= decode_label(&path
->extra
->label
[0]);
9620 if (bgp_is_valid_label(&label
)) {
9622 json_object_int_add(json_out
, "notag", label
);
9623 json_object_array_add(json
, json_out
);
9625 vty_out(vty
, "notag/%d", label
);
9632 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9633 struct bgp_path_info
*path
, int display
,
9634 json_object
*json_paths
)
9637 json_object
*json_path
= NULL
;
9638 json_object
*json_nexthop
= NULL
;
9639 json_object
*json_overlay
= NULL
;
9645 json_path
= json_object_new_object();
9646 json_overlay
= json_object_new_object();
9647 json_nexthop
= json_object_new_object();
9650 /* short status lead text */
9651 route_vty_short_status_out(vty
, path
, p
, json_path
);
9653 /* print prefix and mask */
9655 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9657 vty_out(vty
, "%*s", 17, " ");
9659 /* Print attribute */
9661 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9666 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9668 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9669 &attr
->mp_nexthop_global_in
);
9671 json_object_string_add(json_nexthop
, "afi", "ipv4");
9673 json_object_object_add(json_path
, "nexthop",
9679 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9680 &attr
->mp_nexthop_local
);
9682 json_object_string_addf(json_nexthop
, "ipv6Global",
9684 &attr
->mp_nexthop_global
);
9686 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9688 &attr
->mp_nexthop_local
);
9690 json_object_string_add(json_nexthop
, "afi", "ipv6");
9692 json_object_object_add(json_path
, "nexthop",
9700 json_object_string_add(json_nexthop
, "Error",
9701 "Unsupported address-family");
9702 json_object_string_add(json_nexthop
, "error",
9703 "Unsupported address-family");
9707 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9710 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9712 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9714 if (bgp_attr_get_ecommunity(attr
)) {
9716 struct ecommunity_val
*routermac
= ecommunity_lookup(
9717 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9718 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9721 mac
= ecom_mac2str((char *)routermac
->val
);
9724 vty_out(vty
, "/%s", mac
);
9726 json_object_string_add(json_overlay
, "rmac",
9729 XFREE(MTYPE_TMP
, mac
);
9736 json_object_object_add(json_path
, "overlay", json_overlay
);
9738 json_object_array_add(json_paths
, json_path
);
9742 /* dampening route */
9743 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9744 struct bgp_path_info
*path
, int display
,
9745 afi_t afi
, safi_t safi
, bool use_json
,
9746 json_object
*json_paths
)
9748 struct attr
*attr
= path
->attr
;
9750 char timebuf
[BGP_UPTIME_LEN
];
9751 json_object
*json_path
= NULL
;
9754 json_path
= json_object_new_object();
9756 /* short status lead text */
9757 route_vty_short_status_out(vty
, path
, p
, json_path
);
9759 /* print prefix and mask */
9762 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9764 vty_out(vty
, "%*s", 17, " ");
9766 len
= vty_out(vty
, "%s", path
->peer
->host
);
9770 vty_out(vty
, "\n%*s", 34, " ");
9772 vty_out(vty
, "%*s", len
, " ");
9775 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9776 BGP_UPTIME_LEN
, afi
, safi
,
9780 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9782 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9786 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9787 safi
, use_json
, json_path
);
9790 json_object_string_add(json_path
, "asPath",
9793 json_object_string_add(json_path
, "origin",
9794 bgp_origin_str
[attr
->origin
]);
9795 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9797 json_object_array_add(json_paths
, json_path
);
9802 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9803 struct bgp_path_info
*path
, int display
,
9804 afi_t afi
, safi_t safi
, bool use_json
,
9805 json_object
*json_paths
)
9807 struct attr
*attr
= path
->attr
;
9808 struct bgp_damp_info
*bdi
;
9809 char timebuf
[BGP_UPTIME_LEN
];
9811 json_object
*json_path
= NULL
;
9817 json_path
= json_object_new_object();
9819 bdi
= path
->extra
->damp_info
;
9821 /* short status lead text */
9822 route_vty_short_status_out(vty
, path
, p
, json_path
);
9826 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9828 vty_out(vty
, "%*s", 17, " ");
9830 len
= vty_out(vty
, "%s", path
->peer
->host
);
9833 vty_out(vty
, "\n%*s", 33, " ");
9835 vty_out(vty
, "%*s", len
, " ");
9837 len
= vty_out(vty
, "%d", bdi
->flap
);
9842 vty_out(vty
, "%*s", len
, " ");
9844 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9845 BGP_UPTIME_LEN
, 0, NULL
));
9847 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9848 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9850 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9851 BGP_UPTIME_LEN
, afi
,
9852 safi
, use_json
, NULL
));
9854 vty_out(vty
, "%*s ", 8, " ");
9857 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9859 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9863 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9864 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
9866 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9869 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9870 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9871 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9872 BGP_UPTIME_LEN
, afi
, safi
,
9873 use_json
, json_path
);
9876 json_object_string_add(json_path
, "asPath",
9879 json_object_string_add(json_path
, "origin",
9880 bgp_origin_str
[attr
->origin
]);
9882 json_object_array_add(json_paths
, json_path
);
9886 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9887 int *first
, const char *header
,
9888 json_object
*json_adv_to
)
9890 json_object
*json_peer
= NULL
;
9893 /* 'advertised-to' is a dictionary of peers we have advertised
9895 * prefix too. The key is the peer's IP or swpX, the value is
9897 * hostname if we know it and "" if not.
9899 json_peer
= json_object_new_object();
9902 json_object_string_add(json_peer
, "hostname",
9906 json_object_object_add(json_adv_to
, peer
->conf_if
,
9909 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
9913 vty_out(vty
, "%s", header
);
9918 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9920 vty_out(vty
, " %s(%s)", peer
->hostname
,
9923 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
9927 vty_out(vty
, " %s", peer
->conf_if
);
9929 vty_out(vty
, " %pSU", &peer
->su
);
9934 static void route_vty_out_tx_ids(struct vty
*vty
,
9935 struct bgp_addpath_info_data
*d
)
9939 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9940 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9941 d
->addpath_tx_id
[i
],
9942 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9946 static void route_vty_out_detail_es_info(struct vty
*vty
,
9947 struct bgp_path_info
*pi
,
9949 json_object
*json_path
)
9951 char esi_buf
[ESI_STR_LEN
];
9952 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9953 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9954 ATTR_ES_PEER_ROUTER
);
9955 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9956 ATTR_ES_PEER_ACTIVE
);
9957 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9958 ATTR_ES_PEER_PROXY
);
9959 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9961 json_object
*json_es_info
= NULL
;
9963 json_object_string_add(
9966 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9967 json_es_info
= json_object_new_object();
9969 json_object_boolean_true_add(
9970 json_es_info
, "localEs");
9972 json_object_boolean_true_add(
9973 json_es_info
, "peerActive");
9975 json_object_boolean_true_add(
9976 json_es_info
, "peerProxy");
9978 json_object_boolean_true_add(
9979 json_es_info
, "peerRouter");
9980 if (attr
->mm_sync_seqnum
)
9981 json_object_int_add(
9982 json_es_info
, "peerSeq",
9983 attr
->mm_sync_seqnum
);
9984 json_object_object_add(
9985 json_path
, "es_info",
9989 if (bgp_evpn_attr_is_sync(attr
))
9991 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9993 es_local
? "local-es":"",
9994 peer_proxy
? "proxy " : "",
9995 peer_active
? "active ":"",
9996 peer_router
? "router ":"",
9997 attr
->mm_sync_seqnum
);
9999 vty_out(vty
, " ESI %s %s\n",
10001 es_local
? "local-es":"");
10005 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10006 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
10007 enum rpki_states rpki_curr_state
,
10008 json_object
*json_paths
)
10010 char buf
[INET6_ADDRSTRLEN
];
10012 struct attr
*attr
= path
->attr
;
10014 json_object
*json_bestpath
= NULL
;
10015 json_object
*json_cluster_list
= NULL
;
10016 json_object
*json_cluster_list_list
= NULL
;
10017 json_object
*json_ext_community
= NULL
;
10018 json_object
*json_last_update
= NULL
;
10019 json_object
*json_pmsi
= NULL
;
10020 json_object
*json_nexthop_global
= NULL
;
10021 json_object
*json_nexthop_ll
= NULL
;
10022 json_object
*json_nexthops
= NULL
;
10023 json_object
*json_path
= NULL
;
10024 json_object
*json_peer
= NULL
;
10025 json_object
*json_string
= NULL
;
10026 json_object
*json_adv_to
= NULL
;
10028 struct listnode
*node
, *nnode
;
10030 bool addpath_capable
;
10032 unsigned int first_as
;
10033 bool nexthop_self
=
10034 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10036 char *nexthop_hostname
=
10037 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10041 mpls_label_t label
= MPLS_INVALID_LABEL
;
10044 json_path
= json_object_new_object();
10045 json_peer
= json_object_new_object();
10046 json_nexthop_global
= json_object_new_object();
10049 if (safi
== SAFI_EVPN
) {
10051 vty_out(vty
, " Route %pRN", bn
);
10058 if (path
->extra
&& path
->extra
->num_labels
) {
10059 bgp_evpn_label2str(path
->extra
->label
,
10060 path
->extra
->num_labels
, tag_buf
,
10063 if (safi
== SAFI_EVPN
) {
10065 if (tag_buf
[0] != '\0')
10066 vty_out(vty
, " VNI %s", tag_buf
);
10069 json_object_string_add(json_path
, "VNI",
10071 json_object_string_add(json_path
, "vni",
10077 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10078 struct bgp_path_info
*parent_ri
;
10079 struct bgp_dest
*dest
, *pdest
;
10081 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10082 dest
= parent_ri
->net
;
10083 if (dest
&& dest
->pdest
) {
10084 pdest
= dest
->pdest
;
10085 if (is_pi_family_evpn(parent_ri
)) {
10087 " Imported from %pRD:%pFX, VNI %s",
10088 (struct prefix_rd
*)
10089 bgp_dest_get_prefix(
10091 (struct prefix_evpn
*)
10092 bgp_dest_get_prefix(
10095 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
10096 vty_out(vty
, ", L3NHG %s",
10098 & ATTR_ES_L3_NHG_ACTIVE
)
10101 vty_out(vty
, "\n");
10105 " Imported from %pRD:%pFX\n",
10106 (struct prefix_rd
*)
10107 bgp_dest_get_prefix(
10109 (struct prefix_evpn
*)
10110 bgp_dest_get_prefix(
10116 if (safi
== SAFI_EVPN
10117 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10118 char gwip_buf
[INET6_ADDRSTRLEN
];
10120 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10124 json_object_string_add(json_path
, "gatewayIP",
10127 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10130 if (safi
== SAFI_EVPN
&& !json_path
)
10131 vty_out(vty
, "\n");
10133 /* Line1 display AS-path, Aggregator */
10134 if (attr
->aspath
) {
10136 if (!attr
->aspath
->json
)
10137 aspath_str_update(attr
->aspath
, true);
10138 json_object_lock(attr
->aspath
->json
);
10139 json_object_object_add(json_path
, "aspath",
10140 attr
->aspath
->json
);
10142 if (attr
->aspath
->segments
)
10143 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
10145 vty_out(vty
, " Local");
10149 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10151 json_object_boolean_true_add(json_path
, "removed");
10153 vty_out(vty
, ", (removed)");
10156 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10158 json_object_boolean_true_add(json_path
, "stale");
10160 vty_out(vty
, ", (stale)");
10163 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10165 json_object_int_add(json_path
, "aggregatorAs",
10166 attr
->aggregator_as
);
10167 json_object_string_addf(json_path
, "aggregatorId",
10168 "%pI4", &attr
->aggregator_addr
);
10170 vty_out(vty
, ", (aggregated by %u %pI4)",
10171 attr
->aggregator_as
, &attr
->aggregator_addr
);
10175 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10176 PEER_FLAG_REFLECTOR_CLIENT
)) {
10178 json_object_boolean_true_add(json_path
,
10179 "rxedFromRrClient");
10181 vty_out(vty
, ", (Received from a RR-client)");
10184 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10185 PEER_FLAG_RSERVER_CLIENT
)) {
10187 json_object_boolean_true_add(json_path
,
10188 "rxedFromRsClient");
10190 vty_out(vty
, ", (Received from a RS-client)");
10193 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10195 json_object_boolean_true_add(json_path
,
10196 "dampeningHistoryEntry");
10198 vty_out(vty
, ", (history entry)");
10199 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10201 json_object_boolean_true_add(json_path
,
10202 "dampeningSuppressed");
10204 vty_out(vty
, ", (suppressed due to dampening)");
10208 vty_out(vty
, "\n");
10210 /* Line2 display Next-hop, Neighbor, Router-id */
10211 /* Display the nexthop */
10212 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
10214 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
||
10215 bn_p
->family
== AF_EVPN
) &&
10216 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10217 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10218 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10219 || safi
== SAFI_EVPN
) {
10221 json_object_string_addf(
10222 json_nexthop_global
, "ip", "%pI4",
10223 &attr
->mp_nexthop_global_in
);
10225 if (path
->peer
->hostname
)
10226 json_object_string_add(
10227 json_nexthop_global
, "hostname",
10228 path
->peer
->hostname
);
10230 if (nexthop_hostname
)
10231 vty_out(vty
, " %pI4(%s)",
10232 &attr
->mp_nexthop_global_in
,
10235 vty_out(vty
, " %pI4",
10236 &attr
->mp_nexthop_global_in
);
10240 json_object_string_addf(json_nexthop_global
,
10244 if (path
->peer
->hostname
)
10245 json_object_string_add(
10246 json_nexthop_global
, "hostname",
10247 path
->peer
->hostname
);
10249 if (nexthop_hostname
)
10250 vty_out(vty
, " %pI4(%s)",
10254 vty_out(vty
, " %pI4",
10260 json_object_string_add(json_nexthop_global
, "afi",
10264 json_object_string_addf(json_nexthop_global
, "ip",
10266 &attr
->mp_nexthop_global
);
10268 if (path
->peer
->hostname
)
10269 json_object_string_add(json_nexthop_global
,
10271 path
->peer
->hostname
);
10273 json_object_string_add(json_nexthop_global
, "afi",
10275 json_object_string_add(json_nexthop_global
, "scope",
10278 if (nexthop_hostname
)
10279 vty_out(vty
, " %pI6(%s)",
10280 &attr
->mp_nexthop_global
,
10283 vty_out(vty
, " %pI6",
10284 &attr
->mp_nexthop_global
);
10288 /* Display the IGP cost or 'inaccessible' */
10289 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10291 json_object_boolean_false_add(json_nexthop_global
,
10294 vty_out(vty
, " (inaccessible)");
10296 if (path
->extra
&& path
->extra
->igpmetric
) {
10298 json_object_int_add(json_nexthop_global
,
10300 path
->extra
->igpmetric
);
10302 vty_out(vty
, " (metric %u)",
10303 path
->extra
->igpmetric
);
10306 /* IGP cost is 0, display this only for json */
10309 json_object_int_add(json_nexthop_global
,
10314 json_object_boolean_true_add(json_nexthop_global
,
10318 /* Display peer "from" output */
10319 /* This path was originated locally */
10320 if (path
->peer
== bgp
->peer_self
) {
10322 if (safi
== SAFI_EVPN
|| (bn_p
->family
== AF_INET
&&
10323 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10325 json_object_string_add(json_peer
, "peerId",
10328 vty_out(vty
, " from 0.0.0.0 ");
10331 json_object_string_add(json_peer
, "peerId",
10334 vty_out(vty
, " from :: ");
10338 json_object_string_addf(json_peer
, "routerId", "%pI4",
10341 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10344 /* We RXed this path from one of our peers */
10348 json_object_string_addf(json_peer
, "peerId", "%pSU",
10350 json_object_string_addf(json_peer
, "routerId", "%pI4",
10351 &path
->peer
->remote_id
);
10353 if (path
->peer
->hostname
)
10354 json_object_string_add(json_peer
, "hostname",
10355 path
->peer
->hostname
);
10357 if (path
->peer
->domainname
)
10358 json_object_string_add(json_peer
, "domainname",
10359 path
->peer
->domainname
);
10361 if (path
->peer
->conf_if
)
10362 json_object_string_add(json_peer
, "interface",
10363 path
->peer
->conf_if
);
10365 if (path
->peer
->conf_if
) {
10366 if (path
->peer
->hostname
10367 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10368 BGP_FLAG_SHOW_HOSTNAME
))
10369 vty_out(vty
, " from %s(%s)",
10370 path
->peer
->hostname
,
10371 path
->peer
->conf_if
);
10373 vty_out(vty
, " from %s",
10374 path
->peer
->conf_if
);
10376 if (path
->peer
->hostname
10377 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10378 BGP_FLAG_SHOW_HOSTNAME
))
10379 vty_out(vty
, " from %s(%s)",
10380 path
->peer
->hostname
,
10383 vty_out(vty
, " from %pSU",
10387 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10388 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10390 vty_out(vty
, " (%s)",
10392 &path
->peer
->remote_id
, buf1
,
10398 * Note when vrfid of nexthop is different from that of prefix
10400 if (path
->extra
&& path
->extra
->bgp_orig
) {
10401 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10406 if (path
->extra
->bgp_orig
->inst_type
10407 == BGP_INSTANCE_TYPE_DEFAULT
)
10408 vn
= VRF_DEFAULT_NAME
;
10410 vn
= path
->extra
->bgp_orig
->name
;
10412 json_object_string_add(json_path
, "nhVrfName", vn
);
10414 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10415 json_object_int_add(json_path
, "nhVrfId", -1);
10417 json_object_int_add(json_path
, "nhVrfId",
10418 (int)nexthop_vrfid
);
10421 if (nexthop_vrfid
== VRF_UNKNOWN
)
10422 vty_out(vty
, " vrf ?");
10426 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10427 vty_out(vty
, " vrf %s(%u)",
10428 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10433 if (nexthop_self
) {
10435 json_object_boolean_true_add(json_path
,
10436 "announceNexthopSelf");
10438 vty_out(vty
, " announce-nh-self");
10443 vty_out(vty
, "\n");
10445 /* display the link-local nexthop */
10446 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10448 json_nexthop_ll
= json_object_new_object();
10449 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10450 &attr
->mp_nexthop_local
);
10452 if (path
->peer
->hostname
)
10453 json_object_string_add(json_nexthop_ll
,
10455 path
->peer
->hostname
);
10457 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10458 json_object_string_add(json_nexthop_ll
, "scope",
10461 json_object_boolean_true_add(json_nexthop_ll
,
10464 if (!attr
->mp_nexthop_prefer_global
)
10465 json_object_boolean_true_add(json_nexthop_ll
,
10468 json_object_boolean_true_add(
10469 json_nexthop_global
, "used");
10471 vty_out(vty
, " (%s) %s\n",
10472 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10473 buf
, INET6_ADDRSTRLEN
),
10474 attr
->mp_nexthop_prefer_global
10475 ? "(prefer-global)"
10479 /* If we do not have a link-local nexthop then we must flag the
10480 global as "used" */
10483 json_object_boolean_true_add(json_nexthop_global
,
10487 if (safi
== SAFI_EVPN
&&
10488 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10489 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10492 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10493 * Int/Ext/Local, Atomic, best */
10495 json_object_string_add(json_path
, "origin",
10496 bgp_origin_long_str
[attr
->origin
]);
10498 vty_out(vty
, " Origin %s",
10499 bgp_origin_long_str
[attr
->origin
]);
10501 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10503 json_object_int_add(json_path
, "metric", attr
->med
);
10505 vty_out(vty
, ", metric %u", attr
->med
);
10508 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10510 json_object_int_add(json_path
, "locPrf",
10513 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10516 if (attr
->weight
!= 0) {
10518 json_object_int_add(json_path
, "weight", attr
->weight
);
10520 vty_out(vty
, ", weight %u", attr
->weight
);
10523 if (attr
->tag
!= 0) {
10525 json_object_int_add(json_path
, "tag", attr
->tag
);
10527 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10530 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10532 json_object_boolean_false_add(json_path
, "valid");
10534 vty_out(vty
, ", invalid");
10535 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10537 json_object_boolean_true_add(json_path
, "valid");
10539 vty_out(vty
, ", valid");
10543 json_object_int_add(json_path
, "version", bn
->version
);
10545 if (path
->peer
!= bgp
->peer_self
) {
10546 if (path
->peer
->as
== path
->peer
->local_as
) {
10547 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10549 json_object_string_add(
10551 "confed-internal");
10553 vty_out(vty
, ", confed-internal");
10556 json_object_string_add(
10557 json_peer
, "type", "internal");
10559 vty_out(vty
, ", internal");
10562 if (bgp_confederation_peers_check(bgp
,
10565 json_object_string_add(
10567 "confed-external");
10569 vty_out(vty
, ", confed-external");
10572 json_object_string_add(
10573 json_peer
, "type", "external");
10575 vty_out(vty
, ", external");
10578 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10580 json_object_boolean_true_add(json_path
, "aggregated");
10581 json_object_boolean_true_add(json_path
, "local");
10583 vty_out(vty
, ", aggregated, local");
10585 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10587 json_object_boolean_true_add(json_path
, "sourced");
10589 vty_out(vty
, ", sourced");
10592 json_object_boolean_true_add(json_path
, "sourced");
10593 json_object_boolean_true_add(json_path
, "local");
10595 vty_out(vty
, ", sourced, local");
10599 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10601 json_object_boolean_true_add(json_path
,
10602 "atomicAggregate");
10604 vty_out(vty
, ", atomic-aggregate");
10607 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10609 json_object_int_add(json_path
, "otc", attr
->otc
);
10611 vty_out(vty
, ", otc %u", attr
->otc
);
10614 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10615 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10616 && bgp_path_info_mpath_count(path
))) {
10618 json_object_boolean_true_add(json_path
, "multipath");
10620 vty_out(vty
, ", multipath");
10623 // Mark the bestpath(s)
10624 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10625 first_as
= aspath_get_first_as(attr
->aspath
);
10628 if (!json_bestpath
)
10629 json_bestpath
= json_object_new_object();
10630 json_object_int_add(json_bestpath
, "bestpathFromAs",
10634 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10636 vty_out(vty
, ", bestpath-from-AS Local");
10640 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10642 if (!json_bestpath
)
10643 json_bestpath
= json_object_new_object();
10644 json_object_boolean_true_add(json_bestpath
, "overall");
10645 json_object_string_add(
10646 json_bestpath
, "selectionReason",
10647 bgp_path_selection_reason2str(bn
->reason
));
10649 vty_out(vty
, ", best");
10650 vty_out(vty
, " (%s)",
10651 bgp_path_selection_reason2str(bn
->reason
));
10655 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10657 json_object_string_add(
10658 json_path
, "rpkiValidationState",
10659 bgp_rpki_validation2str(rpki_curr_state
));
10661 vty_out(vty
, ", rpki validation-state: %s",
10662 bgp_rpki_validation2str(rpki_curr_state
));
10666 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10669 vty_out(vty
, "\n");
10671 /* Line 4 display Community */
10672 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10674 if (!bgp_attr_get_community(attr
)->json
)
10675 community_str(bgp_attr_get_community(attr
),
10677 json_object_lock(bgp_attr_get_community(attr
)->json
);
10678 json_object_object_add(
10679 json_path
, "community",
10680 bgp_attr_get_community(attr
)->json
);
10682 vty_out(vty
, " Community: %s\n",
10683 bgp_attr_get_community(attr
)->str
);
10687 /* Line 5 display Extended-community */
10688 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10690 json_ext_community
= json_object_new_object();
10691 json_object_string_add(
10692 json_ext_community
, "string",
10693 bgp_attr_get_ecommunity(attr
)->str
);
10694 json_object_object_add(json_path
, "extendedCommunity",
10695 json_ext_community
);
10697 vty_out(vty
, " Extended Community: %s\n",
10698 bgp_attr_get_ecommunity(attr
)->str
);
10702 /* Line 6 display Large community */
10703 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10705 if (!bgp_attr_get_lcommunity(attr
)->json
)
10706 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10708 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10709 json_object_object_add(
10710 json_path
, "largeCommunity",
10711 bgp_attr_get_lcommunity(attr
)->json
);
10713 vty_out(vty
, " Large Community: %s\n",
10714 bgp_attr_get_lcommunity(attr
)->str
);
10718 /* Line 7 display Originator, Cluster-id */
10719 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10720 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10721 char buf
[BUFSIZ
] = {0};
10723 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10725 json_object_string_addf(json_path
,
10726 "originatorId", "%pI4",
10727 &attr
->originator_id
);
10729 vty_out(vty
, " Originator: %pI4",
10730 &attr
->originator_id
);
10733 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10734 struct cluster_list
*cluster
=
10735 bgp_attr_get_cluster(attr
);
10739 json_cluster_list
= json_object_new_object();
10740 json_cluster_list_list
=
10741 json_object_new_array();
10743 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10744 json_string
= json_object_new_string(
10747 buf
, sizeof(buf
)));
10748 json_object_array_add(
10749 json_cluster_list_list
,
10754 * struct cluster_list does not have
10755 * "str" variable like aspath and community
10756 * do. Add this someday if someone asks
10758 * json_object_string_add(json_cluster_list,
10759 * "string", cluster->str);
10761 json_object_object_add(json_cluster_list
,
10763 json_cluster_list_list
);
10764 json_object_object_add(json_path
, "clusterList",
10765 json_cluster_list
);
10767 vty_out(vty
, ", Cluster list: ");
10769 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10770 vty_out(vty
, "%pI4 ",
10771 &cluster
->list
[i
]);
10777 vty_out(vty
, "\n");
10780 if (path
->extra
&& path
->extra
->damp_info
)
10781 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10784 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10785 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10786 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10790 json_object_int_add(json_path
, "remoteLabel", label
);
10792 vty_out(vty
, " Remote label: %d\n", label
);
10796 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10797 inet_ntop(AF_INET6
, &path
->extra
->sid
[0].sid
, buf
, sizeof(buf
));
10799 json_object_string_add(json_path
, "remoteSid", buf
);
10801 vty_out(vty
, " Remote SID: %s\n", buf
);
10805 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10807 json_object_int_add(json_path
, "labelIndex",
10808 attr
->label_index
);
10810 vty_out(vty
, " Label Index: %d\n",
10811 attr
->label_index
);
10814 /* Line 8 display Addpath IDs */
10815 if (path
->addpath_rx_id
10816 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10818 json_object_int_add(json_path
, "addpathRxId",
10819 path
->addpath_rx_id
);
10821 /* Keep backwards compatibility with the old API
10822 * by putting TX All's ID in the old field
10824 json_object_int_add(
10825 json_path
, "addpathTxId",
10827 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10829 /* ... but create a specific field for each
10832 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10833 json_object_int_add(
10835 bgp_addpath_names(i
)->id_json_name
,
10836 path
->tx_addpath
.addpath_tx_id
[i
]);
10839 vty_out(vty
, " AddPath ID: RX %u, ",
10840 path
->addpath_rx_id
);
10842 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10846 /* If we used addpath to TX a non-bestpath we need to display
10847 * "Advertised to" on a path-by-path basis
10849 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10852 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10854 bgp_addpath_encode_tx(peer
, afi
, safi
);
10855 has_adj
= bgp_adj_out_lookup(
10857 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10858 &path
->tx_addpath
));
10860 if ((addpath_capable
&& has_adj
)
10861 || (!addpath_capable
&& has_adj
10862 && CHECK_FLAG(path
->flags
,
10863 BGP_PATH_SELECTED
))) {
10864 if (json_path
&& !json_adv_to
)
10865 json_adv_to
= json_object_new_object();
10867 route_vty_out_advertised_to(
10869 " Advertised to:", json_adv_to
);
10875 json_object_object_add(
10876 json_path
, "advertisedTo", json_adv_to
);
10880 vty_out(vty
, "\n");
10885 /* Line 9 display Uptime */
10886 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
10888 json_last_update
= json_object_new_object();
10889 json_object_int_add(json_last_update
, "epoch", tbuf
);
10890 json_object_string_add(json_last_update
, "string",
10892 json_object_object_add(json_path
, "lastUpdate",
10895 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10897 /* Line 10 display PMSI tunnel attribute, if present */
10898 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10899 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10900 bgp_attr_get_pmsi_tnl_type(attr
),
10901 PMSI_TNLTYPE_STR_DEFAULT
);
10904 json_pmsi
= json_object_new_object();
10905 json_object_string_add(json_pmsi
, "tunnelType", str
);
10906 json_object_int_add(json_pmsi
, "label",
10907 label2vni(&attr
->label
));
10908 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10910 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10911 str
, label2vni(&attr
->label
));
10914 if (path
->peer
->t_gr_restart
&&
10915 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10916 unsigned long gr_remaining
=
10917 thread_timer_remain_second(path
->peer
->t_gr_restart
);
10920 json_object_int_add(json_path
,
10921 "gracefulRestartSecondsRemaining",
10925 " Time until Graceful Restart stale route deleted: %lu\n",
10929 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
10930 bgp_attr_get_community(attr
) &&
10931 community_include(bgp_attr_get_community(attr
),
10932 COMMUNITY_LLGR_STALE
)) {
10933 unsigned long llgr_remaining
= thread_timer_remain_second(
10934 path
->peer
->t_llgr_stale
[afi
][safi
]);
10937 json_object_int_add(json_path
, "llgrSecondsRemaining",
10941 " Time until Long-lived stale route deleted: %lu\n",
10945 /* Output some debug about internal state of the dest flags */
10947 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10948 json_object_boolean_true_add(json_path
, "processScheduled");
10949 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10950 json_object_boolean_true_add(json_path
, "userCleared");
10951 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10952 json_object_boolean_true_add(json_path
, "labelChanged");
10953 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10954 json_object_boolean_true_add(json_path
, "registeredForLabel");
10955 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10956 json_object_boolean_true_add(json_path
, "selectDefered");
10957 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10958 json_object_boolean_true_add(json_path
, "fibInstalled");
10959 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10960 json_object_boolean_true_add(json_path
, "fibPending");
10962 if (json_nexthop_global
|| json_nexthop_ll
) {
10963 json_nexthops
= json_object_new_array();
10965 if (json_nexthop_global
)
10966 json_object_array_add(json_nexthops
,
10967 json_nexthop_global
);
10969 if (json_nexthop_ll
)
10970 json_object_array_add(json_nexthops
,
10973 json_object_object_add(json_path
, "nexthops",
10977 json_object_object_add(json_path
, "peer", json_peer
);
10978 json_object_array_add(json_paths
, json_path
);
10982 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10983 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10984 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10986 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10987 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10989 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10990 const char *comstr
, int exact
, afi_t afi
,
10991 safi_t safi
, uint16_t show_flags
);
10993 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10994 struct bgp_table
*table
, enum bgp_show_type type
,
10995 void *output_arg
, const char *rd
, int is_last
,
10996 unsigned long *output_cum
, unsigned long *total_cum
,
10997 unsigned long *json_header_depth
, uint16_t show_flags
,
10998 enum rpki_states rpki_target_state
)
11000 struct bgp_path_info
*pi
;
11001 struct bgp_dest
*dest
;
11002 bool header
= true;
11003 bool json_detail_header
= false;
11005 unsigned long output_count
= 0;
11006 unsigned long total_count
= 0;
11008 json_object
*json_paths
= NULL
;
11010 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11011 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11012 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11014 if (output_cum
&& *output_cum
!= 0)
11017 if (use_json
&& !*json_header_depth
) {
11019 *json_header_depth
= 1;
11021 vty_out(vty
, "{\n");
11022 *json_header_depth
= 2;
11026 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11027 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11028 " \"localAS\": %u,\n \"routes\": { ",
11029 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11030 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11033 table
->version
, &bgp
->router_id
,
11034 bgp
->default_local_pref
, bgp
->as
);
11036 vty_out(vty
, " \"routeDistinguishers\" : {");
11037 ++*json_header_depth
;
11041 if (use_json
&& rd
) {
11042 vty_out(vty
, " \"%s\" : { ", rd
);
11045 /* Check for 'json detail', where we need header output once per dest */
11046 if (use_json
&& CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
) &&
11047 type
!= bgp_show_type_dampend_paths
&&
11048 type
!= bgp_show_type_damp_neighbor
&&
11049 type
!= bgp_show_type_flap_statistics
&&
11050 type
!= bgp_show_type_flap_neighbor
)
11051 json_detail_header
= true;
11053 /* Start processing of routes. */
11054 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11055 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11056 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11057 bool json_detail
= json_detail_header
;
11059 pi
= bgp_dest_get_bgp_path_info(dest
);
11065 json_paths
= json_object_new_array();
11069 for (; pi
; pi
= pi
->next
) {
11070 struct community
*picomm
= NULL
;
11072 picomm
= bgp_attr_get_community(pi
->attr
);
11076 if (type
== bgp_show_type_prefix_version
) {
11078 strtoul(output_arg
, NULL
, 10);
11079 if (dest
->version
< version
)
11083 if (type
== bgp_show_type_community_alias
) {
11084 char *alias
= output_arg
;
11085 char **communities
;
11087 bool found
= false;
11090 frrstr_split(picomm
->str
, " ",
11091 &communities
, &num
);
11092 for (int i
= 0; i
< num
; i
++) {
11093 const char *com2alias
=
11094 bgp_community2alias(
11097 && strcmp(alias
, com2alias
)
11103 XFREE(MTYPE_TMP
, communities
);
11107 bgp_attr_get_lcommunity(pi
->attr
)) {
11108 frrstr_split(bgp_attr_get_lcommunity(
11111 " ", &communities
, &num
);
11112 for (int i
= 0; i
< num
; i
++) {
11113 const char *com2alias
=
11114 bgp_community2alias(
11117 && strcmp(alias
, com2alias
)
11123 XFREE(MTYPE_TMP
, communities
);
11130 if (type
== bgp_show_type_rpki
) {
11131 if (dest_p
->family
== AF_INET
11132 || dest_p
->family
== AF_INET6
)
11133 rpki_curr_state
= hook_call(
11134 bgp_rpki_prefix_status
,
11135 pi
->peer
, pi
->attr
, dest_p
);
11136 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11137 && rpki_curr_state
!= rpki_target_state
)
11141 if (type
== bgp_show_type_flap_statistics
11142 || type
== bgp_show_type_flap_neighbor
11143 || type
== bgp_show_type_dampend_paths
11144 || type
== bgp_show_type_damp_neighbor
) {
11145 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11148 if (type
== bgp_show_type_regexp
) {
11149 regex_t
*regex
= output_arg
;
11151 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11155 if (type
== bgp_show_type_prefix_list
) {
11156 struct prefix_list
*plist
= output_arg
;
11158 if (prefix_list_apply(plist
, dest_p
)
11162 if (type
== bgp_show_type_access_list
) {
11163 struct access_list
*alist
= output_arg
;
11165 if (access_list_apply(alist
, dest_p
) !=
11169 if (type
== bgp_show_type_filter_list
) {
11170 struct as_list
*as_list
= output_arg
;
11172 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11173 != AS_FILTER_PERMIT
)
11176 if (type
== bgp_show_type_route_map
) {
11177 struct route_map
*rmap
= output_arg
;
11178 struct bgp_path_info path
;
11179 struct bgp_path_info_extra extra
;
11180 struct attr dummy_attr
= {};
11181 route_map_result_t ret
;
11183 dummy_attr
= *pi
->attr
;
11185 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11186 pi
->peer
, &dummy_attr
);
11188 ret
= route_map_apply(rmap
, dest_p
, &path
);
11189 bgp_attr_flush(&dummy_attr
);
11190 if (ret
== RMAP_DENYMATCH
)
11193 if (type
== bgp_show_type_neighbor
11194 || type
== bgp_show_type_flap_neighbor
11195 || type
== bgp_show_type_damp_neighbor
) {
11196 union sockunion
*su
= output_arg
;
11198 if (pi
->peer
== NULL
11199 || pi
->peer
->su_remote
== NULL
11200 || !sockunion_same(pi
->peer
->su_remote
, su
))
11203 if (type
== bgp_show_type_cidr_only
) {
11204 uint32_t destination
;
11206 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11207 if (IN_CLASSC(destination
)
11208 && dest_p
->prefixlen
== 24)
11210 if (IN_CLASSB(destination
)
11211 && dest_p
->prefixlen
== 16)
11213 if (IN_CLASSA(destination
)
11214 && dest_p
->prefixlen
== 8)
11217 if (type
== bgp_show_type_prefix_longer
) {
11219 if (!prefix_match(p
, dest_p
))
11222 if (type
== bgp_show_type_community_all
) {
11226 if (type
== bgp_show_type_community
) {
11227 struct community
*com
= output_arg
;
11229 if (!picomm
|| !community_match(picomm
, com
))
11232 if (type
== bgp_show_type_community_exact
) {
11233 struct community
*com
= output_arg
;
11235 if (!picomm
|| !community_cmp(picomm
, com
))
11238 if (type
== bgp_show_type_community_list
) {
11239 struct community_list
*list
= output_arg
;
11241 if (!community_list_match(picomm
, list
))
11244 if (type
== bgp_show_type_community_list_exact
) {
11245 struct community_list
*list
= output_arg
;
11247 if (!community_list_exact_match(picomm
, list
))
11250 if (type
== bgp_show_type_lcommunity
) {
11251 struct lcommunity
*lcom
= output_arg
;
11253 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11255 bgp_attr_get_lcommunity(pi
->attr
),
11260 if (type
== bgp_show_type_lcommunity_exact
) {
11261 struct lcommunity
*lcom
= output_arg
;
11263 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11265 bgp_attr_get_lcommunity(pi
->attr
),
11269 if (type
== bgp_show_type_lcommunity_list
) {
11270 struct community_list
*list
= output_arg
;
11272 if (!lcommunity_list_match(
11273 bgp_attr_get_lcommunity(pi
->attr
),
11278 == bgp_show_type_lcommunity_list_exact
) {
11279 struct community_list
*list
= output_arg
;
11281 if (!lcommunity_list_exact_match(
11282 bgp_attr_get_lcommunity(pi
->attr
),
11286 if (type
== bgp_show_type_lcommunity_all
) {
11287 if (!bgp_attr_get_lcommunity(pi
->attr
))
11290 if (type
== bgp_show_type_dampend_paths
11291 || type
== bgp_show_type_damp_neighbor
) {
11292 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11293 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11297 if (!use_json
&& header
) {
11299 "BGP table version is %" PRIu64
11300 ", local router ID is %pI4, vrf id ",
11301 table
->version
, &bgp
->router_id
);
11302 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11303 vty_out(vty
, "%s", VRFID_NONE_STR
);
11305 vty_out(vty
, "%u", bgp
->vrf_id
);
11306 vty_out(vty
, "\n");
11307 vty_out(vty
, "Default local pref %u, ",
11308 bgp
->default_local_pref
);
11309 vty_out(vty
, "local AS %u\n", bgp
->as
);
11310 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11311 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11312 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11313 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11314 if (type
== bgp_show_type_dampend_paths
11315 || type
== bgp_show_type_damp_neighbor
)
11316 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11317 else if (type
== bgp_show_type_flap_statistics
11318 || type
== bgp_show_type_flap_neighbor
)
11319 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11321 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11322 : BGP_SHOW_HEADER
));
11325 } else if (json_detail
&& json_paths
!= NULL
) {
11326 const struct prefix_rd
*prd
;
11327 json_object
*jtemp
;
11329 /* Use common detail header, for most types;
11330 * need a json 'object'.
11333 jtemp
= json_object_new_object();
11334 prd
= bgp_rd_from_dest(dest
, safi
);
11336 route_vty_out_detail_header(
11337 vty
, bgp
, dest
, prd
, table
->afi
,
11340 json_object_array_add(json_paths
, jtemp
);
11342 json_detail
= false;
11345 if (rd
!= NULL
&& !display
&& !output_count
) {
11348 "Route Distinguisher: %s\n",
11351 if (type
== bgp_show_type_dampend_paths
11352 || type
== bgp_show_type_damp_neighbor
)
11353 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11354 AFI_IP
, safi
, use_json
,
11356 else if (type
== bgp_show_type_flap_statistics
11357 || type
== bgp_show_type_flap_neighbor
)
11358 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11359 AFI_IP
, safi
, use_json
,
11362 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
11363 route_vty_out_detail(
11364 vty
, bgp
, dest
, pi
,
11365 family2afi(dest_p
->family
),
11366 safi
, RPKI_NOT_BEING_USED
,
11369 route_vty_out(vty
, dest_p
, pi
, display
,
11370 safi
, json_paths
, wide
);
11380 /* encode prefix */
11381 if (dest_p
->family
== AF_FLOWSPEC
) {
11382 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11385 bgp_fs_nlri_get_string(
11387 dest_p
->u
.prefix_flowspec
.ptr
,
11388 dest_p
->u
.prefix_flowspec
.prefixlen
,
11389 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11390 family2afi(dest_p
->u
11391 .prefix_flowspec
.family
));
11393 vty_out(vty
, "\"%s/%d\": ", retstr
,
11394 dest_p
->u
.prefix_flowspec
11397 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11398 dest_p
->u
.prefix_flowspec
11402 vty_out(vty
, "\"%pFX\": ", dest_p
);
11404 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11406 vty_json(vty
, json_paths
);
11410 json_object_free(json_paths
);
11414 output_count
+= *output_cum
;
11415 *output_cum
= output_count
;
11418 total_count
+= *total_cum
;
11419 *total_cum
= total_count
;
11423 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11427 for (i
= 0; i
< *json_header_depth
; ++i
)
11428 vty_out(vty
, " } ");
11430 vty_out(vty
, "\n");
11434 /* No route is displayed */
11435 if (output_count
== 0) {
11436 if (type
== bgp_show_type_normal
)
11438 "No BGP prefixes displayed, %ld exist\n",
11442 "\nDisplayed %ld routes and %ld total paths\n",
11443 output_count
, total_count
);
11447 return CMD_SUCCESS
;
11450 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11451 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11452 enum bgp_show_type type
, void *output_arg
, bool use_json
)
11454 struct bgp_dest
*dest
, *next
;
11455 unsigned long output_cum
= 0;
11456 unsigned long total_cum
= 0;
11457 unsigned long json_header_depth
= 0;
11458 struct bgp_table
*itable
;
11460 uint16_t show_flags
= 0;
11462 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11465 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11467 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11468 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11470 next
= bgp_route_next(dest
);
11471 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11474 itable
= bgp_dest_get_bgp_table_info(dest
);
11475 if (itable
!= NULL
) {
11476 struct prefix_rd prd
;
11477 char rd
[RD_ADDRSTRLEN
];
11479 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11480 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11481 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11482 rd
, next
== NULL
, &output_cum
,
11483 &total_cum
, &json_header_depth
,
11484 show_flags
, RPKI_NOT_BEING_USED
);
11490 if (output_cum
== 0)
11491 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11495 "\nDisplayed %ld routes and %ld total paths\n",
11496 output_cum
, total_cum
);
11498 return CMD_SUCCESS
;
11501 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11502 enum bgp_show_type type
, void *output_arg
,
11503 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11505 struct bgp_table
*table
;
11506 unsigned long json_header_depth
= 0;
11507 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11510 bgp
= bgp_get_default();
11515 vty_out(vty
, "No BGP process is configured\n");
11517 vty_out(vty
, "{}\n");
11518 return CMD_WARNING
;
11521 /* Labeled-unicast routes live in the unicast table. */
11522 if (safi
== SAFI_LABELED_UNICAST
)
11523 safi
= SAFI_UNICAST
;
11525 table
= bgp
->rib
[afi
][safi
];
11526 /* use MPLS and ENCAP specific shows until they are merged */
11527 if (safi
== SAFI_MPLS_VPN
) {
11528 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11529 output_arg
, use_json
);
11532 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11533 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11534 output_arg
, use_json
,
11538 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11539 NULL
, NULL
, &json_header_depth
, show_flags
,
11540 rpki_target_state
);
11543 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11544 safi_t safi
, uint16_t show_flags
)
11546 struct listnode
*node
, *nnode
;
11549 bool route_output
= false;
11550 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11553 vty_out(vty
, "{\n");
11555 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11556 route_output
= true;
11559 vty_out(vty
, ",\n");
11563 vty_out(vty
, "\"%s\":",
11564 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11568 vty_out(vty
, "\nInstance %s:\n",
11569 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11573 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11574 show_flags
, RPKI_NOT_BEING_USED
);
11578 vty_out(vty
, "}\n");
11579 else if (!route_output
)
11580 vty_out(vty
, "%% BGP instance not found\n");
11583 /* Header of detailed BGP route information */
11584 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11585 struct bgp_dest
*dest
,
11586 const struct prefix_rd
*prd
,
11587 afi_t afi
, safi_t safi
, json_object
*json
)
11589 struct bgp_path_info
*pi
;
11590 const struct prefix
*p
;
11592 struct listnode
*node
, *nnode
;
11593 char buf1
[RD_ADDRSTRLEN
];
11597 int accept_own
= 0;
11598 int route_filter_translated_v4
= 0;
11599 int route_filter_v4
= 0;
11600 int route_filter_translated_v6
= 0;
11601 int route_filter_v6
= 0;
11602 int llgr_stale
= 0;
11604 int accept_own_nexthop
= 0;
11607 int no_advertise
= 0;
11611 int has_valid_label
= 0;
11612 mpls_label_t label
= 0;
11613 json_object
*json_adv_to
= NULL
;
11618 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11620 p
= bgp_dest_get_prefix(dest
);
11621 has_valid_label
= bgp_is_valid_label(&label
);
11623 if (safi
== SAFI_EVPN
) {
11625 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11626 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11628 prd
? ":" : "", (struct prefix_evpn
*)p
);
11630 json_object_string_add(json
, "rd",
11631 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11633 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11638 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11640 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11641 ? prefix_rd2str(prd
, buf1
,
11644 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11648 json_object_string_addf(json
, "prefix", "%pFX", p
);
11649 json_object_int_add(json
, "version", dest
->version
);
11654 if (has_valid_label
) {
11656 json_object_int_add(json
, "localLabel", label
);
11658 vty_out(vty
, "Local label: %d\n", label
);
11662 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11663 vty_out(vty
, "not allocated\n");
11665 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11666 struct community
*picomm
= NULL
;
11668 picomm
= bgp_attr_get_community(pi
->attr
);
11671 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11673 if (bgp_path_suppressed(pi
))
11679 no_advertise
+= community_include(
11680 picomm
, COMMUNITY_NO_ADVERTISE
);
11682 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11684 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11686 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11687 route_filter_translated_v4
+= community_include(
11688 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11689 route_filter_translated_v6
+= community_include(
11690 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11691 route_filter_v4
+= community_include(
11692 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11693 route_filter_v6
+= community_include(
11694 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11696 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11697 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11698 accept_own_nexthop
+= community_include(
11699 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11701 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11702 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11707 vty_out(vty
, "Paths: (%d available", count
);
11709 vty_out(vty
, ", best #%d", best
);
11710 if (safi
== SAFI_UNICAST
) {
11711 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11712 vty_out(vty
, ", table %s",
11715 vty_out(vty
, ", vrf %s",
11719 vty_out(vty
, ", no best path");
11723 ", accept own local route exported and imported in different VRF");
11724 else if (route_filter_translated_v4
)
11726 ", mark translated RTs for VPNv4 route filtering");
11727 else if (route_filter_v4
)
11729 ", attach RT as-is for VPNv4 route filtering");
11730 else if (route_filter_translated_v6
)
11732 ", mark translated RTs for VPNv6 route filtering");
11733 else if (route_filter_v6
)
11735 ", attach RT as-is for VPNv6 route filtering");
11736 else if (llgr_stale
)
11738 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11741 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11742 else if (accept_own_nexthop
)
11744 ", accept local nexthop");
11745 else if (blackhole
)
11746 vty_out(vty
, ", inform peer to blackhole prefix");
11747 else if (no_export
)
11748 vty_out(vty
, ", not advertised to EBGP peer");
11749 else if (no_advertise
)
11750 vty_out(vty
, ", not advertised to any peer");
11752 vty_out(vty
, ", not advertised outside local AS");
11755 ", inform EBGP peer not to advertise to their EBGP peers");
11759 ", Advertisements suppressed by an aggregate.");
11760 vty_out(vty
, ")\n");
11763 /* If we are not using addpath then we can display Advertised to and
11765 * show what peers we advertised the bestpath to. If we are using
11767 * though then we must display Advertised to on a path-by-path basis. */
11768 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11769 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11770 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11771 if (json
&& !json_adv_to
)
11772 json_adv_to
= json_object_new_object();
11774 route_vty_out_advertised_to(
11776 " Advertised to non peer-group peers:\n ",
11783 json_object_object_add(json
, "advertisedTo",
11788 vty_out(vty
, " Not advertised to any peer");
11789 vty_out(vty
, "\n");
11794 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
11795 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11796 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11797 json_object
*json
, enum bgp_path_type pathtype
,
11798 int *display
, enum rpki_states rpki_target_state
)
11800 struct bgp_path_info
*pi
;
11802 json_object
*json_header
= NULL
;
11803 json_object
*json_paths
= NULL
;
11804 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
11806 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11807 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11809 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
11810 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
11811 pi
->peer
, pi
->attr
, p
);
11813 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11814 && rpki_curr_state
!= rpki_target_state
)
11817 if (json
&& !json_paths
) {
11818 /* Instantiate json_paths only if path is valid */
11819 json_paths
= json_object_new_array();
11821 json_header
= json_object_new_object();
11823 json_header
= json
;
11827 route_vty_out_detail_header(
11828 vty
, bgp
, bgp_node
, pfx_rd
,
11829 AFI_IP
, safi
, json_header
);
11834 if (pathtype
== BGP_PATH_SHOW_ALL
11835 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11836 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11837 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11838 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11839 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11840 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
11841 safi
, rpki_curr_state
, json_paths
);
11844 if (json
&& json_paths
) {
11845 json_object_object_add(json_header
, "paths", json_paths
);
11848 json_object_object_addf(json
, json_header
, "%pRD",
11854 * Return rd based on safi
11856 static const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
11860 case SAFI_MPLS_VPN
:
11863 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
11870 /* Display specified route of BGP table. */
11871 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11872 struct bgp_table
*rib
, const char *ip_str
,
11873 afi_t afi
, safi_t safi
,
11874 enum rpki_states rpki_target_state
,
11875 struct prefix_rd
*prd
, int prefix_check
,
11876 enum bgp_path_type pathtype
, bool use_json
)
11880 struct prefix match
;
11881 struct bgp_dest
*dest
;
11882 struct bgp_dest
*rm
;
11883 struct bgp_table
*table
;
11884 json_object
*json
= NULL
;
11885 json_object
*json_paths
= NULL
;
11887 /* Check IP address argument. */
11888 ret
= str2prefix(ip_str
, &match
);
11890 vty_out(vty
, "address is malformed\n");
11891 return CMD_WARNING
;
11894 match
.family
= afi2family(afi
);
11897 json
= json_object_new_object();
11899 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11900 for (dest
= bgp_table_top(rib
); dest
;
11901 dest
= bgp_route_next(dest
)) {
11902 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11904 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11906 table
= bgp_dest_get_bgp_table_info(dest
);
11910 rm
= bgp_node_match(table
, &match
);
11914 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11916 && rm_p
->prefixlen
!= match
.prefixlen
) {
11917 bgp_dest_unlock_node(rm
);
11921 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11922 bgp
, afi
, safi
, json
, pathtype
,
11923 &display
, rpki_target_state
);
11925 bgp_dest_unlock_node(rm
);
11927 } else if (safi
== SAFI_EVPN
) {
11928 struct bgp_dest
*longest_pfx
;
11929 bool is_exact_pfxlen_match
= false;
11931 for (dest
= bgp_table_top(rib
); dest
;
11932 dest
= bgp_route_next(dest
)) {
11933 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11935 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11937 table
= bgp_dest_get_bgp_table_info(dest
);
11941 longest_pfx
= NULL
;
11942 is_exact_pfxlen_match
= false;
11944 * Search through all the prefixes for a match. The
11945 * pfx's are enumerated in ascending order of pfxlens.
11946 * So, the last pfx match is the longest match. Set
11947 * is_exact_pfxlen_match when we get exact pfxlen match
11949 for (rm
= bgp_table_top(table
); rm
;
11950 rm
= bgp_route_next(rm
)) {
11951 const struct prefix
*rm_p
=
11952 bgp_dest_get_prefix(rm
);
11954 * Get prefixlen of the ip-prefix within type5
11957 if (evpn_type5_prefix_match(rm_p
, &match
)
11961 bgp_evpn_get_type5_prefixlen(
11963 if (type5_pfxlen
== match
.prefixlen
) {
11964 is_exact_pfxlen_match
= true;
11965 bgp_dest_unlock_node(rm
);
11974 if (prefix_check
&& !is_exact_pfxlen_match
)
11978 bgp_dest_lock_node(rm
);
11980 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11981 bgp
, afi
, safi
, json
, pathtype
,
11982 &display
, rpki_target_state
);
11984 bgp_dest_unlock_node(rm
);
11986 } else if (safi
== SAFI_FLOWSPEC
) {
11988 json_paths
= json_object_new_array();
11990 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11991 &match
, prefix_check
,
11997 json_object_object_add(json
, "paths",
12000 json_object_free(json_paths
);
12003 dest
= bgp_node_match(rib
, &match
);
12004 if (dest
!= NULL
) {
12005 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12007 || dest_p
->prefixlen
== match
.prefixlen
) {
12008 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12009 safi
, json
, pathtype
,
12010 &display
, rpki_target_state
);
12013 bgp_dest_unlock_node(dest
);
12018 vty_json(vty
, json
);
12021 vty_out(vty
, "%% Network not in table\n");
12022 return CMD_WARNING
;
12026 return CMD_SUCCESS
;
12029 /* Display specified route of Main RIB */
12030 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12031 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12032 int prefix_check
, enum bgp_path_type pathtype
,
12033 enum rpki_states rpki_target_state
, bool use_json
)
12036 bgp
= bgp_get_default();
12039 vty_out(vty
, "No BGP process is configured\n");
12041 vty_out(vty
, "{}\n");
12042 return CMD_WARNING
;
12046 /* labeled-unicast routes live in the unicast table */
12047 if (safi
== SAFI_LABELED_UNICAST
)
12048 safi
= SAFI_UNICAST
;
12050 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12051 afi
, safi
, rpki_target_state
, prd
,
12052 prefix_check
, pathtype
, use_json
);
12055 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12056 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12057 safi_t safi
, bool uj
)
12059 struct lcommunity
*lcom
;
12064 uint16_t show_flags
= 0;
12068 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12070 b
= buffer_new(1024);
12071 for (i
= 0; i
< argc
; i
++) {
12073 buffer_putc(b
, ' ');
12075 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12077 buffer_putstr(b
, argv
[i
]->arg
);
12081 buffer_putc(b
, '\0');
12083 str
= buffer_getstr(b
);
12086 lcom
= lcommunity_str2com(str
);
12087 XFREE(MTYPE_TMP
, str
);
12089 vty_out(vty
, "%% Large-community malformed\n");
12090 return CMD_WARNING
;
12093 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12094 (exact
? bgp_show_type_lcommunity_exact
12095 : bgp_show_type_lcommunity
),
12096 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12098 lcommunity_free(&lcom
);
12102 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12103 const char *lcom
, bool exact
, afi_t afi
,
12104 safi_t safi
, bool uj
)
12106 struct community_list
*list
;
12107 uint16_t show_flags
= 0;
12110 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12113 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12114 LARGE_COMMUNITY_LIST_MASTER
);
12115 if (list
== NULL
) {
12116 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12118 return CMD_WARNING
;
12121 return bgp_show(vty
, bgp
, afi
, safi
,
12122 (exact
? bgp_show_type_lcommunity_list_exact
12123 : bgp_show_type_lcommunity_list
),
12124 list
, show_flags
, RPKI_NOT_BEING_USED
);
12127 DEFUN (show_ip_bgp_large_community_list
,
12128 show_ip_bgp_large_community_list_cmd
,
12129 "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]",
12133 BGP_INSTANCE_HELP_STR
12135 BGP_SAFI_WITH_LABEL_HELP_STR
12136 "Display routes matching the large-community-list\n"
12137 "large-community-list number\n"
12138 "large-community-list name\n"
12139 "Exact match of the large-communities\n"
12142 afi_t afi
= AFI_IP6
;
12143 safi_t safi
= SAFI_UNICAST
;
12145 bool exact_match
= 0;
12146 struct bgp
*bgp
= NULL
;
12147 bool uj
= use_json(argc
, argv
);
12152 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12155 return CMD_WARNING
;
12157 argv_find(argv
, argc
, "large-community-list", &idx
);
12159 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12161 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12164 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12165 exact_match
, afi
, safi
, uj
);
12167 DEFUN (show_ip_bgp_large_community
,
12168 show_ip_bgp_large_community_cmd
,
12169 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12173 BGP_INSTANCE_HELP_STR
12175 BGP_SAFI_WITH_LABEL_HELP_STR
12176 "Display routes matching the large-communities\n"
12177 "List of large-community numbers\n"
12178 "Exact match of the large-communities\n"
12181 afi_t afi
= AFI_IP6
;
12182 safi_t safi
= SAFI_UNICAST
;
12184 bool exact_match
= 0;
12185 struct bgp
*bgp
= NULL
;
12186 bool uj
= use_json(argc
, argv
);
12187 uint16_t show_flags
= 0;
12191 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12194 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12197 return CMD_WARNING
;
12199 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12200 if (argv_find(argv
, argc
, "exact-match", &idx
))
12202 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12203 exact_match
, afi
, safi
, uj
);
12205 return bgp_show(vty
, bgp
, afi
, safi
,
12206 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12207 RPKI_NOT_BEING_USED
);
12210 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12211 safi_t safi
, struct json_object
*json_array
);
12212 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12213 safi_t safi
, struct json_object
*json
);
12216 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12217 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12218 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12219 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12221 bool uj
= use_json(argc
, argv
);
12222 struct bgp
*bgp
= NULL
;
12223 safi_t safi
= SAFI_UNICAST
;
12224 afi_t afi
= AFI_IP6
;
12226 struct json_object
*json_all
= NULL
;
12227 struct json_object
*json_afi_safi
= NULL
;
12229 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12232 return CMD_WARNING
;
12235 json_all
= json_object_new_object();
12237 FOREACH_AFI_SAFI (afi
, safi
) {
12239 * So limit output to those afi/safi pairs that
12240 * actually have something interesting in them
12242 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12247 json_afi_safi
= json_object_new_array();
12248 json_object_object_add(
12250 get_afi_safi_str(afi
, safi
, true),
12253 json_afi_safi
= NULL
;
12256 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12260 vty_json(vty
, json_all
);
12262 return CMD_SUCCESS
;
12265 /* BGP route print out function without JSON */
12266 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12267 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12268 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12272 BGP_INSTANCE_HELP_STR
12275 "BGP RIB advertisement statistics\n"
12278 afi_t afi
= AFI_IP6
;
12279 safi_t safi
= SAFI_UNICAST
;
12280 struct bgp
*bgp
= NULL
;
12282 bool uj
= use_json(argc
, argv
);
12283 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12285 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12288 return CMD_WARNING
;
12291 json_afi_safi
= json_object_new_array();
12293 json_afi_safi
= NULL
;
12295 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12298 json
= json_object_new_object();
12299 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12301 vty_json(vty
, json
);
12306 /* BGP route print out function without JSON */
12307 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12308 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12309 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12311 statistics [json]",
12312 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12313 BGP_SAFI_WITH_LABEL_HELP_STR
12314 "BGP RIB advertisement statistics\n" JSON_STR
)
12316 afi_t afi
= AFI_IP6
;
12317 safi_t safi
= SAFI_UNICAST
;
12318 struct bgp
*bgp
= NULL
;
12320 bool uj
= use_json(argc
, argv
);
12321 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12323 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12326 return CMD_WARNING
;
12329 json_afi_safi
= json_object_new_array();
12331 json_afi_safi
= NULL
;
12333 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12336 json
= json_object_new_object();
12337 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12339 vty_json(vty
, json
);
12344 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12345 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12346 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12347 "]] [all$all] dampening parameters [json]",
12348 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12349 BGP_SAFI_WITH_LABEL_HELP_STR
12350 "Display the entries for all address families\n"
12351 "Display detailed information about dampening\n"
12352 "Display detail of configured dampening parameters\n"
12355 afi_t afi
= AFI_IP6
;
12356 safi_t safi
= SAFI_UNICAST
;
12357 struct bgp
*bgp
= NULL
;
12359 uint16_t show_flags
= 0;
12360 bool uj
= use_json(argc
, argv
);
12364 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12367 /* [<ipv4|ipv6> [all]] */
12369 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12370 if (argv_find(argv
, argc
, "ipv4", &idx
))
12371 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12373 if (argv_find(argv
, argc
, "ipv6", &idx
))
12374 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12377 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12380 return CMD_WARNING
;
12382 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12385 /* BGP route print out function */
12386 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12387 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12388 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12392 |dampening <flap-statistics|dampened-paths>\
12393 |community [AA:NN|local-AS|no-advertise|no-export\
12394 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12395 |accept-own|accept-own-nexthop|route-filter-v6\
12396 |route-filter-v4|route-filter-translated-v6\
12397 |route-filter-translated-v4] [exact-match]\
12398 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12399 |filter-list AS_PATH_FILTER_NAME\
12401 |access-list ACCESSLIST_NAME\
12402 |route-map RMAP_NAME\
12403 |rpki <invalid|valid|notfound>\
12404 |version (1-4294967295)\
12406 |A.B.C.D/M longer-prefixes\
12407 |X:X::X:X/M longer-prefixes\
12408 ] [json$uj [detail$detail] | wide$wide]",
12409 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12410 BGP_SAFI_WITH_LABEL_HELP_STR
12411 "Display the entries for all address families\n"
12412 "Display only routes with non-natural netmasks\n"
12413 "Display detailed information about dampening\n"
12414 "Display flap statistics of routes\n"
12415 "Display paths suppressed due to dampening\n"
12416 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12417 "Do not send outside local AS (well-known community)\n"
12418 "Do not advertise to any peer (well-known community)\n"
12419 "Do not export to next AS (well-known community)\n"
12420 "Graceful shutdown (well-known community)\n"
12421 "Do not export to any peer (well-known community)\n"
12422 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12423 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12424 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12425 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12426 "Should accept VPN route with local nexthop (well-known community)\n"
12427 "RT VPNv6 route filtering (well-known community)\n"
12428 "RT VPNv4 route filtering (well-known community)\n"
12429 "RT translated VPNv6 route filtering (well-known community)\n"
12430 "RT translated VPNv4 route filtering (well-known community)\n"
12431 "Exact match of the communities\n"
12432 "Community-list number\n"
12433 "Community-list name\n"
12434 "Display routes matching the community-list\n"
12435 "Exact match of the communities\n"
12436 "Display routes conforming to the filter-list\n"
12437 "Regular expression access list name\n"
12438 "Display routes conforming to the prefix-list\n"
12439 "Prefix-list name\n"
12440 "Display routes conforming to the access-list\n"
12441 "Access-list name\n"
12442 "Display routes matching the route-map\n"
12443 "A route-map to match on\n"
12444 "RPKI route types\n"
12445 "A valid path as determined by rpki\n"
12446 "A invalid path as determined by rpki\n"
12447 "A path that has no rpki data\n"
12448 "Display prefixes with matching version numbers\n"
12449 "Version number and above\n"
12450 "Display prefixes with matching BGP community alias\n"
12451 "BGP community alias\n"
12453 "Display route and more specific routes\n"
12455 "Display route and more specific routes\n"
12457 "Display detailed version of JSON output\n"
12458 "Increase table width for longer prefixes\n")
12460 afi_t afi
= AFI_IP6
;
12461 safi_t safi
= SAFI_UNICAST
;
12462 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12463 void *output_arg
= NULL
;
12464 struct bgp
*bgp
= NULL
;
12466 int exact_match
= 0;
12467 char *community
= NULL
;
12469 uint16_t show_flags
= 0;
12470 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12475 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12479 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12481 /* [<ipv4|ipv6> [all]] */
12483 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12485 if (argv_find(argv
, argc
, "ipv4", &idx
))
12486 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12488 if (argv_find(argv
, argc
, "ipv6", &idx
))
12489 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12493 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12495 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12498 return CMD_WARNING
;
12500 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12501 sh_type
= bgp_show_type_cidr_only
;
12503 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12504 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12505 sh_type
= bgp_show_type_dampend_paths
;
12506 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12507 sh_type
= bgp_show_type_flap_statistics
;
12510 if (argv_find(argv
, argc
, "community", &idx
)) {
12511 char *maybecomm
= NULL
;
12513 if (idx
+ 1 < argc
) {
12514 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12515 maybecomm
= argv
[idx
+ 1]->arg
;
12517 maybecomm
= argv
[idx
+ 1]->text
;
12520 if (maybecomm
&& !strmatch(maybecomm
, "json")
12521 && !strmatch(maybecomm
, "exact-match"))
12522 community
= maybecomm
;
12524 if (argv_find(argv
, argc
, "exact-match", &idx
))
12528 sh_type
= bgp_show_type_community_all
;
12531 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12532 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12533 struct community_list
*list
;
12535 if (argv_find(argv
, argc
, "exact-match", &idx
))
12538 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12539 COMMUNITY_LIST_MASTER
);
12540 if (list
== NULL
) {
12541 vty_out(vty
, "%% %s community-list not found\n",
12542 clist_number_or_name
);
12543 return CMD_WARNING
;
12547 sh_type
= bgp_show_type_community_list_exact
;
12549 sh_type
= bgp_show_type_community_list
;
12553 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12554 const char *filter
= argv
[++idx
]->arg
;
12555 struct as_list
*as_list
;
12557 as_list
= as_list_lookup(filter
);
12558 if (as_list
== NULL
) {
12559 vty_out(vty
, "%% %s AS-path access-list not found\n",
12561 return CMD_WARNING
;
12564 sh_type
= bgp_show_type_filter_list
;
12565 output_arg
= as_list
;
12568 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12569 const char *prefix_list_str
= argv
[++idx
]->arg
;
12570 struct prefix_list
*plist
;
12572 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12573 if (plist
== NULL
) {
12574 vty_out(vty
, "%% %s prefix-list not found\n",
12576 return CMD_WARNING
;
12579 sh_type
= bgp_show_type_prefix_list
;
12580 output_arg
= plist
;
12583 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12584 const char *access_list_str
= argv
[++idx
]->arg
;
12585 struct access_list
*alist
;
12587 alist
= access_list_lookup(afi
, access_list_str
);
12589 vty_out(vty
, "%% %s access-list not found\n",
12591 return CMD_WARNING
;
12594 sh_type
= bgp_show_type_access_list
;
12595 output_arg
= alist
;
12598 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12599 const char *rmap_str
= argv
[++idx
]->arg
;
12600 struct route_map
*rmap
;
12602 rmap
= route_map_lookup_by_name(rmap_str
);
12604 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12605 return CMD_WARNING
;
12608 sh_type
= bgp_show_type_route_map
;
12612 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12613 sh_type
= bgp_show_type_rpki
;
12614 if (argv_find(argv
, argc
, "valid", &idx
))
12615 rpki_target_state
= RPKI_VALID
;
12616 else if (argv_find(argv
, argc
, "invalid", &idx
))
12617 rpki_target_state
= RPKI_INVALID
;
12620 /* Display prefixes with matching version numbers */
12621 if (argv_find(argv
, argc
, "version", &idx
)) {
12622 sh_type
= bgp_show_type_prefix_version
;
12623 output_arg
= argv
[idx
+ 1]->arg
;
12626 /* Display prefixes with matching BGP community alias */
12627 if (argv_find(argv
, argc
, "alias", &idx
)) {
12628 sh_type
= bgp_show_type_community_alias
;
12629 output_arg
= argv
[idx
+ 1]->arg
;
12632 /* prefix-longer */
12633 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12634 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12635 const char *prefix_str
= argv
[idx
]->arg
;
12637 if (!str2prefix(prefix_str
, &p
)) {
12638 vty_out(vty
, "%% Malformed Prefix\n");
12639 return CMD_WARNING
;
12642 sh_type
= bgp_show_type_prefix_longer
;
12647 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12649 return bgp_show_community(vty
, bgp
, community
,
12650 exact_match
, afi
, safi
,
12653 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12654 output_arg
, show_flags
,
12655 rpki_target_state
);
12657 struct listnode
*node
;
12659 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12663 vty_out(vty
, "{\n");
12665 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12666 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12667 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12670 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12671 FOREACH_SAFI (safi
) {
12672 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12680 vty_out(vty
, ",\n");
12681 vty_out(vty
, "\"%s\":{\n",
12682 get_afi_safi_str(afi
,
12687 "\nFor address family: %s\n",
12693 bgp_show_community(
12694 vty
, abgp
, community
,
12695 exact_match
, afi
, safi
,
12698 bgp_show(vty
, abgp
, afi
, safi
,
12699 sh_type
, output_arg
,
12701 rpki_target_state
);
12703 vty_out(vty
, "}\n");
12707 /* show <ip> bgp all: for each AFI and SAFI*/
12708 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12709 FOREACH_AFI_SAFI (afi
, safi
) {
12710 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12718 vty_out(vty
, ",\n");
12720 vty_out(vty
, "\"%s\":{\n",
12721 get_afi_safi_str(afi
,
12726 "\nFor address family: %s\n",
12732 bgp_show_community(
12733 vty
, abgp
, community
,
12734 exact_match
, afi
, safi
,
12737 bgp_show(vty
, abgp
, afi
, safi
,
12738 sh_type
, output_arg
,
12740 rpki_target_state
);
12742 vty_out(vty
, "}\n");
12747 vty_out(vty
, "}\n");
12749 return CMD_SUCCESS
;
12752 DEFUN (show_ip_bgp_route
,
12753 show_ip_bgp_route_cmd
,
12754 "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]",
12758 BGP_INSTANCE_HELP_STR
12760 BGP_SAFI_WITH_LABEL_HELP_STR
12761 "Network in the BGP routing table to display\n"
12763 "Network in the BGP routing table to display\n"
12765 "Display only the bestpath\n"
12766 "Display only multipaths\n"
12767 "Display only paths that match the specified rpki state\n"
12768 "A valid path as determined by rpki\n"
12769 "A invalid path as determined by rpki\n"
12770 "A path that has no rpki data\n"
12773 int prefix_check
= 0;
12775 afi_t afi
= AFI_IP6
;
12776 safi_t safi
= SAFI_UNICAST
;
12777 char *prefix
= NULL
;
12778 struct bgp
*bgp
= NULL
;
12779 enum bgp_path_type path_type
;
12780 bool uj
= use_json(argc
, argv
);
12784 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12787 return CMD_WARNING
;
12791 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12792 return CMD_WARNING
;
12795 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12796 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12797 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12799 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12800 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12803 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12804 && afi
!= AFI_IP6
) {
12806 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12807 return CMD_WARNING
;
12809 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12810 && afi
!= AFI_IP
) {
12812 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12813 return CMD_WARNING
;
12816 prefix
= argv
[idx
]->arg
;
12818 /* [<bestpath|multipath>] */
12819 if (argv_find(argv
, argc
, "bestpath", &idx
))
12820 path_type
= BGP_PATH_SHOW_BESTPATH
;
12821 else if (argv_find(argv
, argc
, "multipath", &idx
))
12822 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12824 path_type
= BGP_PATH_SHOW_ALL
;
12826 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12827 path_type
, RPKI_NOT_BEING_USED
, uj
);
12830 DEFUN (show_ip_bgp_regexp
,
12831 show_ip_bgp_regexp_cmd
,
12832 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12836 BGP_INSTANCE_HELP_STR
12838 BGP_SAFI_WITH_LABEL_HELP_STR
12839 "Display routes matching the AS path regular expression\n"
12840 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12843 afi_t afi
= AFI_IP6
;
12844 safi_t safi
= SAFI_UNICAST
;
12845 struct bgp
*bgp
= NULL
;
12846 bool uj
= use_json(argc
, argv
);
12847 char *regstr
= NULL
;
12850 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12853 return CMD_WARNING
;
12855 // get index of regex
12856 if (argv_find(argv
, argc
, "REGEX", &idx
))
12857 regstr
= argv
[idx
]->arg
;
12860 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12861 bgp_show_type_regexp
, uj
);
12864 DEFPY (show_ip_bgp_instance_all
,
12865 show_ip_bgp_instance_all_cmd
,
12866 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12870 BGP_INSTANCE_ALL_HELP_STR
12872 BGP_SAFI_WITH_LABEL_HELP_STR
12874 "Increase table width for longer prefixes\n")
12876 afi_t afi
= AFI_IP6
;
12877 safi_t safi
= SAFI_UNICAST
;
12878 struct bgp
*bgp
= NULL
;
12880 uint16_t show_flags
= 0;
12884 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12888 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12890 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12893 return CMD_WARNING
;
12895 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12896 return CMD_SUCCESS
;
12899 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12900 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12905 uint16_t show_flags
= 0;
12908 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12910 if (!config_bgp_aspath_validate(regstr
)) {
12911 vty_out(vty
, "Invalid character in REGEX %s\n",
12913 return CMD_WARNING_CONFIG_FAILED
;
12916 regex
= bgp_regcomp(regstr
);
12918 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12919 return CMD_WARNING
;
12922 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
12923 RPKI_NOT_BEING_USED
);
12924 bgp_regex_free(regex
);
12928 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12929 const char *comstr
, int exact
, afi_t afi
,
12930 safi_t safi
, uint16_t show_flags
)
12932 struct community
*com
;
12935 com
= community_str2com(comstr
);
12937 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12938 return CMD_WARNING
;
12941 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12942 (exact
? bgp_show_type_community_exact
12943 : bgp_show_type_community
),
12944 com
, show_flags
, RPKI_NOT_BEING_USED
);
12945 community_free(&com
);
12951 BGP_STATS_MAXBITLEN
= 0,
12953 BGP_STATS_PREFIXES
,
12955 BGP_STATS_UNAGGREGATEABLE
,
12956 BGP_STATS_MAX_AGGREGATEABLE
,
12957 BGP_STATS_AGGREGATES
,
12959 BGP_STATS_ASPATH_COUNT
,
12960 BGP_STATS_ASPATH_MAXHOPS
,
12961 BGP_STATS_ASPATH_TOTHOPS
,
12962 BGP_STATS_ASPATH_MAXSIZE
,
12963 BGP_STATS_ASPATH_TOTSIZE
,
12964 BGP_STATS_ASN_HIGHEST
,
12968 #define TABLE_STATS_IDX_VTY 0
12969 #define TABLE_STATS_IDX_JSON 1
12971 static const char *table_stats_strs
[][2] = {
12972 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12973 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12974 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12975 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12976 "unaggregateablePrefixes"},
12977 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12978 "maximumAggregateablePrefixes"},
12979 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12980 "bgpAggregateAdvertisements"},
12981 [BGP_STATS_SPACE
] = {"Address space advertised",
12982 "addressSpaceAdvertised"},
12983 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12984 "advertisementsWithPaths"},
12985 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12987 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12989 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12990 "averageAsPathLengthHops"},
12991 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12992 "averageAsPathSizeBytes"},
12993 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12994 [BGP_STATS_MAX
] = {NULL
, NULL
}
12997 struct bgp_table_stats
{
12998 struct bgp_table
*table
;
12999 unsigned long long counts
[BGP_STATS_MAX
];
13002 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13005 double total_space
;
13008 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13009 struct bgp_table_stats
*ts
, unsigned int space
)
13011 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13012 struct bgp_path_info
*pi
;
13013 const struct prefix
*rn_p
;
13015 if (!bgp_dest_has_bgp_path_info_data(dest
))
13018 rn_p
= bgp_dest_get_prefix(dest
);
13019 ts
->counts
[BGP_STATS_PREFIXES
]++;
13020 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13022 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13023 /* check if the prefix is included by any other announcements */
13024 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13025 pdest
= bgp_dest_parent_nolock(pdest
);
13027 if (pdest
== NULL
|| pdest
== top
) {
13028 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13029 /* announced address space */
13031 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13032 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13033 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13036 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13037 ts
->counts
[BGP_STATS_RIB
]++;
13039 if (CHECK_FLAG(pi
->attr
->flag
,
13040 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13041 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13043 /* as-path stats */
13044 if (pi
->attr
->aspath
) {
13045 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13046 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13047 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13049 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13051 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13052 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13054 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13055 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13057 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13058 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13059 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13060 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13065 static void bgp_table_stats_walker(struct thread
*t
)
13067 struct bgp_dest
*dest
, *ndest
;
13068 struct bgp_dest
*top
;
13069 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13070 unsigned int space
= 0;
13072 if (!(top
= bgp_table_top(ts
->table
)))
13075 switch (ts
->table
->afi
) {
13077 space
= IPV4_MAX_BITLEN
;
13080 space
= IPV6_MAX_BITLEN
;
13083 space
= EVPN_ROUTE_PREFIXLEN
;
13089 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13091 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13092 if (ts
->table
->safi
== SAFI_MPLS_VPN
13093 || ts
->table
->safi
== SAFI_ENCAP
13094 || ts
->table
->safi
== SAFI_EVPN
) {
13095 struct bgp_table
*table
;
13097 table
= bgp_dest_get_bgp_table_info(dest
);
13101 top
= bgp_table_top(table
);
13102 for (ndest
= bgp_table_top(table
); ndest
;
13103 ndest
= bgp_route_next(ndest
))
13104 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13106 bgp_table_stats_rn(dest
, top
, ts
, space
);
13111 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13112 struct json_object
*json_array
)
13114 struct listnode
*node
, *nnode
;
13117 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13118 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13121 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13122 safi_t safi
, struct json_object
*json_array
)
13124 struct bgp_table_stats ts
;
13126 int ret
= CMD_SUCCESS
;
13128 struct json_object
*json
= NULL
;
13129 uint32_t bitlen
= 0;
13130 struct json_object
*json_bitlen
;
13133 json
= json_object_new_object();
13135 if (!bgp
->rib
[afi
][safi
]) {
13136 char warning_msg
[50];
13138 snprintf(warning_msg
, sizeof(warning_msg
),
13139 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13143 vty_out(vty
, "%s\n", warning_msg
);
13145 json_object_string_add(json
, "warning", warning_msg
);
13148 goto end_table_stats
;
13152 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13153 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13155 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13157 /* labeled-unicast routes live in the unicast table */
13158 if (safi
== SAFI_LABELED_UNICAST
)
13159 safi
= SAFI_UNICAST
;
13161 memset(&ts
, 0, sizeof(ts
));
13162 ts
.table
= bgp
->rib
[afi
][safi
];
13163 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13165 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13166 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13167 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13171 case BGP_STATS_ASPATH_TOTHOPS
:
13172 case BGP_STATS_ASPATH_TOTSIZE
:
13175 temp_buf
, sizeof(temp_buf
), "%12.2f",
13177 ? (float)ts
.counts
[i
]
13179 [BGP_STATS_ASPATH_COUNT
]
13181 vty_out(vty
, "%-30s: %s",
13182 table_stats_strs
[i
]
13183 [TABLE_STATS_IDX_VTY
],
13186 json_object_double_add(
13188 table_stats_strs
[i
]
13189 [TABLE_STATS_IDX_JSON
],
13191 ? (double)ts
.counts
[i
]
13192 / (double)ts
.counts
13193 [BGP_STATS_ASPATH_COUNT
]
13197 case BGP_STATS_TOTPLEN
:
13200 temp_buf
, sizeof(temp_buf
), "%12.2f",
13202 ? (float)ts
.counts
[i
]
13204 [BGP_STATS_PREFIXES
]
13206 vty_out(vty
, "%-30s: %s",
13207 table_stats_strs
[i
]
13208 [TABLE_STATS_IDX_VTY
],
13211 json_object_double_add(
13213 table_stats_strs
[i
]
13214 [TABLE_STATS_IDX_JSON
],
13216 ? (double)ts
.counts
[i
]
13217 / (double)ts
.counts
13218 [BGP_STATS_PREFIXES
]
13222 case BGP_STATS_SPACE
:
13224 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13226 vty_out(vty
, "%-30s: %s\n",
13227 table_stats_strs
[i
]
13228 [TABLE_STATS_IDX_VTY
],
13231 json_object_double_add(
13233 table_stats_strs
[i
]
13234 [TABLE_STATS_IDX_JSON
],
13235 (double)ts
.total_space
);
13237 if (afi
== AFI_IP6
) {
13239 snprintf(temp_buf
, sizeof(temp_buf
),
13242 * pow(2.0, -128 + 32));
13243 vty_out(vty
, "%30s: %s\n",
13244 "/32 equivalent %s\n",
13247 json_object_double_add(
13248 json
, "/32equivalent",
13249 (double)(ts
.total_space
13254 snprintf(temp_buf
, sizeof(temp_buf
),
13257 * pow(2.0, -128 + 48));
13258 vty_out(vty
, "%30s: %s\n",
13259 "/48 equivalent %s\n",
13262 json_object_double_add(
13263 json
, "/48equivalent",
13264 (double)(ts
.total_space
13270 snprintf(temp_buf
, sizeof(temp_buf
),
13272 ts
.total_space
* 100.
13274 vty_out(vty
, "%30s: %s\n",
13275 "% announced ", temp_buf
);
13277 json_object_double_add(
13278 json
, "%announced",
13279 (double)(ts
.total_space
* 100.
13283 snprintf(temp_buf
, sizeof(temp_buf
),
13286 * pow(2.0, -32 + 8));
13287 vty_out(vty
, "%30s: %s\n",
13288 "/8 equivalent ", temp_buf
);
13290 json_object_double_add(
13291 json
, "/8equivalent",
13292 (double)(ts
.total_space
13293 * pow(2.0, -32 + 8)));
13296 snprintf(temp_buf
, sizeof(temp_buf
),
13299 * pow(2.0, -32 + 24));
13300 vty_out(vty
, "%30s: %s\n",
13301 "/24 equivalent ", temp_buf
);
13303 json_object_double_add(
13304 json
, "/24equivalent",
13305 (double)(ts
.total_space
13306 * pow(2.0, -32 + 24)));
13312 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13314 vty_out(vty
, "%-30s: %s",
13315 table_stats_strs
[i
]
13316 [TABLE_STATS_IDX_VTY
],
13319 json_object_int_add(
13321 table_stats_strs
[i
]
13322 [TABLE_STATS_IDX_JSON
],
13327 vty_out(vty
, "\n");
13332 bitlen
= IPV4_MAX_BITLEN
;
13335 bitlen
= IPV6_MAX_BITLEN
;
13338 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13345 json_bitlen
= json_object_new_array();
13347 for (i
= 0; i
<= bitlen
; i
++) {
13348 struct json_object
*ind_bit
= json_object_new_object();
13350 if (!ts
.prefix_len_count
[i
])
13353 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13354 json_object_int_add(ind_bit
, temp_buf
,
13355 ts
.prefix_len_count
[i
]);
13356 json_object_array_add(json_bitlen
, ind_bit
);
13358 json_object_object_add(json
, "prefixLength", json_bitlen
);
13363 json_object_array_add(json_array
, json
);
13367 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13368 safi_t safi
, struct json_object
*json_array
)
13371 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13372 return CMD_SUCCESS
;
13375 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13387 PCOUNT_BPATH_SELECTED
,
13388 PCOUNT_PFCNT
, /* the figure we display to users */
13392 static const char *const pcount_strs
[] = {
13393 [PCOUNT_ADJ_IN
] = "Adj-in",
13394 [PCOUNT_DAMPED
] = "Damped",
13395 [PCOUNT_REMOVED
] = "Removed",
13396 [PCOUNT_HISTORY
] = "History",
13397 [PCOUNT_STALE
] = "Stale",
13398 [PCOUNT_VALID
] = "Valid",
13399 [PCOUNT_ALL
] = "All RIB",
13400 [PCOUNT_COUNTED
] = "PfxCt counted",
13401 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13402 [PCOUNT_PFCNT
] = "Useable",
13403 [PCOUNT_MAX
] = NULL
,
13406 struct peer_pcounts
{
13407 unsigned int count
[PCOUNT_MAX
];
13408 const struct peer
*peer
;
13409 const struct bgp_table
*table
;
13413 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13415 const struct bgp_adj_in
*ain
;
13416 const struct bgp_path_info
*pi
;
13417 const struct peer
*peer
= pc
->peer
;
13419 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13420 if (ain
->peer
== peer
)
13421 pc
->count
[PCOUNT_ADJ_IN
]++;
13423 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13425 if (pi
->peer
!= peer
)
13428 pc
->count
[PCOUNT_ALL
]++;
13430 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13431 pc
->count
[PCOUNT_DAMPED
]++;
13432 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13433 pc
->count
[PCOUNT_HISTORY
]++;
13434 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13435 pc
->count
[PCOUNT_REMOVED
]++;
13436 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13437 pc
->count
[PCOUNT_STALE
]++;
13438 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13439 pc
->count
[PCOUNT_VALID
]++;
13440 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13441 pc
->count
[PCOUNT_PFCNT
]++;
13442 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13443 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13445 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13446 pc
->count
[PCOUNT_COUNTED
]++;
13447 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13449 EC_LIB_DEVELOPMENT
,
13450 "Attempting to count but flags say it is unusable");
13452 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13454 EC_LIB_DEVELOPMENT
,
13455 "Not counted but flags say we should");
13460 static void bgp_peer_count_walker(struct thread
*t
)
13462 struct bgp_dest
*rn
, *rm
;
13463 const struct bgp_table
*table
;
13464 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13466 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13467 || pc
->safi
== SAFI_EVPN
) {
13468 /* Special handling for 2-level routing tables. */
13469 for (rn
= bgp_table_top(pc
->table
); rn
;
13470 rn
= bgp_route_next(rn
)) {
13471 table
= bgp_dest_get_bgp_table_info(rn
);
13473 for (rm
= bgp_table_top(table
); rm
;
13474 rm
= bgp_route_next(rm
))
13475 bgp_peer_count_proc(rm
, pc
);
13478 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13479 bgp_peer_count_proc(rn
, pc
);
13482 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13483 safi_t safi
, bool use_json
)
13485 struct peer_pcounts pcounts
= {.peer
= peer
};
13487 json_object
*json
= NULL
;
13488 json_object
*json_loop
= NULL
;
13491 json
= json_object_new_object();
13492 json_loop
= json_object_new_object();
13495 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13496 || !peer
->bgp
->rib
[afi
][safi
]) {
13498 json_object_string_add(
13500 "No such neighbor or address family");
13501 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13502 json_object_free(json
);
13503 json_object_free(json_loop
);
13505 vty_out(vty
, "%% No such neighbor or address family\n");
13507 return CMD_WARNING
;
13510 memset(&pcounts
, 0, sizeof(pcounts
));
13511 pcounts
.peer
= peer
;
13512 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13513 pcounts
.safi
= safi
;
13515 /* in-place call via thread subsystem so as to record execution time
13516 * stats for the thread-walk (i.e. ensure this can't be blamed on
13517 * on just vty_read()).
13519 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13522 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13523 json_object_string_add(json
, "multiProtocol",
13524 get_afi_safi_str(afi
, safi
, true));
13525 json_object_int_add(json
, "pfxCounter",
13526 peer
->pcount
[afi
][safi
]);
13528 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13529 json_object_int_add(json_loop
, pcount_strs
[i
],
13532 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13534 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13535 json_object_string_add(json
, "pfxctDriftFor",
13537 json_object_string_add(
13538 json
, "recommended",
13539 "Please report this bug, with the above command output");
13541 vty_json(vty
, json
);
13545 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13546 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13547 peer
->hostname
, peer
->host
,
13548 get_afi_safi_str(afi
, safi
, false));
13550 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13551 get_afi_safi_str(afi
, safi
, false));
13554 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13555 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13557 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13558 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13561 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13562 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13564 "Please report this bug, with the above command output\n");
13568 return CMD_SUCCESS
;
13571 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13572 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13573 "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]",
13577 BGP_INSTANCE_HELP_STR
13580 "Detailed information on TCP and BGP neighbor connections\n"
13581 "Neighbor to display information about\n"
13582 "Neighbor to display information about\n"
13583 "Neighbor on BGP configured interface\n"
13584 "Display detailed prefix count information\n"
13587 afi_t afi
= AFI_IP6
;
13588 safi_t safi
= SAFI_UNICAST
;
13591 struct bgp
*bgp
= NULL
;
13592 bool uj
= use_json(argc
, argv
);
13597 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13600 return CMD_WARNING
;
13602 argv_find(argv
, argc
, "neighbors", &idx
);
13603 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13605 return CMD_WARNING
;
13607 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13610 #ifdef KEEP_OLD_VPN_COMMANDS
13611 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13612 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13613 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13618 "Display information about all VPNv4 NLRIs\n"
13619 "Detailed information on TCP and BGP neighbor connections\n"
13620 "Neighbor to display information about\n"
13621 "Neighbor to display information about\n"
13622 "Neighbor on BGP configured interface\n"
13623 "Display detailed prefix count information\n"
13628 bool uj
= use_json(argc
, argv
);
13630 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13632 return CMD_WARNING
;
13634 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13637 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13638 show_ip_bgp_vpn_all_route_prefix_cmd
,
13639 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13644 "Display information about all VPNv4 NLRIs\n"
13645 "Network in the BGP routing table to display\n"
13646 "Network in the BGP routing table to display\n"
13650 char *network
= NULL
;
13651 struct bgp
*bgp
= bgp_get_default();
13653 vty_out(vty
, "Can't find default instance\n");
13654 return CMD_WARNING
;
13657 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13658 network
= argv
[idx
]->arg
;
13659 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13660 network
= argv
[idx
]->arg
;
13662 vty_out(vty
, "Unable to figure out Network\n");
13663 return CMD_WARNING
;
13666 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13667 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13668 use_json(argc
, argv
));
13670 #endif /* KEEP_OLD_VPN_COMMANDS */
13672 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13673 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13674 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13679 "Network in the BGP routing table to display\n"
13680 "Network in the BGP routing table to display\n"
13681 "Network in the BGP routing table to display\n"
13682 "Network in the BGP routing table to display\n"
13686 char *network
= NULL
;
13687 int prefix_check
= 0;
13689 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13690 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13691 network
= argv
[idx
]->arg
;
13692 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13693 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13694 network
= argv
[idx
]->arg
;
13697 vty_out(vty
, "Unable to figure out Network\n");
13698 return CMD_WARNING
;
13700 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13701 prefix_check
, BGP_PATH_SHOW_ALL
,
13702 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13705 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13706 struct bgp_table
*table
, int *header1
,
13707 int *header2
, json_object
*json
,
13708 json_object
*json_scode
,
13709 json_object
*json_ocode
, bool wide
)
13711 uint64_t version
= table
? table
->version
: 0;
13715 json_object_int_add(json
, "bgpTableVersion", version
);
13716 json_object_string_addf(json
, "bgpLocalRouterId",
13717 "%pI4", &peer
->bgp
->router_id
);
13718 json_object_int_add(json
, "defaultLocPrf",
13719 peer
->bgp
->default_local_pref
);
13720 json_object_int_add(json
, "localAS",
13721 peer
->change_local_as
13722 ? peer
->change_local_as
13724 json_object_object_add(json
, "bgpStatusCodes",
13726 json_object_object_add(json
, "bgpOriginCodes",
13730 "BGP table version is %" PRIu64
13731 ", local router ID is %pI4, vrf id ",
13732 version
, &peer
->bgp
->router_id
);
13733 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
13734 vty_out(vty
, "%s", VRFID_NONE_STR
);
13736 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
13737 vty_out(vty
, "\n");
13738 vty_out(vty
, "Default local pref %u, ",
13739 peer
->bgp
->default_local_pref
);
13740 vty_out(vty
, "local AS %u\n",
13741 peer
->change_local_as
? peer
->change_local_as
13743 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13744 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13745 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13746 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13752 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13753 : BGP_SHOW_HEADER
));
13759 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13760 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13761 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13762 json_object
*json_scode
, json_object
*json_ocode
,
13763 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13764 unsigned long *output_count
, unsigned long *filtered_count
)
13766 struct bgp_adj_in
*ain
;
13767 struct bgp_adj_out
*adj
;
13768 struct bgp_dest
*dest
;
13772 struct update_subgroup
*subgrp
;
13773 struct peer_af
*paf
;
13774 bool route_filtered
;
13775 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13776 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13777 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13778 || (safi
== SAFI_EVPN
))
13784 subgrp
= peer_subgroup(peer
, afi
, safi
);
13786 if (type
== bgp_show_adj_route_advertised
&& subgrp
13787 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13789 json_object_int_add(json
, "bgpTableVersion",
13791 json_object_string_addf(json
, "bgpLocalRouterId",
13792 "%pI4", &bgp
->router_id
);
13793 json_object_int_add(json
, "defaultLocPrf",
13794 bgp
->default_local_pref
);
13795 json_object_int_add(json
, "localAS",
13796 peer
->change_local_as
13797 ? peer
->change_local_as
13799 json_object_object_add(json
, "bgpStatusCodes",
13801 json_object_object_add(json
, "bgpOriginCodes",
13803 json_object_string_add(
13804 json
, "bgpOriginatingDefaultNetwork",
13805 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13808 "BGP table version is %" PRIu64
13809 ", local router ID is %pI4, vrf id ",
13810 table
->version
, &bgp
->router_id
);
13811 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13812 vty_out(vty
, "%s", VRFID_NONE_STR
);
13814 vty_out(vty
, "%u", bgp
->vrf_id
);
13815 vty_out(vty
, "\n");
13816 vty_out(vty
, "Default local pref %u, ",
13817 bgp
->default_local_pref
);
13818 vty_out(vty
, "local AS %u\n",
13819 peer
->change_local_as
? peer
->change_local_as
13821 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13822 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13823 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13824 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13826 vty_out(vty
, "Originating default network %s\n\n",
13827 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13832 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13833 if (type
== bgp_show_adj_route_received
13834 || type
== bgp_show_adj_route_filtered
) {
13835 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13836 if (ain
->peer
!= peer
)
13839 show_adj_route_header(vty
, peer
, table
, header1
,
13840 header2
, json
, json_scode
,
13843 if ((safi
== SAFI_MPLS_VPN
)
13844 || (safi
== SAFI_ENCAP
)
13845 || (safi
== SAFI_EVPN
)) {
13847 json_object_string_add(
13848 json_ar
, "rd", rd_str
);
13849 else if (show_rd
&& rd_str
) {
13851 "Route Distinguisher: %s\n",
13858 route_filtered
= false;
13860 /* Filter prefix using distribute list,
13861 * filter list or prefix list
13863 const struct prefix
*rn_p
=
13864 bgp_dest_get_prefix(dest
);
13865 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13868 route_filtered
= true;
13870 /* Filter prefix using route-map */
13871 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13872 safi
, rmap_name
, NULL
,
13875 if (type
== bgp_show_adj_route_filtered
&&
13876 !route_filtered
&& ret
!= RMAP_DENY
) {
13877 bgp_attr_flush(&attr
);
13881 if (type
== bgp_show_adj_route_received
13882 && (route_filtered
|| ret
== RMAP_DENY
))
13883 (*filtered_count
)++;
13885 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
13886 use_json
, json_ar
, wide
);
13887 bgp_attr_flush(&attr
);
13890 } else if (type
== bgp_show_adj_route_advertised
) {
13891 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13892 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13893 if (paf
->peer
!= peer
|| !adj
->attr
)
13896 show_adj_route_header(vty
, peer
, table
,
13901 const struct prefix
*rn_p
=
13902 bgp_dest_get_prefix(dest
);
13905 ret
= bgp_output_modifier(
13906 peer
, rn_p
, &attr
, afi
, safi
,
13909 if (ret
!= RMAP_DENY
) {
13910 if ((safi
== SAFI_MPLS_VPN
)
13911 || (safi
== SAFI_ENCAP
)
13912 || (safi
== SAFI_EVPN
)) {
13914 json_object_string_add(
13921 "Route Distinguisher: %s\n",
13927 vty
, dest
, rn_p
, &attr
,
13928 safi
, use_json
, json_ar
,
13932 (*filtered_count
)++;
13935 bgp_attr_flush(&attr
);
13937 } else if (type
== bgp_show_adj_route_bestpath
) {
13938 struct bgp_path_info
*pi
;
13940 show_adj_route_header(vty
, peer
, table
, header1
,
13941 header2
, json
, json_scode
,
13944 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13946 if (pi
->peer
!= peer
)
13949 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13952 route_vty_out_tmp(vty
, dest
,
13953 bgp_dest_get_prefix(dest
),
13954 pi
->attr
, safi
, use_json
,
13962 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13963 safi_t safi
, enum bgp_show_adj_route_type type
,
13964 const char *rmap_name
, uint16_t show_flags
)
13967 struct bgp_table
*table
;
13968 json_object
*json
= NULL
;
13969 json_object
*json_scode
= NULL
;
13970 json_object
*json_ocode
= NULL
;
13971 json_object
*json_ar
= NULL
;
13972 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13974 /* Init BGP headers here so they're only displayed once
13975 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13981 * Initialize variables for each RD
13982 * All prefixes under an RD is aggregated within "json_routes"
13984 char rd_str
[BUFSIZ
] = {0};
13985 json_object
*json_routes
= NULL
;
13988 /* For 2-tier tables, prefix counts need to be
13989 * maintained across multiple runs of show_adj_route()
13991 unsigned long output_count_per_rd
;
13992 unsigned long filtered_count_per_rd
;
13993 unsigned long output_count
= 0;
13994 unsigned long filtered_count
= 0;
13997 json
= json_object_new_object();
13998 json_ar
= json_object_new_object();
13999 json_scode
= json_object_new_object();
14000 json_ocode
= json_object_new_object();
14002 json_object_string_add(json_scode
, "suppressed", "s");
14003 json_object_string_add(json_scode
, "damped", "d");
14004 json_object_string_add(json_scode
, "history", "h");
14005 json_object_string_add(json_scode
, "valid", "*");
14006 json_object_string_add(json_scode
, "best", ">");
14007 json_object_string_add(json_scode
, "multipath", "=");
14008 json_object_string_add(json_scode
, "internal", "i");
14009 json_object_string_add(json_scode
, "ribFailure", "r");
14010 json_object_string_add(json_scode
, "stale", "S");
14011 json_object_string_add(json_scode
, "removed", "R");
14013 json_object_string_add(json_ocode
, "igp", "i");
14014 json_object_string_add(json_ocode
, "egp", "e");
14015 json_object_string_add(json_ocode
, "incomplete", "?");
14018 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14020 json_object_string_add(
14022 "No such neighbor or address family");
14023 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14024 json_object_free(json
);
14025 json_object_free(json_ar
);
14026 json_object_free(json_scode
);
14027 json_object_free(json_ocode
);
14029 vty_out(vty
, "%% No such neighbor or address family\n");
14031 return CMD_WARNING
;
14034 if ((type
== bgp_show_adj_route_received
14035 || type
== bgp_show_adj_route_filtered
)
14036 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14037 PEER_FLAG_SOFT_RECONFIG
)) {
14039 json_object_string_add(
14041 "Inbound soft reconfiguration not enabled");
14042 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14043 json_object_free(json
);
14044 json_object_free(json_ar
);
14045 json_object_free(json_scode
);
14046 json_object_free(json_ocode
);
14049 "%% Inbound soft reconfiguration not enabled\n");
14051 return CMD_WARNING
;
14056 /* labeled-unicast routes live in the unicast table */
14057 if (safi
== SAFI_LABELED_UNICAST
)
14058 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14060 table
= bgp
->rib
[afi
][safi
];
14062 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14063 || (safi
== SAFI_EVPN
)) {
14065 struct bgp_dest
*dest
;
14067 for (dest
= bgp_table_top(table
); dest
;
14068 dest
= bgp_route_next(dest
)) {
14069 table
= bgp_dest_get_bgp_table_info(dest
);
14073 output_count_per_rd
= 0;
14074 filtered_count_per_rd
= 0;
14077 json_routes
= json_object_new_object();
14079 const struct prefix_rd
*prd
;
14080 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14083 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
14085 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
14086 rmap_name
, json
, json_routes
, json_scode
,
14087 json_ocode
, show_flags
, &header1
,
14088 &header2
, rd_str
, &output_count_per_rd
,
14089 &filtered_count_per_rd
);
14091 /* Don't include an empty RD in the output! */
14092 if (json_routes
&& (output_count_per_rd
> 0))
14093 json_object_object_add(json_ar
, rd_str
,
14096 output_count
+= output_count_per_rd
;
14097 filtered_count
+= filtered_count_per_rd
;
14100 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14101 json
, json_ar
, json_scode
, json_ocode
,
14102 show_flags
, &header1
, &header2
, rd_str
,
14103 &output_count
, &filtered_count
);
14106 if (type
== bgp_show_adj_route_advertised
)
14107 json_object_object_add(json
, "advertisedRoutes",
14110 json_object_object_add(json
, "receivedRoutes", json_ar
);
14111 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14112 json_object_int_add(json
, "filteredPrefixCounter",
14116 * These fields only give up ownership to `json` when `header1`
14117 * is used (set to zero). See code in `show_adj_route` and
14118 * `show_adj_route_header`.
14120 if (header1
== 1) {
14121 json_object_free(json_scode
);
14122 json_object_free(json_ocode
);
14125 vty_json(vty
, json
);
14126 } else if (output_count
> 0) {
14127 if (filtered_count
> 0)
14129 "\nTotal number of prefixes %ld (%ld filtered)\n",
14130 output_count
, filtered_count
);
14132 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14136 return CMD_SUCCESS
;
14139 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14140 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14141 "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]",
14145 BGP_INSTANCE_HELP_STR
14147 BGP_SAFI_WITH_LABEL_HELP_STR
14148 "Detailed information on TCP and BGP neighbor connections\n"
14149 "Neighbor to display information about\n"
14150 "Neighbor to display information about\n"
14151 "Neighbor on BGP configured interface\n"
14152 "Display the routes selected by best path\n"
14154 "Increase table width for longer prefixes\n")
14156 afi_t afi
= AFI_IP6
;
14157 safi_t safi
= SAFI_UNICAST
;
14158 char *rmap_name
= NULL
;
14159 char *peerstr
= NULL
;
14160 struct bgp
*bgp
= NULL
;
14162 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14164 uint16_t show_flags
= 0;
14167 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14170 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14172 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14176 return CMD_WARNING
;
14178 argv_find(argv
, argc
, "neighbors", &idx
);
14179 peerstr
= argv
[++idx
]->arg
;
14181 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14183 return CMD_WARNING
;
14185 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14189 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
14190 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14191 "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]",
14195 BGP_INSTANCE_HELP_STR
14197 BGP_SAFI_WITH_LABEL_HELP_STR
14198 "Display the entries for all address families\n"
14199 "Detailed information on TCP and BGP neighbor connections\n"
14200 "Neighbor to display information about\n"
14201 "Neighbor to display information about\n"
14202 "Neighbor on BGP configured interface\n"
14203 "Display the routes advertised to a BGP neighbor\n"
14204 "Display the received routes from neighbor\n"
14205 "Display the filtered routes received from neighbor\n"
14206 "Route-map to modify the attributes\n"
14207 "Name of the route map\n"
14209 "Increase table width for longer prefixes\n")
14211 afi_t afi
= AFI_IP6
;
14212 safi_t safi
= SAFI_UNICAST
;
14213 char *peerstr
= NULL
;
14214 struct bgp
*bgp
= NULL
;
14216 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14219 uint16_t show_flags
= 0;
14220 struct listnode
*node
;
14225 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14229 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14230 if (argv_find(argv
, argc
, "ipv4", &idx
))
14231 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14233 if (argv_find(argv
, argc
, "ipv6", &idx
))
14234 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14238 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14240 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14243 return CMD_WARNING
;
14245 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14246 argv_find(argv
, argc
, "neighbors", &idx
);
14247 peerstr
= argv
[++idx
]->arg
;
14249 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14251 return CMD_WARNING
;
14253 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14254 type
= bgp_show_adj_route_advertised
;
14255 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14256 type
= bgp_show_adj_route_received
;
14257 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14258 type
= bgp_show_adj_route_filtered
;
14261 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14264 vty_out(vty
, "{\n");
14266 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14267 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14268 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14270 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14271 FOREACH_SAFI (safi
) {
14272 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14279 vty_out(vty
, ",\n");
14280 vty_out(vty
, "\"%s\":",
14281 get_afi_safi_str(afi
, safi
,
14285 "\nFor address family: %s\n",
14286 get_afi_safi_str(afi
, safi
,
14289 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14290 route_map
, show_flags
);
14294 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14295 FOREACH_AFI_SAFI (afi
, safi
) {
14296 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14303 vty_out(vty
, ",\n");
14304 vty_out(vty
, "\"%s\":",
14305 get_afi_safi_str(afi
, safi
,
14309 "\nFor address family: %s\n",
14310 get_afi_safi_str(afi
, safi
,
14313 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14314 route_map
, show_flags
);
14319 vty_out(vty
, "}\n");
14321 return CMD_SUCCESS
;
14324 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14325 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14326 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14330 BGP_INSTANCE_HELP_STR
14333 BGP_AF_MODIFIER_STR
14334 "Detailed information on TCP and BGP neighbor connections\n"
14335 "Neighbor to display information about\n"
14336 "Neighbor to display information about\n"
14337 "Neighbor on BGP configured interface\n"
14338 "Display information received from a BGP neighbor\n"
14339 "Display the prefixlist filter\n"
14342 afi_t afi
= AFI_IP6
;
14343 safi_t safi
= SAFI_UNICAST
;
14344 char *peerstr
= NULL
;
14349 struct bgp
*bgp
= NULL
;
14350 bool uj
= use_json(argc
, argv
);
14355 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14358 return CMD_WARNING
;
14360 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14361 argv_find(argv
, argc
, "neighbors", &idx
);
14362 peerstr
= argv
[++idx
]->arg
;
14364 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14366 return CMD_WARNING
;
14368 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14369 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14372 vty_out(vty
, "Address Family: %s\n",
14373 get_afi_safi_str(afi
, safi
, false));
14374 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14377 vty_out(vty
, "{}\n");
14379 vty_out(vty
, "No functional output\n");
14382 return CMD_SUCCESS
;
14385 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14386 afi_t afi
, safi_t safi
,
14387 enum bgp_show_type type
, bool use_json
)
14389 uint16_t show_flags
= 0;
14392 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14394 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14396 json_object
*json_no
= NULL
;
14397 json_no
= json_object_new_object();
14398 json_object_string_add(
14399 json_no
, "warning",
14400 "No such neighbor or address family");
14401 vty_out(vty
, "%s\n",
14402 json_object_to_json_string(json_no
));
14403 json_object_free(json_no
);
14405 vty_out(vty
, "%% No such neighbor or address family\n");
14406 return CMD_WARNING
;
14409 /* labeled-unicast routes live in the unicast table */
14410 if (safi
== SAFI_LABELED_UNICAST
)
14411 safi
= SAFI_UNICAST
;
14413 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14414 RPKI_NOT_BEING_USED
);
14417 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14418 show_ip_bgp_flowspec_routes_detailed_cmd
,
14419 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14423 BGP_INSTANCE_HELP_STR
14426 "Detailed information on flowspec entries\n"
14429 afi_t afi
= AFI_IP6
;
14430 safi_t safi
= SAFI_UNICAST
;
14431 struct bgp
*bgp
= NULL
;
14433 bool uj
= use_json(argc
, argv
);
14434 uint16_t show_flags
= BGP_SHOW_OPT_DETAIL
;
14438 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14441 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14444 return CMD_WARNING
;
14446 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14447 show_flags
, RPKI_NOT_BEING_USED
);
14450 DEFUN (show_ip_bgp_neighbor_routes
,
14451 show_ip_bgp_neighbor_routes_cmd
,
14452 "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]",
14456 BGP_INSTANCE_HELP_STR
14458 BGP_SAFI_WITH_LABEL_HELP_STR
14459 "Detailed information on TCP and BGP neighbor connections\n"
14460 "Neighbor to display information about\n"
14461 "Neighbor to display information about\n"
14462 "Neighbor on BGP configured interface\n"
14463 "Display flap statistics of the routes learned from neighbor\n"
14464 "Display the dampened routes received from neighbor\n"
14465 "Display routes learned from neighbor\n"
14468 char *peerstr
= NULL
;
14469 struct bgp
*bgp
= NULL
;
14470 afi_t afi
= AFI_IP6
;
14471 safi_t safi
= SAFI_UNICAST
;
14473 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14475 bool uj
= use_json(argc
, argv
);
14480 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14483 return CMD_WARNING
;
14485 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14486 argv_find(argv
, argc
, "neighbors", &idx
);
14487 peerstr
= argv
[++idx
]->arg
;
14489 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14491 return CMD_WARNING
;
14493 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14494 sh_type
= bgp_show_type_flap_neighbor
;
14495 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14496 sh_type
= bgp_show_type_damp_neighbor
;
14497 else if (argv_find(argv
, argc
, "routes", &idx
))
14498 sh_type
= bgp_show_type_neighbor
;
14500 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14503 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14505 struct bgp_distance
{
14506 /* Distance value for the IP source prefix. */
14509 /* Name of the access-list to be matched. */
14513 DEFUN (show_bgp_afi_vpn_rd_route
,
14514 show_bgp_afi_vpn_rd_route_cmd
,
14515 "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]",
14519 BGP_AF_MODIFIER_STR
14520 "Display information for a route distinguisher\n"
14521 "Route Distinguisher\n"
14522 "All Route Distinguishers\n"
14523 "Network in the BGP routing table to display\n"
14524 "Network in the BGP routing table to display\n"
14528 struct prefix_rd prd
;
14529 afi_t afi
= AFI_MAX
;
14532 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14533 vty_out(vty
, "%% Malformed Address Family\n");
14534 return CMD_WARNING
;
14537 if (!strcmp(argv
[5]->arg
, "all"))
14538 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14539 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14540 RPKI_NOT_BEING_USED
,
14541 use_json(argc
, argv
));
14543 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14545 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14546 return CMD_WARNING
;
14549 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14550 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14551 use_json(argc
, argv
));
14554 static struct bgp_distance
*bgp_distance_new(void)
14556 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14559 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14561 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14564 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14565 const char *ip_str
, const char *access_list_str
)
14572 struct bgp_dest
*dest
;
14573 struct bgp_distance
*bdistance
;
14575 afi
= bgp_node_afi(vty
);
14576 safi
= bgp_node_safi(vty
);
14578 ret
= str2prefix(ip_str
, &p
);
14580 vty_out(vty
, "Malformed prefix\n");
14581 return CMD_WARNING_CONFIG_FAILED
;
14584 distance
= atoi(distance_str
);
14586 /* Get BGP distance node. */
14587 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14588 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14590 bgp_dest_unlock_node(dest
);
14592 bdistance
= bgp_distance_new();
14593 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14596 /* Set distance value. */
14597 bdistance
->distance
= distance
;
14599 /* Reset access-list configuration. */
14600 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14601 if (access_list_str
)
14602 bdistance
->access_list
=
14603 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14605 return CMD_SUCCESS
;
14608 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14609 const char *ip_str
, const char *access_list_str
)
14616 struct bgp_dest
*dest
;
14617 struct bgp_distance
*bdistance
;
14619 afi
= bgp_node_afi(vty
);
14620 safi
= bgp_node_safi(vty
);
14622 ret
= str2prefix(ip_str
, &p
);
14624 vty_out(vty
, "Malformed prefix\n");
14625 return CMD_WARNING_CONFIG_FAILED
;
14628 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14630 vty_out(vty
, "Can't find specified prefix\n");
14631 return CMD_WARNING_CONFIG_FAILED
;
14634 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14635 distance
= atoi(distance_str
);
14637 if (bdistance
->distance
!= distance
) {
14638 vty_out(vty
, "Distance does not match configured\n");
14639 bgp_dest_unlock_node(dest
);
14640 return CMD_WARNING_CONFIG_FAILED
;
14643 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14644 bgp_distance_free(bdistance
);
14646 bgp_dest_set_bgp_path_info(dest
, NULL
);
14647 bgp_dest_unlock_node(dest
);
14648 bgp_dest_unlock_node(dest
);
14650 return CMD_SUCCESS
;
14653 /* Apply BGP information to distance method. */
14654 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14655 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14657 struct bgp_dest
*dest
;
14658 struct prefix q
= {0};
14660 struct bgp_distance
*bdistance
;
14661 struct access_list
*alist
;
14662 struct bgp_static
*bgp_static
;
14667 peer
= pinfo
->peer
;
14669 if (pinfo
->attr
->distance
)
14670 return pinfo
->attr
->distance
;
14672 /* Check source address.
14673 * Note: for aggregate route, peer can have unspec af type.
14675 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14676 && !sockunion2hostprefix(&peer
->su
, &q
))
14679 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14681 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14682 bgp_dest_unlock_node(dest
);
14684 if (bdistance
->access_list
) {
14685 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14687 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14688 return bdistance
->distance
;
14690 return bdistance
->distance
;
14693 /* Backdoor check. */
14694 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14696 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14697 bgp_dest_unlock_node(dest
);
14699 if (bgp_static
->backdoor
) {
14700 if (bgp
->distance_local
[afi
][safi
])
14701 return bgp
->distance_local
[afi
][safi
];
14703 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14707 if (peer
->sort
== BGP_PEER_EBGP
) {
14708 if (bgp
->distance_ebgp
[afi
][safi
])
14709 return bgp
->distance_ebgp
[afi
][safi
];
14710 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14711 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14712 if (bgp
->distance_ibgp
[afi
][safi
])
14713 return bgp
->distance_ibgp
[afi
][safi
];
14714 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14716 if (bgp
->distance_local
[afi
][safi
])
14717 return bgp
->distance_local
[afi
][safi
];
14718 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14722 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14723 * we should tell ZEBRA update the routes for a specific
14724 * AFI/SAFI to reflect changes in RIB.
14726 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
14728 safi_t update_safi
)
14733 FOREACH_AFI_SAFI (afi
, safi
) {
14734 if (!bgp_fibupd_safi(safi
))
14737 if (afi
!= update_afi
&& safi
!= update_safi
)
14740 if (BGP_DEBUG(zebra
, ZEBRA
))
14742 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14743 __func__
, afi
, safi
);
14744 bgp_zebra_announce_table(bgp
, afi
, safi
);
14748 DEFUN (bgp_distance
,
14750 "distance bgp (1-255) (1-255) (1-255)",
14751 "Define an administrative distance\n"
14753 "Distance for routes external to the AS\n"
14754 "Distance for routes internal to the AS\n"
14755 "Distance for local routes\n")
14757 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14758 int idx_number
= 2;
14759 int idx_number_2
= 3;
14760 int idx_number_3
= 4;
14761 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
14762 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
14763 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
14767 afi
= bgp_node_afi(vty
);
14768 safi
= bgp_node_safi(vty
);
14770 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
14771 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
14772 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
14773 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
14774 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
14775 bgp
->distance_local
[afi
][safi
] = distance_local
;
14776 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14778 return CMD_SUCCESS
;
14781 DEFUN (no_bgp_distance
,
14782 no_bgp_distance_cmd
,
14783 "no distance bgp [(1-255) (1-255) (1-255)]",
14785 "Define an administrative distance\n"
14787 "Distance for routes external to the AS\n"
14788 "Distance for routes internal to the AS\n"
14789 "Distance for local routes\n")
14791 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14795 afi
= bgp_node_afi(vty
);
14796 safi
= bgp_node_safi(vty
);
14798 if (bgp
->distance_ebgp
[afi
][safi
] != 0
14799 || bgp
->distance_ibgp
[afi
][safi
] != 0
14800 || bgp
->distance_local
[afi
][safi
] != 0) {
14801 bgp
->distance_ebgp
[afi
][safi
] = 0;
14802 bgp
->distance_ibgp
[afi
][safi
] = 0;
14803 bgp
->distance_local
[afi
][safi
] = 0;
14804 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14806 return CMD_SUCCESS
;
14810 DEFUN (bgp_distance_source
,
14811 bgp_distance_source_cmd
,
14812 "distance (1-255) A.B.C.D/M",
14813 "Define an administrative distance\n"
14814 "Administrative distance\n"
14815 "IP source prefix\n")
14817 int idx_number
= 1;
14818 int idx_ipv4_prefixlen
= 2;
14819 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14820 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14821 return CMD_SUCCESS
;
14824 DEFUN (no_bgp_distance_source
,
14825 no_bgp_distance_source_cmd
,
14826 "no distance (1-255) A.B.C.D/M",
14828 "Define an administrative distance\n"
14829 "Administrative distance\n"
14830 "IP source prefix\n")
14832 int idx_number
= 2;
14833 int idx_ipv4_prefixlen
= 3;
14834 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14835 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14836 return CMD_SUCCESS
;
14839 DEFUN (bgp_distance_source_access_list
,
14840 bgp_distance_source_access_list_cmd
,
14841 "distance (1-255) A.B.C.D/M WORD",
14842 "Define an administrative distance\n"
14843 "Administrative distance\n"
14844 "IP source prefix\n"
14845 "Access list name\n")
14847 int idx_number
= 1;
14848 int idx_ipv4_prefixlen
= 2;
14850 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14851 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14852 return CMD_SUCCESS
;
14855 DEFUN (no_bgp_distance_source_access_list
,
14856 no_bgp_distance_source_access_list_cmd
,
14857 "no distance (1-255) A.B.C.D/M WORD",
14859 "Define an administrative distance\n"
14860 "Administrative distance\n"
14861 "IP source prefix\n"
14862 "Access list name\n")
14864 int idx_number
= 2;
14865 int idx_ipv4_prefixlen
= 3;
14867 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14868 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14869 return CMD_SUCCESS
;
14872 DEFUN (ipv6_bgp_distance_source
,
14873 ipv6_bgp_distance_source_cmd
,
14874 "distance (1-255) X:X::X:X/M",
14875 "Define an administrative distance\n"
14876 "Administrative distance\n"
14877 "IP source prefix\n")
14879 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
14880 return CMD_SUCCESS
;
14883 DEFUN (no_ipv6_bgp_distance_source
,
14884 no_ipv6_bgp_distance_source_cmd
,
14885 "no distance (1-255) X:X::X:X/M",
14887 "Define an administrative distance\n"
14888 "Administrative distance\n"
14889 "IP source prefix\n")
14891 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
14892 return CMD_SUCCESS
;
14895 DEFUN (ipv6_bgp_distance_source_access_list
,
14896 ipv6_bgp_distance_source_access_list_cmd
,
14897 "distance (1-255) X:X::X:X/M WORD",
14898 "Define an administrative distance\n"
14899 "Administrative distance\n"
14900 "IP source prefix\n"
14901 "Access list name\n")
14903 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
14904 return CMD_SUCCESS
;
14907 DEFUN (no_ipv6_bgp_distance_source_access_list
,
14908 no_ipv6_bgp_distance_source_access_list_cmd
,
14909 "no distance (1-255) X:X::X:X/M WORD",
14911 "Define an administrative distance\n"
14912 "Administrative distance\n"
14913 "IP source prefix\n"
14914 "Access list name\n")
14916 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
14917 return CMD_SUCCESS
;
14920 DEFUN (bgp_damp_set
,
14922 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
14923 "BGP Specific commands\n"
14924 "Enable route-flap dampening\n"
14925 "Half-life time for the penalty\n"
14926 "Value to start reusing a route\n"
14927 "Value to start suppressing a route\n"
14928 "Maximum duration to suppress a stable route\n")
14930 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14931 int idx_half_life
= 2;
14933 int idx_suppress
= 4;
14934 int idx_max_suppress
= 5;
14935 int half
= DEFAULT_HALF_LIFE
* 60;
14936 int reuse
= DEFAULT_REUSE
;
14937 int suppress
= DEFAULT_SUPPRESS
;
14938 int max
= 4 * half
;
14941 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14942 reuse
= atoi(argv
[idx_reuse
]->arg
);
14943 suppress
= atoi(argv
[idx_suppress
]->arg
);
14944 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
14945 } else if (argc
== 3) {
14946 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14951 * These can't be 0 but our SA doesn't understand the
14952 * way our cli is constructed
14956 if (suppress
< reuse
) {
14958 "Suppress value cannot be less than reuse value \n");
14962 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
14963 reuse
, suppress
, max
);
14966 DEFUN (bgp_damp_unset
,
14967 bgp_damp_unset_cmd
,
14968 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
14970 "BGP Specific commands\n"
14971 "Enable route-flap dampening\n"
14972 "Half-life time for the penalty\n"
14973 "Value to start reusing a route\n"
14974 "Value to start suppressing a route\n"
14975 "Maximum duration to suppress a stable route\n")
14977 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14978 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
14981 /* Display specified route of BGP table. */
14982 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14983 const char *ip_str
, afi_t afi
, safi_t safi
,
14984 struct prefix_rd
*prd
, int prefix_check
)
14987 struct prefix match
;
14988 struct bgp_dest
*dest
;
14989 struct bgp_dest
*rm
;
14990 struct bgp_path_info
*pi
;
14991 struct bgp_path_info
*pi_temp
;
14993 struct bgp_table
*table
;
14995 /* BGP structure lookup. */
14997 bgp
= bgp_lookup_by_name(view_name
);
14999 vty_out(vty
, "%% Can't find BGP instance %s\n",
15001 return CMD_WARNING
;
15004 bgp
= bgp_get_default();
15006 vty_out(vty
, "%% No BGP process is configured\n");
15007 return CMD_WARNING
;
15011 /* Check IP address argument. */
15012 ret
= str2prefix(ip_str
, &match
);
15014 vty_out(vty
, "%% address is malformed\n");
15015 return CMD_WARNING
;
15018 match
.family
= afi2family(afi
);
15020 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15021 || (safi
== SAFI_EVPN
)) {
15022 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15023 dest
= bgp_route_next(dest
)) {
15024 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15026 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15028 table
= bgp_dest_get_bgp_table_info(dest
);
15031 rm
= bgp_node_match(table
, &match
);
15035 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15038 || rm_p
->prefixlen
== match
.prefixlen
) {
15039 pi
= bgp_dest_get_bgp_path_info(rm
);
15041 if (pi
->extra
&& pi
->extra
->damp_info
) {
15042 pi_temp
= pi
->next
;
15043 bgp_damp_info_free(
15044 pi
->extra
->damp_info
,
15052 bgp_dest_unlock_node(rm
);
15055 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15056 if (dest
!= NULL
) {
15057 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15060 || dest_p
->prefixlen
== match
.prefixlen
) {
15061 pi
= bgp_dest_get_bgp_path_info(dest
);
15063 if (pi
->extra
&& pi
->extra
->damp_info
) {
15064 pi_temp
= pi
->next
;
15065 bgp_damp_info_free(
15066 pi
->extra
->damp_info
,
15074 bgp_dest_unlock_node(dest
);
15078 return CMD_SUCCESS
;
15081 DEFUN (clear_ip_bgp_dampening
,
15082 clear_ip_bgp_dampening_cmd
,
15083 "clear ip bgp dampening",
15087 "Clear route flap dampening information\n")
15089 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15090 return CMD_SUCCESS
;
15093 DEFUN (clear_ip_bgp_dampening_prefix
,
15094 clear_ip_bgp_dampening_prefix_cmd
,
15095 "clear ip bgp dampening A.B.C.D/M",
15099 "Clear route flap dampening information\n"
15102 int idx_ipv4_prefixlen
= 4;
15103 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15104 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15107 DEFUN (clear_ip_bgp_dampening_address
,
15108 clear_ip_bgp_dampening_address_cmd
,
15109 "clear ip bgp dampening A.B.C.D",
15113 "Clear route flap dampening information\n"
15114 "Network to clear damping information\n")
15117 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15118 SAFI_UNICAST
, NULL
, 0);
15121 DEFUN (clear_ip_bgp_dampening_address_mask
,
15122 clear_ip_bgp_dampening_address_mask_cmd
,
15123 "clear ip bgp dampening A.B.C.D A.B.C.D",
15127 "Clear route flap dampening information\n"
15128 "Network to clear damping information\n"
15132 int idx_ipv4_2
= 5;
15134 char prefix_str
[BUFSIZ
];
15136 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15137 prefix_str
, sizeof(prefix_str
));
15139 vty_out(vty
, "%% Inconsistent address and mask\n");
15140 return CMD_WARNING
;
15143 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15147 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15149 struct vty
*vty
= arg
;
15150 struct peer
*peer
= bucket
->data
;
15152 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15155 DEFUN (show_bgp_listeners
,
15156 show_bgp_listeners_cmd
,
15157 "show bgp listeners",
15160 "Display Listen Sockets and who created them\n")
15162 bgp_dump_listener_info(vty
);
15164 return CMD_SUCCESS
;
15167 DEFUN (show_bgp_peerhash
,
15168 show_bgp_peerhash_cmd
,
15169 "show bgp peerhash",
15172 "Display information about the BGP peerhash\n")
15174 struct list
*instances
= bm
->bgp
;
15175 struct listnode
*node
;
15178 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15179 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15180 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15184 return CMD_SUCCESS
;
15187 /* also used for encap safi */
15188 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15189 afi_t afi
, safi_t safi
)
15191 struct bgp_dest
*pdest
;
15192 struct bgp_dest
*dest
;
15193 struct bgp_table
*table
;
15194 const struct prefix
*p
;
15195 const struct prefix_rd
*prd
;
15196 struct bgp_static
*bgp_static
;
15197 mpls_label_t label
;
15199 /* Network configuration. */
15200 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15201 pdest
= bgp_route_next(pdest
)) {
15202 table
= bgp_dest_get_bgp_table_info(pdest
);
15206 for (dest
= bgp_table_top(table
); dest
;
15207 dest
= bgp_route_next(dest
)) {
15208 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15209 if (bgp_static
== NULL
)
15212 p
= bgp_dest_get_prefix(dest
);
15213 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
15216 /* "network" configuration display. */
15217 label
= decode_label(&bgp_static
->label
);
15219 vty_out(vty
, " network %pFX rd %pRD", p
, prd
);
15220 if (safi
== SAFI_MPLS_VPN
)
15221 vty_out(vty
, " label %u", label
);
15223 if (bgp_static
->rmap
.name
)
15224 vty_out(vty
, " route-map %s",
15225 bgp_static
->rmap
.name
);
15227 if (bgp_static
->backdoor
)
15228 vty_out(vty
, " backdoor");
15230 vty_out(vty
, "\n");
15235 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15236 afi_t afi
, safi_t safi
)
15238 struct bgp_dest
*pdest
;
15239 struct bgp_dest
*dest
;
15240 struct bgp_table
*table
;
15241 const struct prefix
*p
;
15242 const struct prefix_rd
*prd
;
15243 struct bgp_static
*bgp_static
;
15244 char buf
[PREFIX_STRLEN
* 2];
15245 char buf2
[SU_ADDRSTRLEN
];
15246 char esi_buf
[ESI_STR_LEN
];
15248 /* Network configuration. */
15249 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15250 pdest
= bgp_route_next(pdest
)) {
15251 table
= bgp_dest_get_bgp_table_info(pdest
);
15255 for (dest
= bgp_table_top(table
); dest
;
15256 dest
= bgp_route_next(dest
)) {
15257 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15258 if (bgp_static
== NULL
)
15261 char *macrouter
= NULL
;
15263 if (bgp_static
->router_mac
)
15264 macrouter
= prefix_mac2str(
15265 bgp_static
->router_mac
, NULL
, 0);
15266 if (bgp_static
->eth_s_id
)
15267 esi_to_str(bgp_static
->eth_s_id
,
15268 esi_buf
, sizeof(esi_buf
));
15269 p
= bgp_dest_get_prefix(dest
);
15270 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15272 /* "network" configuration display. */
15273 if (p
->u
.prefix_evpn
.route_type
== 5) {
15274 char local_buf
[PREFIX_STRLEN
];
15275 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15276 struct prefix_evpn
*)p
)
15280 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
15281 local_buf
, PREFIX_STRLEN
);
15282 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15283 p
->u
.prefix_evpn
.prefix_addr
15284 .ip_prefix_length
);
15286 prefix2str(p
, buf
, sizeof(buf
));
15289 if (bgp_static
->gatewayIp
.family
== AF_INET
15290 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15291 inet_ntop(bgp_static
->gatewayIp
.family
,
15292 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15295 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15296 buf
, prd
, p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15297 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15300 XFREE(MTYPE_TMP
, macrouter
);
15305 /* Configuration of static route announcement and aggregate
15307 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15310 struct bgp_dest
*dest
;
15311 const struct prefix
*p
;
15312 struct bgp_static
*bgp_static
;
15313 struct bgp_aggregate
*bgp_aggregate
;
15315 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15316 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15320 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15321 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15325 /* Network configuration. */
15326 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15327 dest
= bgp_route_next(dest
)) {
15328 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15329 if (bgp_static
== NULL
)
15332 p
= bgp_dest_get_prefix(dest
);
15334 vty_out(vty
, " network %pFX", p
);
15336 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15337 vty_out(vty
, " label-index %u",
15338 bgp_static
->label_index
);
15340 if (bgp_static
->rmap
.name
)
15341 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15343 if (bgp_static
->backdoor
)
15344 vty_out(vty
, " backdoor");
15346 vty_out(vty
, "\n");
15349 /* Aggregate-address configuration. */
15350 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15351 dest
= bgp_route_next(dest
)) {
15352 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15353 if (bgp_aggregate
== NULL
)
15356 p
= bgp_dest_get_prefix(dest
);
15358 vty_out(vty
, " aggregate-address %pFX", p
);
15360 if (bgp_aggregate
->as_set
)
15361 vty_out(vty
, " as-set");
15363 if (bgp_aggregate
->summary_only
)
15364 vty_out(vty
, " summary-only");
15366 if (bgp_aggregate
->rmap
.name
)
15367 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15369 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15370 vty_out(vty
, " origin %s",
15371 bgp_origin2str(bgp_aggregate
->origin
));
15373 if (bgp_aggregate
->match_med
)
15374 vty_out(vty
, " matching-MED-only");
15376 if (bgp_aggregate
->suppress_map_name
)
15377 vty_out(vty
, " suppress-map %s",
15378 bgp_aggregate
->suppress_map_name
);
15380 vty_out(vty
, "\n");
15384 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15387 struct bgp_dest
*dest
;
15388 struct bgp_distance
*bdistance
;
15390 /* Distance configuration. */
15391 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15392 && bgp
->distance_local
[afi
][safi
]
15393 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15394 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15395 || bgp
->distance_local
[afi
][safi
]
15396 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15397 vty_out(vty
, " distance bgp %d %d %d\n",
15398 bgp
->distance_ebgp
[afi
][safi
],
15399 bgp
->distance_ibgp
[afi
][safi
],
15400 bgp
->distance_local
[afi
][safi
]);
15403 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15404 dest
= bgp_route_next(dest
)) {
15405 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15406 if (bdistance
!= NULL
)
15407 vty_out(vty
, " distance %d %pBD %s\n",
15408 bdistance
->distance
, dest
,
15409 bdistance
->access_list
? bdistance
->access_list
15414 /* Allocate routing table structure and install commands. */
15415 void bgp_route_init(void)
15420 /* Init BGP distance table. */
15421 FOREACH_AFI_SAFI (afi
, safi
)
15422 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15424 /* IPv4 BGP commands. */
15425 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15426 install_element(BGP_NODE
, &bgp_network_cmd
);
15427 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15429 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15431 /* IPv4 unicast configuration. */
15432 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15433 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15434 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15436 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15438 /* IPv4 multicast configuration. */
15439 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15440 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15441 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15442 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15444 /* IPv4 labeled-unicast configuration. */
15445 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15446 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15448 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15449 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15450 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15451 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15452 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15453 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15454 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15455 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15457 install_element(VIEW_NODE
,
15458 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15459 install_element(VIEW_NODE
,
15460 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15461 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15462 install_element(VIEW_NODE
,
15463 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15464 #ifdef KEEP_OLD_VPN_COMMANDS
15465 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15466 #endif /* KEEP_OLD_VPN_COMMANDS */
15467 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15468 install_element(VIEW_NODE
,
15469 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15471 /* BGP dampening clear commands */
15472 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15473 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15475 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15476 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15479 install_element(ENABLE_NODE
,
15480 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15481 #ifdef KEEP_OLD_VPN_COMMANDS
15482 install_element(ENABLE_NODE
,
15483 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15484 #endif /* KEEP_OLD_VPN_COMMANDS */
15486 /* New config IPv6 BGP commands. */
15487 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15488 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15489 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15491 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15493 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15495 /* IPv6 labeled unicast address family. */
15496 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15497 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15499 install_element(BGP_NODE
, &bgp_distance_cmd
);
15500 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15501 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15502 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15503 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15504 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15505 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15506 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15507 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15508 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15509 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15510 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15511 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15512 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15513 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15514 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15515 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15516 install_element(BGP_IPV4M_NODE
,
15517 &no_bgp_distance_source_access_list_cmd
);
15518 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15519 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15520 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15521 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15522 install_element(BGP_IPV6_NODE
,
15523 &ipv6_bgp_distance_source_access_list_cmd
);
15524 install_element(BGP_IPV6_NODE
,
15525 &no_ipv6_bgp_distance_source_access_list_cmd
);
15526 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15527 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15528 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15529 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15530 install_element(BGP_IPV6M_NODE
,
15531 &ipv6_bgp_distance_source_access_list_cmd
);
15532 install_element(BGP_IPV6M_NODE
,
15533 &no_ipv6_bgp_distance_source_access_list_cmd
);
15535 /* BGP dampening */
15536 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15537 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15538 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15539 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15540 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15541 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15542 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15543 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15544 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15545 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15546 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15547 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15548 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15549 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15551 /* Large Communities */
15552 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15553 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15555 /* show bgp ipv4 flowspec detailed */
15556 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15558 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15559 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15562 void bgp_route_finish(void)
15567 FOREACH_AFI_SAFI (afi
, safi
) {
15568 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15569 bgp_distance_table
[afi
][safi
] = NULL
;