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 "%s: 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 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5656 bgp_dest_get_prefix(
5659 bgp_path_info_set_flag(dest
, pi
,
5667 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5669 if (peer
->sort
== BGP_PEER_IBGP
)
5672 if (peer
->sort
== BGP_PEER_EBGP
5673 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5674 || FILTER_LIST_OUT_NAME(filter
)
5675 || DISTRIBUTE_OUT_NAME(filter
)))
5680 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5682 if (peer
->sort
== BGP_PEER_IBGP
)
5685 if (peer
->sort
== BGP_PEER_EBGP
5686 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5687 || FILTER_LIST_IN_NAME(filter
)
5688 || DISTRIBUTE_IN_NAME(filter
)))
5693 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5696 struct bgp_dest
*dest
;
5697 struct bgp_path_info
*pi
;
5698 struct bgp_path_info
*next
;
5700 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5701 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5702 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5706 /* Unimport EVPN routes from VRFs */
5707 if (safi
== SAFI_EVPN
)
5708 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5711 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5712 && pi
->type
== ZEBRA_ROUTE_BGP
5713 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5714 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5715 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5717 if (bgp_fibupd_safi(safi
))
5718 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5721 bgp_path_info_reap(dest
, pi
);
5725 /* Delete all kernel routes. */
5726 void bgp_cleanup_routes(struct bgp
*bgp
)
5729 struct bgp_dest
*dest
;
5730 struct bgp_table
*table
;
5732 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5733 if (afi
== AFI_L2VPN
)
5735 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5738 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5740 if (afi
!= AFI_L2VPN
) {
5742 safi
= SAFI_MPLS_VPN
;
5743 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5744 dest
= bgp_route_next(dest
)) {
5745 table
= bgp_dest_get_bgp_table_info(dest
);
5746 if (table
!= NULL
) {
5747 bgp_cleanup_table(bgp
, table
, safi
);
5748 bgp_table_finish(&table
);
5749 bgp_dest_set_bgp_table_info(dest
, NULL
);
5750 bgp_dest_unlock_node(dest
);
5754 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5755 dest
= bgp_route_next(dest
)) {
5756 table
= bgp_dest_get_bgp_table_info(dest
);
5757 if (table
!= NULL
) {
5758 bgp_cleanup_table(bgp
, table
, safi
);
5759 bgp_table_finish(&table
);
5760 bgp_dest_set_bgp_table_info(dest
, NULL
);
5761 bgp_dest_unlock_node(dest
);
5766 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5767 dest
= bgp_route_next(dest
)) {
5768 table
= bgp_dest_get_bgp_table_info(dest
);
5769 if (table
!= NULL
) {
5770 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5771 bgp_table_finish(&table
);
5772 bgp_dest_set_bgp_table_info(dest
, NULL
);
5773 bgp_dest_unlock_node(dest
);
5778 void bgp_reset(void)
5781 bgp_zclient_reset();
5782 access_list_reset();
5783 prefix_list_reset();
5786 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5788 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5789 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5790 PEER_CAP_ADDPATH_AF_TX_RCV
));
5793 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5795 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5796 struct bgp_nlri
*packet
)
5805 bool addpath_capable
;
5806 uint32_t addpath_id
;
5809 lim
= pnt
+ packet
->length
;
5811 safi
= packet
->safi
;
5813 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5815 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5816 syntactic validity. If the field is syntactically incorrect,
5817 then the Error Subcode is set to Invalid Network Field. */
5818 for (; pnt
< lim
; pnt
+= psize
) {
5819 /* Clear prefix structure. */
5820 memset(&p
, 0, sizeof(p
));
5822 if (addpath_capable
) {
5824 /* When packet overflow occurs return immediately. */
5825 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5826 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5828 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5829 addpath_id
= ntohl(addpath_id
);
5830 pnt
+= BGP_ADDPATH_ID_LEN
;
5833 /* Fetch prefix length. */
5834 p
.prefixlen
= *pnt
++;
5835 /* afi/safi validity already verified by caller,
5836 * bgp_update_receive */
5837 p
.family
= afi2family(afi
);
5839 /* Prefix length check. */
5840 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5843 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5844 peer
->host
, p
.prefixlen
, packet
->afi
);
5845 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5848 /* Packet size overflow check. */
5849 psize
= PSIZE(p
.prefixlen
);
5851 /* When packet overflow occur return immediately. */
5852 if (pnt
+ psize
> lim
) {
5855 "%s [Error] Update packet error (prefix length %d overflows packet)",
5856 peer
->host
, p
.prefixlen
);
5857 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5860 /* Defensive coding, double-check the psize fits in a struct
5861 * prefix for the v4 and v6 afi's and unicast/multicast */
5862 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
5865 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5866 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
5867 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5870 /* Fetch prefix from NLRI packet. */
5871 memcpy(p
.u
.val
, pnt
, psize
);
5873 /* Check address. */
5874 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5875 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5876 /* From RFC4271 Section 6.3:
5878 * If a prefix in the NLRI field is semantically
5880 * (e.g., an unexpected multicast IP address),
5882 * be logged locally, and the prefix SHOULD be
5887 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5888 peer
->host
, &p
.u
.prefix4
);
5893 /* Check address. */
5894 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5895 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5898 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5899 peer
->host
, &p
.u
.prefix6
);
5903 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5906 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5907 peer
->host
, &p
.u
.prefix6
);
5913 /* Normal process. */
5915 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5916 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5917 NULL
, NULL
, 0, 0, NULL
);
5919 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5920 safi
, ZEBRA_ROUTE_BGP
,
5921 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5924 /* Do not send BGP notification twice when maximum-prefix count
5926 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5927 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5929 /* Address family configuration mismatch. */
5931 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5934 /* Packet length consistency check. */
5938 "%s [Error] Update packet error (prefix length mismatch with total length)",
5940 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5943 return BGP_NLRI_PARSE_OK
;
5946 static struct bgp_static
*bgp_static_new(void)
5948 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5951 static void bgp_static_free(struct bgp_static
*bgp_static
)
5953 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5954 route_map_counter_decrement(bgp_static
->rmap
.map
);
5956 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5957 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5960 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5961 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5963 struct bgp_dest
*dest
;
5964 struct bgp_path_info
*pi
;
5965 struct bgp_path_info
*new;
5966 struct bgp_path_info rmap_path
;
5968 struct attr
*attr_new
;
5969 route_map_result_t ret
;
5970 #ifdef ENABLE_BGP_VNC
5971 int vnc_implicit_withdraw
= 0;
5976 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5978 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
5980 attr
.nexthop
= bgp_static
->igpnexthop
;
5981 attr
.med
= bgp_static
->igpmetric
;
5982 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5985 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
5987 if (bgp_static
->atomic
)
5988 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5990 /* Store label index, if required. */
5991 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5992 attr
.label_index
= bgp_static
->label_index
;
5993 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5996 /* Apply route-map. */
5997 if (bgp_static
->rmap
.name
) {
5998 struct attr attr_tmp
= attr
;
6000 memset(&rmap_path
, 0, sizeof(rmap_path
));
6001 rmap_path
.peer
= bgp
->peer_self
;
6002 rmap_path
.attr
= &attr_tmp
;
6004 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6006 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6008 bgp
->peer_self
->rmap_type
= 0;
6010 if (ret
== RMAP_DENYMATCH
) {
6011 /* Free uninterned attribute. */
6012 bgp_attr_flush(&attr_tmp
);
6014 /* Unintern original. */
6015 aspath_unintern(&attr
.aspath
);
6016 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6017 bgp_dest_unlock_node(dest
);
6021 if (bgp_in_graceful_shutdown(bgp
))
6022 bgp_attr_add_gshut_community(&attr_tmp
);
6024 attr_new
= bgp_attr_intern(&attr_tmp
);
6027 if (bgp_in_graceful_shutdown(bgp
))
6028 bgp_attr_add_gshut_community(&attr
);
6030 attr_new
= bgp_attr_intern(&attr
);
6033 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6034 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6035 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6039 if (attrhash_cmp(pi
->attr
, attr_new
)
6040 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6041 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6042 bgp_dest_unlock_node(dest
);
6043 bgp_attr_unintern(&attr_new
);
6044 aspath_unintern(&attr
.aspath
);
6047 /* The attribute is changed. */
6048 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6050 /* Rewrite BGP route information. */
6051 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6052 bgp_path_info_restore(dest
, pi
);
6054 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6055 #ifdef ENABLE_BGP_VNC
6056 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6057 && (safi
== SAFI_UNICAST
)) {
6058 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6060 * Implicit withdraw case.
6061 * We have to do this before pi is
6064 ++vnc_implicit_withdraw
;
6065 vnc_import_bgp_del_route(bgp
, p
, pi
);
6066 vnc_import_bgp_exterior_del_route(
6071 bgp_attr_unintern(&pi
->attr
);
6072 pi
->attr
= attr_new
;
6073 pi
->uptime
= monotime(NULL
);
6074 #ifdef ENABLE_BGP_VNC
6075 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6076 && (safi
== SAFI_UNICAST
)) {
6077 if (vnc_implicit_withdraw
) {
6078 vnc_import_bgp_add_route(bgp
, p
, pi
);
6079 vnc_import_bgp_exterior_add_route(
6085 /* Nexthop reachability check. */
6086 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6087 && (safi
== SAFI_UNICAST
6088 || safi
== SAFI_LABELED_UNICAST
)) {
6090 struct bgp
*bgp_nexthop
= bgp
;
6092 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6093 bgp_nexthop
= pi
->extra
->bgp_orig
;
6095 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6096 afi
, safi
, pi
, NULL
,
6098 bgp_path_info_set_flag(dest
, pi
,
6101 if (BGP_DEBUG(nht
, NHT
)) {
6102 char buf1
[INET6_ADDRSTRLEN
];
6103 inet_ntop(p
->family
,
6107 "%s(%s): Route not in table, not advertising",
6110 bgp_path_info_unset_flag(
6111 dest
, pi
, BGP_PATH_VALID
);
6114 /* Delete the NHT structure if any, if we're
6116 * enabling/disabling import check. We
6117 * deregister the route
6118 * from NHT to avoid overloading NHT and the
6119 * process interaction
6121 bgp_unlink_nexthop(pi
);
6122 bgp_path_info_set_flag(dest
, pi
,
6125 /* Process change. */
6126 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6127 bgp_process(bgp
, dest
, afi
, safi
);
6129 if (SAFI_UNICAST
== safi
6130 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6132 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6133 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6137 bgp_dest_unlock_node(dest
);
6138 aspath_unintern(&attr
.aspath
);
6143 /* Make new BGP info. */
6144 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6146 /* Nexthop reachability check. */
6147 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6148 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6149 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6151 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6153 if (BGP_DEBUG(nht
, NHT
)) {
6154 char buf1
[INET6_ADDRSTRLEN
];
6155 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6158 "%s(%s): Route not in table, not advertising",
6161 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6164 /* Delete the NHT structure if any, if we're toggling between
6165 * enabling/disabling import check. We deregister the route
6166 * from NHT to avoid overloading NHT and the process interaction
6168 bgp_unlink_nexthop(new);
6170 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6173 /* Aggregate address increment. */
6174 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6176 /* Register new BGP information. */
6177 bgp_path_info_add(dest
, new);
6179 /* route_node_get lock */
6180 bgp_dest_unlock_node(dest
);
6182 /* Process change. */
6183 bgp_process(bgp
, dest
, afi
, safi
);
6185 if (SAFI_UNICAST
== safi
6186 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6187 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6188 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6191 /* Unintern original. */
6192 aspath_unintern(&attr
.aspath
);
6195 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6198 struct bgp_dest
*dest
;
6199 struct bgp_path_info
*pi
;
6201 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6203 /* Check selected route and self inserted route. */
6204 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6205 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6206 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6209 /* Withdraw static BGP route from routing table. */
6211 if (SAFI_UNICAST
== safi
6212 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6213 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6214 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6216 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6217 bgp_unlink_nexthop(pi
);
6218 bgp_path_info_delete(dest
, pi
);
6219 bgp_process(bgp
, dest
, afi
, safi
);
6222 /* Unlock bgp_node_lookup. */
6223 bgp_dest_unlock_node(dest
);
6227 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6229 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6230 afi_t afi
, safi_t safi
,
6231 struct prefix_rd
*prd
)
6233 struct bgp_dest
*dest
;
6234 struct bgp_path_info
*pi
;
6236 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6238 /* Check selected route and self inserted route. */
6239 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6240 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6241 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6244 /* Withdraw static BGP route from routing table. */
6246 #ifdef ENABLE_BGP_VNC
6247 rfapiProcessWithdraw(
6248 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6249 1); /* Kill, since it is an administrative change */
6251 if (SAFI_MPLS_VPN
== safi
6252 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6253 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6255 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6256 bgp_path_info_delete(dest
, pi
);
6257 bgp_process(bgp
, dest
, afi
, safi
);
6260 /* Unlock bgp_node_lookup. */
6261 bgp_dest_unlock_node(dest
);
6264 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6265 struct bgp_static
*bgp_static
, afi_t afi
,
6268 struct bgp_dest
*dest
;
6269 struct bgp_path_info
*new;
6270 struct attr
*attr_new
;
6271 struct attr attr
= {0};
6272 struct bgp_path_info
*pi
;
6273 #ifdef ENABLE_BGP_VNC
6274 mpls_label_t label
= 0;
6276 uint32_t num_labels
= 0;
6280 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6282 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6285 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6287 attr
.nexthop
= bgp_static
->igpnexthop
;
6288 attr
.med
= bgp_static
->igpmetric
;
6289 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6291 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6292 || (safi
== SAFI_ENCAP
)) {
6293 if (afi
== AFI_IP
) {
6294 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6295 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6298 if (afi
== AFI_L2VPN
) {
6299 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6300 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6301 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6302 &bgp_static
->gatewayIp
.u
.prefix4
,
6304 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6305 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6306 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6307 &bgp_static
->gatewayIp
.u
.prefix6
,
6310 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6311 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6312 struct bgp_encap_type_vxlan bet
;
6313 memset(&bet
, 0, sizeof(bet
));
6314 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6315 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6317 if (bgp_static
->router_mac
) {
6318 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6321 /* Apply route-map. */
6322 if (bgp_static
->rmap
.name
) {
6323 struct attr attr_tmp
= attr
;
6324 struct bgp_path_info rmap_path
;
6325 route_map_result_t ret
;
6327 rmap_path
.peer
= bgp
->peer_self
;
6328 rmap_path
.attr
= &attr_tmp
;
6330 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6332 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6334 bgp
->peer_self
->rmap_type
= 0;
6336 if (ret
== RMAP_DENYMATCH
) {
6337 /* Free uninterned attribute. */
6338 bgp_attr_flush(&attr_tmp
);
6340 /* Unintern original. */
6341 aspath_unintern(&attr
.aspath
);
6342 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6344 bgp_dest_unlock_node(dest
);
6348 attr_new
= bgp_attr_intern(&attr_tmp
);
6350 attr_new
= bgp_attr_intern(&attr
);
6353 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6354 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6355 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6359 if (attrhash_cmp(pi
->attr
, attr_new
)
6360 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6361 bgp_dest_unlock_node(dest
);
6362 bgp_attr_unintern(&attr_new
);
6363 aspath_unintern(&attr
.aspath
);
6366 /* The attribute is changed. */
6367 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6369 /* Rewrite BGP route information. */
6370 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6371 bgp_path_info_restore(dest
, pi
);
6373 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6374 bgp_attr_unintern(&pi
->attr
);
6375 pi
->attr
= attr_new
;
6376 pi
->uptime
= monotime(NULL
);
6377 #ifdef ENABLE_BGP_VNC
6379 label
= decode_label(&pi
->extra
->label
[0]);
6382 /* Process change. */
6383 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6384 bgp_process(bgp
, dest
, afi
, safi
);
6386 if (SAFI_MPLS_VPN
== safi
6387 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6388 vpn_leak_to_vrf_update(bgp
, pi
);
6390 #ifdef ENABLE_BGP_VNC
6391 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6392 pi
->attr
, afi
, safi
, pi
->type
,
6393 pi
->sub_type
, &label
);
6395 bgp_dest_unlock_node(dest
);
6396 aspath_unintern(&attr
.aspath
);
6402 /* Make new BGP info. */
6403 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6405 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6406 bgp_path_info_extra_get(new);
6408 new->extra
->label
[0] = bgp_static
->label
;
6409 new->extra
->num_labels
= num_labels
;
6411 #ifdef ENABLE_BGP_VNC
6412 label
= decode_label(&bgp_static
->label
);
6415 /* Aggregate address increment. */
6416 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6418 /* Register new BGP information. */
6419 bgp_path_info_add(dest
, new);
6420 /* route_node_get lock */
6421 bgp_dest_unlock_node(dest
);
6423 /* Process change. */
6424 bgp_process(bgp
, dest
, afi
, safi
);
6426 if (SAFI_MPLS_VPN
== safi
6427 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6428 vpn_leak_to_vrf_update(bgp
, new);
6430 #ifdef ENABLE_BGP_VNC
6431 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6432 safi
, new->type
, new->sub_type
, &label
);
6435 /* Unintern original. */
6436 aspath_unintern(&attr
.aspath
);
6439 /* Configure static BGP network. When user don't run zebra, static
6440 route should be installed as valid. */
6441 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6442 const char *ip_str
, afi_t afi
, safi_t safi
,
6443 const char *rmap
, int backdoor
, uint32_t label_index
)
6445 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6448 struct bgp_static
*bgp_static
;
6449 struct bgp_dest
*dest
;
6450 uint8_t need_update
= 0;
6452 /* Convert IP prefix string to struct prefix. */
6453 ret
= str2prefix(ip_str
, &p
);
6455 vty_out(vty
, "%% Malformed prefix\n");
6456 return CMD_WARNING_CONFIG_FAILED
;
6458 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6459 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6460 return CMD_WARNING_CONFIG_FAILED
;
6467 /* Set BGP static route configuration. */
6468 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6471 vty_out(vty
, "%% Can't find static route specified\n");
6472 return CMD_WARNING_CONFIG_FAILED
;
6475 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6477 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6478 && (label_index
!= bgp_static
->label_index
)) {
6480 "%% label-index doesn't match static route\n");
6481 bgp_dest_unlock_node(dest
);
6482 return CMD_WARNING_CONFIG_FAILED
;
6485 if ((rmap
&& bgp_static
->rmap
.name
)
6486 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6488 "%% route-map name doesn't match static route\n");
6489 bgp_dest_unlock_node(dest
);
6490 return CMD_WARNING_CONFIG_FAILED
;
6493 /* Update BGP RIB. */
6494 if (!bgp_static
->backdoor
)
6495 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6497 /* Clear configuration. */
6498 bgp_static_free(bgp_static
);
6499 bgp_dest_set_bgp_static_info(dest
, NULL
);
6500 bgp_dest_unlock_node(dest
);
6501 bgp_dest_unlock_node(dest
);
6504 /* Set BGP static route configuration. */
6505 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6506 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6508 /* Configuration change. */
6509 /* Label index cannot be changed. */
6510 if (bgp_static
->label_index
!= label_index
) {
6511 vty_out(vty
, "%% cannot change label-index\n");
6512 bgp_dest_unlock_node(dest
);
6513 return CMD_WARNING_CONFIG_FAILED
;
6516 /* Check previous routes are installed into BGP. */
6517 if (bgp_static
->valid
6518 && bgp_static
->backdoor
!= backdoor
)
6521 bgp_static
->backdoor
= backdoor
;
6524 XFREE(MTYPE_ROUTE_MAP_NAME
,
6525 bgp_static
->rmap
.name
);
6526 route_map_counter_decrement(
6527 bgp_static
->rmap
.map
);
6528 bgp_static
->rmap
.name
=
6529 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6530 bgp_static
->rmap
.map
=
6531 route_map_lookup_by_name(rmap
);
6532 route_map_counter_increment(
6533 bgp_static
->rmap
.map
);
6535 XFREE(MTYPE_ROUTE_MAP_NAME
,
6536 bgp_static
->rmap
.name
);
6537 route_map_counter_decrement(
6538 bgp_static
->rmap
.map
);
6539 bgp_static
->rmap
.map
= NULL
;
6540 bgp_static
->valid
= 0;
6542 bgp_dest_unlock_node(dest
);
6544 /* New configuration. */
6545 bgp_static
= bgp_static_new();
6546 bgp_static
->backdoor
= backdoor
;
6547 bgp_static
->valid
= 0;
6548 bgp_static
->igpmetric
= 0;
6549 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6550 bgp_static
->label_index
= label_index
;
6553 XFREE(MTYPE_ROUTE_MAP_NAME
,
6554 bgp_static
->rmap
.name
);
6555 route_map_counter_decrement(
6556 bgp_static
->rmap
.map
);
6557 bgp_static
->rmap
.name
=
6558 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6559 bgp_static
->rmap
.map
=
6560 route_map_lookup_by_name(rmap
);
6561 route_map_counter_increment(
6562 bgp_static
->rmap
.map
);
6564 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6567 bgp_static
->valid
= 1;
6569 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6571 if (!bgp_static
->backdoor
)
6572 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6578 void bgp_static_add(struct bgp
*bgp
)
6582 struct bgp_dest
*dest
;
6583 struct bgp_dest
*rm
;
6584 struct bgp_table
*table
;
6585 struct bgp_static
*bgp_static
;
6587 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6588 FOREACH_AFI_SAFI (afi
, safi
)
6589 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6590 dest
= bgp_route_next(dest
)) {
6591 if (!bgp_dest_has_bgp_path_info_data(dest
))
6594 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6595 || (safi
== SAFI_EVPN
)) {
6596 table
= bgp_dest_get_bgp_table_info(dest
);
6598 for (rm
= bgp_table_top(table
); rm
;
6599 rm
= bgp_route_next(rm
)) {
6601 bgp_dest_get_bgp_static_info(
6603 bgp_static_update_safi(
6604 bgp
, bgp_dest_get_prefix(rm
),
6605 bgp_static
, afi
, safi
);
6609 bgp
, bgp_dest_get_prefix(dest
),
6610 bgp_dest_get_bgp_static_info(dest
), afi
,
6614 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6617 /* Called from bgp_delete(). Delete all static routes from the BGP
6619 void bgp_static_delete(struct bgp
*bgp
)
6623 struct bgp_dest
*dest
;
6624 struct bgp_dest
*rm
;
6625 struct bgp_table
*table
;
6626 struct bgp_static
*bgp_static
;
6628 FOREACH_AFI_SAFI (afi
, safi
)
6629 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6630 dest
= bgp_route_next(dest
)) {
6631 if (!bgp_dest_has_bgp_path_info_data(dest
))
6634 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6635 || (safi
== SAFI_EVPN
)) {
6636 table
= bgp_dest_get_bgp_table_info(dest
);
6638 for (rm
= bgp_table_top(table
); rm
;
6639 rm
= bgp_route_next(rm
)) {
6641 bgp_dest_get_bgp_static_info(
6646 bgp_static_withdraw_safi(
6647 bgp
, bgp_dest_get_prefix(rm
),
6649 (struct prefix_rd
*)
6650 bgp_dest_get_prefix(
6652 bgp_static_free(bgp_static
);
6653 bgp_dest_set_bgp_static_info(rm
,
6655 bgp_dest_unlock_node(rm
);
6658 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6659 bgp_static_withdraw(bgp
,
6660 bgp_dest_get_prefix(dest
),
6662 bgp_static_free(bgp_static
);
6663 bgp_dest_set_bgp_static_info(dest
, NULL
);
6664 bgp_dest_unlock_node(dest
);
6669 void bgp_static_redo_import_check(struct bgp
*bgp
)
6673 struct bgp_dest
*dest
;
6674 struct bgp_dest
*rm
;
6675 struct bgp_table
*table
;
6676 struct bgp_static
*bgp_static
;
6678 /* Use this flag to force reprocessing of the route */
6679 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6680 FOREACH_AFI_SAFI (afi
, safi
) {
6681 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6682 dest
= bgp_route_next(dest
)) {
6683 if (!bgp_dest_has_bgp_path_info_data(dest
))
6686 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6687 || (safi
== SAFI_EVPN
)) {
6688 table
= bgp_dest_get_bgp_table_info(dest
);
6690 for (rm
= bgp_table_top(table
); rm
;
6691 rm
= bgp_route_next(rm
)) {
6693 bgp_dest_get_bgp_static_info(
6695 bgp_static_update_safi(
6696 bgp
, bgp_dest_get_prefix(rm
),
6697 bgp_static
, afi
, safi
);
6700 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6701 bgp_static_update(bgp
,
6702 bgp_dest_get_prefix(dest
),
6703 bgp_static
, afi
, safi
);
6707 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6710 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6713 struct bgp_table
*table
;
6714 struct bgp_dest
*dest
;
6715 struct bgp_path_info
*pi
;
6717 /* Do not install the aggregate route if BGP is in the
6718 * process of termination.
6720 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6721 || (bgp
->peer_self
== NULL
))
6724 table
= bgp
->rib
[afi
][safi
];
6725 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6726 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6727 if (pi
->peer
== bgp
->peer_self
6728 && ((pi
->type
== ZEBRA_ROUTE_BGP
6729 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6730 || (pi
->type
!= ZEBRA_ROUTE_BGP
6732 == BGP_ROUTE_REDISTRIBUTE
))) {
6733 bgp_aggregate_decrement(
6734 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6736 bgp_unlink_nexthop(pi
);
6737 bgp_path_info_delete(dest
, pi
);
6738 bgp_process(bgp
, dest
, afi
, safi
);
6745 * Purge all networks and redistributed routes from routing table.
6746 * Invoked upon the instance going down.
6748 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6753 FOREACH_AFI_SAFI (afi
, safi
)
6754 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6759 * Currently this is used to set static routes for VPN and ENCAP.
6760 * I think it can probably be factored with bgp_static_set.
6762 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6763 const char *ip_str
, const char *rd_str
,
6764 const char *label_str
, const char *rmap_str
,
6765 int evpn_type
, const char *esi
, const char *gwip
,
6766 const char *ethtag
, const char *routermac
)
6768 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6771 struct prefix_rd prd
;
6772 struct bgp_dest
*pdest
;
6773 struct bgp_dest
*dest
;
6774 struct bgp_table
*table
;
6775 struct bgp_static
*bgp_static
;
6776 mpls_label_t label
= MPLS_INVALID_LABEL
;
6777 struct prefix gw_ip
;
6779 /* validate ip prefix */
6780 ret
= str2prefix(ip_str
, &p
);
6782 vty_out(vty
, "%% Malformed prefix\n");
6783 return CMD_WARNING_CONFIG_FAILED
;
6786 if ((afi
== AFI_L2VPN
)
6787 && (bgp_build_evpn_prefix(evpn_type
,
6788 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6789 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6790 return CMD_WARNING_CONFIG_FAILED
;
6793 ret
= str2prefix_rd(rd_str
, &prd
);
6795 vty_out(vty
, "%% Malformed rd\n");
6796 return CMD_WARNING_CONFIG_FAILED
;
6800 unsigned long label_val
;
6801 label_val
= strtoul(label_str
, NULL
, 10);
6802 encode_label(label_val
, &label
);
6805 if (safi
== SAFI_EVPN
) {
6806 if (esi
&& str2esi(esi
, NULL
) == 0) {
6807 vty_out(vty
, "%% Malformed ESI\n");
6808 return CMD_WARNING_CONFIG_FAILED
;
6810 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6811 vty_out(vty
, "%% Malformed Router MAC\n");
6812 return CMD_WARNING_CONFIG_FAILED
;
6815 memset(&gw_ip
, 0, sizeof(gw_ip
));
6816 ret
= str2prefix(gwip
, &gw_ip
);
6818 vty_out(vty
, "%% Malformed GatewayIp\n");
6819 return CMD_WARNING_CONFIG_FAILED
;
6821 if ((gw_ip
.family
== AF_INET
6822 && is_evpn_prefix_ipaddr_v6(
6823 (struct prefix_evpn
*)&p
))
6824 || (gw_ip
.family
== AF_INET6
6825 && is_evpn_prefix_ipaddr_v4(
6826 (struct prefix_evpn
*)&p
))) {
6828 "%% GatewayIp family differs with IP prefix\n");
6829 return CMD_WARNING_CONFIG_FAILED
;
6833 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6834 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6835 bgp_dest_set_bgp_table_info(pdest
,
6836 bgp_table_init(bgp
, afi
, safi
));
6837 table
= bgp_dest_get_bgp_table_info(pdest
);
6839 dest
= bgp_node_get(table
, &p
);
6841 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6842 vty_out(vty
, "%% Same network configuration exists\n");
6843 bgp_dest_unlock_node(dest
);
6845 /* New configuration. */
6846 bgp_static
= bgp_static_new();
6847 bgp_static
->backdoor
= 0;
6848 bgp_static
->valid
= 0;
6849 bgp_static
->igpmetric
= 0;
6850 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6851 bgp_static
->label
= label
;
6852 bgp_static
->prd
= prd
;
6855 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6856 route_map_counter_decrement(bgp_static
->rmap
.map
);
6857 bgp_static
->rmap
.name
=
6858 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6859 bgp_static
->rmap
.map
=
6860 route_map_lookup_by_name(rmap_str
);
6861 route_map_counter_increment(bgp_static
->rmap
.map
);
6864 if (safi
== SAFI_EVPN
) {
6866 bgp_static
->eth_s_id
=
6869 str2esi(esi
, bgp_static
->eth_s_id
);
6872 bgp_static
->router_mac
=
6873 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
6874 (void)prefix_str2mac(routermac
,
6875 bgp_static
->router_mac
);
6878 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
6880 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6882 bgp_static
->valid
= 1;
6883 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
6889 /* Configure static BGP network. */
6890 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6891 const char *ip_str
, const char *rd_str
,
6892 const char *label_str
, int evpn_type
, const char *esi
,
6893 const char *gwip
, const char *ethtag
)
6895 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6898 struct prefix_rd prd
;
6899 struct bgp_dest
*pdest
;
6900 struct bgp_dest
*dest
;
6901 struct bgp_table
*table
;
6902 struct bgp_static
*bgp_static
;
6903 mpls_label_t label
= MPLS_INVALID_LABEL
;
6905 /* Convert IP prefix string to struct prefix. */
6906 ret
= str2prefix(ip_str
, &p
);
6908 vty_out(vty
, "%% Malformed prefix\n");
6909 return CMD_WARNING_CONFIG_FAILED
;
6912 if ((afi
== AFI_L2VPN
)
6913 && (bgp_build_evpn_prefix(evpn_type
,
6914 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6915 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6916 return CMD_WARNING_CONFIG_FAILED
;
6918 ret
= str2prefix_rd(rd_str
, &prd
);
6920 vty_out(vty
, "%% Malformed rd\n");
6921 return CMD_WARNING_CONFIG_FAILED
;
6925 unsigned long label_val
;
6926 label_val
= strtoul(label_str
, NULL
, 10);
6927 encode_label(label_val
, &label
);
6930 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6931 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6932 bgp_dest_set_bgp_table_info(pdest
,
6933 bgp_table_init(bgp
, afi
, safi
));
6935 bgp_dest_unlock_node(pdest
);
6936 table
= bgp_dest_get_bgp_table_info(pdest
);
6938 dest
= bgp_node_lookup(table
, &p
);
6941 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6943 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6944 bgp_static_free(bgp_static
);
6945 bgp_dest_set_bgp_static_info(dest
, NULL
);
6946 bgp_dest_unlock_node(dest
);
6947 bgp_dest_unlock_node(dest
);
6949 vty_out(vty
, "%% Can't find the route\n");
6954 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6955 const char *rmap_name
)
6957 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6958 struct bgp_rmap
*rmap
;
6960 rmap
= &bgp
->table_map
[afi
][safi
];
6962 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6963 route_map_counter_decrement(rmap
->map
);
6964 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6965 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6966 route_map_counter_increment(rmap
->map
);
6968 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6969 route_map_counter_decrement(rmap
->map
);
6973 if (bgp_fibupd_safi(safi
))
6974 bgp_zebra_announce_table(bgp
, afi
, safi
);
6979 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6980 const char *rmap_name
)
6982 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6983 struct bgp_rmap
*rmap
;
6985 rmap
= &bgp
->table_map
[afi
][safi
];
6986 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6987 route_map_counter_decrement(rmap
->map
);
6990 if (bgp_fibupd_safi(safi
))
6991 bgp_zebra_announce_table(bgp
, afi
, safi
);
6996 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6999 if (bgp
->table_map
[afi
][safi
].name
) {
7000 vty_out(vty
, " table-map %s\n",
7001 bgp
->table_map
[afi
][safi
].name
);
7005 DEFUN (bgp_table_map
,
7008 "BGP table to RIB route download filter\n"
7009 "Name of the route map\n")
7012 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7013 argv
[idx_word
]->arg
);
7015 DEFUN (no_bgp_table_map
,
7016 no_bgp_table_map_cmd
,
7017 "no table-map WORD",
7019 "BGP table to RIB route download filter\n"
7020 "Name of the route map\n")
7023 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7024 argv
[idx_word
]->arg
);
7030 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7031 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7032 backdoor$backdoor}]",
7034 "Specify a network to announce via BGP\n"
7039 "Route-map to modify the attributes\n"
7040 "Name of the route map\n"
7041 "Label index to associate with the prefix\n"
7042 "Label index value\n"
7043 "Specify a BGP backdoor route\n")
7045 char addr_prefix_str
[BUFSIZ
];
7050 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7052 sizeof(addr_prefix_str
));
7054 vty_out(vty
, "%% Inconsistent address and mask\n");
7055 return CMD_WARNING_CONFIG_FAILED
;
7059 return bgp_static_set(
7060 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7061 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7062 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7065 DEFPY(ipv6_bgp_network
,
7066 ipv6_bgp_network_cmd
,
7067 "[no] network X:X::X:X/M$prefix \
7068 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7070 "Specify a network to announce via BGP\n"
7072 "Route-map to modify the attributes\n"
7073 "Name of the route map\n"
7074 "Label index to associate with the prefix\n"
7075 "Label index value\n")
7077 return bgp_static_set(
7078 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7079 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7082 static struct bgp_aggregate
*bgp_aggregate_new(void)
7084 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7087 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7089 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7090 route_map_counter_decrement(aggregate
->suppress_map
);
7091 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7092 route_map_counter_decrement(aggregate
->rmap
.map
);
7093 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7097 * Helper function to avoid repeated code: prepare variables for a
7098 * `route_map_apply` call.
7100 * \returns `true` on route map match, otherwise `false`.
7102 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7103 struct bgp_aggregate
*aggregate
,
7104 struct bgp_path_info
*pi
)
7106 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7107 route_map_result_t rmr
= RMAP_DENYMATCH
;
7108 struct bgp_path_info rmap_path
= {};
7109 struct attr attr
= {};
7111 /* No route map entries created, just don't match. */
7112 if (aggregate
->suppress_map
== NULL
)
7115 /* Call route map matching and return result. */
7116 attr
.aspath
= aspath_empty();
7117 rmap_path
.peer
= bgp
->peer_self
;
7118 rmap_path
.attr
= &attr
;
7120 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7121 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7122 bgp
->peer_self
->rmap_type
= 0;
7124 bgp_attr_flush(&attr
);
7125 aspath_unintern(&attr
.aspath
);
7127 return rmr
== RMAP_PERMITMATCH
;
7130 /** Test whether the aggregation has suppressed this path or not. */
7131 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7132 struct bgp_path_info
*pi
)
7134 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7137 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7141 * Suppress this path and keep the reference.
7143 * \returns `true` if needs processing otherwise `false`.
7145 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7146 struct bgp_path_info
*pi
)
7148 struct bgp_path_info_extra
*pie
;
7150 /* Path is already suppressed by this aggregation. */
7151 if (aggr_suppress_exists(aggregate
, pi
))
7154 pie
= bgp_path_info_extra_get(pi
);
7156 /* This is the first suppression, allocate memory and list it. */
7157 if (pie
->aggr_suppressors
== NULL
)
7158 pie
->aggr_suppressors
= list_new();
7160 listnode_add(pie
->aggr_suppressors
, aggregate
);
7162 /* Only mark for processing if suppressed. */
7163 if (listcount(pie
->aggr_suppressors
) == 1) {
7164 if (BGP_DEBUG(update
, UPDATE_OUT
))
7165 zlog_debug("aggregate-address suppressing: %pFX",
7166 bgp_dest_get_prefix(pi
->net
));
7168 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7176 * Unsuppress this path and remove the reference.
7178 * \returns `true` if needs processing otherwise `false`.
7180 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7181 struct bgp_path_info
*pi
)
7183 /* Path wasn't suppressed. */
7184 if (!aggr_suppress_exists(aggregate
, pi
))
7187 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7189 /* Unsuppress and free extra memory if last item. */
7190 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7191 if (BGP_DEBUG(update
, UPDATE_OUT
))
7192 zlog_debug("aggregate-address unsuppressing: %pFX",
7193 bgp_dest_get_prefix(pi
->net
));
7195 list_delete(&pi
->extra
->aggr_suppressors
);
7196 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7203 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7204 struct aspath
*aspath
,
7205 struct community
*comm
,
7206 struct ecommunity
*ecomm
,
7207 struct lcommunity
*lcomm
)
7209 static struct aspath
*ae
= NULL
;
7212 ae
= aspath_empty();
7217 if (origin
!= pi
->attr
->origin
)
7220 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7223 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7226 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7229 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7232 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7238 static void bgp_aggregate_install(
7239 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7240 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7241 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7242 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7244 struct bgp_dest
*dest
;
7245 struct bgp_table
*table
;
7246 struct bgp_path_info
*pi
, *orig
, *new;
7249 table
= bgp
->rib
[afi
][safi
];
7251 dest
= bgp_node_get(table
, p
);
7253 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7254 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7255 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7259 * If we have paths with different MEDs, then don't install
7260 * (or uninstall) the aggregate route.
7262 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7263 goto uninstall_aggregate_route
;
7265 if (aggregate
->count
> 0) {
7267 * If the aggregate information has not changed
7268 * no need to re-install it again.
7270 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7271 ecommunity
, lcommunity
)) {
7272 bgp_dest_unlock_node(dest
);
7275 aspath_free(aspath
);
7277 community_free(&community
);
7279 ecommunity_free(&ecommunity
);
7281 lcommunity_free(&lcommunity
);
7287 * Mark the old as unusable
7290 bgp_path_info_delete(dest
, pi
);
7292 attr
= bgp_attr_aggregate_intern(
7293 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7294 aggregate
, atomic_aggregate
, p
);
7297 bgp_dest_unlock_node(dest
);
7298 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7299 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7300 zlog_debug("%s: %pFX null attribute", __func__
,
7305 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7306 bgp
->peer_self
, attr
, dest
);
7308 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7310 bgp_path_info_add(dest
, new);
7311 bgp_process(bgp
, dest
, afi
, safi
);
7313 uninstall_aggregate_route
:
7314 for (pi
= orig
; pi
; pi
= pi
->next
)
7315 if (pi
->peer
== bgp
->peer_self
7316 && pi
->type
== ZEBRA_ROUTE_BGP
7317 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7320 /* Withdraw static BGP route from routing table. */
7322 bgp_path_info_delete(dest
, pi
);
7323 bgp_process(bgp
, dest
, afi
, safi
);
7327 bgp_dest_unlock_node(dest
);
7331 * Check if the current path has different MED than other known paths.
7333 * \returns `true` if the MED matched the others else `false`.
7335 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7336 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7338 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7340 /* This is the first route being analyzed. */
7341 if (!aggregate
->med_initialized
) {
7342 aggregate
->med_initialized
= true;
7343 aggregate
->med_mismatched
= false;
7344 aggregate
->med_matched_value
= cur_med
;
7346 /* Check if routes with different MED showed up. */
7347 if (cur_med
!= aggregate
->med_matched_value
)
7348 aggregate
->med_mismatched
= true;
7351 return !aggregate
->med_mismatched
;
7355 * Initializes and tests all routes in the aggregate address path for MED
7358 * \returns `true` if all MEDs are the same otherwise `false`.
7360 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7361 struct bgp
*bgp
, const struct prefix
*p
,
7362 afi_t afi
, safi_t safi
)
7364 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7365 const struct prefix
*dest_p
;
7366 struct bgp_dest
*dest
, *top
;
7367 struct bgp_path_info
*pi
;
7368 bool med_matched
= true;
7370 aggregate
->med_initialized
= false;
7372 top
= bgp_node_get(table
, p
);
7373 for (dest
= bgp_node_get(table
, p
); dest
;
7374 dest
= bgp_route_next_until(dest
, top
)) {
7375 dest_p
= bgp_dest_get_prefix(dest
);
7376 if (dest_p
->prefixlen
<= p
->prefixlen
)
7379 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7380 if (BGP_PATH_HOLDDOWN(pi
))
7382 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7384 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7385 med_matched
= false;
7392 bgp_dest_unlock_node(top
);
7398 * Toggles the route suppression status for this aggregate address
7401 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7402 struct bgp
*bgp
, const struct prefix
*p
,
7403 afi_t afi
, safi_t safi
, bool suppress
)
7405 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7406 const struct prefix
*dest_p
;
7407 struct bgp_dest
*dest
, *top
;
7408 struct bgp_path_info
*pi
;
7409 bool toggle_suppression
;
7411 /* We've found a different MED we must revert any suppressed routes. */
7412 top
= bgp_node_get(table
, p
);
7413 for (dest
= bgp_node_get(table
, p
); dest
;
7414 dest
= bgp_route_next_until(dest
, top
)) {
7415 dest_p
= bgp_dest_get_prefix(dest
);
7416 if (dest_p
->prefixlen
<= p
->prefixlen
)
7419 toggle_suppression
= false;
7420 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7421 if (BGP_PATH_HOLDDOWN(pi
))
7423 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7426 /* We are toggling suppression back. */
7428 /* Suppress route if not suppressed already. */
7429 if (aggr_suppress_path(aggregate
, pi
))
7430 toggle_suppression
= true;
7434 /* Install route if there is no more suppression. */
7435 if (aggr_unsuppress_path(aggregate
, pi
))
7436 toggle_suppression
= true;
7439 if (toggle_suppression
)
7440 bgp_process(bgp
, dest
, afi
, safi
);
7442 bgp_dest_unlock_node(top
);
7446 * Aggregate address MED matching incremental test: this function is called
7447 * when the initial aggregation occurred and we are only testing a single
7450 * In addition to testing and setting the MED validity it also installs back
7451 * suppressed routes (if summary is configured).
7453 * Must not be called in `bgp_aggregate_route`.
7455 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7456 struct bgp
*bgp
, const struct prefix
*p
,
7457 afi_t afi
, safi_t safi
,
7458 struct bgp_path_info
*pi
)
7460 /* MED matching disabled. */
7461 if (!aggregate
->match_med
)
7464 /* Aggregation with different MED, recheck if we have got equal MEDs
7467 if (aggregate
->med_mismatched
&&
7468 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7469 aggregate
->summary_only
)
7470 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7473 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7475 /* No mismatches, just quit. */
7476 if (!aggregate
->med_mismatched
)
7479 /* Route summarization is disabled. */
7480 if (!aggregate
->summary_only
)
7483 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7486 /* Update an aggregate as routes are added/removed from the BGP table */
7487 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7488 safi_t safi
, struct bgp_aggregate
*aggregate
)
7490 struct bgp_table
*table
;
7491 struct bgp_dest
*top
;
7492 struct bgp_dest
*dest
;
7494 struct aspath
*aspath
= NULL
;
7495 struct community
*community
= NULL
;
7496 struct ecommunity
*ecommunity
= NULL
;
7497 struct lcommunity
*lcommunity
= NULL
;
7498 struct bgp_path_info
*pi
;
7499 unsigned long match
= 0;
7500 uint8_t atomic_aggregate
= 0;
7502 /* If the bgp instance is being deleted or self peer is deleted
7503 * then do not create aggregate route
7505 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7506 || (bgp
->peer_self
== NULL
))
7509 /* Initialize and test routes for MED difference. */
7510 if (aggregate
->match_med
)
7511 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7514 * Reset aggregate count: we might've been called from route map
7515 * update so in that case we must retest all more specific routes.
7517 * \see `bgp_route_map_process_update`.
7519 aggregate
->count
= 0;
7520 aggregate
->incomplete_origin_count
= 0;
7521 aggregate
->incomplete_origin_count
= 0;
7522 aggregate
->egp_origin_count
= 0;
7524 /* ORIGIN attribute: If at least one route among routes that are
7525 aggregated has ORIGIN with the value INCOMPLETE, then the
7526 aggregated route must have the ORIGIN attribute with the value
7527 INCOMPLETE. Otherwise, if at least one route among routes that
7528 are aggregated has ORIGIN with the value EGP, then the aggregated
7529 route must have the origin attribute with the value EGP. In all
7530 other case the value of the ORIGIN attribute of the aggregated
7531 route is INTERNAL. */
7532 origin
= BGP_ORIGIN_IGP
;
7534 table
= bgp
->rib
[afi
][safi
];
7536 top
= bgp_node_get(table
, p
);
7537 for (dest
= bgp_node_get(table
, p
); dest
;
7538 dest
= bgp_route_next_until(dest
, top
)) {
7539 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7541 if (dest_p
->prefixlen
<= p
->prefixlen
)
7544 /* If suppress fib is enabled and route not installed
7545 * in FIB, skip the route
7547 if (!bgp_check_advertise(bgp
, dest
))
7552 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7553 if (BGP_PATH_HOLDDOWN(pi
))
7557 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7558 atomic_aggregate
= 1;
7560 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7564 * summary-only aggregate route suppress
7565 * aggregated route announcements.
7568 * Don't create summaries if MED didn't match
7569 * otherwise neither the specific routes and the
7570 * aggregation will be announced.
7572 if (aggregate
->summary_only
7573 && AGGREGATE_MED_VALID(aggregate
)) {
7574 if (aggr_suppress_path(aggregate
, pi
))
7579 * Suppress more specific routes that match the route
7583 * Don't suppress routes if MED matching is enabled and
7584 * it mismatched otherwise we might end up with no
7585 * routes for this path.
7587 if (aggregate
->suppress_map_name
7588 && AGGREGATE_MED_VALID(aggregate
)
7589 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7590 if (aggr_suppress_path(aggregate
, pi
))
7597 * If at least one route among routes that are
7598 * aggregated has ORIGIN with the value INCOMPLETE,
7599 * then the aggregated route MUST have the ORIGIN
7600 * attribute with the value INCOMPLETE. Otherwise, if
7601 * at least one route among routes that are aggregated
7602 * has ORIGIN with the value EGP, then the aggregated
7603 * route MUST have the ORIGIN attribute with the value
7606 switch (pi
->attr
->origin
) {
7607 case BGP_ORIGIN_INCOMPLETE
:
7608 aggregate
->incomplete_origin_count
++;
7610 case BGP_ORIGIN_EGP
:
7611 aggregate
->egp_origin_count
++;
7619 if (!aggregate
->as_set
)
7623 * as-set aggregate route generate origin, as path,
7624 * and community aggregation.
7626 /* Compute aggregate route's as-path.
7628 bgp_compute_aggregate_aspath_hash(aggregate
,
7631 /* Compute aggregate route's community.
7633 if (bgp_attr_get_community(pi
->attr
))
7634 bgp_compute_aggregate_community_hash(
7636 bgp_attr_get_community(pi
->attr
));
7638 /* Compute aggregate route's extended community.
7640 if (bgp_attr_get_ecommunity(pi
->attr
))
7641 bgp_compute_aggregate_ecommunity_hash(
7643 bgp_attr_get_ecommunity(pi
->attr
));
7645 /* Compute aggregate route's large community.
7647 if (bgp_attr_get_lcommunity(pi
->attr
))
7648 bgp_compute_aggregate_lcommunity_hash(
7650 bgp_attr_get_lcommunity(pi
->attr
));
7653 bgp_process(bgp
, dest
, afi
, safi
);
7655 if (aggregate
->as_set
) {
7656 bgp_compute_aggregate_aspath_val(aggregate
);
7657 bgp_compute_aggregate_community_val(aggregate
);
7658 bgp_compute_aggregate_ecommunity_val(aggregate
);
7659 bgp_compute_aggregate_lcommunity_val(aggregate
);
7663 bgp_dest_unlock_node(top
);
7666 if (aggregate
->incomplete_origin_count
> 0)
7667 origin
= BGP_ORIGIN_INCOMPLETE
;
7668 else if (aggregate
->egp_origin_count
> 0)
7669 origin
= BGP_ORIGIN_EGP
;
7671 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7672 origin
= aggregate
->origin
;
7674 if (aggregate
->as_set
) {
7675 if (aggregate
->aspath
)
7676 /* Retrieve aggregate route's as-path.
7678 aspath
= aspath_dup(aggregate
->aspath
);
7680 if (aggregate
->community
)
7681 /* Retrieve aggregate route's community.
7683 community
= community_dup(aggregate
->community
);
7685 if (aggregate
->ecommunity
)
7686 /* Retrieve aggregate route's ecommunity.
7688 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7690 if (aggregate
->lcommunity
)
7691 /* Retrieve aggregate route's lcommunity.
7693 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7696 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7697 ecommunity
, lcommunity
, atomic_aggregate
,
7701 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7702 safi_t safi
, struct bgp_aggregate
*aggregate
)
7704 struct bgp_table
*table
;
7705 struct bgp_dest
*top
;
7706 struct bgp_dest
*dest
;
7707 struct bgp_path_info
*pi
;
7708 unsigned long match
;
7710 table
= bgp
->rib
[afi
][safi
];
7712 /* If routes exists below this node, generate aggregate routes. */
7713 top
= bgp_node_get(table
, p
);
7714 for (dest
= bgp_node_get(table
, p
); dest
;
7715 dest
= bgp_route_next_until(dest
, top
)) {
7716 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7718 if (dest_p
->prefixlen
<= p
->prefixlen
)
7722 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7723 if (BGP_PATH_HOLDDOWN(pi
))
7726 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7730 * This route is suppressed: attempt to unsuppress it.
7732 * `aggr_unsuppress_path` will fail if this particular
7733 * aggregate route was not the suppressor.
7735 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7736 listcount(pi
->extra
->aggr_suppressors
)) {
7737 if (aggr_unsuppress_path(aggregate
, pi
))
7743 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7744 aggregate
->incomplete_origin_count
--;
7745 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7746 aggregate
->egp_origin_count
--;
7748 if (aggregate
->as_set
) {
7749 /* Remove as-path from aggregate.
7751 bgp_remove_aspath_from_aggregate_hash(
7755 if (bgp_attr_get_community(pi
->attr
))
7756 /* Remove community from aggregate.
7758 bgp_remove_comm_from_aggregate_hash(
7760 bgp_attr_get_community(
7763 if (bgp_attr_get_ecommunity(pi
->attr
))
7764 /* Remove ecommunity from aggregate.
7766 bgp_remove_ecomm_from_aggregate_hash(
7768 bgp_attr_get_ecommunity(
7771 if (bgp_attr_get_lcommunity(pi
->attr
))
7772 /* Remove lcommunity from aggregate.
7774 bgp_remove_lcomm_from_aggregate_hash(
7776 bgp_attr_get_lcommunity(
7781 /* If this node was suppressed, process the change. */
7783 bgp_process(bgp
, dest
, afi
, safi
);
7785 if (aggregate
->as_set
) {
7786 aspath_free(aggregate
->aspath
);
7787 aggregate
->aspath
= NULL
;
7788 if (aggregate
->community
)
7789 community_free(&aggregate
->community
);
7790 if (aggregate
->ecommunity
)
7791 ecommunity_free(&aggregate
->ecommunity
);
7792 if (aggregate
->lcommunity
)
7793 lcommunity_free(&aggregate
->lcommunity
);
7796 bgp_dest_unlock_node(top
);
7799 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7800 const struct prefix
*aggr_p
,
7801 struct bgp_path_info
*pinew
, afi_t afi
,
7803 struct bgp_aggregate
*aggregate
)
7806 struct aspath
*aspath
= NULL
;
7807 uint8_t atomic_aggregate
= 0;
7808 struct community
*community
= NULL
;
7809 struct ecommunity
*ecommunity
= NULL
;
7810 struct lcommunity
*lcommunity
= NULL
;
7812 /* If the bgp instance is being deleted or self peer is deleted
7813 * then do not create aggregate route
7815 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7816 || (bgp
->peer_self
== NULL
))
7819 /* ORIGIN attribute: If at least one route among routes that are
7820 * aggregated has ORIGIN with the value INCOMPLETE, then the
7821 * aggregated route must have the ORIGIN attribute with the value
7822 * INCOMPLETE. Otherwise, if at least one route among routes that
7823 * are aggregated has ORIGIN with the value EGP, then the aggregated
7824 * route must have the origin attribute with the value EGP. In all
7825 * other case the value of the ORIGIN attribute of the aggregated
7826 * route is INTERNAL.
7828 origin
= BGP_ORIGIN_IGP
;
7833 * This must be called before `summary` check to avoid
7834 * "suppressing" twice.
7836 if (aggregate
->match_med
)
7837 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7840 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7841 aggr_suppress_path(aggregate
, pinew
);
7843 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7844 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7845 aggr_suppress_path(aggregate
, pinew
);
7847 switch (pinew
->attr
->origin
) {
7848 case BGP_ORIGIN_INCOMPLETE
:
7849 aggregate
->incomplete_origin_count
++;
7851 case BGP_ORIGIN_EGP
:
7852 aggregate
->egp_origin_count
++;
7860 if (aggregate
->incomplete_origin_count
> 0)
7861 origin
= BGP_ORIGIN_INCOMPLETE
;
7862 else if (aggregate
->egp_origin_count
> 0)
7863 origin
= BGP_ORIGIN_EGP
;
7865 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7866 origin
= aggregate
->origin
;
7868 if (aggregate
->as_set
) {
7869 /* Compute aggregate route's as-path.
7871 bgp_compute_aggregate_aspath(aggregate
,
7872 pinew
->attr
->aspath
);
7874 /* Compute aggregate route's community.
7876 if (bgp_attr_get_community(pinew
->attr
))
7877 bgp_compute_aggregate_community(
7878 aggregate
, bgp_attr_get_community(pinew
->attr
));
7880 /* Compute aggregate route's extended community.
7882 if (bgp_attr_get_ecommunity(pinew
->attr
))
7883 bgp_compute_aggregate_ecommunity(
7885 bgp_attr_get_ecommunity(pinew
->attr
));
7887 /* Compute aggregate route's large community.
7889 if (bgp_attr_get_lcommunity(pinew
->attr
))
7890 bgp_compute_aggregate_lcommunity(
7892 bgp_attr_get_lcommunity(pinew
->attr
));
7894 /* Retrieve aggregate route's as-path.
7896 if (aggregate
->aspath
)
7897 aspath
= aspath_dup(aggregate
->aspath
);
7899 /* Retrieve aggregate route's community.
7901 if (aggregate
->community
)
7902 community
= community_dup(aggregate
->community
);
7904 /* Retrieve aggregate route's ecommunity.
7906 if (aggregate
->ecommunity
)
7907 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7909 /* Retrieve aggregate route's lcommunity.
7911 if (aggregate
->lcommunity
)
7912 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7915 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7916 aspath
, community
, ecommunity
,
7917 lcommunity
, atomic_aggregate
, aggregate
);
7920 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7922 struct bgp_path_info
*pi
,
7923 struct bgp_aggregate
*aggregate
,
7924 const struct prefix
*aggr_p
)
7927 struct aspath
*aspath
= NULL
;
7928 uint8_t atomic_aggregate
= 0;
7929 struct community
*community
= NULL
;
7930 struct ecommunity
*ecommunity
= NULL
;
7931 struct lcommunity
*lcommunity
= NULL
;
7932 unsigned long match
= 0;
7934 /* If the bgp instance is being deleted or self peer is deleted
7935 * then do not create aggregate route
7937 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7938 || (bgp
->peer_self
== NULL
))
7941 if (BGP_PATH_HOLDDOWN(pi
))
7944 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7947 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7948 if (aggr_unsuppress_path(aggregate
, pi
))
7951 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7952 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7953 if (aggr_unsuppress_path(aggregate
, pi
))
7957 * This must be called after `summary`, `suppress-map` check to avoid
7958 * "unsuppressing" twice.
7960 if (aggregate
->match_med
)
7961 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
7963 if (aggregate
->count
> 0)
7966 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7967 aggregate
->incomplete_origin_count
--;
7968 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7969 aggregate
->egp_origin_count
--;
7971 if (aggregate
->as_set
) {
7972 /* Remove as-path from aggregate.
7974 bgp_remove_aspath_from_aggregate(aggregate
,
7977 if (bgp_attr_get_community(pi
->attr
))
7978 /* Remove community from aggregate.
7980 bgp_remove_community_from_aggregate(
7981 aggregate
, bgp_attr_get_community(pi
->attr
));
7983 if (bgp_attr_get_ecommunity(pi
->attr
))
7984 /* Remove ecommunity from aggregate.
7986 bgp_remove_ecommunity_from_aggregate(
7987 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
7989 if (bgp_attr_get_lcommunity(pi
->attr
))
7990 /* Remove lcommunity from aggregate.
7992 bgp_remove_lcommunity_from_aggregate(
7993 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
7996 /* If this node was suppressed, process the change. */
7998 bgp_process(bgp
, pi
->net
, afi
, safi
);
8000 origin
= BGP_ORIGIN_IGP
;
8001 if (aggregate
->incomplete_origin_count
> 0)
8002 origin
= BGP_ORIGIN_INCOMPLETE
;
8003 else if (aggregate
->egp_origin_count
> 0)
8004 origin
= BGP_ORIGIN_EGP
;
8006 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8007 origin
= aggregate
->origin
;
8009 if (aggregate
->as_set
) {
8010 /* Retrieve aggregate route's as-path.
8012 if (aggregate
->aspath
)
8013 aspath
= aspath_dup(aggregate
->aspath
);
8015 /* Retrieve aggregate route's community.
8017 if (aggregate
->community
)
8018 community
= community_dup(aggregate
->community
);
8020 /* Retrieve aggregate route's ecommunity.
8022 if (aggregate
->ecommunity
)
8023 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8025 /* Retrieve aggregate route's lcommunity.
8027 if (aggregate
->lcommunity
)
8028 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8031 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8032 aspath
, community
, ecommunity
,
8033 lcommunity
, atomic_aggregate
, aggregate
);
8036 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8037 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8039 struct bgp_dest
*child
;
8040 struct bgp_dest
*dest
;
8041 struct bgp_aggregate
*aggregate
;
8042 struct bgp_table
*table
;
8044 table
= bgp
->aggregate
[afi
][safi
];
8046 /* No aggregates configured. */
8047 if (bgp_table_top_nolock(table
) == NULL
)
8050 if (p
->prefixlen
== 0)
8053 if (BGP_PATH_HOLDDOWN(pi
))
8056 /* If suppress fib is enabled and route not installed
8057 * in FIB, do not update the aggregate route
8059 if (!bgp_check_advertise(bgp
, pi
->net
))
8062 child
= bgp_node_get(table
, p
);
8064 /* Aggregate address configuration check. */
8065 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8066 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8068 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8069 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8070 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8074 bgp_dest_unlock_node(child
);
8077 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8078 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8080 struct bgp_dest
*child
;
8081 struct bgp_dest
*dest
;
8082 struct bgp_aggregate
*aggregate
;
8083 struct bgp_table
*table
;
8085 table
= bgp
->aggregate
[afi
][safi
];
8087 /* No aggregates configured. */
8088 if (bgp_table_top_nolock(table
) == NULL
)
8091 if (p
->prefixlen
== 0)
8094 child
= bgp_node_get(table
, p
);
8096 /* Aggregate address configuration check. */
8097 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8098 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8100 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8101 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8102 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8106 bgp_dest_unlock_node(child
);
8109 /* Aggregate route attribute. */
8110 #define AGGREGATE_SUMMARY_ONLY 1
8111 #define AGGREGATE_AS_SET 1
8112 #define AGGREGATE_AS_UNSET 0
8114 static const char *bgp_origin2str(uint8_t origin
)
8117 case BGP_ORIGIN_IGP
:
8119 case BGP_ORIGIN_EGP
:
8121 case BGP_ORIGIN_INCOMPLETE
:
8122 return "incomplete";
8127 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8130 case RPKI_NOT_BEING_USED
:
8140 assert(!"We should never get here this is a dev escape");
8144 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8145 afi_t afi
, safi_t safi
)
8147 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8150 struct bgp_dest
*dest
;
8151 struct bgp_aggregate
*aggregate
;
8153 /* Convert string to prefix structure. */
8154 ret
= str2prefix(prefix_str
, &p
);
8156 vty_out(vty
, "Malformed prefix\n");
8157 return CMD_WARNING_CONFIG_FAILED
;
8161 /* Old configuration check. */
8162 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8165 "%% There is no aggregate-address configuration.\n");
8166 return CMD_WARNING_CONFIG_FAILED
;
8169 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8170 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8171 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8172 NULL
, NULL
, 0, aggregate
);
8174 /* Unlock aggregate address configuration. */
8175 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8177 if (aggregate
->community
)
8178 community_free(&aggregate
->community
);
8180 if (aggregate
->community_hash
) {
8181 /* Delete all communities in the hash.
8183 hash_clean(aggregate
->community_hash
,
8184 bgp_aggr_community_remove
);
8185 /* Free up the community_hash.
8187 hash_free(aggregate
->community_hash
);
8190 if (aggregate
->ecommunity
)
8191 ecommunity_free(&aggregate
->ecommunity
);
8193 if (aggregate
->ecommunity_hash
) {
8194 /* Delete all ecommunities in the hash.
8196 hash_clean(aggregate
->ecommunity_hash
,
8197 bgp_aggr_ecommunity_remove
);
8198 /* Free up the ecommunity_hash.
8200 hash_free(aggregate
->ecommunity_hash
);
8203 if (aggregate
->lcommunity
)
8204 lcommunity_free(&aggregate
->lcommunity
);
8206 if (aggregate
->lcommunity_hash
) {
8207 /* Delete all lcommunities in the hash.
8209 hash_clean(aggregate
->lcommunity_hash
,
8210 bgp_aggr_lcommunity_remove
);
8211 /* Free up the lcommunity_hash.
8213 hash_free(aggregate
->lcommunity_hash
);
8216 if (aggregate
->aspath
)
8217 aspath_free(aggregate
->aspath
);
8219 if (aggregate
->aspath_hash
) {
8220 /* Delete all as-paths in the hash.
8222 hash_clean(aggregate
->aspath_hash
,
8223 bgp_aggr_aspath_remove
);
8224 /* Free up the aspath_hash.
8226 hash_free(aggregate
->aspath_hash
);
8229 bgp_aggregate_free(aggregate
);
8230 bgp_dest_unlock_node(dest
);
8231 bgp_dest_unlock_node(dest
);
8236 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8237 safi_t safi
, const char *rmap
,
8238 uint8_t summary_only
, uint8_t as_set
,
8239 uint8_t origin
, bool match_med
,
8240 const char *suppress_map
)
8242 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8245 struct bgp_dest
*dest
;
8246 struct bgp_aggregate
*aggregate
;
8247 uint8_t as_set_new
= as_set
;
8249 if (suppress_map
&& summary_only
) {
8251 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8252 return CMD_WARNING_CONFIG_FAILED
;
8255 /* Convert string to prefix structure. */
8256 ret
= str2prefix(prefix_str
, &p
);
8258 vty_out(vty
, "Malformed prefix\n");
8259 return CMD_WARNING_CONFIG_FAILED
;
8263 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8264 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8265 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8267 return CMD_WARNING_CONFIG_FAILED
;
8270 /* Old configuration check. */
8271 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8272 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8275 vty_out(vty
, "There is already same aggregate network.\n");
8276 /* try to remove the old entry */
8277 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8279 vty_out(vty
, "Error deleting aggregate.\n");
8280 bgp_dest_unlock_node(dest
);
8281 return CMD_WARNING_CONFIG_FAILED
;
8285 /* Make aggregate address structure. */
8286 aggregate
= bgp_aggregate_new();
8287 aggregate
->summary_only
= summary_only
;
8288 aggregate
->match_med
= match_med
;
8290 /* Network operators MUST NOT locally generate any new
8291 * announcements containing AS_SET or AS_CONFED_SET. If they have
8292 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8293 * SHOULD withdraw those routes and re-announce routes for the
8294 * aggregate or component prefixes (i.e., the more-specific routes
8295 * subsumed by the previously aggregated route) without AS_SET
8296 * or AS_CONFED_SET in the updates.
8298 if (bgp
->reject_as_sets
) {
8299 if (as_set
== AGGREGATE_AS_SET
) {
8300 as_set_new
= AGGREGATE_AS_UNSET
;
8302 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8305 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8309 aggregate
->as_set
= as_set_new
;
8310 aggregate
->safi
= safi
;
8311 /* Override ORIGIN attribute if defined.
8312 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8313 * to IGP which is not what rfc4271 says.
8314 * This enables the same behavior, optionally.
8316 aggregate
->origin
= origin
;
8319 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8320 route_map_counter_decrement(aggregate
->rmap
.map
);
8321 aggregate
->rmap
.name
=
8322 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8323 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8324 route_map_counter_increment(aggregate
->rmap
.map
);
8328 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8329 route_map_counter_decrement(aggregate
->suppress_map
);
8331 aggregate
->suppress_map_name
=
8332 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8333 aggregate
->suppress_map
=
8334 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8335 route_map_counter_increment(aggregate
->suppress_map
);
8338 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8340 /* Aggregate address insert into BGP routing table. */
8341 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8346 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8347 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8349 "|summary-only$summary_only"
8350 "|route-map RMAP_NAME$rmap_name"
8351 "|origin <egp|igp|incomplete>$origin_s"
8352 "|matching-MED-only$match_med"
8353 "|suppress-map RMAP_NAME$suppress_map"
8356 "Configure BGP aggregate entries\n"
8357 "Aggregate prefix\n"
8358 "Aggregate address\n"
8360 "Generate AS set path information\n"
8361 "Filter more specific routes from updates\n"
8362 "Apply route map to aggregate network\n"
8367 "Unknown heritage\n"
8368 "Only aggregate routes with matching MED\n"
8369 "Suppress the selected more specific routes\n"
8370 "Route map with the route selectors\n")
8372 const char *prefix_s
= NULL
;
8373 safi_t safi
= bgp_node_safi(vty
);
8374 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8375 int as_set
= AGGREGATE_AS_UNSET
;
8376 char prefix_buf
[PREFIX2STR_BUFFER
];
8379 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8382 vty_out(vty
, "%% Inconsistent address and mask\n");
8383 return CMD_WARNING_CONFIG_FAILED
;
8385 prefix_s
= prefix_buf
;
8387 prefix_s
= prefix_str
;
8390 if (strcmp(origin_s
, "egp") == 0)
8391 origin
= BGP_ORIGIN_EGP
;
8392 else if (strcmp(origin_s
, "igp") == 0)
8393 origin
= BGP_ORIGIN_IGP
;
8394 else if (strcmp(origin_s
, "incomplete") == 0)
8395 origin
= BGP_ORIGIN_INCOMPLETE
;
8399 as_set
= AGGREGATE_AS_SET
;
8401 /* Handle configuration removal, otherwise installation. */
8403 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8405 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8406 summary_only
!= NULL
, as_set
, origin
,
8407 match_med
!= NULL
, suppress_map
);
8410 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8411 "[no] aggregate-address X:X::X:X/M$prefix [{"
8413 "|summary-only$summary_only"
8414 "|route-map RMAP_NAME$rmap_name"
8415 "|origin <egp|igp|incomplete>$origin_s"
8416 "|matching-MED-only$match_med"
8417 "|suppress-map RMAP_NAME$suppress_map"
8420 "Configure BGP aggregate entries\n"
8421 "Aggregate prefix\n"
8422 "Generate AS set path information\n"
8423 "Filter more specific routes from updates\n"
8424 "Apply route map to aggregate network\n"
8429 "Unknown heritage\n"
8430 "Only aggregate routes with matching MED\n"
8431 "Suppress the selected more specific routes\n"
8432 "Route map with the route selectors\n")
8434 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8435 int as_set
= AGGREGATE_AS_UNSET
;
8438 if (strcmp(origin_s
, "egp") == 0)
8439 origin
= BGP_ORIGIN_EGP
;
8440 else if (strcmp(origin_s
, "igp") == 0)
8441 origin
= BGP_ORIGIN_IGP
;
8442 else if (strcmp(origin_s
, "incomplete") == 0)
8443 origin
= BGP_ORIGIN_INCOMPLETE
;
8447 as_set
= AGGREGATE_AS_SET
;
8449 /* Handle configuration removal, otherwise installation. */
8451 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8454 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8455 rmap_name
, summary_only
!= NULL
, as_set
,
8456 origin
, match_med
!= NULL
, suppress_map
);
8459 /* Redistribute route treatment. */
8460 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8461 const union g_addr
*nexthop
, ifindex_t ifindex
,
8462 enum nexthop_types_t nhtype
, uint8_t distance
,
8463 enum blackhole_type bhtype
, uint32_t metric
,
8464 uint8_t type
, unsigned short instance
,
8467 struct bgp_path_info
*new;
8468 struct bgp_path_info
*bpi
;
8469 struct bgp_path_info rmap_path
;
8470 struct bgp_dest
*bn
;
8472 struct attr
*new_attr
;
8474 route_map_result_t ret
;
8475 struct bgp_redist
*red
;
8477 /* Make default attribute. */
8478 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8480 * This must not be NULL to satisfy Coverity SA
8482 assert(attr
.aspath
);
8485 case NEXTHOP_TYPE_IFINDEX
:
8486 switch (p
->family
) {
8488 attr
.nexthop
.s_addr
= INADDR_ANY
;
8489 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8492 memset(&attr
.mp_nexthop_global
, 0,
8493 sizeof(attr
.mp_nexthop_global
));
8494 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8498 case NEXTHOP_TYPE_IPV4
:
8499 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8500 attr
.nexthop
= nexthop
->ipv4
;
8501 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8503 case NEXTHOP_TYPE_IPV6
:
8504 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8505 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8506 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8508 case NEXTHOP_TYPE_BLACKHOLE
:
8509 switch (p
->family
) {
8511 attr
.nexthop
.s_addr
= INADDR_ANY
;
8512 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8515 memset(&attr
.mp_nexthop_global
, 0,
8516 sizeof(attr
.mp_nexthop_global
));
8517 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8520 attr
.bh_type
= bhtype
;
8523 attr
.nh_type
= nhtype
;
8524 attr
.nh_ifindex
= ifindex
;
8527 attr
.distance
= distance
;
8528 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8531 afi
= family2afi(p
->family
);
8533 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8535 struct attr attr_new
;
8537 /* Copy attribute for modification. */
8540 if (red
->redist_metric_flag
)
8541 attr_new
.med
= red
->redist_metric
;
8543 /* Apply route-map. */
8544 if (red
->rmap
.name
) {
8545 memset(&rmap_path
, 0, sizeof(rmap_path
));
8546 rmap_path
.peer
= bgp
->peer_self
;
8547 rmap_path
.attr
= &attr_new
;
8549 SET_FLAG(bgp
->peer_self
->rmap_type
,
8550 PEER_RMAP_TYPE_REDISTRIBUTE
);
8552 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8554 bgp
->peer_self
->rmap_type
= 0;
8556 if (ret
== RMAP_DENYMATCH
) {
8557 /* Free uninterned attribute. */
8558 bgp_attr_flush(&attr_new
);
8560 /* Unintern original. */
8561 aspath_unintern(&attr
.aspath
);
8562 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8567 if (bgp_in_graceful_shutdown(bgp
))
8568 bgp_attr_add_gshut_community(&attr_new
);
8570 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8571 SAFI_UNICAST
, p
, NULL
);
8573 new_attr
= bgp_attr_intern(&attr_new
);
8575 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8576 if (bpi
->peer
== bgp
->peer_self
8577 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8581 /* Ensure the (source route) type is updated. */
8583 if (attrhash_cmp(bpi
->attr
, new_attr
)
8584 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8585 bgp_attr_unintern(&new_attr
);
8586 aspath_unintern(&attr
.aspath
);
8587 bgp_dest_unlock_node(bn
);
8590 /* The attribute is changed. */
8591 bgp_path_info_set_flag(bn
, bpi
,
8592 BGP_PATH_ATTR_CHANGED
);
8594 /* Rewrite BGP route information. */
8595 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8596 bgp_path_info_restore(bn
, bpi
);
8598 bgp_aggregate_decrement(
8599 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8600 bgp_attr_unintern(&bpi
->attr
);
8601 bpi
->attr
= new_attr
;
8602 bpi
->uptime
= monotime(NULL
);
8604 /* Process change. */
8605 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8607 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8608 bgp_dest_unlock_node(bn
);
8609 aspath_unintern(&attr
.aspath
);
8611 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8613 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8615 vpn_leak_from_vrf_update(
8616 bgp_get_default(), bgp
, bpi
);
8622 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8623 bgp
->peer_self
, new_attr
, bn
);
8624 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8626 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8627 bgp_path_info_add(bn
, new);
8628 bgp_dest_unlock_node(bn
);
8629 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8630 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8632 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8633 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8635 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8639 /* Unintern original. */
8640 aspath_unintern(&attr
.aspath
);
8643 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8644 unsigned short instance
)
8647 struct bgp_dest
*dest
;
8648 struct bgp_path_info
*pi
;
8649 struct bgp_redist
*red
;
8651 afi
= family2afi(p
->family
);
8653 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8655 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8656 SAFI_UNICAST
, p
, NULL
);
8658 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8659 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8663 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8664 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8666 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8669 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8670 bgp_path_info_delete(dest
, pi
);
8671 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8673 bgp_dest_unlock_node(dest
);
8677 /* Withdraw specified route type's route. */
8678 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8679 unsigned short instance
)
8681 struct bgp_dest
*dest
;
8682 struct bgp_path_info
*pi
;
8683 struct bgp_table
*table
;
8685 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8687 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8688 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8689 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8690 && pi
->instance
== instance
)
8694 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8695 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8697 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8700 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8701 pi
, afi
, SAFI_UNICAST
);
8702 bgp_path_info_delete(dest
, pi
);
8703 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8708 /* Static function to display route. */
8709 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8710 struct vty
*vty
, json_object
*json
, bool wide
)
8715 if (p
->family
== AF_INET
) {
8717 len
= vty_out(vty
, "%pFX", p
);
8719 json_object_string_add(json
, "prefix",
8720 inet_ntop(p
->family
,
8723 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8724 json_object_string_addf(json
, "network", "%pFX", p
);
8725 json_object_int_add(json
, "version", dest
->version
);
8727 } else if (p
->family
== AF_ETHERNET
) {
8728 len
= vty_out(vty
, "%pFX", p
);
8729 } else if (p
->family
== AF_EVPN
) {
8731 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8733 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8734 } else if (p
->family
== AF_FLOWSPEC
) {
8735 route_vty_out_flowspec(vty
, p
, NULL
,
8737 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8738 NLRI_STRING_FORMAT_MIN
, json
);
8741 len
= vty_out(vty
, "%pFX", p
);
8743 json_object_string_add(json
, "prefix",
8744 inet_ntop(p
->family
,
8747 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8748 json_object_string_addf(json
, "network", "%pFX", p
);
8749 json_object_int_add(json
, "version", dest
->version
);
8754 len
= wide
? (45 - len
) : (17 - len
);
8756 vty_out(vty
, "\n%*s", 20, " ");
8758 vty_out(vty
, "%*s", len
, " ");
8762 enum bgp_display_type
{
8766 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8769 case bgp_path_selection_none
:
8770 return "Nothing to Select";
8771 case bgp_path_selection_first
:
8772 return "First path received";
8773 case bgp_path_selection_evpn_sticky_mac
:
8774 return "EVPN Sticky Mac";
8775 case bgp_path_selection_evpn_seq
:
8776 return "EVPN sequence number";
8777 case bgp_path_selection_evpn_lower_ip
:
8778 return "EVPN lower IP";
8779 case bgp_path_selection_evpn_local_path
:
8780 return "EVPN local ES path";
8781 case bgp_path_selection_evpn_non_proxy
:
8782 return "EVPN non proxy";
8783 case bgp_path_selection_weight
:
8785 case bgp_path_selection_local_pref
:
8786 return "Local Pref";
8787 case bgp_path_selection_local_route
:
8788 return "Local Route";
8789 case bgp_path_selection_confed_as_path
:
8790 return "Confederation based AS Path";
8791 case bgp_path_selection_as_path
:
8793 case bgp_path_selection_origin
:
8795 case bgp_path_selection_med
:
8797 case bgp_path_selection_peer
:
8799 case bgp_path_selection_confed
:
8800 return "Confed Peer Type";
8801 case bgp_path_selection_igp_metric
:
8802 return "IGP Metric";
8803 case bgp_path_selection_older
:
8804 return "Older Path";
8805 case bgp_path_selection_router_id
:
8807 case bgp_path_selection_cluster_length
:
8808 return "Cluster length";
8809 case bgp_path_selection_stale
:
8810 return "Path Staleness";
8811 case bgp_path_selection_local_configured
:
8812 return "Locally configured route";
8813 case bgp_path_selection_neighbor_ip
:
8814 return "Neighbor IP";
8815 case bgp_path_selection_default
:
8816 return "Nothing left to compare";
8818 return "Invalid (internal error)";
8821 /* Print the short form route status for a bgp_path_info */
8822 static void route_vty_short_status_out(struct vty
*vty
,
8823 struct bgp_path_info
*path
,
8824 const struct prefix
*p
,
8825 json_object
*json_path
)
8827 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8831 /* Route status display. */
8832 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8833 json_object_boolean_true_add(json_path
, "removed");
8835 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8836 json_object_boolean_true_add(json_path
, "stale");
8838 if (path
->extra
&& bgp_path_suppressed(path
))
8839 json_object_boolean_true_add(json_path
, "suppressed");
8841 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8842 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8843 json_object_boolean_true_add(json_path
, "valid");
8846 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8847 json_object_boolean_true_add(json_path
, "history");
8849 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8850 json_object_boolean_true_add(json_path
, "damped");
8852 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8853 json_object_boolean_true_add(json_path
, "bestpath");
8854 json_object_string_add(json_path
, "selectionReason",
8855 bgp_path_selection_reason2str(
8856 path
->net
->reason
));
8859 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8860 json_object_boolean_true_add(json_path
, "multipath");
8862 /* Internal route. */
8863 if ((path
->peer
->as
)
8864 && (path
->peer
->as
== path
->peer
->local_as
))
8865 json_object_string_add(json_path
, "pathFrom",
8868 json_object_string_add(json_path
, "pathFrom",
8874 /* RPKI validation state */
8876 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
8878 if (rpki_state
== RPKI_VALID
)
8880 else if (rpki_state
== RPKI_INVALID
)
8882 else if (rpki_state
== RPKI_NOTFOUND
)
8885 /* Route status display. */
8886 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8888 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8890 else if (bgp_path_suppressed(path
))
8892 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8893 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8899 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8901 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8903 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8905 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8910 /* Internal route. */
8911 if (path
->peer
&& (path
->peer
->as
)
8912 && (path
->peer
->as
== path
->peer
->local_as
))
8918 static char *bgp_nexthop_hostname(struct peer
*peer
,
8919 struct bgp_nexthop_cache
*bnc
)
8922 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8923 return peer
->hostname
;
8927 /* called from terminal list command */
8928 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8929 struct bgp_path_info
*path
, int display
, safi_t safi
,
8930 json_object
*json_paths
, bool wide
)
8933 struct attr
*attr
= path
->attr
;
8934 json_object
*json_path
= NULL
;
8935 json_object
*json_nexthops
= NULL
;
8936 json_object
*json_nexthop_global
= NULL
;
8937 json_object
*json_nexthop_ll
= NULL
;
8938 json_object
*json_ext_community
= NULL
;
8939 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8941 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8942 bool nexthop_othervrf
= false;
8943 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8944 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8945 char *nexthop_hostname
=
8946 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8947 char esi_buf
[ESI_STR_LEN
];
8950 json_path
= json_object_new_object();
8952 /* short status lead text */
8953 route_vty_short_status_out(vty
, path
, p
, json_path
);
8956 /* print prefix and mask */
8958 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8960 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8962 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
8966 * If vrf id of nexthop is different from that of prefix,
8967 * set up printable string to append
8969 if (path
->extra
&& path
->extra
->bgp_orig
) {
8970 const char *self
= "";
8975 nexthop_othervrf
= true;
8976 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8978 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8979 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8980 "@%s%s", VRFID_NONE_STR
, self
);
8982 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8983 path
->extra
->bgp_orig
->vrf_id
, self
);
8985 if (path
->extra
->bgp_orig
->inst_type
8986 != BGP_INSTANCE_TYPE_DEFAULT
)
8988 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8990 const char *self
= "";
8995 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8999 * For ENCAP and EVPN routes, nexthop address family is not
9000 * neccessarily the same as the prefix address family.
9001 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9002 * EVPN routes are also exchanged with a MP nexthop. Currently,
9004 * is only IPv4, the value will be present in either
9006 * attr->mp_nexthop_global_in
9008 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9011 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9015 snprintf(nexthop
, sizeof(nexthop
), "%s",
9016 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
9020 snprintf(nexthop
, sizeof(nexthop
), "%s",
9021 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
9025 snprintf(nexthop
, sizeof(nexthop
), "?");
9030 json_nexthop_global
= json_object_new_object();
9032 json_object_string_add(json_nexthop_global
, "ip",
9035 if (path
->peer
->hostname
)
9036 json_object_string_add(json_nexthop_global
,
9038 path
->peer
->hostname
);
9040 json_object_string_add(json_nexthop_global
, "afi",
9041 (af
== AF_INET
) ? "ipv4"
9043 json_object_boolean_true_add(json_nexthop_global
,
9046 if (nexthop_hostname
)
9047 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9048 nexthop_hostname
, vrf_id_str
);
9050 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9052 len
= wide
? (41 - len
) : (16 - len
);
9054 vty_out(vty
, "\n%*s", 36, " ");
9056 vty_out(vty
, "%*s", len
, " ");
9058 } else if (safi
== SAFI_EVPN
) {
9060 json_nexthop_global
= json_object_new_object();
9062 json_object_string_addf(json_nexthop_global
, "ip",
9064 &attr
->mp_nexthop_global_in
);
9066 if (path
->peer
->hostname
)
9067 json_object_string_add(json_nexthop_global
,
9069 path
->peer
->hostname
);
9071 json_object_string_add(json_nexthop_global
, "afi",
9073 json_object_boolean_true_add(json_nexthop_global
,
9076 if (nexthop_hostname
)
9077 len
= vty_out(vty
, "%pI4(%s)%s",
9078 &attr
->mp_nexthop_global_in
,
9079 nexthop_hostname
, vrf_id_str
);
9081 len
= vty_out(vty
, "%pI4%s",
9082 &attr
->mp_nexthop_global_in
,
9085 len
= wide
? (41 - len
) : (16 - len
);
9087 vty_out(vty
, "\n%*s", 36, " ");
9089 vty_out(vty
, "%*s", len
, " ");
9091 } else if (safi
== SAFI_FLOWSPEC
) {
9092 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9094 json_nexthop_global
= json_object_new_object();
9096 json_object_string_add(json_nexthop_global
,
9098 json_object_string_addf(json_nexthop_global
,
9102 if (path
->peer
->hostname
)
9103 json_object_string_add(
9104 json_nexthop_global
, "hostname",
9105 path
->peer
->hostname
);
9107 json_object_boolean_true_add(
9108 json_nexthop_global
,
9111 if (nexthop_hostname
)
9112 len
= vty_out(vty
, "%pI4(%s)%s",
9117 len
= vty_out(vty
, "%pI4%s",
9121 len
= wide
? (41 - len
) : (16 - len
);
9123 vty_out(vty
, "\n%*s", 36, " ");
9125 vty_out(vty
, "%*s", len
, " ");
9128 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9130 json_nexthop_global
= json_object_new_object();
9132 json_object_string_addf(json_nexthop_global
, "ip",
9133 "%pI4", &attr
->nexthop
);
9135 if (path
->peer
->hostname
)
9136 json_object_string_add(json_nexthop_global
,
9138 path
->peer
->hostname
);
9140 json_object_string_add(json_nexthop_global
, "afi",
9142 json_object_boolean_true_add(json_nexthop_global
,
9145 if (nexthop_hostname
)
9146 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9147 nexthop_hostname
, vrf_id_str
);
9149 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9152 len
= wide
? (41 - len
) : (16 - len
);
9154 vty_out(vty
, "\n%*s", 36, " ");
9156 vty_out(vty
, "%*s", len
, " ");
9161 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9163 json_nexthop_global
= json_object_new_object();
9164 json_object_string_addf(json_nexthop_global
, "ip",
9166 &attr
->mp_nexthop_global
);
9168 if (path
->peer
->hostname
)
9169 json_object_string_add(json_nexthop_global
,
9171 path
->peer
->hostname
);
9173 json_object_string_add(json_nexthop_global
, "afi",
9175 json_object_string_add(json_nexthop_global
, "scope",
9178 /* We display both LL & GL if both have been
9180 if ((attr
->mp_nexthop_len
9181 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9182 || (path
->peer
->conf_if
)) {
9183 json_nexthop_ll
= json_object_new_object();
9184 json_object_string_addf(
9185 json_nexthop_ll
, "ip", "%pI6",
9186 &attr
->mp_nexthop_local
);
9188 if (path
->peer
->hostname
)
9189 json_object_string_add(
9190 json_nexthop_ll
, "hostname",
9191 path
->peer
->hostname
);
9193 json_object_string_add(json_nexthop_ll
, "afi",
9195 json_object_string_add(json_nexthop_ll
, "scope",
9198 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9199 &attr
->mp_nexthop_local
)
9201 && !attr
->mp_nexthop_prefer_global
)
9202 json_object_boolean_true_add(
9203 json_nexthop_ll
, "used");
9205 json_object_boolean_true_add(
9206 json_nexthop_global
, "used");
9208 json_object_boolean_true_add(
9209 json_nexthop_global
, "used");
9211 /* Display LL if LL/Global both in table unless
9212 * prefer-global is set */
9213 if (((attr
->mp_nexthop_len
9214 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9215 && !attr
->mp_nexthop_prefer_global
)
9216 || (path
->peer
->conf_if
)) {
9217 if (path
->peer
->conf_if
) {
9218 len
= vty_out(vty
, "%s",
9219 path
->peer
->conf_if
);
9220 /* len of IPv6 addr + max len of def
9222 len
= wide
? (41 - len
) : (16 - len
);
9225 vty_out(vty
, "\n%*s", 36, " ");
9227 vty_out(vty
, "%*s", len
, " ");
9229 if (nexthop_hostname
)
9232 &attr
->mp_nexthop_local
,
9238 &attr
->mp_nexthop_local
,
9241 len
= wide
? (41 - len
) : (16 - len
);
9244 vty_out(vty
, "\n%*s", 36, " ");
9246 vty_out(vty
, "%*s", len
, " ");
9249 if (nexthop_hostname
)
9250 len
= vty_out(vty
, "%pI6(%s)%s",
9251 &attr
->mp_nexthop_global
,
9255 len
= vty_out(vty
, "%pI6%s",
9256 &attr
->mp_nexthop_global
,
9259 len
= wide
? (41 - len
) : (16 - len
);
9262 vty_out(vty
, "\n%*s", 36, " ");
9264 vty_out(vty
, "%*s", len
, " ");
9270 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9272 json_object_int_add(json_path
, "metric", attr
->med
);
9274 vty_out(vty
, "%7u", attr
->med
);
9276 vty_out(vty
, "%10u", attr
->med
);
9277 else if (!json_paths
) {
9279 vty_out(vty
, "%*s", 7, " ");
9281 vty_out(vty
, "%*s", 10, " ");
9285 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9287 json_object_int_add(json_path
, "locPrf",
9290 vty_out(vty
, "%7u", attr
->local_pref
);
9291 else if (!json_paths
)
9295 json_object_int_add(json_path
, "weight", attr
->weight
);
9297 vty_out(vty
, "%7u ", attr
->weight
);
9300 json_object_string_addf(json_path
, "peerId", "%pSU",
9306 json_object_string_add(json_path
, "path",
9309 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9314 json_object_string_add(json_path
, "origin",
9315 bgp_origin_long_str
[attr
->origin
]);
9317 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9320 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9321 json_object_string_add(json_path
, "esi",
9322 esi_to_str(&attr
->esi
,
9323 esi_buf
, sizeof(esi_buf
)));
9325 if (safi
== SAFI_EVPN
&&
9326 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9327 json_ext_community
= json_object_new_object();
9328 json_object_string_add(
9329 json_ext_community
, "string",
9330 bgp_attr_get_ecommunity(attr
)->str
);
9331 json_object_object_add(json_path
,
9332 "extendedCommunity",
9333 json_ext_community
);
9337 json_object_boolean_true_add(json_path
,
9338 "announceNexthopSelf");
9339 if (nexthop_othervrf
) {
9340 json_object_string_add(json_path
, "nhVrfName",
9343 json_object_int_add(json_path
, "nhVrfId",
9344 ((nexthop_vrfid
== VRF_UNKNOWN
)
9346 : (int)nexthop_vrfid
));
9351 if (json_nexthop_global
|| json_nexthop_ll
) {
9352 json_nexthops
= json_object_new_array();
9354 if (json_nexthop_global
)
9355 json_object_array_add(json_nexthops
,
9356 json_nexthop_global
);
9358 if (json_nexthop_ll
)
9359 json_object_array_add(json_nexthops
,
9362 json_object_object_add(json_path
, "nexthops",
9366 json_object_array_add(json_paths
, json_path
);
9370 if (safi
== SAFI_EVPN
) {
9371 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9372 /* XXX - add these params to the json out */
9373 vty_out(vty
, "%*s", 20, " ");
9374 vty_out(vty
, "ESI:%s",
9375 esi_to_str(&attr
->esi
, esi_buf
,
9381 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9382 vty_out(vty
, "%*s", 20, " ");
9383 vty_out(vty
, "%s\n",
9384 bgp_attr_get_ecommunity(attr
)->str
);
9388 #ifdef ENABLE_BGP_VNC
9389 /* prints an additional line, indented, with VNC info, if
9391 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9392 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9397 /* called from terminal list command */
9398 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9399 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9400 bool use_json
, json_object
*json_ar
, bool wide
)
9402 json_object
*json_status
= NULL
;
9403 json_object
*json_net
= NULL
;
9407 /* Route status display. */
9409 json_status
= json_object_new_object();
9410 json_net
= json_object_new_object();
9417 /* print prefix and mask */
9419 if (safi
== SAFI_EVPN
)
9420 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9421 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9422 json_object_string_add(
9423 json_net
, "addrPrefix",
9424 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9426 json_object_int_add(json_net
, "prefixLen",
9428 json_object_string_addf(json_net
, "network", "%pFX", p
);
9431 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9433 /* Print attribute */
9436 if (p
->family
== AF_INET
&&
9437 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9438 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9439 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9440 json_object_string_addf(
9441 json_net
, "nextHop", "%pI4",
9442 &attr
->mp_nexthop_global_in
);
9444 json_object_string_addf(
9445 json_net
, "nextHop", "%pI4",
9447 } else if (p
->family
== AF_INET6
||
9448 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9449 json_object_string_addf(
9450 json_net
, "nextHopGlobal", "%pI6",
9451 &attr
->mp_nexthop_global
);
9452 } else if (p
->family
== AF_EVPN
&&
9453 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9454 json_object_string_addf(
9455 json_net
, "nextHop", "%pI4",
9456 &attr
->mp_nexthop_global_in
);
9460 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9461 json_object_int_add(json_net
, "metric",
9464 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9465 json_object_int_add(json_net
, "locPrf",
9468 json_object_int_add(json_net
, "weight", attr
->weight
);
9472 json_object_string_add(json_net
, "path",
9476 json_object_string_add(json_net
, "bgpOriginCode",
9477 bgp_origin_str
[attr
->origin
]);
9479 if (p
->family
== AF_INET
&&
9480 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9481 safi
== SAFI_EVPN
||
9482 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9483 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9484 || safi
== SAFI_EVPN
)
9485 vty_out(vty
, "%-16pI4",
9486 &attr
->mp_nexthop_global_in
);
9488 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9490 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9491 } else if (p
->family
== AF_INET6
||
9492 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9498 &attr
->mp_nexthop_global
, buf
,
9500 len
= wide
? (41 - len
) : (16 - len
);
9502 vty_out(vty
, "\n%*s", 36, " ");
9504 vty_out(vty
, "%*s", len
, " ");
9507 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9509 vty_out(vty
, "%7u", attr
->med
);
9511 vty_out(vty
, "%10u", attr
->med
);
9517 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9518 vty_out(vty
, "%7u", attr
->local_pref
);
9522 vty_out(vty
, "%7u ", attr
->weight
);
9526 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9529 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9533 json_object_boolean_true_add(json_status
, "*");
9534 json_object_boolean_true_add(json_status
, ">");
9535 json_object_object_add(json_net
, "appliedStatusSymbols",
9537 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9542 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9543 struct bgp_path_info
*path
, int display
, safi_t safi
,
9546 json_object
*json_out
= NULL
;
9548 mpls_label_t label
= MPLS_INVALID_LABEL
;
9554 json_out
= json_object_new_object();
9556 /* short status lead text */
9557 route_vty_short_status_out(vty
, path
, p
, json_out
);
9559 /* print prefix and mask */
9562 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9564 vty_out(vty
, "%*s", 17, " ");
9567 /* Print attribute */
9569 if (((p
->family
== AF_INET
) &&
9570 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9571 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9572 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9573 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9574 || safi
== SAFI_EVPN
) {
9576 json_object_string_addf(
9577 json_out
, "mpNexthopGlobalIn", "%pI4",
9578 &attr
->mp_nexthop_global_in
);
9580 vty_out(vty
, "%-16pI4",
9581 &attr
->mp_nexthop_global_in
);
9584 json_object_string_addf(json_out
, "nexthop",
9585 "%pI4", &attr
->nexthop
);
9587 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9589 } else if (((p
->family
== AF_INET6
) &&
9590 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9591 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9592 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9595 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9597 json_object_string_addf(
9598 json_out
, "mpNexthopGlobalIn", "%pI6",
9599 &attr
->mp_nexthop_global
);
9603 &attr
->mp_nexthop_global
,
9604 buf_a
, sizeof(buf_a
)));
9605 } else if (attr
->mp_nexthop_len
9606 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9607 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9608 &attr
->mp_nexthop_global
,
9609 &attr
->mp_nexthop_local
);
9611 json_object_string_add(json_out
,
9612 "mpNexthopGlobalLocal",
9615 vty_out(vty
, "%s", buf_a
);
9619 label
= decode_label(&path
->extra
->label
[0]);
9621 if (bgp_is_valid_label(&label
)) {
9623 json_object_int_add(json_out
, "notag", label
);
9624 json_object_array_add(json
, json_out
);
9626 vty_out(vty
, "notag/%d", label
);
9633 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9634 struct bgp_path_info
*path
, int display
,
9635 json_object
*json_paths
)
9638 json_object
*json_path
= NULL
;
9639 json_object
*json_nexthop
= NULL
;
9640 json_object
*json_overlay
= NULL
;
9646 json_path
= json_object_new_object();
9647 json_overlay
= json_object_new_object();
9648 json_nexthop
= json_object_new_object();
9651 /* short status lead text */
9652 route_vty_short_status_out(vty
, path
, p
, json_path
);
9654 /* print prefix and mask */
9656 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9658 vty_out(vty
, "%*s", 17, " ");
9660 /* Print attribute */
9662 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9667 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9669 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9670 &attr
->mp_nexthop_global_in
);
9672 json_object_string_add(json_nexthop
, "afi", "ipv4");
9674 json_object_object_add(json_path
, "nexthop",
9680 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9681 &attr
->mp_nexthop_local
);
9683 json_object_string_addf(json_nexthop
, "ipv6Global",
9685 &attr
->mp_nexthop_global
);
9687 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9689 &attr
->mp_nexthop_local
);
9691 json_object_string_add(json_nexthop
, "afi", "ipv6");
9693 json_object_object_add(json_path
, "nexthop",
9701 json_object_string_add(json_nexthop
, "Error",
9702 "Unsupported address-family");
9703 json_object_string_add(json_nexthop
, "error",
9704 "Unsupported address-family");
9708 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9711 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9713 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9715 if (bgp_attr_get_ecommunity(attr
)) {
9717 struct ecommunity_val
*routermac
= ecommunity_lookup(
9718 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9719 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9722 mac
= ecom_mac2str((char *)routermac
->val
);
9725 vty_out(vty
, "/%s", mac
);
9727 json_object_string_add(json_overlay
, "rmac",
9730 XFREE(MTYPE_TMP
, mac
);
9737 json_object_object_add(json_path
, "overlay", json_overlay
);
9739 json_object_array_add(json_paths
, json_path
);
9743 /* dampening route */
9744 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9745 struct bgp_path_info
*path
, int display
,
9746 afi_t afi
, safi_t safi
, bool use_json
,
9747 json_object
*json_paths
)
9749 struct attr
*attr
= path
->attr
;
9751 char timebuf
[BGP_UPTIME_LEN
];
9752 json_object
*json_path
= NULL
;
9755 json_path
= json_object_new_object();
9757 /* short status lead text */
9758 route_vty_short_status_out(vty
, path
, p
, json_path
);
9760 /* print prefix and mask */
9763 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9765 vty_out(vty
, "%*s", 17, " ");
9767 len
= vty_out(vty
, "%s", path
->peer
->host
);
9771 vty_out(vty
, "\n%*s", 34, " ");
9773 vty_out(vty
, "%*s", len
, " ");
9776 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9777 BGP_UPTIME_LEN
, afi
, safi
,
9781 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9783 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9787 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9788 safi
, use_json
, json_path
);
9791 json_object_string_add(json_path
, "asPath",
9794 json_object_string_add(json_path
, "origin",
9795 bgp_origin_str
[attr
->origin
]);
9796 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9798 json_object_array_add(json_paths
, json_path
);
9803 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9804 struct bgp_path_info
*path
, int display
,
9805 afi_t afi
, safi_t safi
, bool use_json
,
9806 json_object
*json_paths
)
9808 struct attr
*attr
= path
->attr
;
9809 struct bgp_damp_info
*bdi
;
9810 char timebuf
[BGP_UPTIME_LEN
];
9812 json_object
*json_path
= NULL
;
9818 json_path
= json_object_new_object();
9820 bdi
= path
->extra
->damp_info
;
9822 /* short status lead text */
9823 route_vty_short_status_out(vty
, path
, p
, json_path
);
9827 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9829 vty_out(vty
, "%*s", 17, " ");
9831 len
= vty_out(vty
, "%s", path
->peer
->host
);
9834 vty_out(vty
, "\n%*s", 33, " ");
9836 vty_out(vty
, "%*s", len
, " ");
9838 len
= vty_out(vty
, "%d", bdi
->flap
);
9843 vty_out(vty
, "%*s", len
, " ");
9845 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9846 BGP_UPTIME_LEN
, 0, NULL
));
9848 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9849 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9851 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9852 BGP_UPTIME_LEN
, afi
,
9853 safi
, use_json
, NULL
));
9855 vty_out(vty
, "%*s ", 8, " ");
9858 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9860 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9864 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9865 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
9867 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9870 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9871 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9872 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9873 BGP_UPTIME_LEN
, afi
, safi
,
9874 use_json
, json_path
);
9877 json_object_string_add(json_path
, "asPath",
9880 json_object_string_add(json_path
, "origin",
9881 bgp_origin_str
[attr
->origin
]);
9883 json_object_array_add(json_paths
, json_path
);
9887 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9888 int *first
, const char *header
,
9889 json_object
*json_adv_to
)
9891 json_object
*json_peer
= NULL
;
9894 /* 'advertised-to' is a dictionary of peers we have advertised
9896 * prefix too. The key is the peer's IP or swpX, the value is
9898 * hostname if we know it and "" if not.
9900 json_peer
= json_object_new_object();
9903 json_object_string_add(json_peer
, "hostname",
9907 json_object_object_add(json_adv_to
, peer
->conf_if
,
9910 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
9914 vty_out(vty
, "%s", header
);
9919 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9921 vty_out(vty
, " %s(%s)", peer
->hostname
,
9924 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
9928 vty_out(vty
, " %s", peer
->conf_if
);
9930 vty_out(vty
, " %pSU", &peer
->su
);
9935 static void route_vty_out_tx_ids(struct vty
*vty
,
9936 struct bgp_addpath_info_data
*d
)
9940 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9941 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9942 d
->addpath_tx_id
[i
],
9943 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9947 static void route_vty_out_detail_es_info(struct vty
*vty
,
9948 struct bgp_path_info
*pi
,
9950 json_object
*json_path
)
9952 char esi_buf
[ESI_STR_LEN
];
9953 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9954 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9955 ATTR_ES_PEER_ROUTER
);
9956 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9957 ATTR_ES_PEER_ACTIVE
);
9958 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9959 ATTR_ES_PEER_PROXY
);
9960 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9962 json_object
*json_es_info
= NULL
;
9964 json_object_string_add(
9967 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9968 json_es_info
= json_object_new_object();
9970 json_object_boolean_true_add(
9971 json_es_info
, "localEs");
9973 json_object_boolean_true_add(
9974 json_es_info
, "peerActive");
9976 json_object_boolean_true_add(
9977 json_es_info
, "peerProxy");
9979 json_object_boolean_true_add(
9980 json_es_info
, "peerRouter");
9981 if (attr
->mm_sync_seqnum
)
9982 json_object_int_add(
9983 json_es_info
, "peerSeq",
9984 attr
->mm_sync_seqnum
);
9985 json_object_object_add(
9986 json_path
, "es_info",
9990 if (bgp_evpn_attr_is_sync(attr
))
9992 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9994 es_local
? "local-es":"",
9995 peer_proxy
? "proxy " : "",
9996 peer_active
? "active ":"",
9997 peer_router
? "router ":"",
9998 attr
->mm_sync_seqnum
);
10000 vty_out(vty
, " ESI %s %s\n",
10002 es_local
? "local-es":"");
10006 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10007 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
10008 enum rpki_states rpki_curr_state
,
10009 json_object
*json_paths
)
10011 char buf
[INET6_ADDRSTRLEN
];
10013 struct attr
*attr
= path
->attr
;
10015 json_object
*json_bestpath
= NULL
;
10016 json_object
*json_cluster_list
= NULL
;
10017 json_object
*json_cluster_list_list
= NULL
;
10018 json_object
*json_ext_community
= NULL
;
10019 json_object
*json_last_update
= NULL
;
10020 json_object
*json_pmsi
= NULL
;
10021 json_object
*json_nexthop_global
= NULL
;
10022 json_object
*json_nexthop_ll
= NULL
;
10023 json_object
*json_nexthops
= NULL
;
10024 json_object
*json_path
= NULL
;
10025 json_object
*json_peer
= NULL
;
10026 json_object
*json_string
= NULL
;
10027 json_object
*json_adv_to
= NULL
;
10029 struct listnode
*node
, *nnode
;
10031 bool addpath_capable
;
10033 unsigned int first_as
;
10034 bool nexthop_self
=
10035 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10037 char *nexthop_hostname
=
10038 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10042 mpls_label_t label
= MPLS_INVALID_LABEL
;
10045 json_path
= json_object_new_object();
10046 json_peer
= json_object_new_object();
10047 json_nexthop_global
= json_object_new_object();
10050 if (safi
== SAFI_EVPN
) {
10052 vty_out(vty
, " Route %pRN", bn
);
10059 if (path
->extra
&& path
->extra
->num_labels
) {
10060 bgp_evpn_label2str(path
->extra
->label
,
10061 path
->extra
->num_labels
, tag_buf
,
10064 if (safi
== SAFI_EVPN
) {
10066 if (tag_buf
[0] != '\0')
10067 vty_out(vty
, " VNI %s", tag_buf
);
10070 json_object_string_add(json_path
, "VNI",
10072 json_object_string_add(json_path
, "vni",
10078 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10079 struct bgp_path_info
*parent_ri
;
10080 struct bgp_dest
*dest
, *pdest
;
10082 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10083 dest
= parent_ri
->net
;
10084 if (dest
&& dest
->pdest
) {
10085 pdest
= dest
->pdest
;
10087 (struct prefix_rd
*)bgp_dest_get_prefix(
10089 buf1
, sizeof(buf1
));
10090 if (is_pi_family_evpn(parent_ri
)) {
10092 " Imported from %s:%pFX, VNI %s",
10094 (struct prefix_evpn
*)
10095 bgp_dest_get_prefix(
10098 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
10099 vty_out(vty
, ", L3NHG %s",
10101 & ATTR_ES_L3_NHG_ACTIVE
)
10104 vty_out(vty
, "\n");
10108 " Imported from %s:%pFX\n",
10110 (struct prefix_evpn
*)
10111 bgp_dest_get_prefix(
10117 if (safi
== SAFI_EVPN
10118 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10119 char gwip_buf
[INET6_ADDRSTRLEN
];
10121 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10125 json_object_string_add(json_path
, "gatewayIP",
10128 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10131 if (safi
== SAFI_EVPN
&& !json_path
)
10132 vty_out(vty
, "\n");
10134 /* Line1 display AS-path, Aggregator */
10135 if (attr
->aspath
) {
10137 if (!attr
->aspath
->json
)
10138 aspath_str_update(attr
->aspath
, true);
10139 json_object_lock(attr
->aspath
->json
);
10140 json_object_object_add(json_path
, "aspath",
10141 attr
->aspath
->json
);
10143 if (attr
->aspath
->segments
)
10144 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
10146 vty_out(vty
, " Local");
10150 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10152 json_object_boolean_true_add(json_path
, "removed");
10154 vty_out(vty
, ", (removed)");
10157 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10159 json_object_boolean_true_add(json_path
, "stale");
10161 vty_out(vty
, ", (stale)");
10164 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10166 json_object_int_add(json_path
, "aggregatorAs",
10167 attr
->aggregator_as
);
10168 json_object_string_addf(json_path
, "aggregatorId",
10169 "%pI4", &attr
->aggregator_addr
);
10171 vty_out(vty
, ", (aggregated by %u %pI4)",
10172 attr
->aggregator_as
, &attr
->aggregator_addr
);
10176 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10177 PEER_FLAG_REFLECTOR_CLIENT
)) {
10179 json_object_boolean_true_add(json_path
,
10180 "rxedFromRrClient");
10182 vty_out(vty
, ", (Received from a RR-client)");
10185 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10186 PEER_FLAG_RSERVER_CLIENT
)) {
10188 json_object_boolean_true_add(json_path
,
10189 "rxedFromRsClient");
10191 vty_out(vty
, ", (Received from a RS-client)");
10194 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10196 json_object_boolean_true_add(json_path
,
10197 "dampeningHistoryEntry");
10199 vty_out(vty
, ", (history entry)");
10200 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10202 json_object_boolean_true_add(json_path
,
10203 "dampeningSuppressed");
10205 vty_out(vty
, ", (suppressed due to dampening)");
10209 vty_out(vty
, "\n");
10211 /* Line2 display Next-hop, Neighbor, Router-id */
10212 /* Display the nexthop */
10213 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
10215 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
||
10216 bn_p
->family
== AF_EVPN
) &&
10217 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10218 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10219 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10220 || safi
== SAFI_EVPN
) {
10222 json_object_string_addf(
10223 json_nexthop_global
, "ip", "%pI4",
10224 &attr
->mp_nexthop_global_in
);
10226 if (path
->peer
->hostname
)
10227 json_object_string_add(
10228 json_nexthop_global
, "hostname",
10229 path
->peer
->hostname
);
10231 if (nexthop_hostname
)
10232 vty_out(vty
, " %pI4(%s)",
10233 &attr
->mp_nexthop_global_in
,
10236 vty_out(vty
, " %pI4",
10237 &attr
->mp_nexthop_global_in
);
10241 json_object_string_addf(json_nexthop_global
,
10245 if (path
->peer
->hostname
)
10246 json_object_string_add(
10247 json_nexthop_global
, "hostname",
10248 path
->peer
->hostname
);
10250 if (nexthop_hostname
)
10251 vty_out(vty
, " %pI4(%s)",
10255 vty_out(vty
, " %pI4",
10261 json_object_string_add(json_nexthop_global
, "afi",
10265 json_object_string_addf(json_nexthop_global
, "ip",
10267 &attr
->mp_nexthop_global
);
10269 if (path
->peer
->hostname
)
10270 json_object_string_add(json_nexthop_global
,
10272 path
->peer
->hostname
);
10274 json_object_string_add(json_nexthop_global
, "afi",
10276 json_object_string_add(json_nexthop_global
, "scope",
10279 if (nexthop_hostname
)
10280 vty_out(vty
, " %pI6(%s)",
10281 &attr
->mp_nexthop_global
,
10284 vty_out(vty
, " %pI6",
10285 &attr
->mp_nexthop_global
);
10289 /* Display the IGP cost or 'inaccessible' */
10290 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10292 json_object_boolean_false_add(json_nexthop_global
,
10295 vty_out(vty
, " (inaccessible)");
10297 if (path
->extra
&& path
->extra
->igpmetric
) {
10299 json_object_int_add(json_nexthop_global
,
10301 path
->extra
->igpmetric
);
10303 vty_out(vty
, " (metric %u)",
10304 path
->extra
->igpmetric
);
10307 /* IGP cost is 0, display this only for json */
10310 json_object_int_add(json_nexthop_global
,
10315 json_object_boolean_true_add(json_nexthop_global
,
10319 /* Display peer "from" output */
10320 /* This path was originated locally */
10321 if (path
->peer
== bgp
->peer_self
) {
10323 if (safi
== SAFI_EVPN
|| (bn_p
->family
== AF_INET
&&
10324 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10326 json_object_string_add(json_peer
, "peerId",
10329 vty_out(vty
, " from 0.0.0.0 ");
10332 json_object_string_add(json_peer
, "peerId",
10335 vty_out(vty
, " from :: ");
10339 json_object_string_addf(json_peer
, "routerId", "%pI4",
10342 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10345 /* We RXed this path from one of our peers */
10349 json_object_string_addf(json_peer
, "peerId", "%pSU",
10351 json_object_string_addf(json_peer
, "routerId", "%pI4",
10352 &path
->peer
->remote_id
);
10354 if (path
->peer
->hostname
)
10355 json_object_string_add(json_peer
, "hostname",
10356 path
->peer
->hostname
);
10358 if (path
->peer
->domainname
)
10359 json_object_string_add(json_peer
, "domainname",
10360 path
->peer
->domainname
);
10362 if (path
->peer
->conf_if
)
10363 json_object_string_add(json_peer
, "interface",
10364 path
->peer
->conf_if
);
10366 if (path
->peer
->conf_if
) {
10367 if (path
->peer
->hostname
10368 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10369 BGP_FLAG_SHOW_HOSTNAME
))
10370 vty_out(vty
, " from %s(%s)",
10371 path
->peer
->hostname
,
10372 path
->peer
->conf_if
);
10374 vty_out(vty
, " from %s",
10375 path
->peer
->conf_if
);
10377 if (path
->peer
->hostname
10378 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10379 BGP_FLAG_SHOW_HOSTNAME
))
10380 vty_out(vty
, " from %s(%s)",
10381 path
->peer
->hostname
,
10384 vty_out(vty
, " from %pSU",
10388 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10389 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10391 vty_out(vty
, " (%s)",
10393 &path
->peer
->remote_id
, buf1
,
10399 * Note when vrfid of nexthop is different from that of prefix
10401 if (path
->extra
&& path
->extra
->bgp_orig
) {
10402 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10407 if (path
->extra
->bgp_orig
->inst_type
10408 == BGP_INSTANCE_TYPE_DEFAULT
)
10409 vn
= VRF_DEFAULT_NAME
;
10411 vn
= path
->extra
->bgp_orig
->name
;
10413 json_object_string_add(json_path
, "nhVrfName", vn
);
10415 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10416 json_object_int_add(json_path
, "nhVrfId", -1);
10418 json_object_int_add(json_path
, "nhVrfId",
10419 (int)nexthop_vrfid
);
10422 if (nexthop_vrfid
== VRF_UNKNOWN
)
10423 vty_out(vty
, " vrf ?");
10427 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10428 vty_out(vty
, " vrf %s(%u)",
10429 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10434 if (nexthop_self
) {
10436 json_object_boolean_true_add(json_path
,
10437 "announceNexthopSelf");
10439 vty_out(vty
, " announce-nh-self");
10444 vty_out(vty
, "\n");
10446 /* display the link-local nexthop */
10447 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10449 json_nexthop_ll
= json_object_new_object();
10450 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10451 &attr
->mp_nexthop_local
);
10453 if (path
->peer
->hostname
)
10454 json_object_string_add(json_nexthop_ll
,
10456 path
->peer
->hostname
);
10458 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10459 json_object_string_add(json_nexthop_ll
, "scope",
10462 json_object_boolean_true_add(json_nexthop_ll
,
10465 if (!attr
->mp_nexthop_prefer_global
)
10466 json_object_boolean_true_add(json_nexthop_ll
,
10469 json_object_boolean_true_add(
10470 json_nexthop_global
, "used");
10472 vty_out(vty
, " (%s) %s\n",
10473 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10474 buf
, INET6_ADDRSTRLEN
),
10475 attr
->mp_nexthop_prefer_global
10476 ? "(prefer-global)"
10480 /* If we do not have a link-local nexthop then we must flag the
10481 global as "used" */
10484 json_object_boolean_true_add(json_nexthop_global
,
10488 if (safi
== SAFI_EVPN
&&
10489 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10490 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10493 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10494 * Int/Ext/Local, Atomic, best */
10496 json_object_string_add(json_path
, "origin",
10497 bgp_origin_long_str
[attr
->origin
]);
10499 vty_out(vty
, " Origin %s",
10500 bgp_origin_long_str
[attr
->origin
]);
10502 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10504 json_object_int_add(json_path
, "metric", attr
->med
);
10506 vty_out(vty
, ", metric %u", attr
->med
);
10509 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10511 json_object_int_add(json_path
, "locPrf",
10514 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10517 if (attr
->weight
!= 0) {
10519 json_object_int_add(json_path
, "weight", attr
->weight
);
10521 vty_out(vty
, ", weight %u", attr
->weight
);
10524 if (attr
->tag
!= 0) {
10526 json_object_int_add(json_path
, "tag", attr
->tag
);
10528 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10531 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10533 json_object_boolean_false_add(json_path
, "valid");
10535 vty_out(vty
, ", invalid");
10536 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10538 json_object_boolean_true_add(json_path
, "valid");
10540 vty_out(vty
, ", valid");
10544 json_object_int_add(json_path
, "version", bn
->version
);
10546 if (path
->peer
!= bgp
->peer_self
) {
10547 if (path
->peer
->as
== path
->peer
->local_as
) {
10548 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10550 json_object_string_add(
10552 "confed-internal");
10554 vty_out(vty
, ", confed-internal");
10557 json_object_string_add(
10558 json_peer
, "type", "internal");
10560 vty_out(vty
, ", internal");
10563 if (bgp_confederation_peers_check(bgp
,
10566 json_object_string_add(
10568 "confed-external");
10570 vty_out(vty
, ", confed-external");
10573 json_object_string_add(
10574 json_peer
, "type", "external");
10576 vty_out(vty
, ", external");
10579 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10581 json_object_boolean_true_add(json_path
, "aggregated");
10582 json_object_boolean_true_add(json_path
, "local");
10584 vty_out(vty
, ", aggregated, local");
10586 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10588 json_object_boolean_true_add(json_path
, "sourced");
10590 vty_out(vty
, ", sourced");
10593 json_object_boolean_true_add(json_path
, "sourced");
10594 json_object_boolean_true_add(json_path
, "local");
10596 vty_out(vty
, ", sourced, local");
10600 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10602 json_object_boolean_true_add(json_path
,
10603 "atomicAggregate");
10605 vty_out(vty
, ", atomic-aggregate");
10608 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10610 json_object_int_add(json_path
, "otc", attr
->otc
);
10612 vty_out(vty
, ", otc %u", attr
->otc
);
10615 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10616 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10617 && bgp_path_info_mpath_count(path
))) {
10619 json_object_boolean_true_add(json_path
, "multipath");
10621 vty_out(vty
, ", multipath");
10624 // Mark the bestpath(s)
10625 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10626 first_as
= aspath_get_first_as(attr
->aspath
);
10629 if (!json_bestpath
)
10630 json_bestpath
= json_object_new_object();
10631 json_object_int_add(json_bestpath
, "bestpathFromAs",
10635 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10637 vty_out(vty
, ", bestpath-from-AS Local");
10641 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10643 if (!json_bestpath
)
10644 json_bestpath
= json_object_new_object();
10645 json_object_boolean_true_add(json_bestpath
, "overall");
10646 json_object_string_add(
10647 json_bestpath
, "selectionReason",
10648 bgp_path_selection_reason2str(bn
->reason
));
10650 vty_out(vty
, ", best");
10651 vty_out(vty
, " (%s)",
10652 bgp_path_selection_reason2str(bn
->reason
));
10656 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10658 json_object_string_add(
10659 json_path
, "rpkiValidationState",
10660 bgp_rpki_validation2str(rpki_curr_state
));
10662 vty_out(vty
, ", rpki validation-state: %s",
10663 bgp_rpki_validation2str(rpki_curr_state
));
10667 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10670 vty_out(vty
, "\n");
10672 /* Line 4 display Community */
10673 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10675 if (!bgp_attr_get_community(attr
)->json
)
10676 community_str(bgp_attr_get_community(attr
),
10678 json_object_lock(bgp_attr_get_community(attr
)->json
);
10679 json_object_object_add(
10680 json_path
, "community",
10681 bgp_attr_get_community(attr
)->json
);
10683 vty_out(vty
, " Community: %s\n",
10684 bgp_attr_get_community(attr
)->str
);
10688 /* Line 5 display Extended-community */
10689 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10691 json_ext_community
= json_object_new_object();
10692 json_object_string_add(
10693 json_ext_community
, "string",
10694 bgp_attr_get_ecommunity(attr
)->str
);
10695 json_object_object_add(json_path
, "extendedCommunity",
10696 json_ext_community
);
10698 vty_out(vty
, " Extended Community: %s\n",
10699 bgp_attr_get_ecommunity(attr
)->str
);
10703 /* Line 6 display Large community */
10704 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10706 if (!bgp_attr_get_lcommunity(attr
)->json
)
10707 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10709 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10710 json_object_object_add(
10711 json_path
, "largeCommunity",
10712 bgp_attr_get_lcommunity(attr
)->json
);
10714 vty_out(vty
, " Large Community: %s\n",
10715 bgp_attr_get_lcommunity(attr
)->str
);
10719 /* Line 7 display Originator, Cluster-id */
10720 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10721 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10722 char buf
[BUFSIZ
] = {0};
10724 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10726 json_object_string_addf(json_path
,
10727 "originatorId", "%pI4",
10728 &attr
->originator_id
);
10730 vty_out(vty
, " Originator: %pI4",
10731 &attr
->originator_id
);
10734 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10735 struct cluster_list
*cluster
=
10736 bgp_attr_get_cluster(attr
);
10740 json_cluster_list
= json_object_new_object();
10741 json_cluster_list_list
=
10742 json_object_new_array();
10744 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10745 json_string
= json_object_new_string(
10748 buf
, sizeof(buf
)));
10749 json_object_array_add(
10750 json_cluster_list_list
,
10755 * struct cluster_list does not have
10756 * "str" variable like aspath and community
10757 * do. Add this someday if someone asks
10759 * json_object_string_add(json_cluster_list,
10760 * "string", cluster->str);
10762 json_object_object_add(json_cluster_list
,
10764 json_cluster_list_list
);
10765 json_object_object_add(json_path
, "clusterList",
10766 json_cluster_list
);
10768 vty_out(vty
, ", Cluster list: ");
10770 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10771 vty_out(vty
, "%pI4 ",
10772 &cluster
->list
[i
]);
10778 vty_out(vty
, "\n");
10781 if (path
->extra
&& path
->extra
->damp_info
)
10782 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10785 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10786 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10787 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10791 json_object_int_add(json_path
, "remoteLabel", label
);
10793 vty_out(vty
, " Remote label: %d\n", label
);
10797 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10798 inet_ntop(AF_INET6
, &path
->extra
->sid
[0].sid
, buf
, sizeof(buf
));
10800 json_object_string_add(json_path
, "remoteSid", buf
);
10802 vty_out(vty
, " Remote SID: %s\n", buf
);
10806 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10808 json_object_int_add(json_path
, "labelIndex",
10809 attr
->label_index
);
10811 vty_out(vty
, " Label Index: %d\n",
10812 attr
->label_index
);
10815 /* Line 8 display Addpath IDs */
10816 if (path
->addpath_rx_id
10817 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10819 json_object_int_add(json_path
, "addpathRxId",
10820 path
->addpath_rx_id
);
10822 /* Keep backwards compatibility with the old API
10823 * by putting TX All's ID in the old field
10825 json_object_int_add(
10826 json_path
, "addpathTxId",
10828 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10830 /* ... but create a specific field for each
10833 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10834 json_object_int_add(
10836 bgp_addpath_names(i
)->id_json_name
,
10837 path
->tx_addpath
.addpath_tx_id
[i
]);
10840 vty_out(vty
, " AddPath ID: RX %u, ",
10841 path
->addpath_rx_id
);
10843 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10847 /* If we used addpath to TX a non-bestpath we need to display
10848 * "Advertised to" on a path-by-path basis
10850 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10853 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10855 bgp_addpath_encode_tx(peer
, afi
, safi
);
10856 has_adj
= bgp_adj_out_lookup(
10858 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10859 &path
->tx_addpath
));
10861 if ((addpath_capable
&& has_adj
)
10862 || (!addpath_capable
&& has_adj
10863 && CHECK_FLAG(path
->flags
,
10864 BGP_PATH_SELECTED
))) {
10865 if (json_path
&& !json_adv_to
)
10866 json_adv_to
= json_object_new_object();
10868 route_vty_out_advertised_to(
10870 " Advertised to:", json_adv_to
);
10876 json_object_object_add(
10877 json_path
, "advertisedTo", json_adv_to
);
10881 vty_out(vty
, "\n");
10886 /* Line 9 display Uptime */
10887 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
10889 json_last_update
= json_object_new_object();
10890 json_object_int_add(json_last_update
, "epoch", tbuf
);
10891 json_object_string_add(json_last_update
, "string",
10893 json_object_object_add(json_path
, "lastUpdate",
10896 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10898 /* Line 10 display PMSI tunnel attribute, if present */
10899 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10900 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10901 bgp_attr_get_pmsi_tnl_type(attr
),
10902 PMSI_TNLTYPE_STR_DEFAULT
);
10905 json_pmsi
= json_object_new_object();
10906 json_object_string_add(json_pmsi
, "tunnelType", str
);
10907 json_object_int_add(json_pmsi
, "label",
10908 label2vni(&attr
->label
));
10909 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10911 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10912 str
, label2vni(&attr
->label
));
10915 if (path
->peer
->t_gr_restart
&&
10916 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10917 unsigned long gr_remaining
=
10918 thread_timer_remain_second(path
->peer
->t_gr_restart
);
10921 json_object_int_add(json_path
,
10922 "gracefulRestartSecondsRemaining",
10926 " Time until Graceful Restart stale route deleted: %lu\n",
10930 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
10931 bgp_attr_get_community(attr
) &&
10932 community_include(bgp_attr_get_community(attr
),
10933 COMMUNITY_LLGR_STALE
)) {
10934 unsigned long llgr_remaining
= thread_timer_remain_second(
10935 path
->peer
->t_llgr_stale
[afi
][safi
]);
10938 json_object_int_add(json_path
, "llgrSecondsRemaining",
10942 " Time until Long-lived stale route deleted: %lu\n",
10946 /* Output some debug about internal state of the dest flags */
10948 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10949 json_object_boolean_true_add(json_path
, "processScheduled");
10950 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10951 json_object_boolean_true_add(json_path
, "userCleared");
10952 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10953 json_object_boolean_true_add(json_path
, "labelChanged");
10954 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10955 json_object_boolean_true_add(json_path
, "registeredForLabel");
10956 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10957 json_object_boolean_true_add(json_path
, "selectDefered");
10958 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10959 json_object_boolean_true_add(json_path
, "fibInstalled");
10960 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10961 json_object_boolean_true_add(json_path
, "fibPending");
10963 if (json_nexthop_global
|| json_nexthop_ll
) {
10964 json_nexthops
= json_object_new_array();
10966 if (json_nexthop_global
)
10967 json_object_array_add(json_nexthops
,
10968 json_nexthop_global
);
10970 if (json_nexthop_ll
)
10971 json_object_array_add(json_nexthops
,
10974 json_object_object_add(json_path
, "nexthops",
10978 json_object_object_add(json_path
, "peer", json_peer
);
10979 json_object_array_add(json_paths
, json_path
);
10983 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10984 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10985 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10987 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10988 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10990 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10991 const char *comstr
, int exact
, afi_t afi
,
10992 safi_t safi
, uint16_t show_flags
);
10994 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10995 struct bgp_table
*table
, enum bgp_show_type type
,
10996 void *output_arg
, const char *rd
, int is_last
,
10997 unsigned long *output_cum
, unsigned long *total_cum
,
10998 unsigned long *json_header_depth
, uint16_t show_flags
,
10999 enum rpki_states rpki_target_state
)
11001 struct bgp_path_info
*pi
;
11002 struct bgp_dest
*dest
;
11003 bool header
= true;
11004 bool json_detail_header
= false;
11006 unsigned long output_count
= 0;
11007 unsigned long total_count
= 0;
11009 json_object
*json_paths
= NULL
;
11011 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11012 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11013 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11015 if (output_cum
&& *output_cum
!= 0)
11018 if (use_json
&& !*json_header_depth
) {
11020 *json_header_depth
= 1;
11022 vty_out(vty
, "{\n");
11023 *json_header_depth
= 2;
11027 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11028 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11029 " \"localAS\": %u,\n \"routes\": { ",
11030 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11031 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11034 table
->version
, &bgp
->router_id
,
11035 bgp
->default_local_pref
, bgp
->as
);
11037 vty_out(vty
, " \"routeDistinguishers\" : {");
11038 ++*json_header_depth
;
11042 if (use_json
&& rd
) {
11043 vty_out(vty
, " \"%s\" : { ", rd
);
11046 /* Check for 'json detail', where we need header output once per dest */
11047 if (use_json
&& CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
) &&
11048 type
!= bgp_show_type_dampend_paths
&&
11049 type
!= bgp_show_type_damp_neighbor
&&
11050 type
!= bgp_show_type_flap_statistics
&&
11051 type
!= bgp_show_type_flap_neighbor
)
11052 json_detail_header
= true;
11054 /* Start processing of routes. */
11055 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11056 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11057 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11058 bool json_detail
= json_detail_header
;
11060 pi
= bgp_dest_get_bgp_path_info(dest
);
11066 json_paths
= json_object_new_array();
11070 for (; pi
; pi
= pi
->next
) {
11071 struct community
*picomm
= NULL
;
11073 picomm
= bgp_attr_get_community(pi
->attr
);
11077 if (type
== bgp_show_type_prefix_version
) {
11079 strtoul(output_arg
, NULL
, 10);
11080 if (dest
->version
< version
)
11084 if (type
== bgp_show_type_community_alias
) {
11085 char *alias
= output_arg
;
11086 char **communities
;
11088 bool found
= false;
11091 frrstr_split(picomm
->str
, " ",
11092 &communities
, &num
);
11093 for (int i
= 0; i
< num
; i
++) {
11094 const char *com2alias
=
11095 bgp_community2alias(
11098 && strcmp(alias
, com2alias
)
11104 XFREE(MTYPE_TMP
, communities
);
11108 bgp_attr_get_lcommunity(pi
->attr
)) {
11109 frrstr_split(bgp_attr_get_lcommunity(
11112 " ", &communities
, &num
);
11113 for (int i
= 0; i
< num
; i
++) {
11114 const char *com2alias
=
11115 bgp_community2alias(
11118 && strcmp(alias
, com2alias
)
11124 XFREE(MTYPE_TMP
, communities
);
11131 if (type
== bgp_show_type_rpki
) {
11132 if (dest_p
->family
== AF_INET
11133 || dest_p
->family
== AF_INET6
)
11134 rpki_curr_state
= hook_call(
11135 bgp_rpki_prefix_status
,
11136 pi
->peer
, pi
->attr
, dest_p
);
11137 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11138 && rpki_curr_state
!= rpki_target_state
)
11142 if (type
== bgp_show_type_flap_statistics
11143 || type
== bgp_show_type_flap_neighbor
11144 || type
== bgp_show_type_dampend_paths
11145 || type
== bgp_show_type_damp_neighbor
) {
11146 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11149 if (type
== bgp_show_type_regexp
) {
11150 regex_t
*regex
= output_arg
;
11152 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11156 if (type
== bgp_show_type_prefix_list
) {
11157 struct prefix_list
*plist
= output_arg
;
11159 if (prefix_list_apply(plist
, dest_p
)
11163 if (type
== bgp_show_type_access_list
) {
11164 struct access_list
*alist
= output_arg
;
11166 if (access_list_apply(alist
, dest_p
) !=
11170 if (type
== bgp_show_type_filter_list
) {
11171 struct as_list
*as_list
= output_arg
;
11173 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11174 != AS_FILTER_PERMIT
)
11177 if (type
== bgp_show_type_route_map
) {
11178 struct route_map
*rmap
= output_arg
;
11179 struct bgp_path_info path
;
11180 struct bgp_path_info_extra extra
;
11181 struct attr dummy_attr
= {};
11182 route_map_result_t ret
;
11184 dummy_attr
= *pi
->attr
;
11186 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11187 pi
->peer
, &dummy_attr
);
11189 ret
= route_map_apply(rmap
, dest_p
, &path
);
11190 bgp_attr_flush(&dummy_attr
);
11191 if (ret
== RMAP_DENYMATCH
)
11194 if (type
== bgp_show_type_neighbor
11195 || type
== bgp_show_type_flap_neighbor
11196 || type
== bgp_show_type_damp_neighbor
) {
11197 union sockunion
*su
= output_arg
;
11199 if (pi
->peer
== NULL
11200 || pi
->peer
->su_remote
== NULL
11201 || !sockunion_same(pi
->peer
->su_remote
, su
))
11204 if (type
== bgp_show_type_cidr_only
) {
11205 uint32_t destination
;
11207 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11208 if (IN_CLASSC(destination
)
11209 && dest_p
->prefixlen
== 24)
11211 if (IN_CLASSB(destination
)
11212 && dest_p
->prefixlen
== 16)
11214 if (IN_CLASSA(destination
)
11215 && dest_p
->prefixlen
== 8)
11218 if (type
== bgp_show_type_prefix_longer
) {
11220 if (!prefix_match(p
, dest_p
))
11223 if (type
== bgp_show_type_community_all
) {
11227 if (type
== bgp_show_type_community
) {
11228 struct community
*com
= output_arg
;
11230 if (!picomm
|| !community_match(picomm
, com
))
11233 if (type
== bgp_show_type_community_exact
) {
11234 struct community
*com
= output_arg
;
11236 if (!picomm
|| !community_cmp(picomm
, com
))
11239 if (type
== bgp_show_type_community_list
) {
11240 struct community_list
*list
= output_arg
;
11242 if (!community_list_match(picomm
, list
))
11245 if (type
== bgp_show_type_community_list_exact
) {
11246 struct community_list
*list
= output_arg
;
11248 if (!community_list_exact_match(picomm
, list
))
11251 if (type
== bgp_show_type_lcommunity
) {
11252 struct lcommunity
*lcom
= output_arg
;
11254 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11256 bgp_attr_get_lcommunity(pi
->attr
),
11261 if (type
== bgp_show_type_lcommunity_exact
) {
11262 struct lcommunity
*lcom
= output_arg
;
11264 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11266 bgp_attr_get_lcommunity(pi
->attr
),
11270 if (type
== bgp_show_type_lcommunity_list
) {
11271 struct community_list
*list
= output_arg
;
11273 if (!lcommunity_list_match(
11274 bgp_attr_get_lcommunity(pi
->attr
),
11279 == bgp_show_type_lcommunity_list_exact
) {
11280 struct community_list
*list
= output_arg
;
11282 if (!lcommunity_list_exact_match(
11283 bgp_attr_get_lcommunity(pi
->attr
),
11287 if (type
== bgp_show_type_lcommunity_all
) {
11288 if (!bgp_attr_get_lcommunity(pi
->attr
))
11291 if (type
== bgp_show_type_dampend_paths
11292 || type
== bgp_show_type_damp_neighbor
) {
11293 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11294 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11298 if (!use_json
&& header
) {
11300 "BGP table version is %" PRIu64
11301 ", local router ID is %pI4, vrf id ",
11302 table
->version
, &bgp
->router_id
);
11303 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11304 vty_out(vty
, "%s", VRFID_NONE_STR
);
11306 vty_out(vty
, "%u", bgp
->vrf_id
);
11307 vty_out(vty
, "\n");
11308 vty_out(vty
, "Default local pref %u, ",
11309 bgp
->default_local_pref
);
11310 vty_out(vty
, "local AS %u\n", bgp
->as
);
11311 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11312 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11313 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11314 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11315 if (type
== bgp_show_type_dampend_paths
11316 || type
== bgp_show_type_damp_neighbor
)
11317 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11318 else if (type
== bgp_show_type_flap_statistics
11319 || type
== bgp_show_type_flap_neighbor
)
11320 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11322 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11323 : BGP_SHOW_HEADER
));
11326 } else if (json_detail
&& json_paths
!= NULL
) {
11327 const struct prefix_rd
*prd
;
11328 json_object
*jtemp
;
11330 /* Use common detail header, for most types;
11331 * need a json 'object'.
11334 jtemp
= json_object_new_object();
11335 prd
= bgp_rd_from_dest(dest
, safi
);
11337 route_vty_out_detail_header(
11338 vty
, bgp
, dest
, prd
, table
->afi
,
11341 json_object_array_add(json_paths
, jtemp
);
11343 json_detail
= false;
11346 if (rd
!= NULL
&& !display
&& !output_count
) {
11349 "Route Distinguisher: %s\n",
11352 if (type
== bgp_show_type_dampend_paths
11353 || type
== bgp_show_type_damp_neighbor
)
11354 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11355 AFI_IP
, safi
, use_json
,
11357 else if (type
== bgp_show_type_flap_statistics
11358 || type
== bgp_show_type_flap_neighbor
)
11359 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11360 AFI_IP
, safi
, use_json
,
11363 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
11364 route_vty_out_detail(
11365 vty
, bgp
, dest
, pi
,
11366 family2afi(dest_p
->family
),
11367 safi
, RPKI_NOT_BEING_USED
,
11370 route_vty_out(vty
, dest_p
, pi
, display
,
11371 safi
, json_paths
, wide
);
11381 /* encode prefix */
11382 if (dest_p
->family
== AF_FLOWSPEC
) {
11383 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11386 bgp_fs_nlri_get_string(
11388 dest_p
->u
.prefix_flowspec
.ptr
,
11389 dest_p
->u
.prefix_flowspec
.prefixlen
,
11390 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11391 family2afi(dest_p
->u
11392 .prefix_flowspec
.family
));
11394 vty_out(vty
, "\"%s/%d\": ", retstr
,
11395 dest_p
->u
.prefix_flowspec
11398 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11399 dest_p
->u
.prefix_flowspec
11403 vty_out(vty
, "\"%pFX\": ", dest_p
);
11405 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11407 vty_json(vty
, json_paths
);
11411 json_object_free(json_paths
);
11415 output_count
+= *output_cum
;
11416 *output_cum
= output_count
;
11419 total_count
+= *total_cum
;
11420 *total_cum
= total_count
;
11424 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11428 for (i
= 0; i
< *json_header_depth
; ++i
)
11429 vty_out(vty
, " } ");
11431 vty_out(vty
, "\n");
11435 /* No route is displayed */
11436 if (output_count
== 0) {
11437 if (type
== bgp_show_type_normal
)
11439 "No BGP prefixes displayed, %ld exist\n",
11443 "\nDisplayed %ld routes and %ld total paths\n",
11444 output_count
, total_count
);
11448 return CMD_SUCCESS
;
11451 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11452 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11453 enum bgp_show_type type
, void *output_arg
, bool use_json
)
11455 struct bgp_dest
*dest
, *next
;
11456 unsigned long output_cum
= 0;
11457 unsigned long total_cum
= 0;
11458 unsigned long json_header_depth
= 0;
11459 struct bgp_table
*itable
;
11461 uint16_t show_flags
= 0;
11463 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11466 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11468 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11469 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11471 next
= bgp_route_next(dest
);
11472 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11475 itable
= bgp_dest_get_bgp_table_info(dest
);
11476 if (itable
!= NULL
) {
11477 struct prefix_rd prd
;
11478 char rd
[RD_ADDRSTRLEN
];
11480 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11481 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11482 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11483 rd
, next
== NULL
, &output_cum
,
11484 &total_cum
, &json_header_depth
,
11485 show_flags
, RPKI_NOT_BEING_USED
);
11491 if (output_cum
== 0)
11492 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11496 "\nDisplayed %ld routes and %ld total paths\n",
11497 output_cum
, total_cum
);
11499 return CMD_SUCCESS
;
11502 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11503 enum bgp_show_type type
, void *output_arg
,
11504 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11506 struct bgp_table
*table
;
11507 unsigned long json_header_depth
= 0;
11508 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11511 bgp
= bgp_get_default();
11516 vty_out(vty
, "No BGP process is configured\n");
11518 vty_out(vty
, "{}\n");
11519 return CMD_WARNING
;
11522 /* Labeled-unicast routes live in the unicast table. */
11523 if (safi
== SAFI_LABELED_UNICAST
)
11524 safi
= SAFI_UNICAST
;
11526 table
= bgp
->rib
[afi
][safi
];
11527 /* use MPLS and ENCAP specific shows until they are merged */
11528 if (safi
== SAFI_MPLS_VPN
) {
11529 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11530 output_arg
, use_json
);
11533 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11534 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11535 output_arg
, use_json
,
11539 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11540 NULL
, NULL
, &json_header_depth
, show_flags
,
11541 rpki_target_state
);
11544 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11545 safi_t safi
, uint16_t show_flags
)
11547 struct listnode
*node
, *nnode
;
11550 bool route_output
= false;
11551 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11554 vty_out(vty
, "{\n");
11556 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11557 route_output
= true;
11560 vty_out(vty
, ",\n");
11564 vty_out(vty
, "\"%s\":",
11565 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11569 vty_out(vty
, "\nInstance %s:\n",
11570 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11574 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11575 show_flags
, RPKI_NOT_BEING_USED
);
11579 vty_out(vty
, "}\n");
11580 else if (!route_output
)
11581 vty_out(vty
, "%% BGP instance not found\n");
11584 /* Header of detailed BGP route information */
11585 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11586 struct bgp_dest
*dest
,
11587 const struct prefix_rd
*prd
,
11588 afi_t afi
, safi_t safi
, json_object
*json
)
11590 struct bgp_path_info
*pi
;
11591 const struct prefix
*p
;
11593 struct listnode
*node
, *nnode
;
11594 char buf1
[RD_ADDRSTRLEN
];
11598 int accept_own
= 0;
11599 int route_filter_translated_v4
= 0;
11600 int route_filter_v4
= 0;
11601 int route_filter_translated_v6
= 0;
11602 int route_filter_v6
= 0;
11603 int llgr_stale
= 0;
11605 int accept_own_nexthop
= 0;
11608 int no_advertise
= 0;
11612 int has_valid_label
= 0;
11613 mpls_label_t label
= 0;
11614 json_object
*json_adv_to
= NULL
;
11619 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11621 p
= bgp_dest_get_prefix(dest
);
11622 has_valid_label
= bgp_is_valid_label(&label
);
11624 if (safi
== SAFI_EVPN
) {
11626 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11627 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11629 prd
? ":" : "", (struct prefix_evpn
*)p
);
11631 json_object_string_add(json
, "rd",
11632 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11634 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11639 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11641 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11642 ? prefix_rd2str(prd
, buf1
,
11645 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11649 json_object_string_addf(json
, "prefix", "%pFX", p
);
11650 json_object_int_add(json
, "version", dest
->version
);
11655 if (has_valid_label
) {
11657 json_object_int_add(json
, "localLabel", label
);
11659 vty_out(vty
, "Local label: %d\n", label
);
11663 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11664 vty_out(vty
, "not allocated\n");
11666 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11667 struct community
*picomm
= NULL
;
11669 picomm
= bgp_attr_get_community(pi
->attr
);
11672 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11674 if (bgp_path_suppressed(pi
))
11680 no_advertise
+= community_include(
11681 picomm
, COMMUNITY_NO_ADVERTISE
);
11683 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11685 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11687 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11688 route_filter_translated_v4
+= community_include(
11689 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11690 route_filter_translated_v6
+= community_include(
11691 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11692 route_filter_v4
+= community_include(
11693 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11694 route_filter_v6
+= community_include(
11695 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11697 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11698 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11699 accept_own_nexthop
+= community_include(
11700 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11702 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11703 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11708 vty_out(vty
, "Paths: (%d available", count
);
11710 vty_out(vty
, ", best #%d", best
);
11711 if (safi
== SAFI_UNICAST
) {
11712 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11713 vty_out(vty
, ", table %s",
11716 vty_out(vty
, ", vrf %s",
11720 vty_out(vty
, ", no best path");
11724 ", accept own local route exported and imported in different VRF");
11725 else if (route_filter_translated_v4
)
11727 ", mark translated RTs for VPNv4 route filtering");
11728 else if (route_filter_v4
)
11730 ", attach RT as-is for VPNv4 route filtering");
11731 else if (route_filter_translated_v6
)
11733 ", mark translated RTs for VPNv6 route filtering");
11734 else if (route_filter_v6
)
11736 ", attach RT as-is for VPNv6 route filtering");
11737 else if (llgr_stale
)
11739 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11742 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11743 else if (accept_own_nexthop
)
11745 ", accept local nexthop");
11746 else if (blackhole
)
11747 vty_out(vty
, ", inform peer to blackhole prefix");
11748 else if (no_export
)
11749 vty_out(vty
, ", not advertised to EBGP peer");
11750 else if (no_advertise
)
11751 vty_out(vty
, ", not advertised to any peer");
11753 vty_out(vty
, ", not advertised outside local AS");
11756 ", inform EBGP peer not to advertise to their EBGP peers");
11760 ", Advertisements suppressed by an aggregate.");
11761 vty_out(vty
, ")\n");
11764 /* If we are not using addpath then we can display Advertised to and
11766 * show what peers we advertised the bestpath to. If we are using
11768 * though then we must display Advertised to on a path-by-path basis. */
11769 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11770 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11771 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11772 if (json
&& !json_adv_to
)
11773 json_adv_to
= json_object_new_object();
11775 route_vty_out_advertised_to(
11777 " Advertised to non peer-group peers:\n ",
11784 json_object_object_add(json
, "advertisedTo",
11789 vty_out(vty
, " Not advertised to any peer");
11790 vty_out(vty
, "\n");
11795 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
11796 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11797 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11798 json_object
*json
, enum bgp_path_type pathtype
,
11799 int *display
, enum rpki_states rpki_target_state
)
11801 struct bgp_path_info
*pi
;
11803 char rdbuf
[RD_ADDRSTRLEN
];
11804 json_object
*json_header
= NULL
;
11805 json_object
*json_paths
= NULL
;
11806 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
11808 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11809 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11811 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
11812 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
11813 pi
->peer
, pi
->attr
, p
);
11815 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11816 && rpki_curr_state
!= rpki_target_state
)
11819 if (json
&& !json_paths
) {
11820 /* Instantiate json_paths only if path is valid */
11821 json_paths
= json_object_new_array();
11823 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11824 json_header
= json_object_new_object();
11826 json_header
= json
;
11830 route_vty_out_detail_header(
11831 vty
, bgp
, bgp_node
, pfx_rd
,
11832 AFI_IP
, safi
, json_header
);
11837 if (pathtype
== BGP_PATH_SHOW_ALL
11838 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11839 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11840 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11841 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11842 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11843 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
11844 safi
, rpki_curr_state
, json_paths
);
11847 if (json
&& json_paths
) {
11848 json_object_object_add(json_header
, "paths", json_paths
);
11851 json_object_object_add(json
, rdbuf
, json_header
);
11856 * Return rd based on safi
11858 static const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
11862 case SAFI_MPLS_VPN
:
11865 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
11872 /* Display specified route of BGP table. */
11873 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11874 struct bgp_table
*rib
, const char *ip_str
,
11875 afi_t afi
, safi_t safi
,
11876 enum rpki_states rpki_target_state
,
11877 struct prefix_rd
*prd
, int prefix_check
,
11878 enum bgp_path_type pathtype
, bool use_json
)
11882 struct prefix match
;
11883 struct bgp_dest
*dest
;
11884 struct bgp_dest
*rm
;
11885 struct bgp_table
*table
;
11886 json_object
*json
= NULL
;
11887 json_object
*json_paths
= NULL
;
11889 /* Check IP address argument. */
11890 ret
= str2prefix(ip_str
, &match
);
11892 vty_out(vty
, "address is malformed\n");
11893 return CMD_WARNING
;
11896 match
.family
= afi2family(afi
);
11899 json
= json_object_new_object();
11901 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11902 for (dest
= bgp_table_top(rib
); dest
;
11903 dest
= bgp_route_next(dest
)) {
11904 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11906 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11908 table
= bgp_dest_get_bgp_table_info(dest
);
11912 rm
= bgp_node_match(table
, &match
);
11916 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11918 && rm_p
->prefixlen
!= match
.prefixlen
) {
11919 bgp_dest_unlock_node(rm
);
11923 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11924 bgp
, afi
, safi
, json
, pathtype
,
11925 &display
, rpki_target_state
);
11927 bgp_dest_unlock_node(rm
);
11929 } else if (safi
== SAFI_EVPN
) {
11930 struct bgp_dest
*longest_pfx
;
11931 bool is_exact_pfxlen_match
= false;
11933 for (dest
= bgp_table_top(rib
); dest
;
11934 dest
= bgp_route_next(dest
)) {
11935 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11937 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11939 table
= bgp_dest_get_bgp_table_info(dest
);
11943 longest_pfx
= NULL
;
11944 is_exact_pfxlen_match
= false;
11946 * Search through all the prefixes for a match. The
11947 * pfx's are enumerated in ascending order of pfxlens.
11948 * So, the last pfx match is the longest match. Set
11949 * is_exact_pfxlen_match when we get exact pfxlen match
11951 for (rm
= bgp_table_top(table
); rm
;
11952 rm
= bgp_route_next(rm
)) {
11953 const struct prefix
*rm_p
=
11954 bgp_dest_get_prefix(rm
);
11956 * Get prefixlen of the ip-prefix within type5
11959 if (evpn_type5_prefix_match(rm_p
, &match
)
11963 bgp_evpn_get_type5_prefixlen(
11965 if (type5_pfxlen
== match
.prefixlen
) {
11966 is_exact_pfxlen_match
= true;
11967 bgp_dest_unlock_node(rm
);
11976 if (prefix_check
&& !is_exact_pfxlen_match
)
11980 bgp_dest_lock_node(rm
);
11982 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11983 bgp
, afi
, safi
, json
, pathtype
,
11984 &display
, rpki_target_state
);
11986 bgp_dest_unlock_node(rm
);
11988 } else if (safi
== SAFI_FLOWSPEC
) {
11990 json_paths
= json_object_new_array();
11992 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11993 &match
, prefix_check
,
11999 json_object_object_add(json
, "paths",
12002 json_object_free(json_paths
);
12005 dest
= bgp_node_match(rib
, &match
);
12006 if (dest
!= NULL
) {
12007 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12009 || dest_p
->prefixlen
== match
.prefixlen
) {
12010 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12011 safi
, json
, pathtype
,
12012 &display
, rpki_target_state
);
12015 bgp_dest_unlock_node(dest
);
12020 vty_json(vty
, json
);
12023 vty_out(vty
, "%% Network not in table\n");
12024 return CMD_WARNING
;
12028 return CMD_SUCCESS
;
12031 /* Display specified route of Main RIB */
12032 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12033 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12034 int prefix_check
, enum bgp_path_type pathtype
,
12035 enum rpki_states rpki_target_state
, bool use_json
)
12038 bgp
= bgp_get_default();
12041 vty_out(vty
, "No BGP process is configured\n");
12043 vty_out(vty
, "{}\n");
12044 return CMD_WARNING
;
12048 /* labeled-unicast routes live in the unicast table */
12049 if (safi
== SAFI_LABELED_UNICAST
)
12050 safi
= SAFI_UNICAST
;
12052 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12053 afi
, safi
, rpki_target_state
, prd
,
12054 prefix_check
, pathtype
, use_json
);
12057 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12058 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12059 safi_t safi
, bool uj
)
12061 struct lcommunity
*lcom
;
12066 uint16_t show_flags
= 0;
12070 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12072 b
= buffer_new(1024);
12073 for (i
= 0; i
< argc
; i
++) {
12075 buffer_putc(b
, ' ');
12077 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12079 buffer_putstr(b
, argv
[i
]->arg
);
12083 buffer_putc(b
, '\0');
12085 str
= buffer_getstr(b
);
12088 lcom
= lcommunity_str2com(str
);
12089 XFREE(MTYPE_TMP
, str
);
12091 vty_out(vty
, "%% Large-community malformed\n");
12092 return CMD_WARNING
;
12095 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12096 (exact
? bgp_show_type_lcommunity_exact
12097 : bgp_show_type_lcommunity
),
12098 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12100 lcommunity_free(&lcom
);
12104 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12105 const char *lcom
, bool exact
, afi_t afi
,
12106 safi_t safi
, bool uj
)
12108 struct community_list
*list
;
12109 uint16_t show_flags
= 0;
12112 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12115 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12116 LARGE_COMMUNITY_LIST_MASTER
);
12117 if (list
== NULL
) {
12118 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12120 return CMD_WARNING
;
12123 return bgp_show(vty
, bgp
, afi
, safi
,
12124 (exact
? bgp_show_type_lcommunity_list_exact
12125 : bgp_show_type_lcommunity_list
),
12126 list
, show_flags
, RPKI_NOT_BEING_USED
);
12129 DEFUN (show_ip_bgp_large_community_list
,
12130 show_ip_bgp_large_community_list_cmd
,
12131 "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]",
12135 BGP_INSTANCE_HELP_STR
12137 BGP_SAFI_WITH_LABEL_HELP_STR
12138 "Display routes matching the large-community-list\n"
12139 "large-community-list number\n"
12140 "large-community-list name\n"
12141 "Exact match of the large-communities\n"
12144 afi_t afi
= AFI_IP6
;
12145 safi_t safi
= SAFI_UNICAST
;
12147 bool exact_match
= 0;
12148 struct bgp
*bgp
= NULL
;
12149 bool uj
= use_json(argc
, argv
);
12154 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12157 return CMD_WARNING
;
12159 argv_find(argv
, argc
, "large-community-list", &idx
);
12161 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12163 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12166 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12167 exact_match
, afi
, safi
, uj
);
12169 DEFUN (show_ip_bgp_large_community
,
12170 show_ip_bgp_large_community_cmd
,
12171 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12175 BGP_INSTANCE_HELP_STR
12177 BGP_SAFI_WITH_LABEL_HELP_STR
12178 "Display routes matching the large-communities\n"
12179 "List of large-community numbers\n"
12180 "Exact match of the large-communities\n"
12183 afi_t afi
= AFI_IP6
;
12184 safi_t safi
= SAFI_UNICAST
;
12186 bool exact_match
= 0;
12187 struct bgp
*bgp
= NULL
;
12188 bool uj
= use_json(argc
, argv
);
12189 uint16_t show_flags
= 0;
12193 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12196 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12199 return CMD_WARNING
;
12201 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12202 if (argv_find(argv
, argc
, "exact-match", &idx
))
12204 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12205 exact_match
, afi
, safi
, uj
);
12207 return bgp_show(vty
, bgp
, afi
, safi
,
12208 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12209 RPKI_NOT_BEING_USED
);
12212 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12213 safi_t safi
, struct json_object
*json_array
);
12214 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12215 safi_t safi
, struct json_object
*json
);
12218 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12219 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12220 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12221 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12223 bool uj
= use_json(argc
, argv
);
12224 struct bgp
*bgp
= NULL
;
12225 safi_t safi
= SAFI_UNICAST
;
12226 afi_t afi
= AFI_IP6
;
12228 struct json_object
*json_all
= NULL
;
12229 struct json_object
*json_afi_safi
= NULL
;
12231 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12234 return CMD_WARNING
;
12237 json_all
= json_object_new_object();
12239 FOREACH_AFI_SAFI (afi
, safi
) {
12241 * So limit output to those afi/safi pairs that
12242 * actually have something interesting in them
12244 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12249 json_afi_safi
= json_object_new_array();
12250 json_object_object_add(
12252 get_afi_safi_str(afi
, safi
, true),
12255 json_afi_safi
= NULL
;
12258 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12262 vty_json(vty
, json_all
);
12264 return CMD_SUCCESS
;
12267 /* BGP route print out function without JSON */
12268 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12269 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12270 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12274 BGP_INSTANCE_HELP_STR
12277 "BGP RIB advertisement statistics\n"
12280 afi_t afi
= AFI_IP6
;
12281 safi_t safi
= SAFI_UNICAST
;
12282 struct bgp
*bgp
= NULL
;
12284 bool uj
= use_json(argc
, argv
);
12285 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12287 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12290 return CMD_WARNING
;
12293 json_afi_safi
= json_object_new_array();
12295 json_afi_safi
= NULL
;
12297 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12300 json
= json_object_new_object();
12301 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12303 vty_json(vty
, json
);
12308 /* BGP route print out function without JSON */
12309 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12310 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12311 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12313 statistics [json]",
12314 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12315 BGP_SAFI_WITH_LABEL_HELP_STR
12316 "BGP RIB advertisement statistics\n" JSON_STR
)
12318 afi_t afi
= AFI_IP6
;
12319 safi_t safi
= SAFI_UNICAST
;
12320 struct bgp
*bgp
= NULL
;
12322 bool uj
= use_json(argc
, argv
);
12323 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12325 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12328 return CMD_WARNING
;
12331 json_afi_safi
= json_object_new_array();
12333 json_afi_safi
= NULL
;
12335 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12338 json
= json_object_new_object();
12339 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12341 vty_json(vty
, json
);
12346 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12347 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12348 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12349 "]] [all$all] dampening parameters [json]",
12350 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12351 BGP_SAFI_WITH_LABEL_HELP_STR
12352 "Display the entries for all address families\n"
12353 "Display detailed information about dampening\n"
12354 "Display detail of configured dampening parameters\n"
12357 afi_t afi
= AFI_IP6
;
12358 safi_t safi
= SAFI_UNICAST
;
12359 struct bgp
*bgp
= NULL
;
12361 uint16_t show_flags
= 0;
12362 bool uj
= use_json(argc
, argv
);
12366 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12369 /* [<ipv4|ipv6> [all]] */
12371 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12372 if (argv_find(argv
, argc
, "ipv4", &idx
))
12373 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12375 if (argv_find(argv
, argc
, "ipv6", &idx
))
12376 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12379 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12382 return CMD_WARNING
;
12384 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12387 /* BGP route print out function */
12388 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12389 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12390 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12394 |dampening <flap-statistics|dampened-paths>\
12395 |community [AA:NN|local-AS|no-advertise|no-export\
12396 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12397 |accept-own|accept-own-nexthop|route-filter-v6\
12398 |route-filter-v4|route-filter-translated-v6\
12399 |route-filter-translated-v4] [exact-match]\
12400 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12401 |filter-list AS_PATH_FILTER_NAME\
12403 |access-list ACCESSLIST_NAME\
12404 |route-map RMAP_NAME\
12405 |rpki <invalid|valid|notfound>\
12406 |version (1-4294967295)\
12408 |A.B.C.D/M longer-prefixes\
12409 |X:X::X:X/M longer-prefixes\
12410 ] [json$uj [detail$detail] | wide$wide]",
12411 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12412 BGP_SAFI_WITH_LABEL_HELP_STR
12413 "Display the entries for all address families\n"
12414 "Display only routes with non-natural netmasks\n"
12415 "Display detailed information about dampening\n"
12416 "Display flap statistics of routes\n"
12417 "Display paths suppressed due to dampening\n"
12418 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12419 "Do not send outside local AS (well-known community)\n"
12420 "Do not advertise to any peer (well-known community)\n"
12421 "Do not export to next AS (well-known community)\n"
12422 "Graceful shutdown (well-known community)\n"
12423 "Do not export to any peer (well-known community)\n"
12424 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12425 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12426 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12427 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12428 "Should accept VPN route with local nexthop (well-known community)\n"
12429 "RT VPNv6 route filtering (well-known community)\n"
12430 "RT VPNv4 route filtering (well-known community)\n"
12431 "RT translated VPNv6 route filtering (well-known community)\n"
12432 "RT translated VPNv4 route filtering (well-known community)\n"
12433 "Exact match of the communities\n"
12434 "Community-list number\n"
12435 "Community-list name\n"
12436 "Display routes matching the community-list\n"
12437 "Exact match of the communities\n"
12438 "Display routes conforming to the filter-list\n"
12439 "Regular expression access list name\n"
12440 "Display routes conforming to the prefix-list\n"
12441 "Prefix-list name\n"
12442 "Display routes conforming to the access-list\n"
12443 "Access-list name\n"
12444 "Display routes matching the route-map\n"
12445 "A route-map to match on\n"
12446 "RPKI route types\n"
12447 "A valid path as determined by rpki\n"
12448 "A invalid path as determined by rpki\n"
12449 "A path that has no rpki data\n"
12450 "Display prefixes with matching version numbers\n"
12451 "Version number and above\n"
12452 "Display prefixes with matching BGP community alias\n"
12453 "BGP community alias\n"
12455 "Display route and more specific routes\n"
12457 "Display route and more specific routes\n"
12459 "Display detailed version of JSON output\n"
12460 "Increase table width for longer prefixes\n")
12462 afi_t afi
= AFI_IP6
;
12463 safi_t safi
= SAFI_UNICAST
;
12464 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12465 void *output_arg
= NULL
;
12466 struct bgp
*bgp
= NULL
;
12468 int exact_match
= 0;
12469 char *community
= NULL
;
12471 uint16_t show_flags
= 0;
12472 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12477 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12481 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12483 /* [<ipv4|ipv6> [all]] */
12485 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12487 if (argv_find(argv
, argc
, "ipv4", &idx
))
12488 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12490 if (argv_find(argv
, argc
, "ipv6", &idx
))
12491 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12495 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12497 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12500 return CMD_WARNING
;
12502 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12503 sh_type
= bgp_show_type_cidr_only
;
12505 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12506 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12507 sh_type
= bgp_show_type_dampend_paths
;
12508 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12509 sh_type
= bgp_show_type_flap_statistics
;
12512 if (argv_find(argv
, argc
, "community", &idx
)) {
12513 char *maybecomm
= NULL
;
12515 if (idx
+ 1 < argc
) {
12516 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12517 maybecomm
= argv
[idx
+ 1]->arg
;
12519 maybecomm
= argv
[idx
+ 1]->text
;
12522 if (maybecomm
&& !strmatch(maybecomm
, "json")
12523 && !strmatch(maybecomm
, "exact-match"))
12524 community
= maybecomm
;
12526 if (argv_find(argv
, argc
, "exact-match", &idx
))
12530 sh_type
= bgp_show_type_community_all
;
12533 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12534 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12535 struct community_list
*list
;
12537 if (argv_find(argv
, argc
, "exact-match", &idx
))
12540 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12541 COMMUNITY_LIST_MASTER
);
12542 if (list
== NULL
) {
12543 vty_out(vty
, "%% %s community-list not found\n",
12544 clist_number_or_name
);
12545 return CMD_WARNING
;
12549 sh_type
= bgp_show_type_community_list_exact
;
12551 sh_type
= bgp_show_type_community_list
;
12555 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12556 const char *filter
= argv
[++idx
]->arg
;
12557 struct as_list
*as_list
;
12559 as_list
= as_list_lookup(filter
);
12560 if (as_list
== NULL
) {
12561 vty_out(vty
, "%% %s AS-path access-list not found\n",
12563 return CMD_WARNING
;
12566 sh_type
= bgp_show_type_filter_list
;
12567 output_arg
= as_list
;
12570 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12571 const char *prefix_list_str
= argv
[++idx
]->arg
;
12572 struct prefix_list
*plist
;
12574 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12575 if (plist
== NULL
) {
12576 vty_out(vty
, "%% %s prefix-list not found\n",
12578 return CMD_WARNING
;
12581 sh_type
= bgp_show_type_prefix_list
;
12582 output_arg
= plist
;
12585 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12586 const char *access_list_str
= argv
[++idx
]->arg
;
12587 struct access_list
*alist
;
12589 alist
= access_list_lookup(afi
, access_list_str
);
12591 vty_out(vty
, "%% %s access-list not found\n",
12593 return CMD_WARNING
;
12596 sh_type
= bgp_show_type_access_list
;
12597 output_arg
= alist
;
12600 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12601 const char *rmap_str
= argv
[++idx
]->arg
;
12602 struct route_map
*rmap
;
12604 rmap
= route_map_lookup_by_name(rmap_str
);
12606 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12607 return CMD_WARNING
;
12610 sh_type
= bgp_show_type_route_map
;
12614 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12615 sh_type
= bgp_show_type_rpki
;
12616 if (argv_find(argv
, argc
, "valid", &idx
))
12617 rpki_target_state
= RPKI_VALID
;
12618 else if (argv_find(argv
, argc
, "invalid", &idx
))
12619 rpki_target_state
= RPKI_INVALID
;
12622 /* Display prefixes with matching version numbers */
12623 if (argv_find(argv
, argc
, "version", &idx
)) {
12624 sh_type
= bgp_show_type_prefix_version
;
12625 output_arg
= argv
[idx
+ 1]->arg
;
12628 /* Display prefixes with matching BGP community alias */
12629 if (argv_find(argv
, argc
, "alias", &idx
)) {
12630 sh_type
= bgp_show_type_community_alias
;
12631 output_arg
= argv
[idx
+ 1]->arg
;
12634 /* prefix-longer */
12635 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12636 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12637 const char *prefix_str
= argv
[idx
]->arg
;
12639 if (!str2prefix(prefix_str
, &p
)) {
12640 vty_out(vty
, "%% Malformed Prefix\n");
12641 return CMD_WARNING
;
12644 sh_type
= bgp_show_type_prefix_longer
;
12649 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12651 return bgp_show_community(vty
, bgp
, community
,
12652 exact_match
, afi
, safi
,
12655 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12656 output_arg
, show_flags
,
12657 rpki_target_state
);
12659 struct listnode
*node
;
12661 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12665 vty_out(vty
, "{\n");
12667 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12668 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12669 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12672 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12673 FOREACH_SAFI (safi
) {
12674 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12682 vty_out(vty
, ",\n");
12683 vty_out(vty
, "\"%s\":{\n",
12684 get_afi_safi_str(afi
,
12689 "\nFor address family: %s\n",
12695 bgp_show_community(
12696 vty
, abgp
, community
,
12697 exact_match
, afi
, safi
,
12700 bgp_show(vty
, abgp
, afi
, safi
,
12701 sh_type
, output_arg
,
12703 rpki_target_state
);
12705 vty_out(vty
, "}\n");
12709 /* show <ip> bgp all: for each AFI and SAFI*/
12710 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12711 FOREACH_AFI_SAFI (afi
, safi
) {
12712 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12720 vty_out(vty
, ",\n");
12722 vty_out(vty
, "\"%s\":{\n",
12723 get_afi_safi_str(afi
,
12728 "\nFor address family: %s\n",
12734 bgp_show_community(
12735 vty
, abgp
, community
,
12736 exact_match
, afi
, safi
,
12739 bgp_show(vty
, abgp
, afi
, safi
,
12740 sh_type
, output_arg
,
12742 rpki_target_state
);
12744 vty_out(vty
, "}\n");
12749 vty_out(vty
, "}\n");
12751 return CMD_SUCCESS
;
12754 DEFUN (show_ip_bgp_route
,
12755 show_ip_bgp_route_cmd
,
12756 "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]",
12760 BGP_INSTANCE_HELP_STR
12762 BGP_SAFI_WITH_LABEL_HELP_STR
12763 "Network in the BGP routing table to display\n"
12765 "Network in the BGP routing table to display\n"
12767 "Display only the bestpath\n"
12768 "Display only multipaths\n"
12769 "Display only paths that match the specified rpki state\n"
12770 "A valid path as determined by rpki\n"
12771 "A invalid path as determined by rpki\n"
12772 "A path that has no rpki data\n"
12775 int prefix_check
= 0;
12777 afi_t afi
= AFI_IP6
;
12778 safi_t safi
= SAFI_UNICAST
;
12779 char *prefix
= NULL
;
12780 struct bgp
*bgp
= NULL
;
12781 enum bgp_path_type path_type
;
12782 bool uj
= use_json(argc
, argv
);
12786 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12789 return CMD_WARNING
;
12793 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12794 return CMD_WARNING
;
12797 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12798 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12799 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12801 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12802 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12805 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12806 && afi
!= AFI_IP6
) {
12808 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12809 return CMD_WARNING
;
12811 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12812 && afi
!= AFI_IP
) {
12814 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12815 return CMD_WARNING
;
12818 prefix
= argv
[idx
]->arg
;
12820 /* [<bestpath|multipath>] */
12821 if (argv_find(argv
, argc
, "bestpath", &idx
))
12822 path_type
= BGP_PATH_SHOW_BESTPATH
;
12823 else if (argv_find(argv
, argc
, "multipath", &idx
))
12824 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12826 path_type
= BGP_PATH_SHOW_ALL
;
12828 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12829 path_type
, RPKI_NOT_BEING_USED
, uj
);
12832 DEFUN (show_ip_bgp_regexp
,
12833 show_ip_bgp_regexp_cmd
,
12834 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12838 BGP_INSTANCE_HELP_STR
12840 BGP_SAFI_WITH_LABEL_HELP_STR
12841 "Display routes matching the AS path regular expression\n"
12842 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12845 afi_t afi
= AFI_IP6
;
12846 safi_t safi
= SAFI_UNICAST
;
12847 struct bgp
*bgp
= NULL
;
12848 bool uj
= use_json(argc
, argv
);
12849 char *regstr
= NULL
;
12852 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12855 return CMD_WARNING
;
12857 // get index of regex
12858 if (argv_find(argv
, argc
, "REGEX", &idx
))
12859 regstr
= argv
[idx
]->arg
;
12862 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12863 bgp_show_type_regexp
, uj
);
12866 DEFPY (show_ip_bgp_instance_all
,
12867 show_ip_bgp_instance_all_cmd
,
12868 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12872 BGP_INSTANCE_ALL_HELP_STR
12874 BGP_SAFI_WITH_LABEL_HELP_STR
12876 "Increase table width for longer prefixes\n")
12878 afi_t afi
= AFI_IP6
;
12879 safi_t safi
= SAFI_UNICAST
;
12880 struct bgp
*bgp
= NULL
;
12882 uint16_t show_flags
= 0;
12886 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12890 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12892 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12895 return CMD_WARNING
;
12897 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12898 return CMD_SUCCESS
;
12901 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12902 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12907 uint16_t show_flags
= 0;
12910 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12912 if (!config_bgp_aspath_validate(regstr
)) {
12913 vty_out(vty
, "Invalid character in REGEX %s\n",
12915 return CMD_WARNING_CONFIG_FAILED
;
12918 regex
= bgp_regcomp(regstr
);
12920 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12921 return CMD_WARNING
;
12924 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
12925 RPKI_NOT_BEING_USED
);
12926 bgp_regex_free(regex
);
12930 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12931 const char *comstr
, int exact
, afi_t afi
,
12932 safi_t safi
, uint16_t show_flags
)
12934 struct community
*com
;
12937 com
= community_str2com(comstr
);
12939 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12940 return CMD_WARNING
;
12943 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12944 (exact
? bgp_show_type_community_exact
12945 : bgp_show_type_community
),
12946 com
, show_flags
, RPKI_NOT_BEING_USED
);
12947 community_free(&com
);
12953 BGP_STATS_MAXBITLEN
= 0,
12955 BGP_STATS_PREFIXES
,
12957 BGP_STATS_UNAGGREGATEABLE
,
12958 BGP_STATS_MAX_AGGREGATEABLE
,
12959 BGP_STATS_AGGREGATES
,
12961 BGP_STATS_ASPATH_COUNT
,
12962 BGP_STATS_ASPATH_MAXHOPS
,
12963 BGP_STATS_ASPATH_TOTHOPS
,
12964 BGP_STATS_ASPATH_MAXSIZE
,
12965 BGP_STATS_ASPATH_TOTSIZE
,
12966 BGP_STATS_ASN_HIGHEST
,
12970 #define TABLE_STATS_IDX_VTY 0
12971 #define TABLE_STATS_IDX_JSON 1
12973 static const char *table_stats_strs
[][2] = {
12974 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12975 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12976 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12977 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12978 "unaggregateablePrefixes"},
12979 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12980 "maximumAggregateablePrefixes"},
12981 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12982 "bgpAggregateAdvertisements"},
12983 [BGP_STATS_SPACE
] = {"Address space advertised",
12984 "addressSpaceAdvertised"},
12985 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12986 "advertisementsWithPaths"},
12987 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12989 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12991 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12992 "averageAsPathLengthHops"},
12993 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12994 "averageAsPathSizeBytes"},
12995 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12996 [BGP_STATS_MAX
] = {NULL
, NULL
}
12999 struct bgp_table_stats
{
13000 struct bgp_table
*table
;
13001 unsigned long long counts
[BGP_STATS_MAX
];
13004 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13007 double total_space
;
13010 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13011 struct bgp_table_stats
*ts
, unsigned int space
)
13013 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13014 struct bgp_path_info
*pi
;
13015 const struct prefix
*rn_p
;
13017 if (!bgp_dest_has_bgp_path_info_data(dest
))
13020 rn_p
= bgp_dest_get_prefix(dest
);
13021 ts
->counts
[BGP_STATS_PREFIXES
]++;
13022 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13024 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13025 /* check if the prefix is included by any other announcements */
13026 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13027 pdest
= bgp_dest_parent_nolock(pdest
);
13029 if (pdest
== NULL
|| pdest
== top
) {
13030 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13031 /* announced address space */
13033 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13034 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13035 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13038 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13039 ts
->counts
[BGP_STATS_RIB
]++;
13041 if (CHECK_FLAG(pi
->attr
->flag
,
13042 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13043 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13045 /* as-path stats */
13046 if (pi
->attr
->aspath
) {
13047 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13048 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13049 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13051 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13053 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13054 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13056 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13057 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13059 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13060 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13061 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13062 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13067 static void bgp_table_stats_walker(struct thread
*t
)
13069 struct bgp_dest
*dest
, *ndest
;
13070 struct bgp_dest
*top
;
13071 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13072 unsigned int space
= 0;
13074 if (!(top
= bgp_table_top(ts
->table
)))
13077 switch (ts
->table
->afi
) {
13079 space
= IPV4_MAX_BITLEN
;
13082 space
= IPV6_MAX_BITLEN
;
13085 space
= EVPN_ROUTE_PREFIXLEN
;
13091 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13093 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13094 if (ts
->table
->safi
== SAFI_MPLS_VPN
13095 || ts
->table
->safi
== SAFI_ENCAP
13096 || ts
->table
->safi
== SAFI_EVPN
) {
13097 struct bgp_table
*table
;
13099 table
= bgp_dest_get_bgp_table_info(dest
);
13103 top
= bgp_table_top(table
);
13104 for (ndest
= bgp_table_top(table
); ndest
;
13105 ndest
= bgp_route_next(ndest
))
13106 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13108 bgp_table_stats_rn(dest
, top
, ts
, space
);
13113 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13114 struct json_object
*json_array
)
13116 struct listnode
*node
, *nnode
;
13119 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13120 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13123 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13124 safi_t safi
, struct json_object
*json_array
)
13126 struct bgp_table_stats ts
;
13128 int ret
= CMD_SUCCESS
;
13130 struct json_object
*json
= NULL
;
13131 uint32_t bitlen
= 0;
13132 struct json_object
*json_bitlen
;
13135 json
= json_object_new_object();
13137 if (!bgp
->rib
[afi
][safi
]) {
13138 char warning_msg
[50];
13140 snprintf(warning_msg
, sizeof(warning_msg
),
13141 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13145 vty_out(vty
, "%s\n", warning_msg
);
13147 json_object_string_add(json
, "warning", warning_msg
);
13150 goto end_table_stats
;
13154 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13155 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13157 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13159 /* labeled-unicast routes live in the unicast table */
13160 if (safi
== SAFI_LABELED_UNICAST
)
13161 safi
= SAFI_UNICAST
;
13163 memset(&ts
, 0, sizeof(ts
));
13164 ts
.table
= bgp
->rib
[afi
][safi
];
13165 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13167 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13168 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13169 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13173 case BGP_STATS_ASPATH_TOTHOPS
:
13174 case BGP_STATS_ASPATH_TOTSIZE
:
13177 temp_buf
, sizeof(temp_buf
), "%12.2f",
13179 ? (float)ts
.counts
[i
]
13181 [BGP_STATS_ASPATH_COUNT
]
13183 vty_out(vty
, "%-30s: %s",
13184 table_stats_strs
[i
]
13185 [TABLE_STATS_IDX_VTY
],
13188 json_object_double_add(
13190 table_stats_strs
[i
]
13191 [TABLE_STATS_IDX_JSON
],
13193 ? (double)ts
.counts
[i
]
13194 / (double)ts
.counts
13195 [BGP_STATS_ASPATH_COUNT
]
13199 case BGP_STATS_TOTPLEN
:
13202 temp_buf
, sizeof(temp_buf
), "%12.2f",
13204 ? (float)ts
.counts
[i
]
13206 [BGP_STATS_PREFIXES
]
13208 vty_out(vty
, "%-30s: %s",
13209 table_stats_strs
[i
]
13210 [TABLE_STATS_IDX_VTY
],
13213 json_object_double_add(
13215 table_stats_strs
[i
]
13216 [TABLE_STATS_IDX_JSON
],
13218 ? (double)ts
.counts
[i
]
13219 / (double)ts
.counts
13220 [BGP_STATS_PREFIXES
]
13224 case BGP_STATS_SPACE
:
13226 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13228 vty_out(vty
, "%-30s: %s\n",
13229 table_stats_strs
[i
]
13230 [TABLE_STATS_IDX_VTY
],
13233 json_object_double_add(
13235 table_stats_strs
[i
]
13236 [TABLE_STATS_IDX_JSON
],
13237 (double)ts
.total_space
);
13239 if (afi
== AFI_IP6
) {
13241 snprintf(temp_buf
, sizeof(temp_buf
),
13244 * pow(2.0, -128 + 32));
13245 vty_out(vty
, "%30s: %s\n",
13246 "/32 equivalent %s\n",
13249 json_object_double_add(
13250 json
, "/32equivalent",
13251 (double)(ts
.total_space
13256 snprintf(temp_buf
, sizeof(temp_buf
),
13259 * pow(2.0, -128 + 48));
13260 vty_out(vty
, "%30s: %s\n",
13261 "/48 equivalent %s\n",
13264 json_object_double_add(
13265 json
, "/48equivalent",
13266 (double)(ts
.total_space
13272 snprintf(temp_buf
, sizeof(temp_buf
),
13274 ts
.total_space
* 100.
13276 vty_out(vty
, "%30s: %s\n",
13277 "% announced ", temp_buf
);
13279 json_object_double_add(
13280 json
, "%announced",
13281 (double)(ts
.total_space
* 100.
13285 snprintf(temp_buf
, sizeof(temp_buf
),
13288 * pow(2.0, -32 + 8));
13289 vty_out(vty
, "%30s: %s\n",
13290 "/8 equivalent ", temp_buf
);
13292 json_object_double_add(
13293 json
, "/8equivalent",
13294 (double)(ts
.total_space
13295 * pow(2.0, -32 + 8)));
13298 snprintf(temp_buf
, sizeof(temp_buf
),
13301 * pow(2.0, -32 + 24));
13302 vty_out(vty
, "%30s: %s\n",
13303 "/24 equivalent ", temp_buf
);
13305 json_object_double_add(
13306 json
, "/24equivalent",
13307 (double)(ts
.total_space
13308 * pow(2.0, -32 + 24)));
13314 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13316 vty_out(vty
, "%-30s: %s",
13317 table_stats_strs
[i
]
13318 [TABLE_STATS_IDX_VTY
],
13321 json_object_int_add(
13323 table_stats_strs
[i
]
13324 [TABLE_STATS_IDX_JSON
],
13329 vty_out(vty
, "\n");
13334 bitlen
= IPV4_MAX_BITLEN
;
13337 bitlen
= IPV6_MAX_BITLEN
;
13340 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13347 json_bitlen
= json_object_new_array();
13349 for (i
= 0; i
<= bitlen
; i
++) {
13350 struct json_object
*ind_bit
= json_object_new_object();
13352 if (!ts
.prefix_len_count
[i
])
13355 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13356 json_object_int_add(ind_bit
, temp_buf
,
13357 ts
.prefix_len_count
[i
]);
13358 json_object_array_add(json_bitlen
, ind_bit
);
13360 json_object_object_add(json
, "prefixLength", json_bitlen
);
13365 json_object_array_add(json_array
, json
);
13369 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13370 safi_t safi
, struct json_object
*json_array
)
13373 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13374 return CMD_SUCCESS
;
13377 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13389 PCOUNT_BPATH_SELECTED
,
13390 PCOUNT_PFCNT
, /* the figure we display to users */
13394 static const char *const pcount_strs
[] = {
13395 [PCOUNT_ADJ_IN
] = "Adj-in",
13396 [PCOUNT_DAMPED
] = "Damped",
13397 [PCOUNT_REMOVED
] = "Removed",
13398 [PCOUNT_HISTORY
] = "History",
13399 [PCOUNT_STALE
] = "Stale",
13400 [PCOUNT_VALID
] = "Valid",
13401 [PCOUNT_ALL
] = "All RIB",
13402 [PCOUNT_COUNTED
] = "PfxCt counted",
13403 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13404 [PCOUNT_PFCNT
] = "Useable",
13405 [PCOUNT_MAX
] = NULL
,
13408 struct peer_pcounts
{
13409 unsigned int count
[PCOUNT_MAX
];
13410 const struct peer
*peer
;
13411 const struct bgp_table
*table
;
13415 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13417 const struct bgp_adj_in
*ain
;
13418 const struct bgp_path_info
*pi
;
13419 const struct peer
*peer
= pc
->peer
;
13421 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13422 if (ain
->peer
== peer
)
13423 pc
->count
[PCOUNT_ADJ_IN
]++;
13425 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13427 if (pi
->peer
!= peer
)
13430 pc
->count
[PCOUNT_ALL
]++;
13432 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13433 pc
->count
[PCOUNT_DAMPED
]++;
13434 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13435 pc
->count
[PCOUNT_HISTORY
]++;
13436 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13437 pc
->count
[PCOUNT_REMOVED
]++;
13438 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13439 pc
->count
[PCOUNT_STALE
]++;
13440 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13441 pc
->count
[PCOUNT_VALID
]++;
13442 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13443 pc
->count
[PCOUNT_PFCNT
]++;
13444 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13445 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13447 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13448 pc
->count
[PCOUNT_COUNTED
]++;
13449 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13451 EC_LIB_DEVELOPMENT
,
13452 "Attempting to count but flags say it is unusable");
13454 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13456 EC_LIB_DEVELOPMENT
,
13457 "Not counted but flags say we should");
13462 static void bgp_peer_count_walker(struct thread
*t
)
13464 struct bgp_dest
*rn
, *rm
;
13465 const struct bgp_table
*table
;
13466 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13468 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13469 || pc
->safi
== SAFI_EVPN
) {
13470 /* Special handling for 2-level routing tables. */
13471 for (rn
= bgp_table_top(pc
->table
); rn
;
13472 rn
= bgp_route_next(rn
)) {
13473 table
= bgp_dest_get_bgp_table_info(rn
);
13475 for (rm
= bgp_table_top(table
); rm
;
13476 rm
= bgp_route_next(rm
))
13477 bgp_peer_count_proc(rm
, pc
);
13480 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13481 bgp_peer_count_proc(rn
, pc
);
13484 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13485 safi_t safi
, bool use_json
)
13487 struct peer_pcounts pcounts
= {.peer
= peer
};
13489 json_object
*json
= NULL
;
13490 json_object
*json_loop
= NULL
;
13493 json
= json_object_new_object();
13494 json_loop
= json_object_new_object();
13497 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13498 || !peer
->bgp
->rib
[afi
][safi
]) {
13500 json_object_string_add(
13502 "No such neighbor or address family");
13503 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13504 json_object_free(json
);
13505 json_object_free(json_loop
);
13507 vty_out(vty
, "%% No such neighbor or address family\n");
13509 return CMD_WARNING
;
13512 memset(&pcounts
, 0, sizeof(pcounts
));
13513 pcounts
.peer
= peer
;
13514 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13515 pcounts
.safi
= safi
;
13517 /* in-place call via thread subsystem so as to record execution time
13518 * stats for the thread-walk (i.e. ensure this can't be blamed on
13519 * on just vty_read()).
13521 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13524 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13525 json_object_string_add(json
, "multiProtocol",
13526 get_afi_safi_str(afi
, safi
, true));
13527 json_object_int_add(json
, "pfxCounter",
13528 peer
->pcount
[afi
][safi
]);
13530 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13531 json_object_int_add(json_loop
, pcount_strs
[i
],
13534 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13536 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13537 json_object_string_add(json
, "pfxctDriftFor",
13539 json_object_string_add(
13540 json
, "recommended",
13541 "Please report this bug, with the above command output");
13543 vty_json(vty
, json
);
13547 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13548 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13549 peer
->hostname
, peer
->host
,
13550 get_afi_safi_str(afi
, safi
, false));
13552 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13553 get_afi_safi_str(afi
, safi
, false));
13556 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13557 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13559 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13560 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13563 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13564 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13566 "Please report this bug, with the above command output\n");
13570 return CMD_SUCCESS
;
13573 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13574 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13575 "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]",
13579 BGP_INSTANCE_HELP_STR
13582 "Detailed information on TCP and BGP neighbor connections\n"
13583 "Neighbor to display information about\n"
13584 "Neighbor to display information about\n"
13585 "Neighbor on BGP configured interface\n"
13586 "Display detailed prefix count information\n"
13589 afi_t afi
= AFI_IP6
;
13590 safi_t safi
= SAFI_UNICAST
;
13593 struct bgp
*bgp
= NULL
;
13594 bool uj
= use_json(argc
, argv
);
13599 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13602 return CMD_WARNING
;
13604 argv_find(argv
, argc
, "neighbors", &idx
);
13605 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13607 return CMD_WARNING
;
13609 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13612 #ifdef KEEP_OLD_VPN_COMMANDS
13613 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13614 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13615 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13620 "Display information about all VPNv4 NLRIs\n"
13621 "Detailed information on TCP and BGP neighbor connections\n"
13622 "Neighbor to display information about\n"
13623 "Neighbor to display information about\n"
13624 "Neighbor on BGP configured interface\n"
13625 "Display detailed prefix count information\n"
13630 bool uj
= use_json(argc
, argv
);
13632 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13634 return CMD_WARNING
;
13636 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13639 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13640 show_ip_bgp_vpn_all_route_prefix_cmd
,
13641 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13646 "Display information about all VPNv4 NLRIs\n"
13647 "Network in the BGP routing table to display\n"
13648 "Network in the BGP routing table to display\n"
13652 char *network
= NULL
;
13653 struct bgp
*bgp
= bgp_get_default();
13655 vty_out(vty
, "Can't find default instance\n");
13656 return CMD_WARNING
;
13659 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13660 network
= argv
[idx
]->arg
;
13661 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13662 network
= argv
[idx
]->arg
;
13664 vty_out(vty
, "Unable to figure out Network\n");
13665 return CMD_WARNING
;
13668 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13669 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13670 use_json(argc
, argv
));
13672 #endif /* KEEP_OLD_VPN_COMMANDS */
13674 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13675 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13676 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13681 "Network in the BGP routing table to display\n"
13682 "Network in the BGP routing table to display\n"
13683 "Network in the BGP routing table to display\n"
13684 "Network in the BGP routing table to display\n"
13688 char *network
= NULL
;
13689 int prefix_check
= 0;
13691 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13692 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13693 network
= argv
[idx
]->arg
;
13694 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13695 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13696 network
= argv
[idx
]->arg
;
13699 vty_out(vty
, "Unable to figure out Network\n");
13700 return CMD_WARNING
;
13702 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13703 prefix_check
, BGP_PATH_SHOW_ALL
,
13704 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13707 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13708 struct bgp_table
*table
, int *header1
,
13709 int *header2
, json_object
*json
,
13710 json_object
*json_scode
,
13711 json_object
*json_ocode
, bool wide
)
13713 uint64_t version
= table
? table
->version
: 0;
13717 json_object_int_add(json
, "bgpTableVersion", version
);
13718 json_object_string_addf(json
, "bgpLocalRouterId",
13719 "%pI4", &peer
->bgp
->router_id
);
13720 json_object_int_add(json
, "defaultLocPrf",
13721 peer
->bgp
->default_local_pref
);
13722 json_object_int_add(json
, "localAS",
13723 peer
->change_local_as
13724 ? peer
->change_local_as
13726 json_object_object_add(json
, "bgpStatusCodes",
13728 json_object_object_add(json
, "bgpOriginCodes",
13732 "BGP table version is %" PRIu64
13733 ", local router ID is %pI4, vrf id ",
13734 version
, &peer
->bgp
->router_id
);
13735 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
13736 vty_out(vty
, "%s", VRFID_NONE_STR
);
13738 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
13739 vty_out(vty
, "\n");
13740 vty_out(vty
, "Default local pref %u, ",
13741 peer
->bgp
->default_local_pref
);
13742 vty_out(vty
, "local AS %u\n",
13743 peer
->change_local_as
? peer
->change_local_as
13745 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13746 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13747 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13748 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13754 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13755 : BGP_SHOW_HEADER
));
13761 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13762 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13763 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13764 json_object
*json_scode
, json_object
*json_ocode
,
13765 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13766 unsigned long *output_count
, unsigned long *filtered_count
)
13768 struct bgp_adj_in
*ain
;
13769 struct bgp_adj_out
*adj
;
13770 struct bgp_dest
*dest
;
13774 struct update_subgroup
*subgrp
;
13775 struct peer_af
*paf
;
13776 bool route_filtered
;
13777 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13778 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13779 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13780 || (safi
== SAFI_EVPN
))
13786 subgrp
= peer_subgroup(peer
, afi
, safi
);
13788 if (type
== bgp_show_adj_route_advertised
&& subgrp
13789 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13791 json_object_int_add(json
, "bgpTableVersion",
13793 json_object_string_addf(json
, "bgpLocalRouterId",
13794 "%pI4", &bgp
->router_id
);
13795 json_object_int_add(json
, "defaultLocPrf",
13796 bgp
->default_local_pref
);
13797 json_object_int_add(json
, "localAS",
13798 peer
->change_local_as
13799 ? peer
->change_local_as
13801 json_object_object_add(json
, "bgpStatusCodes",
13803 json_object_object_add(json
, "bgpOriginCodes",
13805 json_object_string_add(
13806 json
, "bgpOriginatingDefaultNetwork",
13807 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13810 "BGP table version is %" PRIu64
13811 ", local router ID is %pI4, vrf id ",
13812 table
->version
, &bgp
->router_id
);
13813 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13814 vty_out(vty
, "%s", VRFID_NONE_STR
);
13816 vty_out(vty
, "%u", bgp
->vrf_id
);
13817 vty_out(vty
, "\n");
13818 vty_out(vty
, "Default local pref %u, ",
13819 bgp
->default_local_pref
);
13820 vty_out(vty
, "local AS %u\n",
13821 peer
->change_local_as
? peer
->change_local_as
13823 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13824 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13825 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13826 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
13828 vty_out(vty
, "Originating default network %s\n\n",
13829 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13834 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13835 if (type
== bgp_show_adj_route_received
13836 || type
== bgp_show_adj_route_filtered
) {
13837 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13838 if (ain
->peer
!= peer
)
13841 show_adj_route_header(vty
, peer
, table
, header1
,
13842 header2
, json
, json_scode
,
13845 if ((safi
== SAFI_MPLS_VPN
)
13846 || (safi
== SAFI_ENCAP
)
13847 || (safi
== SAFI_EVPN
)) {
13849 json_object_string_add(
13850 json_ar
, "rd", rd_str
);
13851 else if (show_rd
&& rd_str
) {
13853 "Route Distinguisher: %s\n",
13860 route_filtered
= false;
13862 /* Filter prefix using distribute list,
13863 * filter list or prefix list
13865 const struct prefix
*rn_p
=
13866 bgp_dest_get_prefix(dest
);
13867 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13870 route_filtered
= true;
13872 /* Filter prefix using route-map */
13873 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13874 safi
, rmap_name
, NULL
,
13877 if (type
== bgp_show_adj_route_filtered
&&
13878 !route_filtered
&& ret
!= RMAP_DENY
) {
13879 bgp_attr_flush(&attr
);
13883 if (type
== bgp_show_adj_route_received
13884 && (route_filtered
|| ret
== RMAP_DENY
))
13885 (*filtered_count
)++;
13887 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
13888 use_json
, json_ar
, wide
);
13889 bgp_attr_flush(&attr
);
13892 } else if (type
== bgp_show_adj_route_advertised
) {
13893 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13894 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13895 if (paf
->peer
!= peer
|| !adj
->attr
)
13898 show_adj_route_header(vty
, peer
, table
,
13903 const struct prefix
*rn_p
=
13904 bgp_dest_get_prefix(dest
);
13907 ret
= bgp_output_modifier(
13908 peer
, rn_p
, &attr
, afi
, safi
,
13911 if (ret
!= RMAP_DENY
) {
13912 if ((safi
== SAFI_MPLS_VPN
)
13913 || (safi
== SAFI_ENCAP
)
13914 || (safi
== SAFI_EVPN
)) {
13916 json_object_string_add(
13923 "Route Distinguisher: %s\n",
13929 vty
, dest
, rn_p
, &attr
,
13930 safi
, use_json
, json_ar
,
13934 (*filtered_count
)++;
13937 bgp_attr_flush(&attr
);
13939 } else if (type
== bgp_show_adj_route_bestpath
) {
13940 struct bgp_path_info
*pi
;
13942 show_adj_route_header(vty
, peer
, table
, header1
,
13943 header2
, json
, json_scode
,
13946 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13948 if (pi
->peer
!= peer
)
13951 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13954 route_vty_out_tmp(vty
, dest
,
13955 bgp_dest_get_prefix(dest
),
13956 pi
->attr
, safi
, use_json
,
13964 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13965 safi_t safi
, enum bgp_show_adj_route_type type
,
13966 const char *rmap_name
, uint16_t show_flags
)
13969 struct bgp_table
*table
;
13970 json_object
*json
= NULL
;
13971 json_object
*json_scode
= NULL
;
13972 json_object
*json_ocode
= NULL
;
13973 json_object
*json_ar
= NULL
;
13974 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13976 /* Init BGP headers here so they're only displayed once
13977 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13983 * Initialize variables for each RD
13984 * All prefixes under an RD is aggregated within "json_routes"
13986 char rd_str
[BUFSIZ
] = {0};
13987 json_object
*json_routes
= NULL
;
13990 /* For 2-tier tables, prefix counts need to be
13991 * maintained across multiple runs of show_adj_route()
13993 unsigned long output_count_per_rd
;
13994 unsigned long filtered_count_per_rd
;
13995 unsigned long output_count
= 0;
13996 unsigned long filtered_count
= 0;
13999 json
= json_object_new_object();
14000 json_ar
= json_object_new_object();
14001 json_scode
= json_object_new_object();
14002 json_ocode
= json_object_new_object();
14004 json_object_string_add(json_scode
, "suppressed", "s");
14005 json_object_string_add(json_scode
, "damped", "d");
14006 json_object_string_add(json_scode
, "history", "h");
14007 json_object_string_add(json_scode
, "valid", "*");
14008 json_object_string_add(json_scode
, "best", ">");
14009 json_object_string_add(json_scode
, "multipath", "=");
14010 json_object_string_add(json_scode
, "internal", "i");
14011 json_object_string_add(json_scode
, "ribFailure", "r");
14012 json_object_string_add(json_scode
, "stale", "S");
14013 json_object_string_add(json_scode
, "removed", "R");
14015 json_object_string_add(json_ocode
, "igp", "i");
14016 json_object_string_add(json_ocode
, "egp", "e");
14017 json_object_string_add(json_ocode
, "incomplete", "?");
14020 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14022 json_object_string_add(
14024 "No such neighbor or address family");
14025 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14026 json_object_free(json
);
14027 json_object_free(json_ar
);
14028 json_object_free(json_scode
);
14029 json_object_free(json_ocode
);
14031 vty_out(vty
, "%% No such neighbor or address family\n");
14033 return CMD_WARNING
;
14036 if ((type
== bgp_show_adj_route_received
14037 || type
== bgp_show_adj_route_filtered
)
14038 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14039 PEER_FLAG_SOFT_RECONFIG
)) {
14041 json_object_string_add(
14043 "Inbound soft reconfiguration not enabled");
14044 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14045 json_object_free(json
);
14046 json_object_free(json_ar
);
14047 json_object_free(json_scode
);
14048 json_object_free(json_ocode
);
14051 "%% Inbound soft reconfiguration not enabled\n");
14053 return CMD_WARNING
;
14058 /* labeled-unicast routes live in the unicast table */
14059 if (safi
== SAFI_LABELED_UNICAST
)
14060 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14062 table
= bgp
->rib
[afi
][safi
];
14064 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14065 || (safi
== SAFI_EVPN
)) {
14067 struct bgp_dest
*dest
;
14069 for (dest
= bgp_table_top(table
); dest
;
14070 dest
= bgp_route_next(dest
)) {
14071 table
= bgp_dest_get_bgp_table_info(dest
);
14075 output_count_per_rd
= 0;
14076 filtered_count_per_rd
= 0;
14079 json_routes
= json_object_new_object();
14081 const struct prefix_rd
*prd
;
14082 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14085 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
14087 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
14088 rmap_name
, json
, json_routes
, json_scode
,
14089 json_ocode
, show_flags
, &header1
,
14090 &header2
, rd_str
, &output_count_per_rd
,
14091 &filtered_count_per_rd
);
14093 /* Don't include an empty RD in the output! */
14094 if (json_routes
&& (output_count_per_rd
> 0))
14095 json_object_object_add(json_ar
, rd_str
,
14098 output_count
+= output_count_per_rd
;
14099 filtered_count
+= filtered_count_per_rd
;
14102 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14103 json
, json_ar
, json_scode
, json_ocode
,
14104 show_flags
, &header1
, &header2
, rd_str
,
14105 &output_count
, &filtered_count
);
14108 if (type
== bgp_show_adj_route_advertised
)
14109 json_object_object_add(json
, "advertisedRoutes",
14112 json_object_object_add(json
, "receivedRoutes", json_ar
);
14113 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14114 json_object_int_add(json
, "filteredPrefixCounter",
14118 * These fields only give up ownership to `json` when `header1`
14119 * is used (set to zero). See code in `show_adj_route` and
14120 * `show_adj_route_header`.
14122 if (header1
== 1) {
14123 json_object_free(json_scode
);
14124 json_object_free(json_ocode
);
14127 vty_json(vty
, json
);
14128 } else if (output_count
> 0) {
14129 if (filtered_count
> 0)
14131 "\nTotal number of prefixes %ld (%ld filtered)\n",
14132 output_count
, filtered_count
);
14134 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14138 return CMD_SUCCESS
;
14141 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14142 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14143 "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]",
14147 BGP_INSTANCE_HELP_STR
14149 BGP_SAFI_WITH_LABEL_HELP_STR
14150 "Detailed information on TCP and BGP neighbor connections\n"
14151 "Neighbor to display information about\n"
14152 "Neighbor to display information about\n"
14153 "Neighbor on BGP configured interface\n"
14154 "Display the routes selected by best path\n"
14156 "Increase table width for longer prefixes\n")
14158 afi_t afi
= AFI_IP6
;
14159 safi_t safi
= SAFI_UNICAST
;
14160 char *rmap_name
= NULL
;
14161 char *peerstr
= NULL
;
14162 struct bgp
*bgp
= NULL
;
14164 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14166 uint16_t show_flags
= 0;
14169 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14172 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14174 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14178 return CMD_WARNING
;
14180 argv_find(argv
, argc
, "neighbors", &idx
);
14181 peerstr
= argv
[++idx
]->arg
;
14183 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14185 return CMD_WARNING
;
14187 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14191 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
14192 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14193 "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]",
14197 BGP_INSTANCE_HELP_STR
14199 BGP_SAFI_WITH_LABEL_HELP_STR
14200 "Display the entries for all address families\n"
14201 "Detailed information on TCP and BGP neighbor connections\n"
14202 "Neighbor to display information about\n"
14203 "Neighbor to display information about\n"
14204 "Neighbor on BGP configured interface\n"
14205 "Display the routes advertised to a BGP neighbor\n"
14206 "Display the received routes from neighbor\n"
14207 "Display the filtered routes received from neighbor\n"
14208 "Route-map to modify the attributes\n"
14209 "Name of the route map\n"
14211 "Increase table width for longer prefixes\n")
14213 afi_t afi
= AFI_IP6
;
14214 safi_t safi
= SAFI_UNICAST
;
14215 char *peerstr
= NULL
;
14216 struct bgp
*bgp
= NULL
;
14218 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14221 uint16_t show_flags
= 0;
14222 struct listnode
*node
;
14227 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14231 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14232 if (argv_find(argv
, argc
, "ipv4", &idx
))
14233 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14235 if (argv_find(argv
, argc
, "ipv6", &idx
))
14236 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14240 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14242 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14245 return CMD_WARNING
;
14247 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14248 argv_find(argv
, argc
, "neighbors", &idx
);
14249 peerstr
= argv
[++idx
]->arg
;
14251 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14253 return CMD_WARNING
;
14255 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14256 type
= bgp_show_adj_route_advertised
;
14257 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14258 type
= bgp_show_adj_route_received
;
14259 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14260 type
= bgp_show_adj_route_filtered
;
14263 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14266 vty_out(vty
, "{\n");
14268 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14269 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14270 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14272 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14273 FOREACH_SAFI (safi
) {
14274 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14281 vty_out(vty
, ",\n");
14282 vty_out(vty
, "\"%s\":",
14283 get_afi_safi_str(afi
, safi
,
14287 "\nFor address family: %s\n",
14288 get_afi_safi_str(afi
, safi
,
14291 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14292 route_map
, show_flags
);
14296 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14297 FOREACH_AFI_SAFI (afi
, safi
) {
14298 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14305 vty_out(vty
, ",\n");
14306 vty_out(vty
, "\"%s\":",
14307 get_afi_safi_str(afi
, safi
,
14311 "\nFor address family: %s\n",
14312 get_afi_safi_str(afi
, safi
,
14315 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14316 route_map
, show_flags
);
14321 vty_out(vty
, "}\n");
14323 return CMD_SUCCESS
;
14326 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14327 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14328 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14332 BGP_INSTANCE_HELP_STR
14335 BGP_AF_MODIFIER_STR
14336 "Detailed information on TCP and BGP neighbor connections\n"
14337 "Neighbor to display information about\n"
14338 "Neighbor to display information about\n"
14339 "Neighbor on BGP configured interface\n"
14340 "Display information received from a BGP neighbor\n"
14341 "Display the prefixlist filter\n"
14344 afi_t afi
= AFI_IP6
;
14345 safi_t safi
= SAFI_UNICAST
;
14346 char *peerstr
= NULL
;
14351 struct bgp
*bgp
= NULL
;
14352 bool uj
= use_json(argc
, argv
);
14357 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14360 return CMD_WARNING
;
14362 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14363 argv_find(argv
, argc
, "neighbors", &idx
);
14364 peerstr
= argv
[++idx
]->arg
;
14366 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14368 return CMD_WARNING
;
14370 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14371 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14374 vty_out(vty
, "Address Family: %s\n",
14375 get_afi_safi_str(afi
, safi
, false));
14376 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14379 vty_out(vty
, "{}\n");
14381 vty_out(vty
, "No functional output\n");
14384 return CMD_SUCCESS
;
14387 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14388 afi_t afi
, safi_t safi
,
14389 enum bgp_show_type type
, bool use_json
)
14391 uint16_t show_flags
= 0;
14394 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14396 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14398 json_object
*json_no
= NULL
;
14399 json_no
= json_object_new_object();
14400 json_object_string_add(
14401 json_no
, "warning",
14402 "No such neighbor or address family");
14403 vty_out(vty
, "%s\n",
14404 json_object_to_json_string(json_no
));
14405 json_object_free(json_no
);
14407 vty_out(vty
, "%% No such neighbor or address family\n");
14408 return CMD_WARNING
;
14411 /* labeled-unicast routes live in the unicast table */
14412 if (safi
== SAFI_LABELED_UNICAST
)
14413 safi
= SAFI_UNICAST
;
14415 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14416 RPKI_NOT_BEING_USED
);
14419 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14420 show_ip_bgp_flowspec_routes_detailed_cmd
,
14421 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14425 BGP_INSTANCE_HELP_STR
14428 "Detailed information on flowspec entries\n"
14431 afi_t afi
= AFI_IP6
;
14432 safi_t safi
= SAFI_UNICAST
;
14433 struct bgp
*bgp
= NULL
;
14435 bool uj
= use_json(argc
, argv
);
14436 uint16_t show_flags
= BGP_SHOW_OPT_DETAIL
;
14440 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14443 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14446 return CMD_WARNING
;
14448 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14449 show_flags
, RPKI_NOT_BEING_USED
);
14452 DEFUN (show_ip_bgp_neighbor_routes
,
14453 show_ip_bgp_neighbor_routes_cmd
,
14454 "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]",
14458 BGP_INSTANCE_HELP_STR
14460 BGP_SAFI_WITH_LABEL_HELP_STR
14461 "Detailed information on TCP and BGP neighbor connections\n"
14462 "Neighbor to display information about\n"
14463 "Neighbor to display information about\n"
14464 "Neighbor on BGP configured interface\n"
14465 "Display flap statistics of the routes learned from neighbor\n"
14466 "Display the dampened routes received from neighbor\n"
14467 "Display routes learned from neighbor\n"
14470 char *peerstr
= NULL
;
14471 struct bgp
*bgp
= NULL
;
14472 afi_t afi
= AFI_IP6
;
14473 safi_t safi
= SAFI_UNICAST
;
14475 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14477 bool uj
= use_json(argc
, argv
);
14482 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14485 return CMD_WARNING
;
14487 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14488 argv_find(argv
, argc
, "neighbors", &idx
);
14489 peerstr
= argv
[++idx
]->arg
;
14491 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14493 return CMD_WARNING
;
14495 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14496 sh_type
= bgp_show_type_flap_neighbor
;
14497 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14498 sh_type
= bgp_show_type_damp_neighbor
;
14499 else if (argv_find(argv
, argc
, "routes", &idx
))
14500 sh_type
= bgp_show_type_neighbor
;
14502 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14505 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14507 struct bgp_distance
{
14508 /* Distance value for the IP source prefix. */
14511 /* Name of the access-list to be matched. */
14515 DEFUN (show_bgp_afi_vpn_rd_route
,
14516 show_bgp_afi_vpn_rd_route_cmd
,
14517 "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]",
14521 BGP_AF_MODIFIER_STR
14522 "Display information for a route distinguisher\n"
14523 "Route Distinguisher\n"
14524 "All Route Distinguishers\n"
14525 "Network in the BGP routing table to display\n"
14526 "Network in the BGP routing table to display\n"
14530 struct prefix_rd prd
;
14531 afi_t afi
= AFI_MAX
;
14534 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14535 vty_out(vty
, "%% Malformed Address Family\n");
14536 return CMD_WARNING
;
14539 if (!strcmp(argv
[5]->arg
, "all"))
14540 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14541 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14542 RPKI_NOT_BEING_USED
,
14543 use_json(argc
, argv
));
14545 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14547 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14548 return CMD_WARNING
;
14551 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14552 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14553 use_json(argc
, argv
));
14556 static struct bgp_distance
*bgp_distance_new(void)
14558 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14561 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14563 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14566 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14567 const char *ip_str
, const char *access_list_str
)
14574 struct bgp_dest
*dest
;
14575 struct bgp_distance
*bdistance
;
14577 afi
= bgp_node_afi(vty
);
14578 safi
= bgp_node_safi(vty
);
14580 ret
= str2prefix(ip_str
, &p
);
14582 vty_out(vty
, "Malformed prefix\n");
14583 return CMD_WARNING_CONFIG_FAILED
;
14586 distance
= atoi(distance_str
);
14588 /* Get BGP distance node. */
14589 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14590 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14592 bgp_dest_unlock_node(dest
);
14594 bdistance
= bgp_distance_new();
14595 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14598 /* Set distance value. */
14599 bdistance
->distance
= distance
;
14601 /* Reset access-list configuration. */
14602 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14603 if (access_list_str
)
14604 bdistance
->access_list
=
14605 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14607 return CMD_SUCCESS
;
14610 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14611 const char *ip_str
, const char *access_list_str
)
14618 struct bgp_dest
*dest
;
14619 struct bgp_distance
*bdistance
;
14621 afi
= bgp_node_afi(vty
);
14622 safi
= bgp_node_safi(vty
);
14624 ret
= str2prefix(ip_str
, &p
);
14626 vty_out(vty
, "Malformed prefix\n");
14627 return CMD_WARNING_CONFIG_FAILED
;
14630 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14632 vty_out(vty
, "Can't find specified prefix\n");
14633 return CMD_WARNING_CONFIG_FAILED
;
14636 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14637 distance
= atoi(distance_str
);
14639 if (bdistance
->distance
!= distance
) {
14640 vty_out(vty
, "Distance does not match configured\n");
14641 bgp_dest_unlock_node(dest
);
14642 return CMD_WARNING_CONFIG_FAILED
;
14645 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14646 bgp_distance_free(bdistance
);
14648 bgp_dest_set_bgp_path_info(dest
, NULL
);
14649 bgp_dest_unlock_node(dest
);
14650 bgp_dest_unlock_node(dest
);
14652 return CMD_SUCCESS
;
14655 /* Apply BGP information to distance method. */
14656 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14657 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14659 struct bgp_dest
*dest
;
14660 struct prefix q
= {0};
14662 struct bgp_distance
*bdistance
;
14663 struct access_list
*alist
;
14664 struct bgp_static
*bgp_static
;
14669 peer
= pinfo
->peer
;
14671 if (pinfo
->attr
->distance
)
14672 return pinfo
->attr
->distance
;
14674 /* Check source address.
14675 * Note: for aggregate route, peer can have unspec af type.
14677 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14678 && !sockunion2hostprefix(&peer
->su
, &q
))
14681 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14683 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14684 bgp_dest_unlock_node(dest
);
14686 if (bdistance
->access_list
) {
14687 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14689 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14690 return bdistance
->distance
;
14692 return bdistance
->distance
;
14695 /* Backdoor check. */
14696 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14698 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14699 bgp_dest_unlock_node(dest
);
14701 if (bgp_static
->backdoor
) {
14702 if (bgp
->distance_local
[afi
][safi
])
14703 return bgp
->distance_local
[afi
][safi
];
14705 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14709 if (peer
->sort
== BGP_PEER_EBGP
) {
14710 if (bgp
->distance_ebgp
[afi
][safi
])
14711 return bgp
->distance_ebgp
[afi
][safi
];
14712 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14713 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14714 if (bgp
->distance_ibgp
[afi
][safi
])
14715 return bgp
->distance_ibgp
[afi
][safi
];
14716 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14718 if (bgp
->distance_local
[afi
][safi
])
14719 return bgp
->distance_local
[afi
][safi
];
14720 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14724 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14725 * we should tell ZEBRA update the routes for a specific
14726 * AFI/SAFI to reflect changes in RIB.
14728 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
14730 safi_t update_safi
)
14735 FOREACH_AFI_SAFI (afi
, safi
) {
14736 if (!bgp_fibupd_safi(safi
))
14739 if (afi
!= update_afi
&& safi
!= update_safi
)
14742 if (BGP_DEBUG(zebra
, ZEBRA
))
14744 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14745 __func__
, afi
, safi
);
14746 bgp_zebra_announce_table(bgp
, afi
, safi
);
14750 DEFUN (bgp_distance
,
14752 "distance bgp (1-255) (1-255) (1-255)",
14753 "Define an administrative distance\n"
14755 "Distance for routes external to the AS\n"
14756 "Distance for routes internal to the AS\n"
14757 "Distance for local routes\n")
14759 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14760 int idx_number
= 2;
14761 int idx_number_2
= 3;
14762 int idx_number_3
= 4;
14763 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
14764 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
14765 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
14769 afi
= bgp_node_afi(vty
);
14770 safi
= bgp_node_safi(vty
);
14772 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
14773 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
14774 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
14775 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
14776 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
14777 bgp
->distance_local
[afi
][safi
] = distance_local
;
14778 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14780 return CMD_SUCCESS
;
14783 DEFUN (no_bgp_distance
,
14784 no_bgp_distance_cmd
,
14785 "no distance bgp [(1-255) (1-255) (1-255)]",
14787 "Define an administrative distance\n"
14789 "Distance for routes external to the AS\n"
14790 "Distance for routes internal to the AS\n"
14791 "Distance for local routes\n")
14793 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14797 afi
= bgp_node_afi(vty
);
14798 safi
= bgp_node_safi(vty
);
14800 if (bgp
->distance_ebgp
[afi
][safi
] != 0
14801 || bgp
->distance_ibgp
[afi
][safi
] != 0
14802 || bgp
->distance_local
[afi
][safi
] != 0) {
14803 bgp
->distance_ebgp
[afi
][safi
] = 0;
14804 bgp
->distance_ibgp
[afi
][safi
] = 0;
14805 bgp
->distance_local
[afi
][safi
] = 0;
14806 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
14808 return CMD_SUCCESS
;
14812 DEFUN (bgp_distance_source
,
14813 bgp_distance_source_cmd
,
14814 "distance (1-255) A.B.C.D/M",
14815 "Define an administrative distance\n"
14816 "Administrative distance\n"
14817 "IP source prefix\n")
14819 int idx_number
= 1;
14820 int idx_ipv4_prefixlen
= 2;
14821 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14822 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14823 return CMD_SUCCESS
;
14826 DEFUN (no_bgp_distance_source
,
14827 no_bgp_distance_source_cmd
,
14828 "no distance (1-255) A.B.C.D/M",
14830 "Define an administrative distance\n"
14831 "Administrative distance\n"
14832 "IP source prefix\n")
14834 int idx_number
= 2;
14835 int idx_ipv4_prefixlen
= 3;
14836 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14837 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
14838 return CMD_SUCCESS
;
14841 DEFUN (bgp_distance_source_access_list
,
14842 bgp_distance_source_access_list_cmd
,
14843 "distance (1-255) A.B.C.D/M WORD",
14844 "Define an administrative distance\n"
14845 "Administrative distance\n"
14846 "IP source prefix\n"
14847 "Access list name\n")
14849 int idx_number
= 1;
14850 int idx_ipv4_prefixlen
= 2;
14852 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
14853 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14854 return CMD_SUCCESS
;
14857 DEFUN (no_bgp_distance_source_access_list
,
14858 no_bgp_distance_source_access_list_cmd
,
14859 "no distance (1-255) A.B.C.D/M WORD",
14861 "Define an administrative distance\n"
14862 "Administrative distance\n"
14863 "IP source prefix\n"
14864 "Access list name\n")
14866 int idx_number
= 2;
14867 int idx_ipv4_prefixlen
= 3;
14869 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
14870 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
14871 return CMD_SUCCESS
;
14874 DEFUN (ipv6_bgp_distance_source
,
14875 ipv6_bgp_distance_source_cmd
,
14876 "distance (1-255) X:X::X:X/M",
14877 "Define an administrative distance\n"
14878 "Administrative distance\n"
14879 "IP source prefix\n")
14881 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
14882 return CMD_SUCCESS
;
14885 DEFUN (no_ipv6_bgp_distance_source
,
14886 no_ipv6_bgp_distance_source_cmd
,
14887 "no distance (1-255) X:X::X:X/M",
14889 "Define an administrative distance\n"
14890 "Administrative distance\n"
14891 "IP source prefix\n")
14893 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
14894 return CMD_SUCCESS
;
14897 DEFUN (ipv6_bgp_distance_source_access_list
,
14898 ipv6_bgp_distance_source_access_list_cmd
,
14899 "distance (1-255) X:X::X:X/M WORD",
14900 "Define an administrative distance\n"
14901 "Administrative distance\n"
14902 "IP source prefix\n"
14903 "Access list name\n")
14905 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
14906 return CMD_SUCCESS
;
14909 DEFUN (no_ipv6_bgp_distance_source_access_list
,
14910 no_ipv6_bgp_distance_source_access_list_cmd
,
14911 "no distance (1-255) X:X::X:X/M WORD",
14913 "Define an administrative distance\n"
14914 "Administrative distance\n"
14915 "IP source prefix\n"
14916 "Access list name\n")
14918 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
14919 return CMD_SUCCESS
;
14922 DEFUN (bgp_damp_set
,
14924 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
14925 "BGP Specific commands\n"
14926 "Enable route-flap dampening\n"
14927 "Half-life time for the penalty\n"
14928 "Value to start reusing a route\n"
14929 "Value to start suppressing a route\n"
14930 "Maximum duration to suppress a stable route\n")
14932 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14933 int idx_half_life
= 2;
14935 int idx_suppress
= 4;
14936 int idx_max_suppress
= 5;
14937 int half
= DEFAULT_HALF_LIFE
* 60;
14938 int reuse
= DEFAULT_REUSE
;
14939 int suppress
= DEFAULT_SUPPRESS
;
14940 int max
= 4 * half
;
14943 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14944 reuse
= atoi(argv
[idx_reuse
]->arg
);
14945 suppress
= atoi(argv
[idx_suppress
]->arg
);
14946 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
14947 } else if (argc
== 3) {
14948 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
14953 * These can't be 0 but our SA doesn't understand the
14954 * way our cli is constructed
14958 if (suppress
< reuse
) {
14960 "Suppress value cannot be less than reuse value \n");
14964 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
14965 reuse
, suppress
, max
);
14968 DEFUN (bgp_damp_unset
,
14969 bgp_damp_unset_cmd
,
14970 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
14972 "BGP Specific commands\n"
14973 "Enable route-flap dampening\n"
14974 "Half-life time for the penalty\n"
14975 "Value to start reusing a route\n"
14976 "Value to start suppressing a route\n"
14977 "Maximum duration to suppress a stable route\n")
14979 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14980 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
14983 /* Display specified route of BGP table. */
14984 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14985 const char *ip_str
, afi_t afi
, safi_t safi
,
14986 struct prefix_rd
*prd
, int prefix_check
)
14989 struct prefix match
;
14990 struct bgp_dest
*dest
;
14991 struct bgp_dest
*rm
;
14992 struct bgp_path_info
*pi
;
14993 struct bgp_path_info
*pi_temp
;
14995 struct bgp_table
*table
;
14997 /* BGP structure lookup. */
14999 bgp
= bgp_lookup_by_name(view_name
);
15001 vty_out(vty
, "%% Can't find BGP instance %s\n",
15003 return CMD_WARNING
;
15006 bgp
= bgp_get_default();
15008 vty_out(vty
, "%% No BGP process is configured\n");
15009 return CMD_WARNING
;
15013 /* Check IP address argument. */
15014 ret
= str2prefix(ip_str
, &match
);
15016 vty_out(vty
, "%% address is malformed\n");
15017 return CMD_WARNING
;
15020 match
.family
= afi2family(afi
);
15022 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15023 || (safi
== SAFI_EVPN
)) {
15024 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15025 dest
= bgp_route_next(dest
)) {
15026 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15028 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15030 table
= bgp_dest_get_bgp_table_info(dest
);
15033 rm
= bgp_node_match(table
, &match
);
15037 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15040 || rm_p
->prefixlen
== match
.prefixlen
) {
15041 pi
= bgp_dest_get_bgp_path_info(rm
);
15043 if (pi
->extra
&& pi
->extra
->damp_info
) {
15044 pi_temp
= pi
->next
;
15045 bgp_damp_info_free(
15046 pi
->extra
->damp_info
,
15054 bgp_dest_unlock_node(rm
);
15057 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15058 if (dest
!= NULL
) {
15059 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15062 || dest_p
->prefixlen
== match
.prefixlen
) {
15063 pi
= bgp_dest_get_bgp_path_info(dest
);
15065 if (pi
->extra
&& pi
->extra
->damp_info
) {
15066 pi_temp
= pi
->next
;
15067 bgp_damp_info_free(
15068 pi
->extra
->damp_info
,
15076 bgp_dest_unlock_node(dest
);
15080 return CMD_SUCCESS
;
15083 DEFUN (clear_ip_bgp_dampening
,
15084 clear_ip_bgp_dampening_cmd
,
15085 "clear ip bgp dampening",
15089 "Clear route flap dampening information\n")
15091 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15092 return CMD_SUCCESS
;
15095 DEFUN (clear_ip_bgp_dampening_prefix
,
15096 clear_ip_bgp_dampening_prefix_cmd
,
15097 "clear ip bgp dampening A.B.C.D/M",
15101 "Clear route flap dampening information\n"
15104 int idx_ipv4_prefixlen
= 4;
15105 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15106 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15109 DEFUN (clear_ip_bgp_dampening_address
,
15110 clear_ip_bgp_dampening_address_cmd
,
15111 "clear ip bgp dampening A.B.C.D",
15115 "Clear route flap dampening information\n"
15116 "Network to clear damping information\n")
15119 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15120 SAFI_UNICAST
, NULL
, 0);
15123 DEFUN (clear_ip_bgp_dampening_address_mask
,
15124 clear_ip_bgp_dampening_address_mask_cmd
,
15125 "clear ip bgp dampening A.B.C.D A.B.C.D",
15129 "Clear route flap dampening information\n"
15130 "Network to clear damping information\n"
15134 int idx_ipv4_2
= 5;
15136 char prefix_str
[BUFSIZ
];
15138 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15139 prefix_str
, sizeof(prefix_str
));
15141 vty_out(vty
, "%% Inconsistent address and mask\n");
15142 return CMD_WARNING
;
15145 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15149 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15151 struct vty
*vty
= arg
;
15152 struct peer
*peer
= bucket
->data
;
15154 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15157 DEFUN (show_bgp_listeners
,
15158 show_bgp_listeners_cmd
,
15159 "show bgp listeners",
15162 "Display Listen Sockets and who created them\n")
15164 bgp_dump_listener_info(vty
);
15166 return CMD_SUCCESS
;
15169 DEFUN (show_bgp_peerhash
,
15170 show_bgp_peerhash_cmd
,
15171 "show bgp peerhash",
15174 "Display information about the BGP peerhash\n")
15176 struct list
*instances
= bm
->bgp
;
15177 struct listnode
*node
;
15180 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15181 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15182 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15186 return CMD_SUCCESS
;
15189 /* also used for encap safi */
15190 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15191 afi_t afi
, safi_t safi
)
15193 struct bgp_dest
*pdest
;
15194 struct bgp_dest
*dest
;
15195 struct bgp_table
*table
;
15196 const struct prefix
*p
;
15197 const struct prefix_rd
*prd
;
15198 struct bgp_static
*bgp_static
;
15199 mpls_label_t label
;
15200 char rdbuf
[RD_ADDRSTRLEN
];
15202 /* Network configuration. */
15203 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15204 pdest
= bgp_route_next(pdest
)) {
15205 table
= bgp_dest_get_bgp_table_info(pdest
);
15209 for (dest
= bgp_table_top(table
); dest
;
15210 dest
= bgp_route_next(dest
)) {
15211 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15212 if (bgp_static
== NULL
)
15215 p
= bgp_dest_get_prefix(dest
);
15216 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
15219 /* "network" configuration display. */
15220 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
15221 label
= decode_label(&bgp_static
->label
);
15223 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
15224 if (safi
== SAFI_MPLS_VPN
)
15225 vty_out(vty
, " label %u", label
);
15227 if (bgp_static
->rmap
.name
)
15228 vty_out(vty
, " route-map %s",
15229 bgp_static
->rmap
.name
);
15231 if (bgp_static
->backdoor
)
15232 vty_out(vty
, " backdoor");
15234 vty_out(vty
, "\n");
15239 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15240 afi_t afi
, safi_t safi
)
15242 struct bgp_dest
*pdest
;
15243 struct bgp_dest
*dest
;
15244 struct bgp_table
*table
;
15245 const struct prefix
*p
;
15246 const struct prefix_rd
*prd
;
15247 struct bgp_static
*bgp_static
;
15248 char buf
[PREFIX_STRLEN
* 2];
15249 char buf2
[SU_ADDRSTRLEN
];
15250 char rdbuf
[RD_ADDRSTRLEN
];
15251 char esi_buf
[ESI_STR_LEN
];
15253 /* Network configuration. */
15254 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15255 pdest
= bgp_route_next(pdest
)) {
15256 table
= bgp_dest_get_bgp_table_info(pdest
);
15260 for (dest
= bgp_table_top(table
); dest
;
15261 dest
= bgp_route_next(dest
)) {
15262 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15263 if (bgp_static
== NULL
)
15266 char *macrouter
= NULL
;
15268 if (bgp_static
->router_mac
)
15269 macrouter
= prefix_mac2str(
15270 bgp_static
->router_mac
, NULL
, 0);
15271 if (bgp_static
->eth_s_id
)
15272 esi_to_str(bgp_static
->eth_s_id
,
15273 esi_buf
, sizeof(esi_buf
));
15274 p
= bgp_dest_get_prefix(dest
);
15275 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15277 /* "network" configuration display. */
15278 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
15279 if (p
->u
.prefix_evpn
.route_type
== 5) {
15280 char local_buf
[PREFIX_STRLEN
];
15281 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15282 struct prefix_evpn
*)p
)
15286 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
15287 local_buf
, PREFIX_STRLEN
);
15288 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15289 p
->u
.prefix_evpn
.prefix_addr
15290 .ip_prefix_length
);
15292 prefix2str(p
, buf
, sizeof(buf
));
15295 if (bgp_static
->gatewayIp
.family
== AF_INET
15296 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15297 inet_ntop(bgp_static
->gatewayIp
.family
,
15298 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15301 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15303 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15304 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15307 XFREE(MTYPE_TMP
, macrouter
);
15312 /* Configuration of static route announcement and aggregate
15314 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15317 struct bgp_dest
*dest
;
15318 const struct prefix
*p
;
15319 struct bgp_static
*bgp_static
;
15320 struct bgp_aggregate
*bgp_aggregate
;
15322 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15323 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15327 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15328 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15332 /* Network configuration. */
15333 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15334 dest
= bgp_route_next(dest
)) {
15335 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15336 if (bgp_static
== NULL
)
15339 p
= bgp_dest_get_prefix(dest
);
15341 vty_out(vty
, " network %pFX", p
);
15343 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15344 vty_out(vty
, " label-index %u",
15345 bgp_static
->label_index
);
15347 if (bgp_static
->rmap
.name
)
15348 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15350 if (bgp_static
->backdoor
)
15351 vty_out(vty
, " backdoor");
15353 vty_out(vty
, "\n");
15356 /* Aggregate-address configuration. */
15357 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15358 dest
= bgp_route_next(dest
)) {
15359 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15360 if (bgp_aggregate
== NULL
)
15363 p
= bgp_dest_get_prefix(dest
);
15365 vty_out(vty
, " aggregate-address %pFX", p
);
15367 if (bgp_aggregate
->as_set
)
15368 vty_out(vty
, " as-set");
15370 if (bgp_aggregate
->summary_only
)
15371 vty_out(vty
, " summary-only");
15373 if (bgp_aggregate
->rmap
.name
)
15374 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15376 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15377 vty_out(vty
, " origin %s",
15378 bgp_origin2str(bgp_aggregate
->origin
));
15380 if (bgp_aggregate
->match_med
)
15381 vty_out(vty
, " matching-MED-only");
15383 if (bgp_aggregate
->suppress_map_name
)
15384 vty_out(vty
, " suppress-map %s",
15385 bgp_aggregate
->suppress_map_name
);
15387 vty_out(vty
, "\n");
15391 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15394 struct bgp_dest
*dest
;
15395 struct bgp_distance
*bdistance
;
15397 /* Distance configuration. */
15398 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15399 && bgp
->distance_local
[afi
][safi
]
15400 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15401 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15402 || bgp
->distance_local
[afi
][safi
]
15403 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15404 vty_out(vty
, " distance bgp %d %d %d\n",
15405 bgp
->distance_ebgp
[afi
][safi
],
15406 bgp
->distance_ibgp
[afi
][safi
],
15407 bgp
->distance_local
[afi
][safi
]);
15410 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15411 dest
= bgp_route_next(dest
)) {
15412 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15413 if (bdistance
!= NULL
)
15414 vty_out(vty
, " distance %d %pBD %s\n",
15415 bdistance
->distance
, dest
,
15416 bdistance
->access_list
? bdistance
->access_list
15421 /* Allocate routing table structure and install commands. */
15422 void bgp_route_init(void)
15427 /* Init BGP distance table. */
15428 FOREACH_AFI_SAFI (afi
, safi
)
15429 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15431 /* IPv4 BGP commands. */
15432 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15433 install_element(BGP_NODE
, &bgp_network_cmd
);
15434 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15436 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15438 /* IPv4 unicast configuration. */
15439 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15440 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15441 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15443 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15445 /* IPv4 multicast configuration. */
15446 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15447 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15448 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15449 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15451 /* IPv4 labeled-unicast configuration. */
15452 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15453 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15455 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15456 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15457 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15458 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15459 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15460 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15461 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15462 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15464 install_element(VIEW_NODE
,
15465 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15466 install_element(VIEW_NODE
,
15467 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15468 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15469 install_element(VIEW_NODE
,
15470 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15471 #ifdef KEEP_OLD_VPN_COMMANDS
15472 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15473 #endif /* KEEP_OLD_VPN_COMMANDS */
15474 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15475 install_element(VIEW_NODE
,
15476 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15478 /* BGP dampening clear commands */
15479 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15480 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15482 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15483 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15486 install_element(ENABLE_NODE
,
15487 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15488 #ifdef KEEP_OLD_VPN_COMMANDS
15489 install_element(ENABLE_NODE
,
15490 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15491 #endif /* KEEP_OLD_VPN_COMMANDS */
15493 /* New config IPv6 BGP commands. */
15494 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15495 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15496 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15498 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15500 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15502 /* IPv6 labeled unicast address family. */
15503 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15504 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15506 install_element(BGP_NODE
, &bgp_distance_cmd
);
15507 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15508 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15509 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15510 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15511 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15512 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15513 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15514 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15515 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15516 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15517 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15518 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15519 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15520 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15521 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15522 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15523 install_element(BGP_IPV4M_NODE
,
15524 &no_bgp_distance_source_access_list_cmd
);
15525 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15526 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15527 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15528 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15529 install_element(BGP_IPV6_NODE
,
15530 &ipv6_bgp_distance_source_access_list_cmd
);
15531 install_element(BGP_IPV6_NODE
,
15532 &no_ipv6_bgp_distance_source_access_list_cmd
);
15533 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15534 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15535 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15536 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15537 install_element(BGP_IPV6M_NODE
,
15538 &ipv6_bgp_distance_source_access_list_cmd
);
15539 install_element(BGP_IPV6M_NODE
,
15540 &no_ipv6_bgp_distance_source_access_list_cmd
);
15542 /* BGP dampening */
15543 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15544 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15545 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15546 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15547 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15548 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15549 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15550 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15551 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15552 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15553 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15554 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15555 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15556 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15558 /* Large Communities */
15559 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15560 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15562 /* show bgp ipv4 flowspec detailed */
15563 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15565 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15566 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15569 void bgp_route_finish(void)
15574 FOREACH_AFI_SAFI (afi
, safi
) {
15575 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15576 bgp_distance_table
[afi
][safi
] = NULL
;