1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "sockunion.h"
39 #include "workqueue.h"
44 #include "lib_errors.h"
46 #include "bgpd/bgpd.h"
47 #include "bgpd/bgp_table.h"
48 #include "bgpd/bgp_route.h"
49 #include "bgpd/bgp_attr.h"
50 #include "bgpd/bgp_debug.h"
51 #include "bgpd/bgp_errors.h"
52 #include "bgpd/bgp_aspath.h"
53 #include "bgpd/bgp_regex.h"
54 #include "bgpd/bgp_community.h"
55 #include "bgpd/bgp_community_alias.h"
56 #include "bgpd/bgp_ecommunity.h"
57 #include "bgpd/bgp_lcommunity.h"
58 #include "bgpd/bgp_clist.h"
59 #include "bgpd/bgp_packet.h"
60 #include "bgpd/bgp_filter.h"
61 #include "bgpd/bgp_fsm.h"
62 #include "bgpd/bgp_mplsvpn.h"
63 #include "bgpd/bgp_nexthop.h"
64 #include "bgpd/bgp_damp.h"
65 #include "bgpd/bgp_advertise.h"
66 #include "bgpd/bgp_zebra.h"
67 #include "bgpd/bgp_vty.h"
68 #include "bgpd/bgp_mpath.h"
69 #include "bgpd/bgp_nht.h"
70 #include "bgpd/bgp_updgrp.h"
71 #include "bgpd/bgp_label.h"
72 #include "bgpd/bgp_addpath.h"
73 #include "bgpd/bgp_mac.h"
74 #include "bgpd/bgp_network.h"
75 #include "bgpd/bgp_orr.h"
76 #include "bgpd/bgp_trace.h"
77 #include "bgpd/bgp_rpki.h"
80 #include "bgpd/rfapi/rfapi_backend.h"
81 #include "bgpd/rfapi/vnc_import_bgp.h"
82 #include "bgpd/rfapi/vnc_export_bgp.h"
84 #include "bgpd/bgp_encap_types.h"
85 #include "bgpd/bgp_encap_tlv.h"
86 #include "bgpd/bgp_evpn.h"
87 #include "bgpd/bgp_evpn_mh.h"
88 #include "bgpd/bgp_evpn_vty.h"
89 #include "bgpd/bgp_flowspec.h"
90 #include "bgpd/bgp_flowspec_util.h"
91 #include "bgpd/bgp_pbr.h"
93 #include "bgpd/bgp_route_clippy.c"
95 DEFINE_HOOK(bgp_snmp_update_stats
,
96 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
99 DEFINE_HOOK(bgp_rpki_prefix_status
,
100 (struct peer
*peer
, struct attr
*attr
,
101 const struct prefix
*prefix
),
102 (peer
, attr
, prefix
));
104 /* Extern from bgp_dump.c */
105 extern const char *bgp_origin_str
[];
106 extern const char *bgp_origin_long_str
[];
109 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
110 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
111 static const struct message bgp_pmsi_tnltype_str
[] = {
112 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
113 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
114 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
115 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
116 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
117 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
118 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
119 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
123 #define VRFID_NONE_STR "-"
124 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
126 DEFINE_HOOK(bgp_process
,
127 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
128 struct peer
*peer
, bool withdraw
),
129 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
131 /** Test if path is suppressed. */
132 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
134 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
137 return listcount(pi
->extra
->aggr_suppressors
) > 0;
140 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
141 safi_t safi
, const struct prefix
*p
,
142 struct prefix_rd
*prd
)
144 struct bgp_dest
*dest
;
145 struct bgp_dest
*pdest
= NULL
;
149 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
150 || (safi
== SAFI_EVPN
)) {
151 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
153 if (!bgp_dest_has_bgp_path_info_data(pdest
))
154 bgp_dest_set_bgp_table_info(
155 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
157 bgp_dest_unlock_node(pdest
);
158 table
= bgp_dest_get_bgp_table_info(pdest
);
161 dest
= bgp_node_get(table
, p
);
163 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
164 || (safi
== SAFI_EVPN
))
170 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
171 safi_t safi
, const struct prefix
*p
,
172 struct prefix_rd
*prd
)
174 struct bgp_dest
*dest
;
175 struct bgp_dest
*pdest
= NULL
;
180 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
181 || (safi
== SAFI_EVPN
)) {
182 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
186 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
187 bgp_dest_unlock_node(pdest
);
191 table
= bgp_dest_get_bgp_table_info(pdest
);
194 dest
= bgp_node_lookup(table
, p
);
199 /* Allocate bgp_path_info_extra */
200 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
202 struct bgp_path_info_extra
*new;
203 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
204 sizeof(struct bgp_path_info_extra
));
205 new->label
[0] = MPLS_INVALID_LABEL
;
207 new->bgp_fs_pbr
= NULL
;
208 new->bgp_fs_iprule
= NULL
;
212 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
214 struct bgp_path_info_extra
*e
;
216 if (!extra
|| !*extra
)
221 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
226 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
229 /* FIXME: since multiple e may have the same e->parent
230 * and e->parent->net is holding a refcount for each
231 * of them, we need to do some fudging here.
233 * WARNING: if bpi->net->lock drops to 0, bpi may be
234 * freed as well (because bpi->net was holding the
235 * last reference to bpi) => write after free!
239 bpi
= bgp_path_info_lock(bpi
);
240 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
241 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
244 bgp_path_info_unlock(bpi
);
246 bgp_path_info_unlock(e
->parent
);
251 bgp_unlock(e
->bgp_orig
);
254 peer_unlock(e
->peer_orig
);
256 if (e
->aggr_suppressors
)
257 list_delete(&e
->aggr_suppressors
);
260 bgp_evpn_path_mh_info_free(e
->mh_info
);
262 if ((*extra
)->bgp_fs_iprule
)
263 list_delete(&((*extra
)->bgp_fs_iprule
));
264 if ((*extra
)->bgp_fs_pbr
)
265 list_delete(&((*extra
)->bgp_fs_pbr
));
266 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
269 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
270 * allocated if required.
272 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
275 pi
->extra
= bgp_path_info_extra_new();
279 /* Free bgp route information. */
280 void bgp_path_info_free_with_caller(const char *name
,
281 struct bgp_path_info
*path
)
283 frrtrace(2, frr_bgp
, bgp_path_info_free
, path
, name
);
284 bgp_attr_unintern(&path
->attr
);
286 bgp_unlink_nexthop(path
);
287 bgp_path_info_extra_free(&path
->extra
);
288 bgp_path_info_mpath_free(&path
->mpath
);
290 bgp_addpath_free_info_data(&path
->tx_addpath
,
291 &path
->net
->tx_addpath
);
293 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
295 XFREE(MTYPE_BGP_ROUTE
, path
);
298 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
304 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
306 assert(path
&& path
->lock
> 0);
309 if (path
->lock
== 0) {
310 bgp_path_info_free(path
);
317 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
318 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
321 struct bgp_path_info
*old_pi
, *nextpi
;
322 bool set_flag
= false;
323 struct bgp
*bgp
= NULL
;
324 struct bgp_table
*table
= NULL
;
328 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
329 * then the route selection is deferred
331 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
334 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
335 if (BGP_DEBUG(update
, UPDATE_OUT
))
337 "Route %pBD is in workqueue and being processed, not deferred.",
343 table
= bgp_dest_table(dest
);
350 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
351 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
352 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
355 /* Route selection is deferred if there is a stale path which
356 * which indicates peer is in restart mode
358 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
359 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
362 /* If the peer is graceful restart capable and peer is
363 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
366 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
367 && BGP_PEER_RESTARTING_MODE(peer
)
369 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
377 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
380 if (set_flag
&& table
) {
381 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
382 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
383 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
384 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
385 if (BGP_DEBUG(update
, UPDATE_OUT
))
386 zlog_debug("DEFER route %pBD, dest %p", dest
,
394 void bgp_path_info_add_with_caller(const char *name
, struct bgp_dest
*dest
,
395 struct bgp_path_info
*pi
)
397 frrtrace(3, frr_bgp
, bgp_path_info_add
, dest
, pi
, name
);
398 struct bgp_path_info
*top
;
400 top
= bgp_dest_get_bgp_path_info(dest
);
406 bgp_dest_set_bgp_path_info(dest
, pi
);
408 bgp_path_info_lock(pi
);
409 bgp_dest_lock_node(dest
);
410 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
411 bgp_dest_set_defer_flag(dest
, false);
412 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
415 /* Do the actual removal of info from RIB, for use by bgp_process
416 completion callback *only* */
417 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
420 pi
->next
->prev
= pi
->prev
;
422 pi
->prev
->next
= pi
->next
;
424 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
426 bgp_path_info_mpath_dequeue(pi
);
427 bgp_path_info_unlock(pi
);
428 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
429 bgp_dest_unlock_node(dest
);
432 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
434 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
435 /* set of previous already took care of pcount */
436 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
439 /* undo the effects of a previous call to bgp_path_info_delete; typically
440 called when a route is deleted and then quickly re-added before the
441 deletion has been processed */
442 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
444 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
445 /* unset of previous already took care of pcount */
446 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
449 /* Adjust pcount as required */
450 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
452 struct bgp_table
*table
;
454 assert(dest
&& bgp_dest_table(dest
));
455 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
457 table
= bgp_dest_table(dest
);
459 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
462 if (!BGP_PATH_COUNTABLE(pi
)
463 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
465 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
467 /* slight hack, but more robust against errors. */
468 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
469 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
471 flog_err(EC_LIB_DEVELOPMENT
,
472 "Asked to decrement 0 prefix count for peer");
473 } else if (BGP_PATH_COUNTABLE(pi
)
474 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
475 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
476 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
480 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
481 struct bgp_path_info
*pi2
)
483 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
486 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
487 * This is here primarily to keep prefix-count in check.
489 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
492 SET_FLAG(pi
->flags
, flag
);
494 /* early bath if we know it's not a flag that changes countability state
496 if (!CHECK_FLAG(flag
,
497 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
500 bgp_pcount_adjust(dest
, pi
);
503 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
506 UNSET_FLAG(pi
->flags
, flag
);
508 /* early bath if we know it's not a flag that changes countability state
510 if (!CHECK_FLAG(flag
,
511 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
514 bgp_pcount_adjust(dest
, pi
);
517 /* Get MED value. If MED value is missing and "bgp bestpath
518 missing-as-worst" is specified, treat it as the worst value. */
519 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
521 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
524 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
531 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
534 if (pi
->addpath_rx_id
)
535 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
536 pi
->peer
->host
, pi
->addpath_rx_id
);
538 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
543 * Get the ultimate path info.
545 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
547 struct bgp_path_info
*bpi_ultimate
;
549 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
552 for (bpi_ultimate
= info
;
553 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
554 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
560 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
562 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
563 struct bgp_path_info
*exist
, int *paths_eq
,
564 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
565 char *pfx_buf
, afi_t afi
, safi_t safi
,
566 enum bgp_path_selection_reason
*reason
)
568 const struct prefix
*new_p
;
569 struct prefix exist_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
;
602 struct bgp_orr_group
*orr_group
= NULL
;
603 struct listnode
*node
;
604 struct bgp_orr_igp_metric
*igp_metric
= NULL
;
605 struct list
*orr_group_igp_metric_info
= NULL
;
611 *reason
= bgp_path_selection_none
;
613 zlog_debug("%s: new is NULL", pfx_buf
);
618 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
619 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
624 *reason
= bgp_path_selection_first
;
626 zlog_debug("%s(%s): %s is the initial bestpath",
627 pfx_buf
, bgp
->name_pretty
, new_buf
);
632 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
633 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
635 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
636 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
637 exist_buf
, exist
->flags
);
641 existattr
= exist
->attr
;
643 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
644 * Capability" to a neighbor MUST perform the following upon receiving
645 * a route from that neighbor with the "LLGR_STALE" community, or upon
646 * attaching the "LLGR_STALE" community itself per Section 4.2:
648 * Treat the route as the least-preferred in route selection (see
649 * below). See the Risks of Depreferencing Routes section (Section 5.2)
650 * for a discussion of potential risks inherent in doing this.
652 if (bgp_attr_get_community(newattr
) &&
653 community_include(bgp_attr_get_community(newattr
),
654 COMMUNITY_LLGR_STALE
)) {
657 "%s: %s wins over %s due to LLGR_STALE community",
658 pfx_buf
, new_buf
, exist_buf
);
662 if (bgp_attr_get_community(existattr
) &&
663 community_include(bgp_attr_get_community(existattr
),
664 COMMUNITY_LLGR_STALE
)) {
667 "%s: %s loses to %s due to LLGR_STALE community",
668 pfx_buf
, new_buf
, exist_buf
);
672 new_p
= bgp_dest_get_prefix(new->net
);
674 /* For EVPN routes, we cannot just go by local vs remote, we have to
675 * look at the MAC mobility sequence number, if present.
677 if ((safi
== SAFI_EVPN
)
678 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
679 /* This is an error condition described in RFC 7432 Section
681 * states that in this scenario "the PE MUST alert the operator"
683 * does not state what other action to take. In order to provide
685 * consistency in this scenario we are going to prefer the path
689 if (newattr
->sticky
!= existattr
->sticky
) {
691 prefix2str(new_p
, pfx_buf
,
693 * PREFIX2STR_BUFFER
);
694 bgp_path_info_path_with_addpath_rx_str(
695 new, new_buf
, sizeof(new_buf
));
696 bgp_path_info_path_with_addpath_rx_str(
697 exist
, exist_buf
, sizeof(exist_buf
));
700 if (newattr
->sticky
&& !existattr
->sticky
) {
701 *reason
= bgp_path_selection_evpn_sticky_mac
;
704 "%s: %s wins over %s due to sticky MAC flag",
705 pfx_buf
, new_buf
, exist_buf
);
709 if (!newattr
->sticky
&& existattr
->sticky
) {
710 *reason
= bgp_path_selection_evpn_sticky_mac
;
713 "%s: %s loses to %s due to sticky MAC flag",
714 pfx_buf
, new_buf
, exist_buf
);
719 new_esi
= bgp_evpn_attr_get_esi(newattr
);
720 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
721 if (bgp_evpn_is_esi_valid(new_esi
) &&
722 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
728 /* If both paths have the same non-zero ES and
729 * one path is local it wins.
730 * PS: Note the local path wins even if the remote
731 * has the higher MM seq. The local path's
732 * MM seq will be fixed up to match the highest
733 * rem seq, subsequently.
736 char esi_buf
[ESI_STR_LEN
];
738 if (bgp_evpn_is_path_local(bgp
, new)) {
739 *reason
= bgp_path_selection_evpn_local_path
;
742 "%s: %s wins over %s as ES %s is same and local",
743 pfx_buf
, new_buf
, exist_buf
,
744 esi_to_str(new_esi
, esi_buf
,
748 if (bgp_evpn_is_path_local(bgp
, exist
)) {
749 *reason
= bgp_path_selection_evpn_local_path
;
752 "%s: %s loses to %s as ES %s is same and local",
753 pfx_buf
, new_buf
, exist_buf
,
754 esi_to_str(new_esi
, esi_buf
,
760 new_mm_seq
= mac_mobility_seqnum(newattr
);
761 exist_mm_seq
= mac_mobility_seqnum(existattr
);
763 if (new_mm_seq
> exist_mm_seq
) {
764 *reason
= bgp_path_selection_evpn_seq
;
767 "%s: %s wins over %s due to MM seq %u > %u",
768 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
773 if (new_mm_seq
< exist_mm_seq
) {
774 *reason
= bgp_path_selection_evpn_seq
;
777 "%s: %s loses to %s due to MM seq %u < %u",
778 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
783 /* if the sequence numbers and ESI are the same and one path
784 * is non-proxy it wins (over proxy)
786 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
787 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
788 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
789 old_proxy
!= new_proxy
) {
791 *reason
= bgp_path_selection_evpn_non_proxy
;
794 "%s: %s wins over %s, same seq/es and non-proxy",
795 pfx_buf
, new_buf
, exist_buf
);
799 *reason
= bgp_path_selection_evpn_non_proxy
;
802 "%s: %s loses to %s, same seq/es and non-proxy",
803 pfx_buf
, new_buf
, exist_buf
);
808 * if sequence numbers are the same path with the lowest IP
811 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
813 *reason
= bgp_path_selection_evpn_lower_ip
;
816 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
817 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
818 &new->attr
->nexthop
);
822 *reason
= bgp_path_selection_evpn_lower_ip
;
825 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
826 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
827 &new->attr
->nexthop
);
832 /* 1. Weight check. */
833 new_weight
= newattr
->weight
;
834 exist_weight
= existattr
->weight
;
836 if (new_weight
> exist_weight
) {
837 *reason
= bgp_path_selection_weight
;
839 zlog_debug("%s: %s wins over %s due to weight %d > %d",
840 pfx_buf
, new_buf
, exist_buf
, new_weight
,
845 if (new_weight
< exist_weight
) {
846 *reason
= bgp_path_selection_weight
;
848 zlog_debug("%s: %s loses to %s due to weight %d < %d",
849 pfx_buf
, new_buf
, exist_buf
, new_weight
,
854 /* 2. Local preference check. */
855 new_pref
= exist_pref
= bgp
->default_local_pref
;
857 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
858 new_pref
= newattr
->local_pref
;
859 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
860 exist_pref
= existattr
->local_pref
;
862 if (new_pref
> exist_pref
) {
863 *reason
= bgp_path_selection_local_pref
;
866 "%s: %s wins over %s due to localpref %d > %d",
867 pfx_buf
, new_buf
, exist_buf
, new_pref
,
872 if (new_pref
< exist_pref
) {
873 *reason
= bgp_path_selection_local_pref
;
876 "%s: %s loses to %s due to localpref %d < %d",
877 pfx_buf
, new_buf
, exist_buf
, new_pref
,
882 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
883 * extensions defined in this document, the following step is inserted
884 * after the LOCAL_PREF comparison step in the BGP decision process:
885 * When comparing a pair of routes for a BGP destination, the
886 * route with the ACCEPT_OWN community attached is preferred over
887 * the route that does not have the community.
888 * This extra step MUST only be invoked during the best path selection
889 * process of VPN-IP routes.
891 if (safi
== SAFI_MPLS_VPN
&&
892 (CHECK_FLAG(new->peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
) ||
893 CHECK_FLAG(exist
->peer
->af_flags
[afi
][safi
],
894 PEER_FLAG_ACCEPT_OWN
))) {
895 bool new_accept_own
= false;
896 bool exist_accept_own
= false;
897 uint32_t accept_own
= COMMUNITY_ACCEPT_OWN
;
899 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
900 new_accept_own
= community_include(
901 bgp_attr_get_community(newattr
), accept_own
);
902 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
903 exist_accept_own
= community_include(
904 bgp_attr_get_community(existattr
), accept_own
);
906 if (new_accept_own
&& !exist_accept_own
) {
907 *reason
= bgp_path_selection_accept_own
;
910 "%s: %s wins over %s due to accept-own",
911 pfx_buf
, new_buf
, exist_buf
);
915 if (!new_accept_own
&& exist_accept_own
) {
916 *reason
= bgp_path_selection_accept_own
;
919 "%s: %s loses to %s due to accept-own",
920 pfx_buf
, new_buf
, exist_buf
);
925 /* Tie-breaker - AIGP (Metric TLV) attribute */
926 if (CHECK_FLAG(newattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
927 CHECK_FLAG(existattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
928 CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_AIGP
)) {
929 uint64_t new_aigp
= bgp_attr_get_aigp_metric(newattr
);
930 uint64_t exist_aigp
= bgp_attr_get_aigp_metric(existattr
);
932 if (new_aigp
< exist_aigp
) {
933 *reason
= bgp_path_selection_aigp
;
936 "%s: %s wins over %s due to AIGP %" PRIu64
938 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
943 if (new_aigp
> exist_aigp
) {
944 *reason
= bgp_path_selection_aigp
;
947 "%s: %s loses to %s due to AIGP %" PRIu64
949 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
955 /* 3. Local route check. We prefer:
957 * - BGP_ROUTE_AGGREGATE
958 * - BGP_ROUTE_REDISTRIBUTE
960 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
961 new->sub_type
== BGP_ROUTE_IMPORTED
);
962 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
963 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
965 if (new_origin
&& !exist_origin
) {
966 *reason
= bgp_path_selection_local_route
;
969 "%s: %s wins over %s due to preferred BGP_ROUTE type",
970 pfx_buf
, new_buf
, exist_buf
);
974 if (!new_origin
&& exist_origin
) {
975 *reason
= bgp_path_selection_local_route
;
978 "%s: %s loses to %s due to preferred BGP_ROUTE type",
979 pfx_buf
, new_buf
, exist_buf
);
983 /* Here if these are imported routes then get ultimate pi for
986 new = bgp_get_imported_bpi_ultimate(new);
987 exist
= bgp_get_imported_bpi_ultimate(exist
);
989 existattr
= exist
->attr
;
991 /* 4. AS path length check. */
992 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
993 int exist_hops
= aspath_count_hops(existattr
->aspath
);
994 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
996 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
999 aspath_hops
= aspath_count_hops(newattr
->aspath
);
1000 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
1002 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
1003 *reason
= bgp_path_selection_confed_as_path
;
1006 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
1007 pfx_buf
, new_buf
, exist_buf
,
1009 (exist_hops
+ exist_confeds
));
1013 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
1014 *reason
= bgp_path_selection_confed_as_path
;
1017 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1018 pfx_buf
, new_buf
, exist_buf
,
1020 (exist_hops
+ exist_confeds
));
1024 int newhops
= aspath_count_hops(newattr
->aspath
);
1026 if (newhops
< exist_hops
) {
1027 *reason
= bgp_path_selection_as_path
;
1030 "%s: %s wins over %s due to aspath hopcount %d < %d",
1031 pfx_buf
, new_buf
, exist_buf
,
1032 newhops
, exist_hops
);
1036 if (newhops
> exist_hops
) {
1037 *reason
= bgp_path_selection_as_path
;
1040 "%s: %s loses to %s due to aspath hopcount %d > %d",
1041 pfx_buf
, new_buf
, exist_buf
,
1042 newhops
, exist_hops
);
1048 /* 5. Origin check. */
1049 if (newattr
->origin
< existattr
->origin
) {
1050 *reason
= bgp_path_selection_origin
;
1052 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1053 pfx_buf
, new_buf
, exist_buf
,
1054 bgp_origin_long_str
[newattr
->origin
],
1055 bgp_origin_long_str
[existattr
->origin
]);
1059 if (newattr
->origin
> existattr
->origin
) {
1060 *reason
= bgp_path_selection_origin
;
1062 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1063 pfx_buf
, new_buf
, exist_buf
,
1064 bgp_origin_long_str
[newattr
->origin
],
1065 bgp_origin_long_str
[existattr
->origin
]);
1070 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
1071 && aspath_count_hops(existattr
->aspath
) == 0);
1072 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
1073 && aspath_count_confeds(existattr
->aspath
) > 0
1074 && aspath_count_hops(newattr
->aspath
) == 0
1075 && aspath_count_hops(existattr
->aspath
) == 0);
1077 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1078 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1079 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1080 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1081 || internal_as_route
) {
1082 new_med
= bgp_med_value(new->attr
, bgp
);
1083 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1085 if (new_med
< exist_med
) {
1086 *reason
= bgp_path_selection_med
;
1089 "%s: %s wins over %s due to MED %d < %d",
1090 pfx_buf
, new_buf
, exist_buf
, new_med
,
1095 if (new_med
> exist_med
) {
1096 *reason
= bgp_path_selection_med
;
1099 "%s: %s loses to %s due to MED %d > %d",
1100 pfx_buf
, new_buf
, exist_buf
, new_med
,
1106 /* 7. Peer type check. */
1107 new_sort
= new->peer
->sort
;
1108 exist_sort
= exist
->peer
->sort
;
1110 if (new_sort
== BGP_PEER_EBGP
1111 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1112 *reason
= bgp_path_selection_peer
;
1115 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1116 pfx_buf
, new_buf
, exist_buf
);
1117 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1122 if (exist_sort
== BGP_PEER_EBGP
1123 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1124 *reason
= bgp_path_selection_peer
;
1127 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1128 pfx_buf
, new_buf
, exist_buf
);
1129 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1134 /* 8. IGP metric check. */
1138 newm
= new->extra
->igpmetric
;
1140 existm
= exist
->extra
->igpmetric
;
1142 if (new->peer
->orr_group_name
[afi
][safi
]) {
1143 ret
= str2prefix(new->peer
->host
, &exist_p
);
1144 orr_group
= bgp_orr_group_lookup_by_name(
1145 bgp
, afi
, safi
, new->peer
->orr_group_name
[afi
][safi
]);
1147 orr_group_igp_metric_info
= orr_group
->igp_metric_info
;
1148 if (orr_group_igp_metric_info
) {
1149 for (ALL_LIST_ELEMENTS_RO(
1150 orr_group_igp_metric_info
, node
,
1153 prefix_cmp(&exist_p
,
1154 &igp_metric
->prefix
) ==
1156 newm
= igp_metric
->igp_metric
;
1163 if (exist
->peer
->orr_group_name
[afi
][safi
]) {
1164 ret
= str2prefix(exist
->peer
->host
, &exist_p
);
1165 orr_group
= bgp_orr_group_lookup_by_name(
1166 bgp
, afi
, safi
, exist
->peer
->orr_group_name
[afi
][safi
]);
1168 orr_group_igp_metric_info
= orr_group
->igp_metric_info
;
1169 if (orr_group_igp_metric_info
) {
1170 for (ALL_LIST_ELEMENTS_RO(
1171 orr_group_igp_metric_info
, node
,
1174 prefix_cmp(&exist_p
,
1175 &igp_metric
->prefix
) ==
1177 existm
= igp_metric
->igp_metric
;
1185 if (newm
< existm
) {
1186 if (debug
&& peer_sort_ret
< 0)
1188 "%s: %s wins over %s due to IGP metric %u < %u",
1189 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1193 if (newm
> existm
) {
1194 if (debug
&& peer_sort_ret
< 0)
1196 "%s: %s loses to %s due to IGP metric %u > %u",
1197 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1201 /* 9. Same IGP metric. Compare the cluster list length as
1202 representative of IGP hops metric. Rewrite the metric value
1203 pair (newm, existm) with the cluster list length. Prefer the
1204 path with smaller cluster list length. */
1205 if (newm
== existm
) {
1206 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
&&
1207 peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
&&
1208 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1209 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1210 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1212 if (newm
< existm
) {
1213 if (debug
&& peer_sort_ret
< 0)
1215 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1216 pfx_buf
, new_buf
, exist_buf
,
1221 if (newm
> existm
) {
1222 if (debug
&& peer_sort_ret
< 0)
1224 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1225 pfx_buf
, new_buf
, exist_buf
,
1232 /* 10. confed-external vs. confed-internal */
1233 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1234 if (new_sort
== BGP_PEER_CONFED
1235 && exist_sort
== BGP_PEER_IBGP
) {
1236 *reason
= bgp_path_selection_confed
;
1239 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1240 pfx_buf
, new_buf
, exist_buf
);
1241 if (!CHECK_FLAG(bgp
->flags
,
1242 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1247 if (exist_sort
== BGP_PEER_CONFED
1248 && new_sort
== BGP_PEER_IBGP
) {
1249 *reason
= bgp_path_selection_confed
;
1252 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1253 pfx_buf
, new_buf
, exist_buf
);
1254 if (!CHECK_FLAG(bgp
->flags
,
1255 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1261 /* 11. Maximum path check. */
1262 if (newm
== existm
) {
1263 /* If one path has a label but the other does not, do not treat
1264 * them as equals for multipath
1266 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1268 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1271 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1272 pfx_buf
, new_buf
, exist_buf
);
1273 } else if (CHECK_FLAG(bgp
->flags
,
1274 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1277 * For the two paths, all comparison steps till IGP
1279 * have succeeded - including AS_PATH hop count. Since
1281 * bestpath as-path multipath-relax' knob is on, we
1283 * an exact match of AS_PATH. Thus, mark the paths are
1285 * That will trigger both these paths to get into the
1293 "%s: %s and %s are equal via multipath-relax",
1294 pfx_buf
, new_buf
, exist_buf
);
1295 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1296 if (aspath_cmp(new->attr
->aspath
,
1297 exist
->attr
->aspath
)) {
1302 "%s: %s and %s are equal via matching aspaths",
1303 pfx_buf
, new_buf
, exist_buf
);
1305 } else if (new->peer
->as
== exist
->peer
->as
) {
1310 "%s: %s and %s are equal via same remote-as",
1311 pfx_buf
, new_buf
, exist_buf
);
1315 * TODO: If unequal cost ibgp multipath is enabled we can
1316 * mark the paths as equal here instead of returning
1319 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1320 * if either step 7 or 10 (peer type checks) yielded a winner,
1321 * that result was returned immediately. Returning from step 10
1322 * ignored the return value computed in steps 8 and 9 (IGP
1323 * metric checks). In order to preserve that behavior, if
1324 * peer_sort_ret is set, return that rather than igp_metric_ret.
1326 ret
= peer_sort_ret
;
1327 if (peer_sort_ret
< 0) {
1328 ret
= igp_metric_ret
;
1332 "%s: %s wins over %s after IGP metric comparison",
1333 pfx_buf
, new_buf
, exist_buf
);
1336 "%s: %s loses to %s after IGP metric comparison",
1337 pfx_buf
, new_buf
, exist_buf
);
1339 *reason
= bgp_path_selection_igp_metric
;
1345 * At this point, the decision whether to set *paths_eq = 1 has been
1346 * completed. If we deferred returning because of bestpath peer-type
1347 * relax configuration, return now.
1349 if (peer_sort_ret
>= 0)
1350 return peer_sort_ret
;
1352 /* 12. If both paths are external, prefer the path that was received
1353 first (the oldest one). This step minimizes route-flap, since a
1354 newer path won't displace an older one, even if it was the
1355 preferred route based on the additional decision criteria below. */
1356 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1357 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1358 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1359 *reason
= bgp_path_selection_older
;
1362 "%s: %s wins over %s due to oldest external",
1363 pfx_buf
, new_buf
, exist_buf
);
1367 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1368 *reason
= bgp_path_selection_older
;
1371 "%s: %s loses to %s due to oldest external",
1372 pfx_buf
, new_buf
, exist_buf
);
1377 /* 13. Router-ID comparison. */
1378 /* If one of the paths is "stale", the corresponding peer router-id will
1379 * be 0 and would always win over the other path. If originator id is
1380 * used for the comparison, it will decide which path is better.
1382 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1383 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1385 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1386 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1387 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1389 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1391 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1392 *reason
= bgp_path_selection_router_id
;
1395 "%s: %s wins over %s due to Router-ID comparison",
1396 pfx_buf
, new_buf
, exist_buf
);
1400 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1401 *reason
= bgp_path_selection_router_id
;
1404 "%s: %s loses to %s due to Router-ID comparison",
1405 pfx_buf
, new_buf
, exist_buf
);
1409 /* 14. Cluster length comparison. */
1410 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1411 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1413 if (new_cluster
< exist_cluster
) {
1414 *reason
= bgp_path_selection_cluster_length
;
1417 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1418 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1423 if (new_cluster
> exist_cluster
) {
1424 *reason
= bgp_path_selection_cluster_length
;
1427 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1428 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1433 /* 15. Neighbor address comparison. */
1434 /* Do this only if neither path is "stale" as stale paths do not have
1435 * valid peer information (as the connection may or may not be up).
1437 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1438 *reason
= bgp_path_selection_stale
;
1441 "%s: %s wins over %s due to latter path being STALE",
1442 pfx_buf
, new_buf
, exist_buf
);
1446 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1447 *reason
= bgp_path_selection_stale
;
1450 "%s: %s loses to %s due to former path being STALE",
1451 pfx_buf
, new_buf
, exist_buf
);
1455 /* locally configured routes to advertise do not have su_remote */
1456 if (new->peer
->su_remote
== NULL
) {
1457 *reason
= bgp_path_selection_local_configured
;
1460 if (exist
->peer
->su_remote
== NULL
) {
1461 *reason
= bgp_path_selection_local_configured
;
1465 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1468 *reason
= bgp_path_selection_neighbor_ip
;
1471 "%s: %s loses to %s due to Neighor IP comparison",
1472 pfx_buf
, new_buf
, exist_buf
);
1477 *reason
= bgp_path_selection_neighbor_ip
;
1480 "%s: %s wins over %s due to Neighor IP comparison",
1481 pfx_buf
, new_buf
, exist_buf
);
1485 *reason
= bgp_path_selection_default
;
1487 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1488 pfx_buf
, new_buf
, exist_buf
);
1494 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1495 struct bgp_path_info
*exist
, int *paths_eq
)
1497 enum bgp_path_selection_reason reason
;
1498 char pfx_buf
[PREFIX2STR_BUFFER
];
1500 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1501 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1504 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1505 * is preferred, or 0 if they are the same (usually will only occur if
1506 * multipath is enabled
1507 * This version is compatible with */
1508 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1509 struct bgp_path_info
*exist
, char *pfx_buf
,
1510 afi_t afi
, safi_t safi
,
1511 enum bgp_path_selection_reason
*reason
)
1515 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1529 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1530 const struct prefix
*p
,
1531 struct attr
*attr
, afi_t afi
,
1534 struct bgp_filter
*filter
;
1535 enum filter_type ret
= FILTER_PERMIT
;
1537 filter
= &peer
->filter
[afi
][safi
];
1539 #define FILTER_EXIST_WARN(F, f, filter) \
1540 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1541 zlog_debug("%s: Could not find configured input %s-list %s!", \
1542 peer->host, #f, F##_IN_NAME(filter));
1544 if (DISTRIBUTE_IN_NAME(filter
)) {
1545 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1547 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1554 if (PREFIX_LIST_IN_NAME(filter
)) {
1555 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1557 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1564 if (FILTER_LIST_IN_NAME(filter
)) {
1565 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1567 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1568 == AS_FILTER_DENY
) {
1575 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1576 char pfxprint
[PREFIX2STR_BUFFER
];
1578 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1579 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1580 ret
== FILTER_PERMIT
? "permit" : "deny");
1584 #undef FILTER_EXIST_WARN
1587 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1588 const struct prefix
*p
,
1589 struct attr
*attr
, afi_t afi
,
1592 struct bgp_filter
*filter
;
1593 enum filter_type ret
= FILTER_PERMIT
;
1595 filter
= &peer
->filter
[afi
][safi
];
1597 #define FILTER_EXIST_WARN(F, f, filter) \
1598 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1599 zlog_debug("%s: Could not find configured output %s-list %s!", \
1600 peer->host, #f, F##_OUT_NAME(filter));
1602 if (DISTRIBUTE_OUT_NAME(filter
)) {
1603 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1605 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1612 if (PREFIX_LIST_OUT_NAME(filter
)) {
1613 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1615 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1622 if (FILTER_LIST_OUT_NAME(filter
)) {
1623 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1625 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1626 == AS_FILTER_DENY
) {
1632 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1633 char pfxprint
[PREFIX2STR_BUFFER
];
1635 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1636 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1637 ret
== FILTER_PERMIT
? "permit" : "deny");
1642 #undef FILTER_EXIST_WARN
1645 /* If community attribute includes no_export then return 1. */
1646 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1648 if (bgp_attr_get_community(attr
)) {
1649 /* NO_ADVERTISE check. */
1650 if (community_include(bgp_attr_get_community(attr
),
1651 COMMUNITY_NO_ADVERTISE
))
1654 /* NO_EXPORT check. */
1655 if (peer
->sort
== BGP_PEER_EBGP
&&
1656 community_include(bgp_attr_get_community(attr
),
1657 COMMUNITY_NO_EXPORT
))
1660 /* NO_EXPORT_SUBCONFED check. */
1661 if (peer
->sort
== BGP_PEER_EBGP
1662 || peer
->sort
== BGP_PEER_CONFED
)
1663 if (community_include(bgp_attr_get_community(attr
),
1664 COMMUNITY_NO_EXPORT_SUBCONFED
))
1670 /* Route reflection loop check. */
1671 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1673 struct in_addr cluster_id
;
1674 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1677 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1678 cluster_id
= peer
->bgp
->cluster_id
;
1680 cluster_id
= peer
->bgp
->router_id
;
1682 if (cluster_loop_check(cluster
, cluster_id
))
1688 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1690 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1691 if (peer
->local_role
== ROLE_PROVIDER
||
1692 peer
->local_role
== ROLE_RS_SERVER
)
1694 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1698 if (peer
->local_role
== ROLE_CUSTOMER
||
1699 peer
->local_role
== ROLE_PEER
||
1700 peer
->local_role
== ROLE_RS_CLIENT
) {
1701 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1702 attr
->otc
= peer
->as
;
1707 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1709 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1710 if (peer
->local_role
== ROLE_CUSTOMER
||
1711 peer
->local_role
== ROLE_RS_CLIENT
||
1712 peer
->local_role
== ROLE_PEER
)
1716 if (peer
->local_role
== ROLE_PROVIDER
||
1717 peer
->local_role
== ROLE_PEER
||
1718 peer
->local_role
== ROLE_RS_SERVER
) {
1719 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1720 attr
->otc
= peer
->bgp
->as
;
1725 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1727 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1730 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1731 struct attr
*attr
, afi_t afi
, safi_t safi
,
1732 const char *rmap_name
, mpls_label_t
*label
,
1733 uint32_t num_labels
, struct bgp_dest
*dest
)
1735 struct bgp_filter
*filter
;
1736 struct bgp_path_info rmap_path
= { 0 };
1737 struct bgp_path_info_extra extra
= { 0 };
1738 route_map_result_t ret
;
1739 struct route_map
*rmap
= NULL
;
1741 filter
= &peer
->filter
[afi
][safi
];
1743 /* Apply default weight value. */
1744 if (peer
->weight
[afi
][safi
])
1745 attr
->weight
= peer
->weight
[afi
][safi
];
1748 rmap
= route_map_lookup_by_name(rmap_name
);
1753 if (ROUTE_MAP_IN_NAME(filter
)) {
1754 rmap
= ROUTE_MAP_IN(filter
);
1761 /* Route map apply. */
1763 memset(&rmap_path
, 0, sizeof(rmap_path
));
1764 /* Duplicate current value to new structure for modification. */
1765 rmap_path
.peer
= peer
;
1766 rmap_path
.attr
= attr
;
1767 rmap_path
.extra
= &extra
;
1768 rmap_path
.net
= dest
;
1770 extra
.num_labels
= num_labels
;
1771 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1772 memcpy(extra
.label
, label
,
1773 num_labels
* sizeof(mpls_label_t
));
1775 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1777 /* Apply BGP route map to the attribute. */
1778 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1780 peer
->rmap_type
= 0;
1782 if (ret
== RMAP_DENYMATCH
)
1788 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1789 struct attr
*attr
, afi_t afi
, safi_t safi
,
1790 const char *rmap_name
)
1792 struct bgp_path_info rmap_path
;
1793 route_map_result_t ret
;
1794 struct route_map
*rmap
= NULL
;
1798 * So if we get to this point and have no rmap_name
1799 * we want to just show the output as it currently
1805 /* Apply default weight value. */
1806 if (peer
->weight
[afi
][safi
])
1807 attr
->weight
= peer
->weight
[afi
][safi
];
1809 rmap
= route_map_lookup_by_name(rmap_name
);
1812 * If we have a route map name and we do not find
1813 * the routemap that means we have an implicit
1819 memset(&rmap_path
, 0, sizeof(rmap_path
));
1820 /* Route map apply. */
1821 /* Duplicate current value to new structure for modification. */
1822 rmap_path
.peer
= peer
;
1823 rmap_path
.attr
= attr
;
1825 rmap_type
= peer
->rmap_type
;
1826 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1828 /* Apply BGP route map to the attribute. */
1829 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1831 peer
->rmap_type
= rmap_type
;
1833 if (ret
== RMAP_DENYMATCH
)
1835 * caller has multiple error paths with bgp_attr_flush()
1842 /* If this is an EBGP peer with remove-private-AS */
1843 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1844 struct peer
*peer
, struct attr
*attr
)
1846 if (peer
->sort
== BGP_PEER_EBGP
1847 && (peer_af_flag_check(peer
, afi
, safi
,
1848 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1849 || peer_af_flag_check(peer
, afi
, safi
,
1850 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1851 || peer_af_flag_check(peer
, afi
, safi
,
1852 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1853 || peer_af_flag_check(peer
, afi
, safi
,
1854 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1855 // Take action on the entire aspath
1856 if (peer_af_flag_check(peer
, afi
, safi
,
1857 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1858 || peer_af_flag_check(peer
, afi
, safi
,
1859 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1860 if (peer_af_flag_check(
1862 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1863 attr
->aspath
= aspath_replace_private_asns(
1864 attr
->aspath
, bgp
->as
, peer
->as
);
1867 * Even if the aspath consists of just private ASNs we
1868 * need to walk the AS-Path to maintain all instances
1869 * of the peer's ASN to break possible loops.
1872 attr
->aspath
= aspath_remove_private_asns(
1873 attr
->aspath
, peer
->as
);
1876 // 'all' was not specified so the entire aspath must be private
1878 // for us to do anything
1879 else if (aspath_private_as_check(attr
->aspath
)) {
1880 if (peer_af_flag_check(
1882 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1883 attr
->aspath
= aspath_replace_private_asns(
1884 attr
->aspath
, bgp
->as
, peer
->as
);
1887 * Walk the aspath to retain any instances of
1890 attr
->aspath
= aspath_remove_private_asns(
1891 attr
->aspath
, peer
->as
);
1896 /* If this is an EBGP peer with as-override */
1897 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1898 struct peer
*peer
, struct attr
*attr
)
1900 struct aspath
*aspath
;
1902 if (peer
->sort
== BGP_PEER_EBGP
&&
1903 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1904 if (attr
->aspath
->refcnt
)
1905 aspath
= aspath_dup(attr
->aspath
);
1907 aspath
= attr
->aspath
;
1909 attr
->aspath
= aspath_intern(
1910 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1912 aspath_free(aspath
);
1916 void bgp_attr_add_llgr_community(struct attr
*attr
)
1918 struct community
*old
;
1919 struct community
*new;
1920 struct community
*merge
;
1921 struct community
*llgr
;
1923 old
= bgp_attr_get_community(attr
);
1924 llgr
= community_str2com("llgr-stale");
1929 merge
= community_merge(community_dup(old
), llgr
);
1931 if (old
->refcnt
== 0)
1932 community_free(&old
);
1934 new = community_uniq_sort(merge
);
1935 community_free(&merge
);
1937 new = community_dup(llgr
);
1940 community_free(&llgr
);
1942 bgp_attr_set_community(attr
, new);
1945 void bgp_attr_add_gshut_community(struct attr
*attr
)
1947 struct community
*old
;
1948 struct community
*new;
1949 struct community
*merge
;
1950 struct community
*gshut
;
1952 old
= bgp_attr_get_community(attr
);
1953 gshut
= community_str2com("graceful-shutdown");
1958 merge
= community_merge(community_dup(old
), gshut
);
1960 if (old
->refcnt
== 0)
1961 community_free(&old
);
1963 new = community_uniq_sort(merge
);
1964 community_free(&merge
);
1966 new = community_dup(gshut
);
1969 community_free(&gshut
);
1970 bgp_attr_set_community(attr
, new);
1972 /* When we add the graceful-shutdown community we must also
1973 * lower the local-preference */
1974 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1975 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1979 /* Notify BGP Conditional advertisement scanner process. */
1980 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1982 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1983 afi_t afi
= SUBGRP_AFI(subgrp
);
1984 safi_t safi
= SUBGRP_SAFI(subgrp
);
1985 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1987 if (!ADVERTISE_MAP_NAME(filter
))
1990 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1993 peer
->advmap_table_change
= true;
1997 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1999 if (family
== AF_INET
) {
2000 attr
->nexthop
.s_addr
= INADDR_ANY
;
2001 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
2003 if (family
== AF_INET6
)
2004 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
2005 if (family
== AF_EVPN
)
2006 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
2009 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
2010 struct update_subgroup
*subgrp
,
2011 const struct prefix
*p
, struct attr
*attr
,
2012 struct attr
*post_attr
)
2014 struct bgp_filter
*filter
;
2017 struct peer
*onlypeer
;
2019 struct attr
*piattr
;
2020 route_map_result_t ret
;
2025 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
2026 bool nh_reset
= false;
2029 if (DISABLE_BGP_ANNOUNCE
)
2032 afi
= SUBGRP_AFI(subgrp
);
2033 safi
= SUBGRP_SAFI(subgrp
);
2034 peer
= SUBGRP_PEER(subgrp
);
2036 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
2037 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
2040 filter
= &peer
->filter
[afi
][safi
];
2041 bgp
= SUBGRP_INST(subgrp
);
2042 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
2045 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
2046 peer
->pmax_out
[afi
][safi
] != 0 &&
2047 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
2048 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
2049 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
2050 zlog_debug("%s reached maximum prefix to be send (%u)",
2051 peer
->host
, peer
->pmax_out
[afi
][safi
]);
2056 #ifdef ENABLE_BGP_VNC
2057 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
2058 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
2059 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
2062 * direct and direct_ext type routes originate internally even
2063 * though they can have peer pointers that reference other
2066 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2072 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
2073 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
2074 && (pi
->type
== ZEBRA_ROUTE_BGP
)
2075 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2077 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2082 /* With addpath we may be asked to TX all kinds of paths so make sure
2084 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
2085 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
2086 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
2090 /* If this is not the bestpath then check to see if there is an enabled
2092 * feature that requires us to advertise it */
2093 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2094 if (!bgp_addpath_capable(pi
, peer
, afi
, safi
))
2097 /* Aggregate-address suppress check. */
2098 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
2102 * If we are doing VRF 2 VRF leaking via the import
2103 * statement, we want to prevent the route going
2104 * off box as that the RT and RD created are localy
2105 * significant and globaly useless.
2107 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
2108 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
2111 /* If it's labeled safi, make sure the route has a valid label. */
2112 if (safi
== SAFI_LABELED_UNICAST
) {
2113 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
2114 if (!bgp_is_valid_label(&label
)) {
2115 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2116 zlog_debug("u%" PRIu64
":s%" PRIu64
2117 " %pFX is filtered - no label (%p)",
2118 subgrp
->update_group
->id
, subgrp
->id
,
2124 /* Do not send back route to sender. */
2125 if (onlypeer
&& from
== onlypeer
) {
2129 /* Do not send the default route in the BGP table if the neighbor is
2130 * configured for default-originate */
2131 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2132 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2133 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2135 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2139 /* Transparency check. */
2140 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2141 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2146 /* If community is not disabled check the no-export and local. */
2147 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2148 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2149 zlog_debug("%s: community filter check fail for %pFX",
2154 /* If the attribute has originator-id and it is same as remote
2156 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2157 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2158 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2160 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2165 /* ORF prefix-list filter check */
2166 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2167 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2168 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2169 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2170 if (peer
->orf_plist
[afi
][safi
]) {
2171 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2173 if (bgp_debug_update(NULL
, p
,
2174 subgrp
->update_group
, 0))
2176 "%pBP [Update:SEND] %pFX is filtered via ORF",
2182 /* Output filter check. */
2183 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2184 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2185 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2190 /* AS path loop check. */
2191 if (onlypeer
&& onlypeer
->as_path_loop_detection
2192 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
2193 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2195 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2196 onlypeer
, onlypeer
->as
);
2200 /* If we're a CONFED we need to loop check the CONFED ID too */
2201 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2202 if (aspath_loop_check_confed(piattr
->aspath
, bgp
->confed_id
)) {
2203 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2205 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2206 peer
, bgp
->confed_id
);
2211 /* Route-Reflect check. */
2212 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2217 /* IBGP reflection check. */
2218 if (reflect
&& !samepeer_safe
) {
2219 /* A route from a Client peer. */
2220 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2221 PEER_FLAG_REFLECTOR_CLIENT
)) {
2222 /* Reflect to all the Non-Client peers and also to the
2223 Client peers other than the originator. Originator
2225 is already done. So there is noting to do. */
2226 /* no bgp client-to-client reflection check. */
2227 if (CHECK_FLAG(bgp
->flags
,
2228 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2229 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2230 PEER_FLAG_REFLECTOR_CLIENT
))
2233 /* A route from a Non-client peer. Reflect to all other
2235 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2236 PEER_FLAG_REFLECTOR_CLIENT
))
2241 /* For modify attribute, copy it to temporary structure.
2242 * post_attr comes from BGP conditional advertisements, where
2243 * attributes are already processed by advertise-map route-map,
2244 * and this needs to be saved instead of overwriting from the
2252 /* If local-preference is not set. */
2253 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2254 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2255 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2256 attr
->local_pref
= bgp
->default_local_pref
;
2259 /* If originator-id is not set and the route is to be reflected,
2260 set the originator id */
2262 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2263 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2264 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2267 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2269 if (peer
->sort
== BGP_PEER_EBGP
2270 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2271 if (from
!= bgp
->peer_self
&& !transparent
2272 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2273 PEER_FLAG_MED_UNCHANGED
))
2275 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2278 /* Since the nexthop attribute can vary per peer, it is not explicitly
2280 * in announce check, only certain flags and length (or number of
2282 * -- for IPv6/MP_REACH) are set here in order to guide the update
2284 * code in setting the nexthop(s) on a per peer basis in
2286 * Typically, the source nexthop in the attribute is preserved but in
2288 * scenarios where we know it will always be overwritten, we reset the
2289 * nexthop to "0" in an attempt to achieve better Update packing. An
2290 * example of this is when a prefix from each of 2 IBGP peers needs to
2292 * announced to an EBGP peer (and they have the same attributes barring
2296 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2298 #define NEXTHOP_IS_V6 \
2299 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2300 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2301 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2302 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2304 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2306 * the peer (group) is configured to receive link-local nexthop
2308 * and it is available in the prefix OR we're not reflecting the route,
2309 * link-local nexthop address is valid and
2310 * the peer (group) to whom we're going to announce is on a shared
2312 * and this is either a self-originated route or the peer is EBGP.
2313 * By checking if nexthop LL address is valid we are sure that
2314 * we do not announce LL address as `::`.
2316 if (NEXTHOP_IS_V6
) {
2317 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2318 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2319 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2320 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2321 || (!reflect
&& !transparent
2322 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2323 && peer
->shared_network
2324 && (from
== bgp
->peer_self
2325 || peer
->sort
== BGP_PEER_EBGP
))) {
2326 attr
->mp_nexthop_len
=
2327 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2330 /* Clear off link-local nexthop in source, whenever it is not
2332 * ensure more prefixes share the same attribute for
2335 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2336 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2337 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2340 if (bgp_check_role_applicability(afi
, safi
) &&
2341 bgp_otc_egress(peer
, attr
))
2344 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2345 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2347 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2348 filter
->advmap
.aname
&&
2349 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2350 struct bgp_path_info rmap_path
= {0};
2351 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2352 struct attr dummy_attr
= *attr
;
2354 /* Fill temp path_info */
2355 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2356 pi
, peer
, &dummy_attr
);
2358 struct route_map
*amap
=
2359 route_map_lookup_by_name(filter
->advmap
.aname
);
2361 ret
= route_map_apply(amap
, p
, &rmap_path
);
2363 bgp_attr_flush(&dummy_attr
);
2366 * The conditional advertisement mode is Withdraw and this
2367 * prefix is a conditional prefix. Don't advertise it
2369 if (ret
== RMAP_PERMITMATCH
)
2373 /* Route map & unsuppress-map apply. */
2375 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2376 struct bgp_path_info rmap_path
= {0};
2377 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2378 struct attr dummy_attr
= {0};
2380 /* Fill temp path_info */
2381 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2384 /* don't confuse inbound and outbound setting */
2385 RESET_FLAG(attr
->rmap_change_flags
);
2388 * The route reflector is not allowed to modify the attributes
2389 * of the reflected IBGP routes unless explicitly allowed.
2391 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2392 && !CHECK_FLAG(bgp
->flags
,
2393 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2395 rmap_path
.attr
= &dummy_attr
;
2398 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2400 if (bgp_path_suppressed(pi
))
2401 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2404 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2407 bgp_attr_flush(&dummy_attr
);
2408 peer
->rmap_type
= 0;
2410 if (ret
== RMAP_DENYMATCH
) {
2411 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2413 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2414 peer
, p
, ROUTE_MAP_OUT_NAME(filter
));
2415 bgp_attr_flush(rmap_path
.attr
);
2420 /* RFC 8212 to prevent route leaks.
2421 * This specification intends to improve this situation by requiring the
2422 * explicit configuration of both BGP Import and Export Policies for any
2423 * External BGP (EBGP) session such as customers, peers, or
2424 * confederation boundaries for all enabled address families. Through
2425 * codification of the aforementioned requirement, operators will
2426 * benefit from consistent behavior across different BGP
2429 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2430 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2431 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2432 NULL
) > FIFTEENMINUTE2USEC
||
2433 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2435 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2436 monotime(&bgp
->ebgprequirespolicywarning
);
2441 /* draft-ietf-idr-deprecate-as-set-confed-set
2442 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2443 * Eventually, This document (if approved) updates RFC 4271
2444 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2445 * and obsoletes RFC 6472.
2447 if (peer
->bgp
->reject_as_sets
)
2448 if (aspath_check_as_sets(attr
->aspath
))
2451 /* If neighbor soo is configured, then check if the route has
2452 * SoO extended community and validate against the configured
2453 * one. If they match, do not announce, to prevent routing
2456 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2457 peer
->soo
[afi
][safi
]) {
2458 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2459 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2461 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2462 ECOMMUNITY_SITE_ORIGIN
) ||
2463 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2464 ECOMMUNITY_SITE_ORIGIN
) ||
2465 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2466 ECOMMUNITY_SITE_ORIGIN
)) &&
2467 ecommunity_include(ecomm
, ecomm_soo
)) {
2468 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2470 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2471 peer
, p
, ecommunity_str(ecomm_soo
));
2476 /* Codification of AS 0 Processing */
2477 if (aspath_check_as_zero(attr
->aspath
))
2480 if (bgp_in_graceful_shutdown(bgp
)) {
2481 if (peer
->sort
== BGP_PEER_IBGP
2482 || peer
->sort
== BGP_PEER_CONFED
) {
2483 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2484 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2486 bgp_attr_add_gshut_community(attr
);
2490 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2491 * Capability" to a neighbor MUST perform the following upon receiving
2492 * a route from that neighbor with the "LLGR_STALE" community, or upon
2493 * attaching the "LLGR_STALE" community itself per Section 4.2:
2495 * The route SHOULD NOT be advertised to any neighbor from which the
2496 * Long-lived Graceful Restart Capability has not been received.
2498 if (bgp_attr_get_community(attr
) &&
2499 community_include(bgp_attr_get_community(attr
),
2500 COMMUNITY_LLGR_STALE
) &&
2501 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2502 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2505 /* After route-map has been applied, we check to see if the nexthop to
2506 * be carried in the attribute (that is used for the announcement) can
2507 * be cleared off or not. We do this in all cases where we would be
2508 * setting the nexthop to "ourselves". For IPv6, we only need to
2510 * the global nexthop here; the link-local nexthop would have been
2512 * already, and if not, it is required by the update formation code.
2513 * Also see earlier comments in this function.
2516 * If route-map has performed some operation on the nexthop or the peer
2517 * configuration says to pass it unchanged, we cannot reset the nexthop
2518 * here, so only attempt to do it if these aren't true. Note that the
2519 * route-map handler itself might have cleared the nexthop, if for
2521 * it is configured as 'peer-address'.
2523 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2524 piattr
->rmap_change_flags
)
2526 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2527 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2528 /* We can reset the nexthop, if setting (or forcing) it to
2530 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2531 PEER_FLAG_NEXTHOP_SELF
)
2532 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2533 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2535 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2536 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2537 subgroup_announce_reset_nhop(
2538 (peer_cap_enhe(peer
, afi
, safi
)
2544 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2545 /* Can also reset the nexthop if announcing to EBGP, but
2547 * no peer in the subgroup is on a shared subnet.
2548 * Note: 3rd party nexthop currently implemented for
2551 if ((p
->family
== AF_INET
) &&
2552 (!bgp_subgrp_multiaccess_check_v4(
2555 subgroup_announce_reset_nhop(
2556 (peer_cap_enhe(peer
, afi
, safi
)
2563 if ((p
->family
== AF_INET6
) &&
2564 (!bgp_subgrp_multiaccess_check_v6(
2565 piattr
->mp_nexthop_global
,
2567 subgroup_announce_reset_nhop(
2568 (peer_cap_enhe(peer
, afi
, safi
)
2577 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2579 * This flag is used for leaked vpn-vrf routes
2581 int family
= p
->family
;
2583 if (peer_cap_enhe(peer
, afi
, safi
))
2586 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2588 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2589 __func__
, p
, family2str(family
));
2590 subgroup_announce_reset_nhop(family
, attr
);
2595 /* If IPv6/MP and nexthop does not have any override and happens
2597 * be a link-local address, reset it so that we don't pass along
2599 * source's link-local IPv6 address to recipients who may not be
2601 * the same interface.
2603 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2604 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2605 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2610 /* If this is an iBGP, send Origin Validation State (OVS)
2611 * extended community (rfc8097).
2613 if (peer
->sort
== BGP_PEER_IBGP
) {
2614 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2616 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2618 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2619 bgp_attr_set_ecommunity(
2620 attr
, ecommunity_add_origin_validation_state(
2622 bgp_attr_get_ecommunity(attr
)));
2626 * When the next hop is set to ourselves, if all multipaths have
2627 * link-bandwidth announce the cumulative bandwidth as that makes
2628 * the most sense. However, don't modify if the link-bandwidth has
2629 * been explicitly set by user policy.
2632 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2633 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2634 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2635 bgp_attr_set_ecommunity(
2637 ecommunity_replace_linkbw(
2638 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2641 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2646 static void bgp_route_select_timer_expire(struct thread
*thread
)
2648 struct afi_safi_info
*info
;
2653 info
= THREAD_ARG(thread
);
2658 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2659 XFREE(MTYPE_TMP
, info
);
2661 /* Best path selection */
2662 bgp_best_path_select_defer(bgp
, afi
, safi
);
2665 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2666 struct bgp_maxpaths_cfg
*mpath_cfg
,
2667 struct bgp_path_info_pair
*result
, afi_t afi
,
2670 struct bgp_path_info
*new_select
;
2671 struct bgp_path_info
*old_select
;
2672 struct bgp_path_info
*pi
;
2673 struct bgp_path_info
*pi1
;
2674 struct bgp_path_info
*pi2
;
2675 struct bgp_path_info
*nextpi
= NULL
;
2676 int paths_eq
, do_mpath
, debug
;
2677 struct list mp_list
;
2678 char pfx_buf
[PREFIX2STR_BUFFER
];
2679 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2681 bgp_mp_list_init(&mp_list
);
2683 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2685 debug
= bgp_debug_bestpath(dest
);
2688 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2690 dest
->reason
= bgp_path_selection_none
;
2691 /* bgp deterministic-med */
2693 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2695 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2696 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2698 bgp_path_info_unset_flag(dest
, pi1
,
2699 BGP_PATH_DMED_SELECTED
);
2701 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2703 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2705 if (BGP_PATH_HOLDDOWN(pi1
))
2707 if (pi1
->peer
!= bgp
->peer_self
)
2708 if (!peer_established(pi1
->peer
))
2713 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2714 if (CHECK_FLAG(pi2
->flags
,
2715 BGP_PATH_DMED_CHECK
))
2717 if (BGP_PATH_HOLDDOWN(pi2
))
2719 if (pi2
->peer
!= bgp
->peer_self
2722 PEER_STATUS_NSF_WAIT
))
2723 if (pi2
->peer
->status
2727 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2729 && !aspath_cmp_left_confed(
2734 if (bgp_path_info_cmp(
2735 bgp
, pi2
, new_select
,
2736 &paths_eq
, mpath_cfg
, debug
,
2739 bgp_path_info_unset_flag(
2741 BGP_PATH_DMED_SELECTED
);
2745 bgp_path_info_set_flag(
2746 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2749 bgp_path_info_set_flag(dest
, new_select
,
2750 BGP_PATH_DMED_CHECK
);
2751 bgp_path_info_set_flag(dest
, new_select
,
2752 BGP_PATH_DMED_SELECTED
);
2755 bgp_path_info_path_with_addpath_rx_str(
2756 new_select
, path_buf
, sizeof(path_buf
));
2758 "%pBD(%s): %s is the bestpath from AS %u",
2759 dest
, bgp
->name_pretty
, path_buf
,
2760 aspath_get_first_as(
2761 new_select
->attr
->aspath
));
2766 /* Check old selected route and new selected route. */
2769 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2770 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2771 enum bgp_path_selection_reason reason
;
2773 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2776 if (BGP_PATH_HOLDDOWN(pi
)) {
2777 /* reap REMOVED routes, if needs be
2778 * selected route must stay for a while longer though
2780 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2781 && (pi
!= old_select
))
2782 bgp_path_info_reap(dest
, pi
);
2785 zlog_debug("%s: pi %p in holddown", __func__
,
2791 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2792 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2793 if (!peer_established(pi
->peer
)) {
2797 "%s: pi %p non self peer %s not estab state",
2798 __func__
, pi
, pi
->peer
->host
);
2803 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2804 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2805 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2807 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2811 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2813 reason
= dest
->reason
;
2814 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2815 debug
, pfx_buf
, afi
, safi
,
2817 if (new_select
== NULL
&&
2818 reason
!= bgp_path_selection_none
)
2819 dest
->reason
= reason
;
2824 /* Now that we know which path is the bestpath see if any of the other
2826 * qualify as multipaths
2830 bgp_path_info_path_with_addpath_rx_str(
2831 new_select
, path_buf
, sizeof(path_buf
));
2833 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2835 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2836 dest
, bgp
->name_pretty
, path_buf
,
2837 old_select
? old_select
->peer
->host
: "NONE");
2840 if (do_mpath
&& new_select
) {
2841 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2842 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2845 bgp_path_info_path_with_addpath_rx_str(
2846 pi
, path_buf
, sizeof(path_buf
));
2848 if (pi
== new_select
) {
2851 "%pBD(%s): %s is the bestpath, add to the multipath list",
2852 dest
, bgp
->name_pretty
,
2854 bgp_mp_list_add(&mp_list
, pi
);
2858 if (BGP_PATH_HOLDDOWN(pi
))
2861 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2862 && !CHECK_FLAG(pi
->peer
->sflags
,
2863 PEER_STATUS_NSF_WAIT
))
2864 if (!peer_established(pi
->peer
))
2867 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2870 "%pBD: %s has the same nexthop as the bestpath, skip it",
2875 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2876 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2882 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2884 bgp_mp_list_add(&mp_list
, pi
);
2889 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2891 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2892 bgp_mp_list_clear(&mp_list
);
2894 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2896 result
->old
= old_select
;
2897 result
->new = new_select
;
2903 * A new route/change in bestpath of an existing route. Evaluate the path
2904 * for advertisement to the subgroup.
2906 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2907 struct bgp_path_info
*selected
,
2908 struct bgp_dest
*dest
,
2909 uint32_t addpath_tx_id
)
2911 const struct prefix
*p
;
2912 struct peer
*onlypeer
;
2919 p
= bgp_dest_get_prefix(dest
);
2920 afi
= SUBGRP_AFI(subgrp
);
2921 safi
= SUBGRP_SAFI(subgrp
);
2922 bgp
= SUBGRP_INST(subgrp
);
2923 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2926 if (BGP_DEBUG(update
, UPDATE_OUT
))
2927 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2929 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2930 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2931 PEER_STATUS_ORF_WAIT_REFRESH
))
2934 memset(&attr
, 0, sizeof(attr
));
2935 /* It's initialized in bgp_announce_check() */
2937 /* Announcement to the subgroup. If the route is filtered withdraw it.
2938 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2939 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2942 advertise
= bgp_check_advertise(bgp
, dest
);
2945 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2947 /* Route is selected, if the route is already installed
2948 * in FIB, then it is advertised
2951 if (!bgp_check_withdrawal(bgp
, dest
))
2952 bgp_adj_out_set_subgroup(
2953 dest
, subgrp
, &attr
, selected
);
2955 bgp_adj_out_unset_subgroup(
2956 dest
, subgrp
, 1, addpath_tx_id
);
2959 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2963 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2965 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2970 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2971 * This is called at the end of route processing.
2973 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2975 struct bgp_path_info
*pi
;
2977 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2978 if (BGP_PATH_HOLDDOWN(pi
))
2980 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2981 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2986 * Has the route changed from the RIB's perspective? This is invoked only
2987 * if the route selection returns the same best route as earlier - to
2988 * determine if we need to update zebra or not.
2990 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2992 struct bgp_path_info
*mpinfo
;
2994 /* If this is multipath, check all selected paths for any nexthop
2995 * change or attribute change. Some attribute changes (e.g., community)
2996 * aren't of relevance to the RIB, but we'll update zebra to ensure
2997 * we handle the case of BGP nexthop change. This is the behavior
2998 * when the best path has an attribute change anyway.
3000 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
3001 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
3002 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
3006 * If this is multipath, check all selected paths for any nexthop change
3008 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
3009 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
3010 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
3011 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
3015 /* Nothing has changed from the RIB's perspective. */
3019 struct bgp_process_queue
{
3021 STAILQ_HEAD(, bgp_dest
) pqueue
;
3022 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3024 unsigned int queued
;
3027 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
3028 safi_t safi
, struct bgp_dest
*dest
,
3029 struct bgp_path_info
*new_select
,
3030 struct bgp_path_info
*old_select
)
3032 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3034 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
3037 if (advertise_type5_routes(bgp
, afi
) && new_select
3038 && is_route_injectable_into_evpn(new_select
)) {
3040 /* apply the route-map */
3041 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
3042 route_map_result_t ret
;
3043 struct bgp_path_info rmap_path
;
3044 struct bgp_path_info_extra rmap_path_extra
;
3045 struct attr dummy_attr
;
3047 dummy_attr
= *new_select
->attr
;
3049 /* Fill temp path_info */
3050 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3051 new_select
, new_select
->peer
,
3054 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3056 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3059 if (ret
== RMAP_DENYMATCH
) {
3060 bgp_attr_flush(&dummy_attr
);
3061 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3064 bgp_evpn_advertise_type5_route(
3065 bgp
, p
, &dummy_attr
, afi
, safi
);
3067 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3070 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3071 && is_route_injectable_into_evpn(old_select
))
3072 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3076 * Utility to determine whether a particular path_info should use
3077 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3078 * in a path where we basically _know_ this is a BGP-LU route.
3080 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
3082 /* Certain types get imp null; so do paths where the nexthop is
3085 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3086 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3087 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3089 else if (new_select
->extra
== NULL
||
3090 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
3091 /* TODO -- should be configurable? */
3098 * old_select = The old best path
3099 * new_select = the new best path
3101 * if (!old_select && new_select)
3102 * We are sending new information on.
3104 * if (old_select && new_select) {
3105 * if (new_select != old_select)
3106 * We have a new best path send a change
3108 * We've received a update with new attributes that needs
3112 * if (old_select && !new_select)
3113 * We have no eligible route that we can announce or the rn
3116 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3117 afi_t afi
, safi_t safi
)
3119 struct bgp_path_info
*new_select
;
3120 struct bgp_path_info
*old_select
;
3121 struct bgp_path_info_pair old_and_new
;
3124 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3126 debug
= bgp_debug_bestpath(dest
);
3129 "%s: bgp delete in progress, ignoring event, p=%pBD",
3133 /* Is it end of initial update? (after startup) */
3135 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3136 sizeof(bgp
->update_delay_zebra_resume_time
));
3138 bgp
->main_zebra_update_hold
= 0;
3139 FOREACH_AFI_SAFI (afi
, safi
) {
3140 if (bgp_fibupd_safi(safi
))
3141 bgp_zebra_announce_table(bgp
, afi
, safi
);
3143 bgp
->main_peers_update_hold
= 0;
3145 bgp_start_routeadv(bgp
);
3149 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3151 debug
= bgp_debug_bestpath(dest
);
3153 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__
,
3154 dest
, bgp
->name_pretty
, afi2str(afi
),
3157 /* The best path calculation for the route is deferred if
3158 * BGP_NODE_SELECT_DEFER is set
3160 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3161 if (BGP_DEBUG(update
, UPDATE_OUT
))
3162 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
3166 /* Best path selection. */
3167 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3169 old_select
= old_and_new
.old
;
3170 new_select
= old_and_new
.new;
3172 /* Do we need to allocate or free labels?
3173 * Right now, since we only deal with per-prefix labels, it is not
3174 * necessary to do this upon changes to best path. Exceptions:
3175 * - label index has changed -> recalculate resulting label
3176 * - path_info sub_type changed -> switch to/from implicit-null
3177 * - no valid label (due to removed static label binding) -> get new one
3179 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3182 || bgp_label_index_differs(new_select
, old_select
)
3183 || new_select
->sub_type
!= old_select
->sub_type
3184 || !bgp_is_valid_label(&dest
->local_label
)) {
3185 /* Enforced penultimate hop popping:
3186 * implicit-null for local routes, aggregate
3187 * and redistributed routes
3189 if (bgp_lu_need_imp_null(new_select
)) {
3192 BGP_NODE_REGISTERED_FOR_LABEL
)
3195 BGP_NODE_LABEL_REQUESTED
))
3196 bgp_unregister_for_label(dest
);
3197 dest
->local_label
= mpls_lse_encode(
3198 MPLS_LABEL_IMPLICIT_NULL
, 0, 0,
3200 bgp_set_valid_label(&dest
->local_label
);
3202 bgp_register_for_label(dest
,
3205 } else if (CHECK_FLAG(dest
->flags
,
3206 BGP_NODE_REGISTERED_FOR_LABEL
)
3207 || CHECK_FLAG(dest
->flags
,
3208 BGP_NODE_LABEL_REQUESTED
)) {
3209 bgp_unregister_for_label(dest
);
3211 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3212 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3213 bgp_unregister_for_label(dest
);
3218 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3219 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3220 safi2str(safi
), old_select
, new_select
);
3222 /* If best route remains the same and this is not due to user-initiated
3223 * clear, see exactly what needs to be done.
3225 if (old_select
&& old_select
== new_select
3226 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3227 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3228 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3229 if (bgp_zebra_has_route_changed(old_select
)) {
3230 #ifdef ENABLE_BGP_VNC
3231 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3232 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3234 if (bgp_fibupd_safi(safi
)
3235 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3237 if (BGP_SUPPRESS_FIB_ENABLED(bgp
)
3238 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
3239 SET_FLAG(dest
->flags
,
3240 BGP_NODE_FIB_INSTALL_PENDING
);
3242 if (new_select
->type
== ZEBRA_ROUTE_BGP
3243 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3244 || new_select
->sub_type
3245 == BGP_ROUTE_IMPORTED
))
3247 bgp_zebra_announce(dest
, p
, old_select
,
3252 /* If there is a change of interest to peers, reannounce the
3254 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3255 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3256 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3257 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3259 /* unicast routes must also be annouced to
3260 * labeled-unicast update-groups */
3261 if (safi
== SAFI_UNICAST
)
3262 group_announce_route(bgp
, afi
,
3263 SAFI_LABELED_UNICAST
, dest
,
3266 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3267 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3270 /* advertise/withdraw type-5 routes */
3271 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3272 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3273 bgp_process_evpn_route_injection(
3274 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3276 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3277 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3278 bgp_zebra_clear_route_change_flags(dest
);
3279 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3283 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3285 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3287 /* bestpath has changed; bump version */
3288 if (old_select
|| new_select
) {
3289 bgp_bump_version(dest
);
3291 if (!bgp
->t_rmap_def_originate_eval
) {
3295 update_group_refresh_default_originate_route_map
,
3296 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3297 &bgp
->t_rmap_def_originate_eval
);
3302 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3305 zlog_debug("%s: setting SELECTED flag", __func__
);
3306 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3307 bgp_path_info_unset_flag(dest
, new_select
,
3308 BGP_PATH_ATTR_CHANGED
);
3309 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3310 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3313 #ifdef ENABLE_BGP_VNC
3314 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3315 if (old_select
!= new_select
) {
3317 vnc_import_bgp_exterior_del_route(bgp
, p
,
3319 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3322 vnc_import_bgp_exterior_add_route(bgp
, p
,
3324 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3330 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3332 /* unicast routes must also be annouced to labeled-unicast update-groups
3334 if (safi
== SAFI_UNICAST
)
3335 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3339 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3340 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3342 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3343 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3344 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3345 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3347 if (BGP_SUPPRESS_FIB_ENABLED(bgp
))
3348 SET_FLAG(dest
->flags
,
3349 BGP_NODE_FIB_INSTALL_PENDING
);
3351 /* if this is an evpn imported type-5 prefix,
3352 * we need to withdraw the route first to clear
3353 * the nh neigh and the RMAC entry.
3356 is_route_parent_evpn(old_select
))
3357 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3359 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3361 /* Withdraw the route from the kernel. */
3362 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3363 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3364 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3365 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3367 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3371 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3374 /* Clear any route change flags. */
3375 bgp_zebra_clear_route_change_flags(dest
);
3377 /* Reap old select bgp_path_info, if it has been removed */
3378 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3379 bgp_path_info_reap(dest
, old_select
);
3381 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3385 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3386 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3388 struct bgp_dest
*dest
;
3390 struct afi_safi_info
*thread_info
;
3392 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3393 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3395 thread_info
= THREAD_ARG(t
);
3396 XFREE(MTYPE_TMP
, thread_info
);
3397 THREAD_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3400 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3401 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3402 get_afi_safi_str(afi
, safi
, false),
3403 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3406 /* Process the route list */
3407 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3408 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3409 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3410 dest
= bgp_route_next(dest
)) {
3411 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3414 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3415 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3416 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3419 /* If iteration stopped before the entire table was traversed then the
3420 * node needs to be unlocked.
3423 bgp_dest_unlock_node(dest
);
3427 /* Send EOR message when all routes are processed */
3428 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3429 bgp_send_delayed_eor(bgp
);
3430 /* Send route processing complete message to RIB */
3431 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3432 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3436 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3438 thread_info
->afi
= afi
;
3439 thread_info
->safi
= safi
;
3440 thread_info
->bgp
= bgp
;
3442 /* If there are more routes to be processed, start the
3445 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3446 BGP_ROUTE_SELECT_DELAY
,
3447 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3450 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3452 struct bgp_process_queue
*pqnode
= data
;
3453 struct bgp
*bgp
= pqnode
->bgp
;
3454 struct bgp_table
*table
;
3455 struct bgp_dest
*dest
;
3458 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3459 bgp_process_main_one(bgp
, NULL
, 0, 0);
3460 /* should always have dedicated wq call */
3461 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3465 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3466 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3467 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3468 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3469 table
= bgp_dest_table(dest
);
3470 /* note, new DESTs may be added as part of processing */
3471 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3473 bgp_dest_unlock_node(dest
);
3474 bgp_table_unlock(table
);
3480 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3482 struct bgp_process_queue
*pqnode
= data
;
3484 bgp_unlock(pqnode
->bgp
);
3486 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3489 void bgp_process_queue_init(struct bgp
*bgp
)
3491 if (!bgp
->process_queue
) {
3494 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3495 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3498 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3499 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3500 bgp
->process_queue
->spec
.max_retries
= 0;
3501 bgp
->process_queue
->spec
.hold
= 50;
3502 /* Use a higher yield value of 50ms for main queue processing */
3503 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3506 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3508 struct bgp_process_queue
*pqnode
;
3510 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3511 sizeof(struct bgp_process_queue
));
3513 /* unlocked in bgp_processq_del */
3514 pqnode
->bgp
= bgp_lock(bgp
);
3515 STAILQ_INIT(&pqnode
->pqueue
);
3520 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3522 #define ARBITRARY_PROCESS_QLEN 10000
3523 struct work_queue
*wq
= bgp
->process_queue
;
3524 struct bgp_process_queue
*pqnode
;
3525 int pqnode_reuse
= 0;
3527 /* already scheduled for processing? */
3528 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3531 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3534 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3535 if (BGP_DEBUG(update
, UPDATE_OUT
))
3536 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3541 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3542 if (BGP_DEBUG(update
, UPDATE_OUT
))
3544 "Soft reconfigure table in progress for route %p",
3552 /* Add route nodes to an existing work queue item until reaching the
3553 limit only if is from the same BGP view and it's not an EOIU marker
3555 if (work_queue_item_count(wq
)) {
3556 struct work_queue_item
*item
= work_queue_last_item(wq
);
3557 pqnode
= item
->data
;
3559 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3560 || pqnode
->bgp
!= bgp
3561 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3562 pqnode
= bgp_processq_alloc(bgp
);
3566 pqnode
= bgp_processq_alloc(bgp
);
3567 /* all unlocked in bgp_process_wq */
3568 bgp_table_lock(bgp_dest_table(dest
));
3570 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3571 bgp_dest_lock_node(dest
);
3573 /* can't be enqueued twice */
3574 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3575 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3579 work_queue_add(wq
, pqnode
);
3584 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3586 struct bgp_process_queue
*pqnode
;
3588 if (bgp
->process_queue
== NULL
)
3591 pqnode
= bgp_processq_alloc(bgp
);
3593 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3594 work_queue_add(bgp
->process_queue
, pqnode
);
3597 static void bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3601 peer
= THREAD_ARG(thread
);
3602 peer
->t_pmax_restart
= NULL
;
3604 if (bgp_debug_neighbor_events(peer
))
3606 "%s Maximum-prefix restart timer expired, restore peering",
3609 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3610 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3613 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3617 bool filtered
= false;
3618 struct bgp_dest
*dest
;
3619 struct bgp_adj_in
*ain
;
3620 struct attr attr
= {};
3621 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3623 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3624 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3625 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3629 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3633 if (bgp_input_modifier(
3634 peer
, rn_p
, &attr
, afi
, safi
,
3635 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3643 bgp_attr_flush(&attr
);
3650 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3654 iana_safi_t pkt_safi
;
3655 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3656 PEER_FLAG_MAX_PREFIX_FORCE
))
3657 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3658 + peer
->pcount
[afi
][safi
]
3659 : peer
->pcount
[afi
][safi
];
3661 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3664 if (pcount
> peer
->pmax
[afi
][safi
]) {
3665 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3666 PEER_STATUS_PREFIX_LIMIT
)
3671 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3672 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3673 peer
->pmax
[afi
][safi
]);
3674 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3676 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3677 PEER_FLAG_MAX_PREFIX_WARNING
))
3680 /* Convert AFI, SAFI to values for packet. */
3681 pkt_afi
= afi_int2iana(afi
);
3682 pkt_safi
= safi_int2iana(safi
);
3686 ndata
[0] = (pkt_afi
>> 8);
3688 ndata
[2] = pkt_safi
;
3689 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3690 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3691 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3692 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3694 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3695 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3696 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3700 /* Dynamic peers will just close their connection. */
3701 if (peer_dynamic_neighbor(peer
))
3704 /* restart timer start */
3705 if (peer
->pmax_restart
[afi
][safi
]) {
3706 peer
->v_pmax_restart
=
3707 peer
->pmax_restart
[afi
][safi
] * 60;
3709 if (bgp_debug_neighbor_events(peer
))
3711 "%pBP Maximum-prefix restart timer started for %d secs",
3712 peer
, peer
->v_pmax_restart
);
3714 BGP_TIMER_ON(peer
->t_pmax_restart
,
3715 bgp_maximum_prefix_restart_timer
,
3716 peer
->v_pmax_restart
);
3721 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3722 PEER_STATUS_PREFIX_LIMIT
);
3725 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3726 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3727 PEER_STATUS_PREFIX_THRESHOLD
)
3732 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3733 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3734 peer
->pmax
[afi
][safi
]);
3735 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3736 PEER_STATUS_PREFIX_THRESHOLD
);
3738 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3739 PEER_STATUS_PREFIX_THRESHOLD
);
3743 /* Unconditionally remove the route from the RIB, without taking
3744 * damping into consideration (eg, because the session went down)
3746 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3747 struct peer
*peer
, afi_t afi
, safi_t safi
)
3750 struct bgp
*bgp
= NULL
;
3751 bool delete_route
= false;
3753 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3756 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3757 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3759 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3762 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3763 delete_route
= true;
3764 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3765 delete_route
= true;
3767 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3768 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3769 bgp
= pi
->peer
->bgp
;
3770 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3775 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3776 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3779 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3780 struct peer
*peer
, afi_t afi
, safi_t safi
,
3781 struct prefix_rd
*prd
)
3783 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3785 /* apply dampening, if result is suppressed, we'll be retaining
3786 * the bgp_path_info in the RIB for historical reference.
3788 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3789 && peer
->sort
== BGP_PEER_EBGP
)
3790 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3791 == BGP_DAMP_SUPPRESSED
) {
3792 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3797 #ifdef ENABLE_BGP_VNC
3798 if (safi
== SAFI_MPLS_VPN
) {
3799 struct bgp_dest
*pdest
= NULL
;
3800 struct bgp_table
*table
= NULL
;
3802 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3803 (struct prefix
*)prd
);
3804 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3805 table
= bgp_dest_get_bgp_table_info(pdest
);
3807 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3808 peer
->bgp
, prd
, table
, p
, pi
);
3810 bgp_dest_unlock_node(pdest
);
3812 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3813 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3815 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3816 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3821 /* If this is an EVPN route, process for un-import. */
3822 if (safi
== SAFI_EVPN
)
3823 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3825 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3828 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3829 struct peer
*peer
, struct attr
*attr
,
3830 struct bgp_dest
*dest
)
3832 struct bgp_path_info
*new;
3834 /* Make new BGP info. */
3835 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3837 new->instance
= instance
;
3838 new->sub_type
= sub_type
;
3841 new->uptime
= monotime(NULL
);
3846 /* Check if received nexthop is valid or not. */
3847 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3848 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3849 struct bgp_dest
*dest
)
3852 bool is_bgp_static_route
=
3853 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3857 * Only validated for unicast and multicast currently.
3858 * Also valid for EVPN where the nexthop is an IP address.
3859 * If we are a bgp static route being checked then there is
3860 * no need to check to see if the nexthop is martian as
3861 * that it should be ok.
3863 if (is_bgp_static_route
||
3864 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3867 /* If NEXT_HOP is present, validate it. */
3868 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3869 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3870 !ipv4_unicast_valid(&attr
->nexthop
) ||
3871 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3875 /* If MP_NEXTHOP is present, validate it. */
3876 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3877 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3878 * it is not an IPv6 link-local address.
3880 * If we receive an UPDATE with nexthop length set to 32 bytes
3881 * we shouldn't discard an UPDATE if it's set to (::).
3882 * The link-local (2st) is validated along the code path later.
3884 if (attr
->mp_nexthop_len
) {
3885 switch (attr
->mp_nexthop_len
) {
3886 case BGP_ATTR_NHLEN_IPV4
:
3887 case BGP_ATTR_NHLEN_VPNV4
:
3888 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3890 !ipv4_unicast_valid(
3891 &attr
->mp_nexthop_global_in
) ||
3892 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3896 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3897 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3898 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3899 &attr
->mp_nexthop_global
)
3900 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3901 || IN6_IS_ADDR_MULTICAST(
3902 &attr
->mp_nexthop_global
)
3903 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3906 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3907 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3908 || IN6_IS_ADDR_MULTICAST(
3909 &attr
->mp_nexthop_global
)
3910 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3923 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3925 struct community
*old
;
3926 struct community
*new;
3927 struct community
*merge
;
3928 struct community
*no_export
;
3930 old
= bgp_attr_get_community(attr
);
3931 no_export
= community_str2com("no-export");
3936 merge
= community_merge(community_dup(old
), no_export
);
3939 community_free(&old
);
3941 new = community_uniq_sort(merge
);
3942 community_free(&merge
);
3944 new = community_dup(no_export
);
3947 community_free(&no_export
);
3949 bgp_attr_set_community(attr
, new);
3952 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3953 struct attr
*attr
, const struct prefix
*prefix
,
3956 struct listnode
*node
, *nnode
;
3958 bool accept_own_found
= false;
3960 if (safi
!= SAFI_MPLS_VPN
)
3963 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3964 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3967 /* The route in question carries the ACCEPT_OWN community */
3968 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3969 struct community
*comm
= bgp_attr_get_community(attr
);
3971 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3972 accept_own_found
= true;
3975 /* The route in question is targeted to one or more destination VRFs
3976 * on the router (as determined by inspecting the Route Target(s)).
3978 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3979 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3982 if (accept_own_found
&&
3984 bgp
->vpn_policy
[afi
]
3985 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3986 bgp_attr_get_ecommunity(attr
))) {
3987 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3989 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3992 /* Treat this route as imported, because it's leaked
3993 * already from another VRF, and we got an updated
3994 * version from route-reflector with ACCEPT_OWN
3997 *sub_type
= BGP_ROUTE_IMPORTED
;
4006 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4007 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4008 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4009 uint32_t num_labels
, int soft_reconfig
,
4010 struct bgp_route_evpn
*evpn
)
4013 int aspath_loop_count
= 0;
4014 struct bgp_dest
*dest
;
4016 struct attr new_attr
;
4017 struct attr
*attr_new
;
4018 struct bgp_path_info
*pi
;
4019 struct bgp_path_info
*new = NULL
;
4020 struct bgp_path_info_extra
*extra
;
4022 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4024 int do_loop_check
= 1;
4025 int has_valid_label
= 0;
4027 bool force_evpn_import
= false;
4028 safi_t orig_safi
= safi
;
4029 bool leak_success
= true;
4032 if (frrtrace_enabled(frr_bgp
, process_update
)) {
4033 char pfxprint
[PREFIX2STR_BUFFER
];
4035 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
4036 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
4040 #ifdef ENABLE_BGP_VNC
4041 int vnc_implicit_withdraw
= 0;
4044 const struct prefix
*bgp_nht_param_prefix
;
4046 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4047 if (orig_safi
== SAFI_LABELED_UNICAST
)
4048 safi
= SAFI_UNICAST
;
4050 memset(&new_attr
, 0, sizeof(new_attr
));
4051 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4052 new_attr
.label
= MPLS_INVALID_LABEL
;
4055 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4056 /* TODO: Check to see if we can get rid of "is_valid_label" */
4057 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4058 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4060 has_valid_label
= bgp_is_valid_label(label
);
4062 if (has_valid_label
)
4063 assert(label
!= NULL
);
4065 /* Update overlay index of the attribute */
4066 if (afi
== AFI_L2VPN
&& evpn
)
4067 memcpy(&attr
->evpn_overlay
, evpn
,
4068 sizeof(struct bgp_route_evpn
));
4070 /* When peer's soft reconfiguration enabled. Record input packet in
4073 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4074 && peer
!= bgp
->peer_self
)
4075 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4077 /* Update permitted loop count */
4078 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4079 allowas_in
= peer
->allowas_in
[afi
][safi
];
4081 /* Check previously received route. */
4082 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4083 if (pi
->peer
== peer
&& pi
->type
== type
4084 && pi
->sub_type
== sub_type
4085 && pi
->addpath_rx_id
== addpath_id
)
4088 /* AS path local-as loop check. */
4089 if (peer
->change_local_as
) {
4091 aspath_loop_count
= allowas_in
;
4092 else if (!CHECK_FLAG(peer
->flags
,
4093 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4094 aspath_loop_count
= 1;
4096 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4097 > aspath_loop_count
) {
4098 peer
->stat_pfx_aspath_loop
++;
4099 reason
= "as-path contains our own AS;";
4104 /* If the peer is configured for "allowas-in origin" and the last ASN in
4106 * as-path is our ASN then we do not need to call aspath_loop_check
4108 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4109 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4112 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4113 bgp_nht_param_prefix
= NULL
;
4115 bgp_nht_param_prefix
= p
;
4117 /* AS path loop check. */
4118 if (do_loop_check
) {
4119 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4120 peer
->allowas_in
[afi
][safi
]) {
4121 peer
->stat_pfx_aspath_loop
++;
4122 reason
= "as-path contains our own AS;";
4127 /* If we're a CONFED we need to loop check the CONFED ID too */
4128 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4129 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4130 peer
->allowas_in
[afi
][safi
]) {
4131 peer
->stat_pfx_aspath_loop
++;
4132 reason
= "as-path contains our own confed AS;";
4136 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4137 * enabled, then take care of that too.
4139 bool accept_own
= false;
4141 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4142 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4144 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4146 peer
->stat_pfx_originator_loop
++;
4147 reason
= "originator is us;";
4152 /* Route reflector cluster ID check. */
4153 if (bgp_cluster_filter(peer
, attr
)) {
4154 peer
->stat_pfx_cluster_loop
++;
4155 reason
= "reflected from the same cluster;";
4159 /* Apply incoming filter. */
4160 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4161 peer
->stat_pfx_filter
++;
4166 /* RFC 8212 to prevent route leaks.
4167 * This specification intends to improve this situation by requiring the
4168 * explicit configuration of both BGP Import and Export Policies for any
4169 * External BGP (EBGP) session such as customers, peers, or
4170 * confederation boundaries for all enabled address families. Through
4171 * codification of the aforementioned requirement, operators will
4172 * benefit from consistent behavior across different BGP
4175 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4176 if (!bgp_inbound_policy_exists(peer
,
4177 &peer
->filter
[afi
][safi
])) {
4178 reason
= "inbound policy missing";
4179 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4180 NULL
) > FIFTEENMINUTE2USEC
||
4181 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4183 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4184 monotime(&bgp
->ebgprequirespolicywarning
);
4189 /* draft-ietf-idr-deprecate-as-set-confed-set
4190 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4191 * Eventually, This document (if approved) updates RFC 4271
4192 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4193 * and obsoletes RFC 6472.
4195 if (peer
->bgp
->reject_as_sets
)
4196 if (aspath_check_as_sets(attr
->aspath
)) {
4198 "as-path contains AS_SET or AS_CONFED_SET type;";
4204 /* Apply incoming route-map.
4205 * NB: new_attr may now contain newly allocated values from route-map
4207 * commands, so we need bgp_attr_flush in the error paths, until we
4209 * the attr (which takes over the memory references) */
4210 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4213 peer
->stat_pfx_filter
++;
4214 reason
= "route-map;";
4215 bgp_attr_flush(&new_attr
);
4219 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4220 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4221 /* remove from RIB previous entry */
4222 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4225 if (peer
->sort
== BGP_PEER_EBGP
) {
4228 * A BGP speaker receiving an announcement tagged with the
4229 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4230 * NO_EXPORT community as defined in RFC1997, or a
4231 * similar community, to prevent propagation of the
4232 * prefix outside the local AS. The community to prevent
4233 * propagation SHOULD be chosen according to the operator's
4236 if (bgp_attr_get_community(&new_attr
) &&
4237 community_include(bgp_attr_get_community(&new_attr
),
4238 COMMUNITY_BLACKHOLE
))
4239 bgp_attr_add_no_export_community(&new_attr
);
4241 /* If we receive the graceful-shutdown community from an eBGP
4242 * peer we must lower local-preference */
4243 if (bgp_attr_get_community(&new_attr
) &&
4244 community_include(bgp_attr_get_community(&new_attr
),
4246 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4247 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4249 /* If graceful-shutdown is configured globally or
4250 * per neighbor, then add the GSHUT community to
4251 * all paths received from eBGP peers. */
4252 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4253 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4254 bgp_attr_add_gshut_community(&new_attr
);
4257 /* next hop check. */
4258 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4259 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4261 peer
->stat_pfx_nh_invalid
++;
4262 reason
= "martian or self next-hop;";
4263 bgp_attr_flush(&new_attr
);
4267 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4268 peer
->stat_pfx_nh_invalid
++;
4269 reason
= "self mac;";
4270 bgp_attr_flush(&new_attr
);
4274 if (bgp_check_role_applicability(afi
, safi
) &&
4275 bgp_otc_filter(peer
, &new_attr
)) {
4276 reason
= "failing otc validation";
4277 bgp_attr_flush(&new_attr
);
4280 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4282 * Suppress fib is enabled
4283 * BGP_OPT_NO_FIB is not enabled
4284 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4285 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4287 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
4288 && (sub_type
== BGP_ROUTE_NORMAL
)
4289 && (!bgp_option_check(BGP_OPT_NO_FIB
))
4290 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
4291 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
4293 /* If neighbor soo is configured, tag all incoming routes with
4294 * this SoO tag and then filter out advertisements in
4295 * subgroup_announce_check() if it matches the configured SoO
4296 * on the other peer.
4298 if (peer
->soo
[afi
][safi
]) {
4299 struct ecommunity
*old_ecomm
=
4300 bgp_attr_get_ecommunity(&new_attr
);
4301 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4302 struct ecommunity
*new_ecomm
;
4305 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4308 if (!old_ecomm
->refcnt
)
4309 ecommunity_free(&old_ecomm
);
4311 new_ecomm
= ecommunity_dup(ecomm_soo
);
4314 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4317 attr_new
= bgp_attr_intern(&new_attr
);
4319 /* If the update is implicit withdraw. */
4321 pi
->uptime
= monotime(NULL
);
4322 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4324 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4326 /* Same attribute comes in. */
4327 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4329 && (!has_valid_label
4330 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4331 num_labels
* sizeof(mpls_label_t
))
4333 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4334 BGP_CONFIG_DAMPENING
)
4335 && peer
->sort
== BGP_PEER_EBGP
4336 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4337 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4338 bgp_debug_rdpfxpath2str(
4339 afi
, safi
, prd
, p
, label
,
4340 num_labels
, addpath_id
? 1 : 0,
4341 addpath_id
, evpn
, pfx_buf
,
4343 zlog_debug("%pBP rcvd %s", peer
,
4347 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4348 != BGP_DAMP_SUPPRESSED
) {
4349 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4351 bgp_process(bgp
, dest
, afi
, safi
);
4353 } else /* Duplicate - odd */
4355 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4356 if (!peer
->rcvd_attr_printed
) {
4358 "%pBP rcvd UPDATE w/ attr: %s",
4360 peer
->rcvd_attr_str
);
4361 peer
->rcvd_attr_printed
= 1;
4364 bgp_debug_rdpfxpath2str(
4365 afi
, safi
, prd
, p
, label
,
4366 num_labels
, addpath_id
? 1 : 0,
4367 addpath_id
, evpn
, pfx_buf
,
4370 "%pBP rcvd %s...duplicate ignored",
4374 /* graceful restart STALE flag unset. */
4375 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4376 bgp_path_info_unset_flag(
4377 dest
, pi
, BGP_PATH_STALE
);
4378 bgp_dest_set_defer_flag(dest
, false);
4379 bgp_process(bgp
, dest
, afi
, safi
);
4383 bgp_dest_unlock_node(dest
);
4384 bgp_attr_unintern(&attr_new
);
4389 /* Withdraw/Announce before we fully processed the withdraw */
4390 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4391 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4392 bgp_debug_rdpfxpath2str(
4393 afi
, safi
, prd
, p
, label
, num_labels
,
4394 addpath_id
? 1 : 0, addpath_id
, evpn
,
4395 pfx_buf
, sizeof(pfx_buf
));
4397 "%pBP rcvd %s, flapped quicker than processing",
4401 bgp_path_info_restore(dest
, pi
);
4404 * If the BGP_PATH_REMOVED flag is set, then EVPN
4405 * routes would have been unimported already when a
4406 * prior BGP withdraw processing happened. Such routes
4407 * need to be imported again, so flag accordingly.
4409 force_evpn_import
= true;
4411 /* implicit withdraw, decrement aggregate and pcount
4412 * here. only if update is accepted, they'll increment
4415 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4418 /* Received Logging. */
4419 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4420 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4421 num_labels
, addpath_id
? 1 : 0,
4422 addpath_id
, evpn
, pfx_buf
,
4424 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4427 /* graceful restart STALE flag unset. */
4428 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4429 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4430 bgp_dest_set_defer_flag(dest
, false);
4433 /* The attribute is changed. */
4434 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4436 /* Update bgp route dampening information. */
4437 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4438 && peer
->sort
== BGP_PEER_EBGP
) {
4439 /* This is implicit withdraw so we should update
4442 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4443 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4445 #ifdef ENABLE_BGP_VNC
4446 if (safi
== SAFI_MPLS_VPN
) {
4447 struct bgp_dest
*pdest
= NULL
;
4448 struct bgp_table
*table
= NULL
;
4450 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4451 (struct prefix
*)prd
);
4452 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4453 table
= bgp_dest_get_bgp_table_info(pdest
);
4455 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4456 bgp
, prd
, table
, p
, pi
);
4458 bgp_dest_unlock_node(pdest
);
4460 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4461 && (safi
== SAFI_UNICAST
)) {
4462 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4464 * Implicit withdraw case.
4466 ++vnc_implicit_withdraw
;
4467 vnc_import_bgp_del_route(bgp
, p
, pi
);
4468 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4473 /* Special handling for EVPN update of an existing route. If the
4474 * extended community attribute has changed, we need to
4476 * the route using its existing extended community. It will be
4477 * subsequently processed for import with the new extended
4480 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4483 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4485 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4488 cmp
= ecommunity_cmp(
4489 bgp_attr_get_ecommunity(pi
->attr
),
4490 bgp_attr_get_ecommunity(attr_new
));
4492 if (bgp_debug_update(peer
, p
, NULL
, 1))
4494 "Change in EXT-COMM, existing %s new %s",
4496 bgp_attr_get_ecommunity(
4499 bgp_attr_get_ecommunity(
4501 if (safi
== SAFI_EVPN
)
4502 bgp_evpn_unimport_route(
4503 bgp
, afi
, safi
, p
, pi
);
4504 else /* SAFI_MPLS_VPN */
4505 vpn_leak_to_vrf_withdraw(bgp
,
4511 /* Update to new attribute. */
4512 bgp_attr_unintern(&pi
->attr
);
4513 pi
->attr
= attr_new
;
4515 /* Update MPLS label */
4516 if (has_valid_label
) {
4517 extra
= bgp_path_info_extra_get(pi
);
4518 if (extra
->label
!= label
) {
4519 memcpy(&extra
->label
, label
,
4520 num_labels
* sizeof(mpls_label_t
));
4521 extra
->num_labels
= num_labels
;
4523 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4524 bgp_set_valid_label(&extra
->label
[0]);
4527 /* Update SRv6 SID */
4528 if (attr
->srv6_l3vpn
) {
4529 extra
= bgp_path_info_extra_get(pi
);
4530 if (sid_diff(&extra
->sid
[0].sid
,
4531 &attr
->srv6_l3vpn
->sid
)) {
4532 sid_copy(&extra
->sid
[0].sid
,
4533 &attr
->srv6_l3vpn
->sid
);
4534 extra
->num_sids
= 1;
4536 extra
->sid
[0].loc_block_len
= 0;
4537 extra
->sid
[0].loc_node_len
= 0;
4538 extra
->sid
[0].func_len
= 0;
4539 extra
->sid
[0].arg_len
= 0;
4540 extra
->sid
[0].transposition_len
= 0;
4541 extra
->sid
[0].transposition_offset
= 0;
4543 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4544 extra
->sid
[0].loc_block_len
=
4545 attr
->srv6_l3vpn
->loc_block_len
;
4546 extra
->sid
[0].loc_node_len
=
4547 attr
->srv6_l3vpn
->loc_node_len
;
4548 extra
->sid
[0].func_len
=
4549 attr
->srv6_l3vpn
->func_len
;
4550 extra
->sid
[0].arg_len
=
4551 attr
->srv6_l3vpn
->arg_len
;
4552 extra
->sid
[0].transposition_len
=
4554 ->transposition_len
;
4555 extra
->sid
[0].transposition_offset
=
4557 ->transposition_offset
;
4560 } else if (attr
->srv6_vpn
) {
4561 extra
= bgp_path_info_extra_get(pi
);
4562 if (sid_diff(&extra
->sid
[0].sid
,
4563 &attr
->srv6_vpn
->sid
)) {
4564 sid_copy(&extra
->sid
[0].sid
,
4565 &attr
->srv6_vpn
->sid
);
4566 extra
->num_sids
= 1;
4570 #ifdef ENABLE_BGP_VNC
4571 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4572 && (safi
== SAFI_UNICAST
)) {
4573 if (vnc_implicit_withdraw
) {
4575 * Add back the route with its new attributes
4577 * The route is still selected, until the route
4579 * queued by bgp_process actually runs. We have
4581 * update to the VNC side immediately to avoid
4583 * configuration changes (e.g., route-map
4585 * trigger re-importation of the entire RIB.
4587 vnc_import_bgp_add_route(bgp
, p
, pi
);
4588 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4593 /* Update bgp route dampening information. */
4594 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4595 && peer
->sort
== BGP_PEER_EBGP
) {
4596 /* Now we do normal update dampening. */
4597 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4598 if (ret
== BGP_DAMP_SUPPRESSED
) {
4599 bgp_dest_unlock_node(dest
);
4604 /* Nexthop reachability check - for unicast and
4605 * labeled-unicast.. */
4606 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4607 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4608 || (safi
== SAFI_EVPN
&&
4609 bgp_evpn_is_prefix_nht_supported(p
))) {
4610 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4611 && peer
->ttl
== BGP_DEFAULT_TTL
4612 && !CHECK_FLAG(peer
->flags
,
4613 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4614 && !CHECK_FLAG(bgp
->flags
,
4615 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4620 struct bgp
*bgp_nexthop
= bgp
;
4622 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4623 bgp_nexthop
= pi
->extra
->bgp_orig
;
4625 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4627 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4628 safi
, pi
, NULL
, connected
,
4629 bgp_nht_param_prefix
) ||
4630 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4631 bgp_path_info_set_flag(dest
, pi
,
4634 if (BGP_DEBUG(nht
, NHT
)) {
4635 zlog_debug("%s(%pI4): NH unresolved",
4637 (in_addr_t
*)&attr_new
->nexthop
);
4639 bgp_path_info_unset_flag(dest
, pi
,
4644 bgp_path_info_set_flag(dest
, pi
,
4645 BGP_PATH_ACCEPT_OWN
);
4647 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4650 #ifdef ENABLE_BGP_VNC
4651 if (safi
== SAFI_MPLS_VPN
) {
4652 struct bgp_dest
*pdest
= NULL
;
4653 struct bgp_table
*table
= NULL
;
4655 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4656 (struct prefix
*)prd
);
4657 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4658 table
= bgp_dest_get_bgp_table_info(pdest
);
4660 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4661 bgp
, prd
, table
, p
, pi
);
4663 bgp_dest_unlock_node(pdest
);
4667 /* If this is an EVPN route and some attribute has changed,
4668 * or we are explicitly told to perform a route import, process
4669 * route for import. If the extended community has changed, we
4671 * have done the un-import earlier and the import would result
4673 * route getting injected into appropriate L2 VNIs. If it is
4675 * some other attribute change, the import will result in
4677 * the attributes for the route in the VNI(s).
4679 if (safi
== SAFI_EVPN
&&
4680 (!same_attr
|| force_evpn_import
) &&
4681 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4682 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4684 /* Process change. */
4685 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4687 bgp_process(bgp
, dest
, afi
, safi
);
4688 bgp_dest_unlock_node(dest
);
4690 if (SAFI_UNICAST
== safi
4691 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4692 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4694 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4696 if ((SAFI_MPLS_VPN
== safi
)
4697 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4698 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4701 #ifdef ENABLE_BGP_VNC
4702 if (SAFI_MPLS_VPN
== safi
) {
4703 mpls_label_t label_decoded
= decode_label(label
);
4705 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4706 type
, sub_type
, &label_decoded
);
4708 if (SAFI_ENCAP
== safi
) {
4709 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4710 type
, sub_type
, NULL
);
4713 if ((safi
== SAFI_MPLS_VPN
) &&
4714 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4715 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4717 bgp_unlink_nexthop(pi
);
4718 bgp_path_info_delete(dest
, pi
);
4721 } // End of implicit withdraw
4723 /* Received Logging. */
4724 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4725 if (!peer
->rcvd_attr_printed
) {
4726 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4727 peer
->rcvd_attr_str
);
4728 peer
->rcvd_attr_printed
= 1;
4731 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4732 addpath_id
? 1 : 0, addpath_id
, evpn
,
4733 pfx_buf
, sizeof(pfx_buf
));
4734 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4737 /* Make new BGP info. */
4738 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4740 /* Update MPLS label */
4741 if (has_valid_label
) {
4742 extra
= bgp_path_info_extra_get(new);
4743 if (extra
->label
!= label
) {
4744 memcpy(&extra
->label
, label
,
4745 num_labels
* sizeof(mpls_label_t
));
4746 extra
->num_labels
= num_labels
;
4748 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4749 bgp_set_valid_label(&extra
->label
[0]);
4752 /* Update SRv6 SID */
4753 if (safi
== SAFI_MPLS_VPN
) {
4754 extra
= bgp_path_info_extra_get(new);
4755 if (attr
->srv6_l3vpn
) {
4756 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4757 extra
->num_sids
= 1;
4759 extra
->sid
[0].loc_block_len
=
4760 attr
->srv6_l3vpn
->loc_block_len
;
4761 extra
->sid
[0].loc_node_len
=
4762 attr
->srv6_l3vpn
->loc_node_len
;
4763 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4764 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4765 extra
->sid
[0].transposition_len
=
4766 attr
->srv6_l3vpn
->transposition_len
;
4767 extra
->sid
[0].transposition_offset
=
4768 attr
->srv6_l3vpn
->transposition_offset
;
4769 } else if (attr
->srv6_vpn
) {
4770 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4771 extra
->num_sids
= 1;
4775 /* Nexthop reachability check. */
4776 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4777 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4778 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4779 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4780 && peer
->ttl
== BGP_DEFAULT_TTL
4781 && !CHECK_FLAG(peer
->flags
,
4782 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4783 && !CHECK_FLAG(bgp
->flags
,
4784 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4789 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4791 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4792 connected
, bgp_nht_param_prefix
) ||
4793 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4794 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4796 if (BGP_DEBUG(nht
, NHT
))
4797 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4798 &attr_new
->nexthop
);
4799 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4803 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4805 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4808 /* If maximum prefix count is configured and current prefix
4811 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4812 reason
= "maximum-prefix overflow";
4813 bgp_attr_flush(&new_attr
);
4818 new->addpath_rx_id
= addpath_id
;
4820 /* Increment prefix */
4821 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4823 /* Register new BGP information. */
4824 bgp_path_info_add(dest
, new);
4826 /* route_node_get lock */
4827 bgp_dest_unlock_node(dest
);
4829 #ifdef ENABLE_BGP_VNC
4830 if (safi
== SAFI_MPLS_VPN
) {
4831 struct bgp_dest
*pdest
= NULL
;
4832 struct bgp_table
*table
= NULL
;
4834 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4835 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4836 table
= bgp_dest_get_bgp_table_info(pdest
);
4838 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4839 bgp
, prd
, table
, p
, new);
4841 bgp_dest_unlock_node(pdest
);
4845 /* If this is an EVPN route, process for import. */
4846 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4847 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4849 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4851 /* Process change. */
4852 bgp_process(bgp
, dest
, afi
, safi
);
4854 if (SAFI_UNICAST
== safi
4855 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4856 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4857 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4859 if ((SAFI_MPLS_VPN
== safi
)
4860 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4861 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4863 #ifdef ENABLE_BGP_VNC
4864 if (SAFI_MPLS_VPN
== safi
) {
4865 mpls_label_t label_decoded
= decode_label(label
);
4867 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4868 sub_type
, &label_decoded
);
4870 if (SAFI_ENCAP
== safi
) {
4871 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4875 if ((safi
== SAFI_MPLS_VPN
) &&
4876 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4877 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4879 bgp_unlink_nexthop(new);
4880 bgp_path_info_delete(dest
, new);
4885 /* This BGP update is filtered. Log the reason then update BGP
4889 bgp_unlink_nexthop(new);
4890 bgp_path_info_delete(dest
, new);
4891 bgp_path_info_extra_free(&new->extra
);
4892 XFREE(MTYPE_BGP_ROUTE
, new);
4895 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4897 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4898 if (!peer
->rcvd_attr_printed
) {
4899 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4900 peer
->rcvd_attr_str
);
4901 peer
->rcvd_attr_printed
= 1;
4904 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4905 addpath_id
? 1 : 0, addpath_id
, evpn
,
4906 pfx_buf
, sizeof(pfx_buf
));
4907 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4908 peer
, pfx_buf
, reason
);
4912 /* If this is an EVPN route, un-import it as it is now filtered.
4914 if (safi
== SAFI_EVPN
)
4915 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4917 if (SAFI_UNICAST
== safi
4918 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4919 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4921 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4923 if ((SAFI_MPLS_VPN
== safi
)
4924 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4926 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4929 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4932 bgp_dest_unlock_node(dest
);
4934 #ifdef ENABLE_BGP_VNC
4936 * Filtered update is treated as an implicit withdrawal (see
4938 * a few lines above)
4940 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4941 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4949 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4950 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4951 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4952 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4955 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4956 struct bgp_dest
*dest
;
4957 struct bgp_path_info
*pi
;
4959 #ifdef ENABLE_BGP_VNC
4960 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4961 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4969 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4971 /* If peer is soft reconfiguration enabled. Record input packet for
4972 * further calculation.
4974 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4975 * routes that are filtered. This tanks out Quagga RS pretty badly due
4977 * the iteration over all RS clients.
4978 * Since we need to remove the entry from adj_in anyway, do that first
4980 * if there was no entry, we don't need to do anything more.
4982 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4983 && peer
!= bgp
->peer_self
)
4984 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4985 peer
->stat_pfx_dup_withdraw
++;
4987 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4988 bgp_debug_rdpfxpath2str(
4989 afi
, safi
, prd
, p
, label
, num_labels
,
4990 addpath_id
? 1 : 0, addpath_id
, NULL
,
4991 pfx_buf
, sizeof(pfx_buf
));
4993 "%s withdrawing route %s not in adj-in",
4994 peer
->host
, pfx_buf
);
4996 bgp_dest_unlock_node(dest
);
5000 /* Lookup withdrawn route. */
5001 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5002 if (pi
->peer
== peer
&& pi
->type
== type
5003 && pi
->sub_type
== sub_type
5004 && pi
->addpath_rx_id
== addpath_id
)
5008 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5009 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5010 addpath_id
? 1 : 0, addpath_id
, NULL
,
5011 pfx_buf
, sizeof(pfx_buf
));
5012 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
5016 /* Withdraw specified route from routing table. */
5017 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
5018 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
5019 if (SAFI_UNICAST
== safi
5020 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5021 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5022 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5024 if ((SAFI_MPLS_VPN
== safi
)
5025 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5027 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5029 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5030 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5031 addpath_id
? 1 : 0, addpath_id
, NULL
,
5032 pfx_buf
, sizeof(pfx_buf
));
5033 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
5036 /* Unlock bgp_node_get() lock. */
5037 bgp_dest_unlock_node(dest
);
5042 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
5045 struct update_subgroup
*subgrp
;
5046 subgrp
= peer_subgroup(peer
, afi
, safi
);
5047 subgroup_default_originate(subgrp
, withdraw
);
5052 * bgp_stop_announce_route_timer
5054 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5056 if (!paf
->t_announce_route
)
5059 THREAD_OFF(paf
->t_announce_route
);
5063 * bgp_announce_route_timer_expired
5065 * Callback that is invoked when the route announcement timer for a
5068 static void bgp_announce_route_timer_expired(struct thread
*t
)
5070 struct peer_af
*paf
;
5073 paf
= THREAD_ARG(t
);
5076 if (!peer_established(peer
))
5079 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5082 peer_af_announce_route(paf
, 1);
5084 /* Notify BGP conditional advertisement scanner percess */
5085 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5089 * bgp_announce_route
5091 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5093 * if force is true we will force an update even if the update
5094 * limiting code is attempted to kick in.
5096 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5098 struct peer_af
*paf
;
5099 struct update_subgroup
*subgrp
;
5101 paf
= peer_af_find(peer
, afi
, safi
);
5104 subgrp
= PAF_SUBGRP(paf
);
5107 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5108 * or a refresh has already been triggered.
5110 if (!subgrp
|| paf
->t_announce_route
)
5114 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5117 * Start a timer to stagger/delay the announce. This serves
5118 * two purposes - announcement can potentially be combined for
5119 * multiple peers and the announcement doesn't happen in the
5122 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5123 (subgrp
->peer_count
== 1)
5124 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5125 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5126 &paf
->t_announce_route
);
5130 * Announce routes from all AF tables to a peer.
5132 * This should ONLY be called when there is a need to refresh the
5133 * routes to the peer based on a policy change for this peer alone
5134 * or a route refresh request received from the peer.
5135 * The operation will result in splitting the peer from its existing
5136 * subgroups and putting it in new subgroups.
5138 void bgp_announce_route_all(struct peer
*peer
)
5143 FOREACH_AFI_SAFI (afi
, safi
)
5144 bgp_announce_route(peer
, afi
, safi
, false);
5147 /* Flag or unflag bgp_dest to determine whether it should be treated by
5148 * bgp_soft_reconfig_table_task.
5149 * Flag if flag is true. Unflag if flag is false.
5151 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5153 struct bgp_dest
*dest
;
5154 struct bgp_adj_in
*ain
;
5159 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5160 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5161 if (ain
->peer
!= NULL
)
5164 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5165 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5167 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5171 static int bgp_soft_reconfig_table_update(struct peer
*peer
,
5172 struct bgp_dest
*dest
,
5173 struct bgp_adj_in
*ain
, afi_t afi
,
5174 safi_t safi
, struct prefix_rd
*prd
)
5176 struct bgp_path_info
*pi
;
5177 uint32_t num_labels
= 0;
5178 mpls_label_t
*label_pnt
= NULL
;
5179 struct bgp_route_evpn evpn
;
5181 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5182 if (pi
->peer
== peer
)
5185 if (pi
&& pi
->extra
)
5186 num_labels
= pi
->extra
->num_labels
;
5188 label_pnt
= &pi
->extra
->label
[0];
5190 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5193 memset(&evpn
, 0, sizeof(evpn
));
5195 return bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5196 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
5197 BGP_ROUTE_NORMAL
, prd
, label_pnt
, num_labels
, 1,
5201 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5202 struct bgp_table
*table
,
5203 struct prefix_rd
*prd
)
5206 struct bgp_dest
*dest
;
5207 struct bgp_adj_in
*ain
;
5210 table
= peer
->bgp
->rib
[afi
][safi
];
5212 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5213 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5214 if (ain
->peer
!= peer
)
5217 ret
= bgp_soft_reconfig_table_update(peer
, dest
, ain
,
5221 bgp_dest_unlock_node(dest
);
5227 /* Do soft reconfig table per bgp table.
5228 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5229 * when BGP_NODE_SOFT_RECONFIG is set,
5230 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5231 * Schedule a new thread to continue the job.
5232 * Without splitting the full job into several part,
5233 * vtysh waits for the job to finish before responding to a BGP command
5235 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
5237 uint32_t iter
, max_iter
;
5239 struct bgp_dest
*dest
;
5240 struct bgp_adj_in
*ain
;
5242 struct bgp_table
*table
;
5243 struct prefix_rd
*prd
;
5244 struct listnode
*node
, *nnode
;
5246 table
= THREAD_ARG(thread
);
5249 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5250 if (table
->soft_reconfig_init
) {
5251 /* first call of the function with a new srta structure.
5252 * Don't do any treatment this time on nodes
5253 * in order vtysh to respond quickly
5258 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5259 dest
= bgp_route_next(dest
)) {
5260 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5263 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5265 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5266 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5268 if (ain
->peer
!= peer
)
5271 ret
= bgp_soft_reconfig_table_update(
5272 peer
, dest
, ain
, table
->afi
,
5277 bgp_dest_unlock_node(dest
);
5279 table
->soft_reconfig_peers
,
5281 bgp_announce_route(peer
, table
->afi
,
5282 table
->safi
, false);
5284 table
->soft_reconfig_peers
)) {
5286 &table
->soft_reconfig_peers
);
5287 bgp_soft_reconfig_table_flag(
5296 /* we're either starting the initial iteration,
5297 * or we're going to continue an ongoing iteration
5299 if (dest
|| table
->soft_reconfig_init
) {
5300 table
->soft_reconfig_init
= false;
5301 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
5302 table
, 0, &table
->soft_reconfig_thread
);
5305 /* we're done, clean up the background iteration context info and
5306 schedule route annoucement
5308 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5309 listnode_delete(table
->soft_reconfig_peers
, peer
);
5310 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5313 list_delete(&table
->soft_reconfig_peers
);
5317 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5319 * - bgp cannot be NULL
5320 * - if table and peer are NULL, cancel all threads within the bgp instance
5321 * - if table is NULL and peer is not,
5322 * remove peer in all threads within the bgp instance
5323 * - if peer is NULL, cancel all threads matching table within the bgp instance
5325 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5326 const struct bgp_table
*table
,
5327 const struct peer
*peer
)
5330 struct listnode
*node
, *nnode
;
5332 struct bgp_table
*ntable
;
5337 FOREACH_AFI_SAFI (afi
, safi
) {
5338 ntable
= bgp
->rib
[afi
][safi
];
5341 if (table
&& table
!= ntable
)
5344 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5346 if (peer
&& peer
!= npeer
)
5348 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5351 if (!ntable
->soft_reconfig_peers
5352 || !list_isempty(ntable
->soft_reconfig_peers
))
5355 list_delete(&ntable
->soft_reconfig_peers
);
5356 bgp_soft_reconfig_table_flag(ntable
, false);
5357 THREAD_OFF(ntable
->soft_reconfig_thread
);
5362 * Returns false if the peer is not configured for soft reconfig in
5364 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5366 struct bgp_dest
*dest
;
5367 struct bgp_table
*table
;
5368 struct listnode
*node
, *nnode
;
5370 struct peer_af
*paf
;
5372 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5375 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5376 && (safi
!= SAFI_EVPN
)) {
5377 table
= peer
->bgp
->rib
[afi
][safi
];
5381 table
->soft_reconfig_init
= true;
5383 if (!table
->soft_reconfig_peers
)
5384 table
->soft_reconfig_peers
= list_new();
5386 /* add peer to the table soft_reconfig_peers if not already
5389 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5395 listnode_add(table
->soft_reconfig_peers
, peer
);
5397 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5398 * on table would start back at the beginning.
5400 bgp_soft_reconfig_table_flag(table
, true);
5402 if (!table
->soft_reconfig_thread
)
5403 thread_add_event(bm
->master
,
5404 bgp_soft_reconfig_table_task
, table
, 0,
5405 &table
->soft_reconfig_thread
);
5406 /* Cancel bgp_announce_route_timer_expired threads.
5407 * bgp_announce_route_timer_expired threads have been scheduled
5408 * to announce routes as soon as the soft_reconfigure process
5410 * In this case, soft_reconfigure is also scheduled by using
5411 * a thread but is planned after the
5412 * bgp_announce_route_timer_expired threads. It means that,
5413 * without cancelling the threads, the route announcement task
5414 * would run before the soft reconfiguration one. That would
5415 * useless and would block vtysh during several seconds. Route
5416 * announcements are rescheduled as soon as the soft_reconfigure
5419 paf
= peer_af_find(peer
, afi
, safi
);
5421 bgp_stop_announce_route_timer(paf
);
5423 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5424 dest
= bgp_route_next(dest
)) {
5425 table
= bgp_dest_get_bgp_table_info(dest
);
5430 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5431 struct prefix_rd prd
;
5433 prd
.family
= AF_UNSPEC
;
5435 memcpy(&prd
.val
, p
->u
.val
, 8);
5437 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5444 struct bgp_clear_node_queue
{
5445 struct bgp_dest
*dest
;
5448 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5450 struct bgp_clear_node_queue
*cnq
= data
;
5451 struct bgp_dest
*dest
= cnq
->dest
;
5452 struct peer
*peer
= wq
->spec
.data
;
5453 struct bgp_path_info
*pi
;
5455 afi_t afi
= bgp_dest_table(dest
)->afi
;
5456 safi_t safi
= bgp_dest_table(dest
)->safi
;
5458 assert(dest
&& peer
);
5461 /* It is possible that we have multiple paths for a prefix from a peer
5462 * if that peer is using AddPath.
5464 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5465 if (pi
->peer
!= peer
)
5468 /* graceful restart STALE flag set. */
5469 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5470 && peer
->nsf
[afi
][safi
])
5471 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5472 PEER_STATUS_ENHANCED_REFRESH
))
5473 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5474 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5475 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5477 /* If this is an EVPN route, process for
5479 if (safi
== SAFI_EVPN
)
5480 bgp_evpn_unimport_route(
5482 bgp_dest_get_prefix(dest
), pi
);
5483 /* Handle withdraw for VRF route-leaking and L3VPN */
5484 if (SAFI_UNICAST
== safi
5485 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5486 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5487 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5490 if (SAFI_MPLS_VPN
== safi
&&
5491 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5492 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5495 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5501 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5503 struct bgp_clear_node_queue
*cnq
= data
;
5504 struct bgp_dest
*dest
= cnq
->dest
;
5505 struct bgp_table
*table
= bgp_dest_table(dest
);
5507 bgp_dest_unlock_node(dest
);
5508 bgp_table_unlock(table
);
5509 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5512 static void bgp_clear_node_complete(struct work_queue
*wq
)
5514 struct peer
*peer
= wq
->spec
.data
;
5516 /* Tickle FSM to start moving again */
5517 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5519 peer_unlock(peer
); /* bgp_clear_route */
5522 static void bgp_clear_node_queue_init(struct peer
*peer
)
5524 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5526 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5527 #undef CLEAR_QUEUE_NAME_LEN
5529 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5530 peer
->clear_node_queue
->spec
.hold
= 10;
5531 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5532 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5533 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5534 peer
->clear_node_queue
->spec
.max_retries
= 0;
5536 /* we only 'lock' this peer reference when the queue is actually active
5538 peer
->clear_node_queue
->spec
.data
= peer
;
5541 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5542 struct bgp_table
*table
)
5544 struct bgp_dest
*dest
;
5545 int force
= peer
->bgp
->process_queue
? 0 : 1;
5548 table
= peer
->bgp
->rib
[afi
][safi
];
5550 /* If still no table => afi/safi isn't configured at all or smth. */
5554 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5555 struct bgp_path_info
*pi
, *next
;
5556 struct bgp_adj_in
*ain
;
5557 struct bgp_adj_in
*ain_next
;
5559 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5560 * queued for every clearing peer, regardless of whether it is
5561 * relevant to the peer at hand.
5563 * Overview: There are 3 different indices which need to be
5564 * scrubbed, potentially, when a peer is removed:
5566 * 1 peer's routes visible via the RIB (ie accepted routes)
5567 * 2 peer's routes visible by the (optional) peer's adj-in index
5568 * 3 other routes visible by the peer's adj-out index
5570 * 3 there is no hurry in scrubbing, once the struct peer is
5571 * removed from bgp->peer, we could just GC such deleted peer's
5572 * adj-outs at our leisure.
5574 * 1 and 2 must be 'scrubbed' in some way, at least made
5575 * invisible via RIB index before peer session is allowed to be
5576 * brought back up. So one needs to know when such a 'search' is
5581 * - there'd be a single global queue or a single RIB walker
5582 * - rather than tracking which route_nodes still need to be
5583 * examined on a peer basis, we'd track which peers still
5586 * Given that our per-peer prefix-counts now should be reliable,
5587 * this may actually be achievable. It doesn't seem to be a huge
5588 * problem at this time,
5590 * It is possible that we have multiple paths for a prefix from
5592 * if that peer is using AddPath.
5596 ain_next
= ain
->next
;
5598 if (ain
->peer
== peer
)
5599 bgp_adj_in_remove(dest
, ain
);
5604 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5606 if (pi
->peer
!= peer
)
5610 bgp_path_info_reap(dest
, pi
);
5612 struct bgp_clear_node_queue
*cnq
;
5614 /* both unlocked in bgp_clear_node_queue_del */
5615 bgp_table_lock(bgp_dest_table(dest
));
5616 bgp_dest_lock_node(dest
);
5618 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5619 sizeof(struct bgp_clear_node_queue
));
5621 work_queue_add(peer
->clear_node_queue
, cnq
);
5629 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5631 struct bgp_dest
*dest
;
5632 struct bgp_table
*table
;
5634 if (peer
->clear_node_queue
== NULL
)
5635 bgp_clear_node_queue_init(peer
);
5637 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5638 * Idle until it receives a Clearing_Completed event. This protects
5639 * against peers which flap faster than we can we clear, which could
5642 * a) race with routes from the new session being installed before
5643 * clear_route_node visits the node (to delete the route of that
5645 * b) resource exhaustion, clear_route_node likely leads to an entry
5646 * on the process_main queue. Fast-flapping could cause that queue
5650 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5651 * the unlock will happen upon work-queue completion; other wise, the
5652 * unlock happens at the end of this function.
5654 if (!peer
->clear_node_queue
->thread
)
5657 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5658 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5660 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5661 dest
= bgp_route_next(dest
)) {
5662 table
= bgp_dest_get_bgp_table_info(dest
);
5666 bgp_clear_route_table(peer
, afi
, safi
, table
);
5669 /* unlock if no nodes got added to the clear-node-queue. */
5670 if (!peer
->clear_node_queue
->thread
)
5674 void bgp_clear_route_all(struct peer
*peer
)
5679 FOREACH_AFI_SAFI (afi
, safi
)
5680 bgp_clear_route(peer
, afi
, safi
);
5682 #ifdef ENABLE_BGP_VNC
5683 rfapiProcessPeerDown(peer
);
5687 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5689 struct bgp_table
*table
;
5690 struct bgp_dest
*dest
;
5691 struct bgp_adj_in
*ain
;
5692 struct bgp_adj_in
*ain_next
;
5694 table
= peer
->bgp
->rib
[afi
][safi
];
5696 /* It is possible that we have multiple paths for a prefix from a peer
5697 * if that peer is using AddPath.
5699 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5703 ain_next
= ain
->next
;
5705 if (ain
->peer
== peer
)
5706 bgp_adj_in_remove(dest
, ain
);
5713 /* If any of the routes from the peer have been marked with the NO_LLGR
5714 * community, either as sent by the peer, or as the result of a configured
5715 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5716 * operation of [RFC4271].
5718 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5720 struct bgp_dest
*dest
;
5721 struct bgp_path_info
*pi
;
5722 struct bgp_table
*table
;
5724 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5725 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5726 dest
= bgp_route_next(dest
)) {
5727 struct bgp_dest
*rm
;
5729 /* look for neighbor in tables */
5730 table
= bgp_dest_get_bgp_table_info(dest
);
5734 for (rm
= bgp_table_top(table
); rm
;
5735 rm
= bgp_route_next(rm
))
5736 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5738 if (pi
->peer
!= peer
)
5741 peer
->af_sflags
[afi
][safi
],
5742 PEER_STATUS_LLGR_WAIT
) &&
5743 bgp_attr_get_community(pi
->attr
) &&
5745 bgp_attr_get_community(
5749 if (!CHECK_FLAG(pi
->flags
,
5754 * If this is VRF leaked route
5755 * process for withdraw.
5758 BGP_ROUTE_IMPORTED
&&
5759 peer
->bgp
->inst_type
==
5760 BGP_INSTANCE_TYPE_DEFAULT
)
5761 vpn_leak_to_vrf_withdraw(
5764 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5769 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5770 dest
= bgp_route_next(dest
))
5771 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5773 if (pi
->peer
!= peer
)
5775 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5776 PEER_STATUS_LLGR_WAIT
) &&
5777 bgp_attr_get_community(pi
->attr
) &&
5779 bgp_attr_get_community(pi
->attr
),
5782 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5784 if (safi
== SAFI_UNICAST
&&
5785 (peer
->bgp
->inst_type
==
5786 BGP_INSTANCE_TYPE_VRF
||
5787 peer
->bgp
->inst_type
==
5788 BGP_INSTANCE_TYPE_DEFAULT
))
5789 vpn_leak_from_vrf_withdraw(
5790 bgp_get_default(), peer
->bgp
,
5793 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5799 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5801 struct bgp_dest
*dest
, *ndest
;
5802 struct bgp_path_info
*pi
;
5803 struct bgp_table
*table
;
5805 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5806 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5807 dest
= bgp_route_next(dest
)) {
5808 table
= bgp_dest_get_bgp_table_info(dest
);
5812 for (ndest
= bgp_table_top(table
); ndest
;
5813 ndest
= bgp_route_next(ndest
)) {
5814 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5816 if (pi
->peer
!= peer
)
5820 peer
->af_sflags
[afi
][safi
],
5821 PEER_STATUS_ENHANCED_REFRESH
))
5822 && !CHECK_FLAG(pi
->flags
,
5826 BGP_PATH_UNUSEABLE
)) {
5827 if (bgp_debug_neighbor_events(
5830 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5834 bgp_dest_get_prefix(
5837 bgp_path_info_set_flag(
5845 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5846 dest
= bgp_route_next(dest
)) {
5847 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5849 if (pi
->peer
!= peer
)
5852 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5853 PEER_STATUS_ENHANCED_REFRESH
))
5854 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5855 && !CHECK_FLAG(pi
->flags
,
5856 BGP_PATH_UNUSEABLE
)) {
5857 if (bgp_debug_neighbor_events(peer
))
5859 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5862 bgp_dest_get_prefix(
5865 bgp_path_info_set_flag(dest
, pi
,
5873 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5875 if (peer
->sort
== BGP_PEER_IBGP
)
5878 if (peer
->sort
== BGP_PEER_EBGP
5879 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5880 || FILTER_LIST_OUT_NAME(filter
)
5881 || DISTRIBUTE_OUT_NAME(filter
)))
5886 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5888 if (peer
->sort
== BGP_PEER_IBGP
)
5891 if (peer
->sort
== BGP_PEER_EBGP
5892 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5893 || FILTER_LIST_IN_NAME(filter
)
5894 || DISTRIBUTE_IN_NAME(filter
)))
5899 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5902 struct bgp_dest
*dest
;
5903 struct bgp_path_info
*pi
;
5904 struct bgp_path_info
*next
;
5906 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5907 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5908 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5912 /* Unimport EVPN routes from VRFs */
5913 if (safi
== SAFI_EVPN
)
5914 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5917 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5918 && pi
->type
== ZEBRA_ROUTE_BGP
5919 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5920 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5921 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5923 if (bgp_fibupd_safi(safi
))
5924 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5927 bgp_path_info_reap(dest
, pi
);
5931 /* Delete all kernel routes. */
5932 void bgp_cleanup_routes(struct bgp
*bgp
)
5935 struct bgp_dest
*dest
;
5936 struct bgp_table
*table
;
5938 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5939 if (afi
== AFI_L2VPN
)
5941 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5944 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5946 if (afi
!= AFI_L2VPN
) {
5948 safi
= SAFI_MPLS_VPN
;
5949 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5950 dest
= bgp_route_next(dest
)) {
5951 table
= bgp_dest_get_bgp_table_info(dest
);
5952 if (table
!= NULL
) {
5953 bgp_cleanup_table(bgp
, table
, safi
);
5954 bgp_table_finish(&table
);
5955 bgp_dest_set_bgp_table_info(dest
, NULL
);
5956 bgp_dest_unlock_node(dest
);
5960 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5961 dest
= bgp_route_next(dest
)) {
5962 table
= bgp_dest_get_bgp_table_info(dest
);
5963 if (table
!= NULL
) {
5964 bgp_cleanup_table(bgp
, table
, safi
);
5965 bgp_table_finish(&table
);
5966 bgp_dest_set_bgp_table_info(dest
, NULL
);
5967 bgp_dest_unlock_node(dest
);
5972 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5973 dest
= bgp_route_next(dest
)) {
5974 table
= bgp_dest_get_bgp_table_info(dest
);
5975 if (table
!= NULL
) {
5976 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5977 bgp_table_finish(&table
);
5978 bgp_dest_set_bgp_table_info(dest
, NULL
);
5979 bgp_dest_unlock_node(dest
);
5984 void bgp_reset(void)
5987 bgp_zclient_reset();
5988 access_list_reset();
5989 prefix_list_reset();
5992 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5994 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5995 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5996 PEER_CAP_ADDPATH_AF_TX_RCV
));
5999 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
6001 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
6002 struct bgp_nlri
*packet
)
6011 bool addpath_capable
;
6012 uint32_t addpath_id
;
6015 lim
= pnt
+ packet
->length
;
6017 safi
= packet
->safi
;
6019 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
6021 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6022 syntactic validity. If the field is syntactically incorrect,
6023 then the Error Subcode is set to Invalid Network Field. */
6024 for (; pnt
< lim
; pnt
+= psize
) {
6025 /* Clear prefix structure. */
6026 memset(&p
, 0, sizeof(p
));
6028 if (addpath_capable
) {
6030 /* When packet overflow occurs return immediately. */
6031 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
6032 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6034 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
6035 addpath_id
= ntohl(addpath_id
);
6036 pnt
+= BGP_ADDPATH_ID_LEN
;
6039 /* Fetch prefix length. */
6040 p
.prefixlen
= *pnt
++;
6041 /* afi/safi validity already verified by caller,
6042 * bgp_update_receive */
6043 p
.family
= afi2family(afi
);
6045 /* Prefix length check. */
6046 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
6049 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
6050 peer
->host
, p
.prefixlen
, packet
->afi
);
6051 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
6054 /* Packet size overflow check. */
6055 psize
= PSIZE(p
.prefixlen
);
6057 /* When packet overflow occur return immediately. */
6058 if (pnt
+ psize
> lim
) {
6061 "%s [Error] Update packet error (prefix length %d overflows packet)",
6062 peer
->host
, p
.prefixlen
);
6063 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6066 /* Defensive coding, double-check the psize fits in a struct
6067 * prefix for the v4 and v6 afi's and unicast/multicast */
6068 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6071 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6072 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6073 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6076 /* Fetch prefix from NLRI packet. */
6077 memcpy(p
.u
.val
, pnt
, psize
);
6079 /* Check address. */
6080 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6081 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6082 /* From RFC4271 Section 6.3:
6084 * If a prefix in the NLRI field is semantically
6086 * (e.g., an unexpected multicast IP address),
6088 * be logged locally, and the prefix SHOULD be
6093 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6094 peer
->host
, &p
.u
.prefix4
);
6099 /* Check address. */
6100 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6101 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6104 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6105 peer
->host
, &p
.u
.prefix6
);
6109 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6112 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6113 peer
->host
, &p
.u
.prefix6
);
6119 /* Normal process. */
6121 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6122 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
6123 NULL
, NULL
, 0, 0, NULL
);
6125 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
6126 safi
, ZEBRA_ROUTE_BGP
,
6127 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
6130 /* Do not send BGP notification twice when maximum-prefix count
6132 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6133 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6135 /* Address family configuration mismatch. */
6137 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
6140 /* Packet length consistency check. */
6144 "%s [Error] Update packet error (prefix length mismatch with total length)",
6146 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6149 return BGP_NLRI_PARSE_OK
;
6152 static struct bgp_static
*bgp_static_new(void)
6154 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6157 static void bgp_static_free(struct bgp_static
*bgp_static
)
6159 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6160 route_map_counter_decrement(bgp_static
->rmap
.map
);
6162 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6163 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6166 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6167 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6169 struct bgp_dest
*dest
;
6170 struct bgp_path_info
*pi
;
6171 struct bgp_path_info
*new;
6172 struct bgp_path_info rmap_path
;
6174 struct attr
*attr_new
;
6175 route_map_result_t ret
;
6176 #ifdef ENABLE_BGP_VNC
6177 int vnc_implicit_withdraw
= 0;
6182 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6184 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6186 attr
.nexthop
= bgp_static
->igpnexthop
;
6187 attr
.med
= bgp_static
->igpmetric
;
6188 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6191 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6193 if (bgp_static
->igpmetric
)
6194 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6196 if (bgp_static
->atomic
)
6197 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6199 /* Store label index, if required. */
6200 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6201 attr
.label_index
= bgp_static
->label_index
;
6202 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6205 /* Apply route-map. */
6206 if (bgp_static
->rmap
.name
) {
6207 struct attr attr_tmp
= attr
;
6209 memset(&rmap_path
, 0, sizeof(rmap_path
));
6210 rmap_path
.peer
= bgp
->peer_self
;
6211 rmap_path
.attr
= &attr_tmp
;
6213 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6215 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6217 bgp
->peer_self
->rmap_type
= 0;
6219 if (ret
== RMAP_DENYMATCH
) {
6220 /* Free uninterned attribute. */
6221 bgp_attr_flush(&attr_tmp
);
6223 /* Unintern original. */
6224 aspath_unintern(&attr
.aspath
);
6225 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6226 bgp_dest_unlock_node(dest
);
6230 if (bgp_in_graceful_shutdown(bgp
))
6231 bgp_attr_add_gshut_community(&attr_tmp
);
6233 attr_new
= bgp_attr_intern(&attr_tmp
);
6236 if (bgp_in_graceful_shutdown(bgp
))
6237 bgp_attr_add_gshut_community(&attr
);
6239 attr_new
= bgp_attr_intern(&attr
);
6242 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6243 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6244 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6248 if (attrhash_cmp(pi
->attr
, attr_new
)
6249 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6250 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6251 bgp_dest_unlock_node(dest
);
6252 bgp_attr_unintern(&attr_new
);
6253 aspath_unintern(&attr
.aspath
);
6256 /* The attribute is changed. */
6257 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6259 /* Rewrite BGP route information. */
6260 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6261 bgp_path_info_restore(dest
, pi
);
6263 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6264 #ifdef ENABLE_BGP_VNC
6265 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6266 && (safi
== SAFI_UNICAST
)) {
6267 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6269 * Implicit withdraw case.
6270 * We have to do this before pi is
6273 ++vnc_implicit_withdraw
;
6274 vnc_import_bgp_del_route(bgp
, p
, pi
);
6275 vnc_import_bgp_exterior_del_route(
6280 bgp_attr_unintern(&pi
->attr
);
6281 pi
->attr
= attr_new
;
6282 pi
->uptime
= monotime(NULL
);
6283 #ifdef ENABLE_BGP_VNC
6284 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6285 && (safi
== SAFI_UNICAST
)) {
6286 if (vnc_implicit_withdraw
) {
6287 vnc_import_bgp_add_route(bgp
, p
, pi
);
6288 vnc_import_bgp_exterior_add_route(
6294 /* Nexthop reachability check. */
6295 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6296 && (safi
== SAFI_UNICAST
6297 || safi
== SAFI_LABELED_UNICAST
)) {
6299 struct bgp
*bgp_nexthop
= bgp
;
6301 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6302 bgp_nexthop
= pi
->extra
->bgp_orig
;
6304 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6305 afi
, safi
, pi
, NULL
,
6307 bgp_path_info_set_flag(dest
, pi
,
6310 if (BGP_DEBUG(nht
, NHT
)) {
6311 char buf1
[INET6_ADDRSTRLEN
];
6312 inet_ntop(p
->family
,
6316 "%s(%s): Route not in table, not advertising",
6319 bgp_path_info_unset_flag(
6320 dest
, pi
, BGP_PATH_VALID
);
6323 /* Delete the NHT structure if any, if we're
6325 * enabling/disabling import check. We
6326 * deregister the route
6327 * from NHT to avoid overloading NHT and the
6328 * process interaction
6330 bgp_unlink_nexthop(pi
);
6331 bgp_path_info_set_flag(dest
, pi
,
6334 /* Process change. */
6335 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6336 bgp_process(bgp
, dest
, afi
, safi
);
6338 if (SAFI_UNICAST
== safi
6339 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6341 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6342 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6346 bgp_dest_unlock_node(dest
);
6347 aspath_unintern(&attr
.aspath
);
6352 /* Make new BGP info. */
6353 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6355 /* Nexthop reachability check. */
6356 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6357 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6358 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6360 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6362 if (BGP_DEBUG(nht
, NHT
)) {
6363 char buf1
[INET6_ADDRSTRLEN
];
6365 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6368 "%s(%s): Route not in table, not advertising",
6371 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6374 /* Delete the NHT structure if any, if we're toggling between
6375 * enabling/disabling import check. We deregister the route
6376 * from NHT to avoid overloading NHT and the process interaction
6378 bgp_unlink_nexthop(new);
6380 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6383 /* Aggregate address increment. */
6384 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6386 /* Register new BGP information. */
6387 bgp_path_info_add(dest
, new);
6389 /* route_node_get lock */
6390 bgp_dest_unlock_node(dest
);
6392 /* Process change. */
6393 bgp_process(bgp
, dest
, afi
, safi
);
6395 if (SAFI_UNICAST
== safi
6396 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6397 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6398 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6401 /* Unintern original. */
6402 aspath_unintern(&attr
.aspath
);
6405 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6408 struct bgp_dest
*dest
;
6409 struct bgp_path_info
*pi
;
6411 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6413 /* Check selected route and self inserted route. */
6414 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6415 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6416 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6419 /* Withdraw static BGP route from routing table. */
6421 if (SAFI_UNICAST
== safi
6422 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6423 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6424 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6426 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6427 bgp_unlink_nexthop(pi
);
6428 bgp_path_info_delete(dest
, pi
);
6429 bgp_process(bgp
, dest
, afi
, safi
);
6432 /* Unlock bgp_node_lookup. */
6433 bgp_dest_unlock_node(dest
);
6437 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6439 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6440 afi_t afi
, safi_t safi
,
6441 struct prefix_rd
*prd
)
6443 struct bgp_dest
*dest
;
6444 struct bgp_path_info
*pi
;
6446 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6448 /* Check selected route and self inserted route. */
6449 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6450 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6451 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6454 /* Withdraw static BGP route from routing table. */
6456 #ifdef ENABLE_BGP_VNC
6457 rfapiProcessWithdraw(
6458 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6459 1); /* Kill, since it is an administrative change */
6461 if (SAFI_MPLS_VPN
== safi
6462 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6463 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6465 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6466 bgp_path_info_delete(dest
, pi
);
6467 bgp_process(bgp
, dest
, afi
, safi
);
6470 /* Unlock bgp_node_lookup. */
6471 bgp_dest_unlock_node(dest
);
6474 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6475 struct bgp_static
*bgp_static
, afi_t afi
,
6478 struct bgp_dest
*dest
;
6479 struct bgp_path_info
*new;
6480 struct attr
*attr_new
;
6481 struct attr attr
= {0};
6482 struct bgp_path_info
*pi
;
6483 #ifdef ENABLE_BGP_VNC
6484 mpls_label_t label
= 0;
6486 uint32_t num_labels
= 0;
6490 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6492 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6495 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6497 attr
.nexthop
= bgp_static
->igpnexthop
;
6498 attr
.med
= bgp_static
->igpmetric
;
6499 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6501 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6502 || (safi
== SAFI_ENCAP
)) {
6503 if (afi
== AFI_IP
) {
6504 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6505 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6508 if (afi
== AFI_L2VPN
) {
6509 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6510 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6511 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6512 &bgp_static
->gatewayIp
.u
.prefix4
,
6514 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6515 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6516 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6517 &bgp_static
->gatewayIp
.u
.prefix6
,
6520 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6521 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6522 struct bgp_encap_type_vxlan bet
;
6523 memset(&bet
, 0, sizeof(bet
));
6524 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6525 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6527 if (bgp_static
->router_mac
) {
6528 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6531 /* Apply route-map. */
6532 if (bgp_static
->rmap
.name
) {
6533 struct attr attr_tmp
= attr
;
6534 struct bgp_path_info rmap_path
;
6535 route_map_result_t ret
;
6537 rmap_path
.peer
= bgp
->peer_self
;
6538 rmap_path
.attr
= &attr_tmp
;
6540 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6542 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6544 bgp
->peer_self
->rmap_type
= 0;
6546 if (ret
== RMAP_DENYMATCH
) {
6547 /* Free uninterned attribute. */
6548 bgp_attr_flush(&attr_tmp
);
6550 /* Unintern original. */
6551 aspath_unintern(&attr
.aspath
);
6552 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6554 bgp_dest_unlock_node(dest
);
6558 attr_new
= bgp_attr_intern(&attr_tmp
);
6560 attr_new
= bgp_attr_intern(&attr
);
6563 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6564 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6565 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6569 if (attrhash_cmp(pi
->attr
, attr_new
)
6570 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6571 bgp_dest_unlock_node(dest
);
6572 bgp_attr_unintern(&attr_new
);
6573 aspath_unintern(&attr
.aspath
);
6576 /* The attribute is changed. */
6577 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6579 /* Rewrite BGP route information. */
6580 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6581 bgp_path_info_restore(dest
, pi
);
6583 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6584 bgp_attr_unintern(&pi
->attr
);
6585 pi
->attr
= attr_new
;
6586 pi
->uptime
= monotime(NULL
);
6587 #ifdef ENABLE_BGP_VNC
6589 label
= decode_label(&pi
->extra
->label
[0]);
6592 /* Process change. */
6593 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6594 bgp_process(bgp
, dest
, afi
, safi
);
6596 if (SAFI_MPLS_VPN
== safi
6597 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6598 vpn_leak_to_vrf_update(bgp
, pi
,
6601 #ifdef ENABLE_BGP_VNC
6602 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6603 pi
->attr
, afi
, safi
, pi
->type
,
6604 pi
->sub_type
, &label
);
6606 bgp_dest_unlock_node(dest
);
6607 aspath_unintern(&attr
.aspath
);
6613 /* Make new BGP info. */
6614 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6616 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6617 bgp_path_info_extra_get(new);
6619 new->extra
->label
[0] = bgp_static
->label
;
6620 new->extra
->num_labels
= num_labels
;
6622 #ifdef ENABLE_BGP_VNC
6623 label
= decode_label(&bgp_static
->label
);
6626 /* Aggregate address increment. */
6627 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6629 /* Register new BGP information. */
6630 bgp_path_info_add(dest
, new);
6631 /* route_node_get lock */
6632 bgp_dest_unlock_node(dest
);
6634 /* Process change. */
6635 bgp_process(bgp
, dest
, afi
, safi
);
6637 if (SAFI_MPLS_VPN
== safi
6638 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6639 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6641 #ifdef ENABLE_BGP_VNC
6642 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6643 safi
, new->type
, new->sub_type
, &label
);
6646 /* Unintern original. */
6647 aspath_unintern(&attr
.aspath
);
6650 /* Configure static BGP network. When user don't run zebra, static
6651 route should be installed as valid. */
6652 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6653 const char *ip_str
, afi_t afi
, safi_t safi
,
6654 const char *rmap
, int backdoor
, uint32_t label_index
)
6656 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6659 struct bgp_static
*bgp_static
;
6660 struct bgp_dest
*dest
;
6661 uint8_t need_update
= 0;
6663 /* Convert IP prefix string to struct prefix. */
6664 ret
= str2prefix(ip_str
, &p
);
6666 vty_out(vty
, "%% Malformed prefix\n");
6667 return CMD_WARNING_CONFIG_FAILED
;
6669 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6670 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6671 return CMD_WARNING_CONFIG_FAILED
;
6678 /* Set BGP static route configuration. */
6679 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6682 vty_out(vty
, "%% Can't find static route specified\n");
6683 return CMD_WARNING_CONFIG_FAILED
;
6686 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6688 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6689 && (label_index
!= bgp_static
->label_index
)) {
6691 "%% label-index doesn't match static route\n");
6692 bgp_dest_unlock_node(dest
);
6693 return CMD_WARNING_CONFIG_FAILED
;
6696 if ((rmap
&& bgp_static
->rmap
.name
)
6697 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6699 "%% route-map name doesn't match static route\n");
6700 bgp_dest_unlock_node(dest
);
6701 return CMD_WARNING_CONFIG_FAILED
;
6704 /* Update BGP RIB. */
6705 if (!bgp_static
->backdoor
)
6706 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6708 /* Clear configuration. */
6709 bgp_static_free(bgp_static
);
6710 bgp_dest_set_bgp_static_info(dest
, NULL
);
6711 bgp_dest_unlock_node(dest
);
6712 bgp_dest_unlock_node(dest
);
6715 /* Set BGP static route configuration. */
6716 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6717 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6719 /* Configuration change. */
6720 /* Label index cannot be changed. */
6721 if (bgp_static
->label_index
!= label_index
) {
6722 vty_out(vty
, "%% cannot change label-index\n");
6723 bgp_dest_unlock_node(dest
);
6724 return CMD_WARNING_CONFIG_FAILED
;
6727 /* Check previous routes are installed into BGP. */
6728 if (bgp_static
->valid
6729 && bgp_static
->backdoor
!= backdoor
)
6732 bgp_static
->backdoor
= backdoor
;
6735 XFREE(MTYPE_ROUTE_MAP_NAME
,
6736 bgp_static
->rmap
.name
);
6737 route_map_counter_decrement(
6738 bgp_static
->rmap
.map
);
6739 bgp_static
->rmap
.name
=
6740 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6741 bgp_static
->rmap
.map
=
6742 route_map_lookup_by_name(rmap
);
6743 route_map_counter_increment(
6744 bgp_static
->rmap
.map
);
6746 XFREE(MTYPE_ROUTE_MAP_NAME
,
6747 bgp_static
->rmap
.name
);
6748 route_map_counter_decrement(
6749 bgp_static
->rmap
.map
);
6750 bgp_static
->rmap
.map
= NULL
;
6751 bgp_static
->valid
= 0;
6753 bgp_dest_unlock_node(dest
);
6755 /* New configuration. */
6756 bgp_static
= bgp_static_new();
6757 bgp_static
->backdoor
= backdoor
;
6758 bgp_static
->valid
= 0;
6759 bgp_static
->igpmetric
= 0;
6760 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6761 bgp_static
->label_index
= label_index
;
6764 XFREE(MTYPE_ROUTE_MAP_NAME
,
6765 bgp_static
->rmap
.name
);
6766 route_map_counter_decrement(
6767 bgp_static
->rmap
.map
);
6768 bgp_static
->rmap
.name
=
6769 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6770 bgp_static
->rmap
.map
=
6771 route_map_lookup_by_name(rmap
);
6772 route_map_counter_increment(
6773 bgp_static
->rmap
.map
);
6775 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6778 bgp_static
->valid
= 1;
6780 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6782 if (!bgp_static
->backdoor
)
6783 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6789 void bgp_static_add(struct bgp
*bgp
)
6793 struct bgp_dest
*dest
;
6794 struct bgp_dest
*rm
;
6795 struct bgp_table
*table
;
6796 struct bgp_static
*bgp_static
;
6798 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6799 FOREACH_AFI_SAFI (afi
, safi
)
6800 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6801 dest
= bgp_route_next(dest
)) {
6802 if (!bgp_dest_has_bgp_path_info_data(dest
))
6805 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6806 || (safi
== SAFI_EVPN
)) {
6807 table
= bgp_dest_get_bgp_table_info(dest
);
6809 for (rm
= bgp_table_top(table
); rm
;
6810 rm
= bgp_route_next(rm
)) {
6812 bgp_dest_get_bgp_static_info(
6814 bgp_static_update_safi(
6815 bgp
, bgp_dest_get_prefix(rm
),
6816 bgp_static
, afi
, safi
);
6820 bgp
, bgp_dest_get_prefix(dest
),
6821 bgp_dest_get_bgp_static_info(dest
), afi
,
6825 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6828 /* Called from bgp_delete(). Delete all static routes from the BGP
6830 void bgp_static_delete(struct bgp
*bgp
)
6834 struct bgp_dest
*dest
;
6835 struct bgp_dest
*rm
;
6836 struct bgp_table
*table
;
6837 struct bgp_static
*bgp_static
;
6839 FOREACH_AFI_SAFI (afi
, safi
)
6840 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6841 dest
= bgp_route_next(dest
)) {
6842 if (!bgp_dest_has_bgp_path_info_data(dest
))
6845 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6846 || (safi
== SAFI_EVPN
)) {
6847 table
= bgp_dest_get_bgp_table_info(dest
);
6849 for (rm
= bgp_table_top(table
); rm
;
6850 rm
= bgp_route_next(rm
)) {
6852 bgp_dest_get_bgp_static_info(
6857 bgp_static_withdraw_safi(
6858 bgp
, bgp_dest_get_prefix(rm
),
6860 (struct prefix_rd
*)
6861 bgp_dest_get_prefix(
6863 bgp_static_free(bgp_static
);
6864 bgp_dest_set_bgp_static_info(rm
,
6866 bgp_dest_unlock_node(rm
);
6869 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6870 bgp_static_withdraw(bgp
,
6871 bgp_dest_get_prefix(dest
),
6873 bgp_static_free(bgp_static
);
6874 bgp_dest_set_bgp_static_info(dest
, NULL
);
6875 bgp_dest_unlock_node(dest
);
6880 void bgp_static_redo_import_check(struct bgp
*bgp
)
6884 struct bgp_dest
*dest
;
6885 struct bgp_dest
*rm
;
6886 struct bgp_table
*table
;
6887 struct bgp_static
*bgp_static
;
6889 /* Use this flag to force reprocessing of the route */
6890 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6891 FOREACH_AFI_SAFI (afi
, safi
) {
6892 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6893 dest
= bgp_route_next(dest
)) {
6894 if (!bgp_dest_has_bgp_path_info_data(dest
))
6897 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6898 || (safi
== SAFI_EVPN
)) {
6899 table
= bgp_dest_get_bgp_table_info(dest
);
6901 for (rm
= bgp_table_top(table
); rm
;
6902 rm
= bgp_route_next(rm
)) {
6904 bgp_dest_get_bgp_static_info(
6906 bgp_static_update_safi(
6907 bgp
, bgp_dest_get_prefix(rm
),
6908 bgp_static
, afi
, safi
);
6911 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6912 bgp_static_update(bgp
,
6913 bgp_dest_get_prefix(dest
),
6914 bgp_static
, afi
, safi
);
6918 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6921 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6924 struct bgp_table
*table
;
6925 struct bgp_dest
*dest
;
6926 struct bgp_path_info
*pi
;
6928 /* Do not install the aggregate route if BGP is in the
6929 * process of termination.
6931 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6932 || (bgp
->peer_self
== NULL
))
6935 table
= bgp
->rib
[afi
][safi
];
6936 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6937 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6938 if (pi
->peer
== bgp
->peer_self
6939 && ((pi
->type
== ZEBRA_ROUTE_BGP
6940 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6941 || (pi
->type
!= ZEBRA_ROUTE_BGP
6943 == BGP_ROUTE_REDISTRIBUTE
))) {
6944 bgp_aggregate_decrement(
6945 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6947 bgp_unlink_nexthop(pi
);
6948 bgp_path_info_delete(dest
, pi
);
6949 bgp_process(bgp
, dest
, afi
, safi
);
6956 * Purge all networks and redistributed routes from routing table.
6957 * Invoked upon the instance going down.
6959 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6964 FOREACH_AFI_SAFI (afi
, safi
)
6965 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6970 * Currently this is used to set static routes for VPN and ENCAP.
6971 * I think it can probably be factored with bgp_static_set.
6973 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6974 const char *ip_str
, const char *rd_str
,
6975 const char *label_str
, const char *rmap_str
,
6976 int evpn_type
, const char *esi
, const char *gwip
,
6977 const char *ethtag
, const char *routermac
)
6979 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6982 struct prefix_rd prd
;
6983 struct bgp_dest
*pdest
;
6984 struct bgp_dest
*dest
;
6985 struct bgp_table
*table
;
6986 struct bgp_static
*bgp_static
;
6987 mpls_label_t label
= MPLS_INVALID_LABEL
;
6988 struct prefix gw_ip
;
6990 /* validate ip prefix */
6991 ret
= str2prefix(ip_str
, &p
);
6993 vty_out(vty
, "%% Malformed prefix\n");
6994 return CMD_WARNING_CONFIG_FAILED
;
6997 if ((afi
== AFI_L2VPN
)
6998 && (bgp_build_evpn_prefix(evpn_type
,
6999 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7000 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7001 return CMD_WARNING_CONFIG_FAILED
;
7004 ret
= str2prefix_rd(rd_str
, &prd
);
7006 vty_out(vty
, "%% Malformed rd\n");
7007 return CMD_WARNING_CONFIG_FAILED
;
7011 unsigned long label_val
;
7012 label_val
= strtoul(label_str
, NULL
, 10);
7013 encode_label(label_val
, &label
);
7016 if (safi
== SAFI_EVPN
) {
7017 if (esi
&& str2esi(esi
, NULL
) == 0) {
7018 vty_out(vty
, "%% Malformed ESI\n");
7019 return CMD_WARNING_CONFIG_FAILED
;
7021 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
7022 vty_out(vty
, "%% Malformed Router MAC\n");
7023 return CMD_WARNING_CONFIG_FAILED
;
7026 memset(&gw_ip
, 0, sizeof(gw_ip
));
7027 ret
= str2prefix(gwip
, &gw_ip
);
7029 vty_out(vty
, "%% Malformed GatewayIp\n");
7030 return CMD_WARNING_CONFIG_FAILED
;
7032 if ((gw_ip
.family
== AF_INET
7033 && is_evpn_prefix_ipaddr_v6(
7034 (struct prefix_evpn
*)&p
))
7035 || (gw_ip
.family
== AF_INET6
7036 && is_evpn_prefix_ipaddr_v4(
7037 (struct prefix_evpn
*)&p
))) {
7039 "%% GatewayIp family differs with IP prefix\n");
7040 return CMD_WARNING_CONFIG_FAILED
;
7044 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7045 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7046 bgp_dest_set_bgp_table_info(pdest
,
7047 bgp_table_init(bgp
, afi
, safi
));
7048 table
= bgp_dest_get_bgp_table_info(pdest
);
7050 dest
= bgp_node_get(table
, &p
);
7052 if (bgp_dest_has_bgp_path_info_data(dest
)) {
7053 vty_out(vty
, "%% Same network configuration exists\n");
7054 bgp_dest_unlock_node(dest
);
7056 /* New configuration. */
7057 bgp_static
= bgp_static_new();
7058 bgp_static
->backdoor
= 0;
7059 bgp_static
->valid
= 0;
7060 bgp_static
->igpmetric
= 0;
7061 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7062 bgp_static
->label
= label
;
7063 bgp_static
->prd
= prd
;
7066 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7067 route_map_counter_decrement(bgp_static
->rmap
.map
);
7068 bgp_static
->rmap
.name
=
7069 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7070 bgp_static
->rmap
.map
=
7071 route_map_lookup_by_name(rmap_str
);
7072 route_map_counter_increment(bgp_static
->rmap
.map
);
7075 if (safi
== SAFI_EVPN
) {
7077 bgp_static
->eth_s_id
=
7080 str2esi(esi
, bgp_static
->eth_s_id
);
7083 bgp_static
->router_mac
=
7084 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7085 (void)prefix_str2mac(routermac
,
7086 bgp_static
->router_mac
);
7089 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7091 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7093 bgp_static
->valid
= 1;
7094 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7100 /* Configure static BGP network. */
7101 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7102 const char *ip_str
, const char *rd_str
,
7103 const char *label_str
, int evpn_type
, const char *esi
,
7104 const char *gwip
, const char *ethtag
)
7106 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7109 struct prefix_rd prd
;
7110 struct bgp_dest
*pdest
;
7111 struct bgp_dest
*dest
;
7112 struct bgp_table
*table
;
7113 struct bgp_static
*bgp_static
;
7114 mpls_label_t label
= MPLS_INVALID_LABEL
;
7116 /* Convert IP prefix string to struct prefix. */
7117 ret
= str2prefix(ip_str
, &p
);
7119 vty_out(vty
, "%% Malformed prefix\n");
7120 return CMD_WARNING_CONFIG_FAILED
;
7123 if ((afi
== AFI_L2VPN
)
7124 && (bgp_build_evpn_prefix(evpn_type
,
7125 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7126 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7127 return CMD_WARNING_CONFIG_FAILED
;
7129 ret
= str2prefix_rd(rd_str
, &prd
);
7131 vty_out(vty
, "%% Malformed rd\n");
7132 return CMD_WARNING_CONFIG_FAILED
;
7136 unsigned long label_val
;
7137 label_val
= strtoul(label_str
, NULL
, 10);
7138 encode_label(label_val
, &label
);
7141 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7142 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7143 bgp_dest_set_bgp_table_info(pdest
,
7144 bgp_table_init(bgp
, afi
, safi
));
7146 bgp_dest_unlock_node(pdest
);
7147 table
= bgp_dest_get_bgp_table_info(pdest
);
7149 dest
= bgp_node_lookup(table
, &p
);
7152 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7154 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7155 bgp_static_free(bgp_static
);
7156 bgp_dest_set_bgp_static_info(dest
, NULL
);
7157 bgp_dest_unlock_node(dest
);
7158 bgp_dest_unlock_node(dest
);
7160 vty_out(vty
, "%% Can't find the route\n");
7165 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7166 const char *rmap_name
)
7168 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7169 struct bgp_rmap
*rmap
;
7171 rmap
= &bgp
->table_map
[afi
][safi
];
7173 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7174 route_map_counter_decrement(rmap
->map
);
7175 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7176 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7177 route_map_counter_increment(rmap
->map
);
7179 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7180 route_map_counter_decrement(rmap
->map
);
7184 if (bgp_fibupd_safi(safi
))
7185 bgp_zebra_announce_table(bgp
, afi
, safi
);
7190 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7191 const char *rmap_name
)
7193 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7194 struct bgp_rmap
*rmap
;
7196 rmap
= &bgp
->table_map
[afi
][safi
];
7197 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7198 route_map_counter_decrement(rmap
->map
);
7201 if (bgp_fibupd_safi(safi
))
7202 bgp_zebra_announce_table(bgp
, afi
, safi
);
7207 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7210 if (bgp
->table_map
[afi
][safi
].name
) {
7211 vty_out(vty
, " table-map %s\n",
7212 bgp
->table_map
[afi
][safi
].name
);
7216 DEFUN (bgp_table_map
,
7219 "BGP table to RIB route download filter\n"
7220 "Name of the route map\n")
7223 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7224 argv
[idx_word
]->arg
);
7226 DEFUN (no_bgp_table_map
,
7227 no_bgp_table_map_cmd
,
7228 "no table-map WORD",
7230 "BGP table to RIB route download filter\n"
7231 "Name of the route map\n")
7234 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7235 argv
[idx_word
]->arg
);
7241 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7242 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7243 backdoor$backdoor}]",
7245 "Specify a network to announce via BGP\n"
7250 "Route-map to modify the attributes\n"
7251 "Name of the route map\n"
7252 "Label index to associate with the prefix\n"
7253 "Label index value\n"
7254 "Specify a BGP backdoor route\n")
7256 char addr_prefix_str
[BUFSIZ
];
7261 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7263 sizeof(addr_prefix_str
));
7265 vty_out(vty
, "%% Inconsistent address and mask\n");
7266 return CMD_WARNING_CONFIG_FAILED
;
7270 return bgp_static_set(
7271 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7272 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7273 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7276 DEFPY(ipv6_bgp_network
,
7277 ipv6_bgp_network_cmd
,
7278 "[no] network X:X::X:X/M$prefix \
7279 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7281 "Specify a network to announce via BGP\n"
7283 "Route-map to modify the attributes\n"
7284 "Name of the route map\n"
7285 "Label index to associate with the prefix\n"
7286 "Label index value\n")
7288 return bgp_static_set(
7289 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7290 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7293 static struct bgp_aggregate
*bgp_aggregate_new(void)
7295 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7298 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7300 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7301 route_map_counter_decrement(aggregate
->suppress_map
);
7302 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7303 route_map_counter_decrement(aggregate
->rmap
.map
);
7304 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7308 * Helper function to avoid repeated code: prepare variables for a
7309 * `route_map_apply` call.
7311 * \returns `true` on route map match, otherwise `false`.
7313 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7314 struct bgp_aggregate
*aggregate
,
7315 struct bgp_path_info
*pi
)
7317 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7318 route_map_result_t rmr
= RMAP_DENYMATCH
;
7319 struct bgp_path_info rmap_path
= {};
7320 struct attr attr
= {};
7322 /* No route map entries created, just don't match. */
7323 if (aggregate
->suppress_map
== NULL
)
7326 /* Call route map matching and return result. */
7327 attr
.aspath
= aspath_empty();
7328 rmap_path
.peer
= bgp
->peer_self
;
7329 rmap_path
.attr
= &attr
;
7331 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7332 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7333 bgp
->peer_self
->rmap_type
= 0;
7335 bgp_attr_flush(&attr
);
7336 aspath_unintern(&attr
.aspath
);
7338 return rmr
== RMAP_PERMITMATCH
;
7341 /** Test whether the aggregation has suppressed this path or not. */
7342 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7343 struct bgp_path_info
*pi
)
7345 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7348 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7352 * Suppress this path and keep the reference.
7354 * \returns `true` if needs processing otherwise `false`.
7356 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7357 struct bgp_path_info
*pi
)
7359 struct bgp_path_info_extra
*pie
;
7361 /* Path is already suppressed by this aggregation. */
7362 if (aggr_suppress_exists(aggregate
, pi
))
7365 pie
= bgp_path_info_extra_get(pi
);
7367 /* This is the first suppression, allocate memory and list it. */
7368 if (pie
->aggr_suppressors
== NULL
)
7369 pie
->aggr_suppressors
= list_new();
7371 listnode_add(pie
->aggr_suppressors
, aggregate
);
7373 /* Only mark for processing if suppressed. */
7374 if (listcount(pie
->aggr_suppressors
) == 1) {
7375 if (BGP_DEBUG(update
, UPDATE_OUT
))
7376 zlog_debug("aggregate-address suppressing: %pFX",
7377 bgp_dest_get_prefix(pi
->net
));
7379 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7387 * Unsuppress this path and remove the reference.
7389 * \returns `true` if needs processing otherwise `false`.
7391 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7392 struct bgp_path_info
*pi
)
7394 /* Path wasn't suppressed. */
7395 if (!aggr_suppress_exists(aggregate
, pi
))
7398 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7400 /* Unsuppress and free extra memory if last item. */
7401 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7402 if (BGP_DEBUG(update
, UPDATE_OUT
))
7403 zlog_debug("aggregate-address unsuppressing: %pFX",
7404 bgp_dest_get_prefix(pi
->net
));
7406 list_delete(&pi
->extra
->aggr_suppressors
);
7407 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7414 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7415 struct aspath
*aspath
,
7416 struct community
*comm
,
7417 struct ecommunity
*ecomm
,
7418 struct lcommunity
*lcomm
)
7420 static struct aspath
*ae
= NULL
;
7423 ae
= aspath_empty();
7428 if (origin
!= pi
->attr
->origin
)
7431 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7434 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7437 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7440 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7443 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7449 static void bgp_aggregate_install(
7450 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7451 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7452 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7453 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7455 struct bgp_dest
*dest
;
7456 struct bgp_table
*table
;
7457 struct bgp_path_info
*pi
, *orig
, *new;
7460 table
= bgp
->rib
[afi
][safi
];
7462 dest
= bgp_node_get(table
, p
);
7464 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7465 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7466 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7470 * If we have paths with different MEDs, then don't install
7471 * (or uninstall) the aggregate route.
7473 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7474 goto uninstall_aggregate_route
;
7476 if (aggregate
->count
> 0) {
7478 * If the aggregate information has not changed
7479 * no need to re-install it again.
7481 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7482 ecommunity
, lcommunity
)) {
7483 bgp_dest_unlock_node(dest
);
7486 aspath_free(aspath
);
7488 community_free(&community
);
7490 ecommunity_free(&ecommunity
);
7492 lcommunity_free(&lcommunity
);
7498 * Mark the old as unusable
7501 bgp_path_info_delete(dest
, pi
);
7503 attr
= bgp_attr_aggregate_intern(
7504 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7505 aggregate
, atomic_aggregate
, p
);
7508 bgp_dest_unlock_node(dest
);
7509 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7510 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7511 zlog_debug("%s: %pFX null attribute", __func__
,
7516 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7517 bgp
->peer_self
, attr
, dest
);
7519 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7521 bgp_path_info_add(dest
, new);
7522 bgp_process(bgp
, dest
, afi
, safi
);
7524 uninstall_aggregate_route
:
7525 for (pi
= orig
; pi
; pi
= pi
->next
)
7526 if (pi
->peer
== bgp
->peer_self
7527 && pi
->type
== ZEBRA_ROUTE_BGP
7528 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7531 /* Withdraw static BGP route from routing table. */
7533 bgp_path_info_delete(dest
, pi
);
7534 bgp_process(bgp
, dest
, afi
, safi
);
7538 bgp_dest_unlock_node(dest
);
7542 * Check if the current path has different MED than other known paths.
7544 * \returns `true` if the MED matched the others else `false`.
7546 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7547 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7549 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7551 /* This is the first route being analyzed. */
7552 if (!aggregate
->med_initialized
) {
7553 aggregate
->med_initialized
= true;
7554 aggregate
->med_mismatched
= false;
7555 aggregate
->med_matched_value
= cur_med
;
7557 /* Check if routes with different MED showed up. */
7558 if (cur_med
!= aggregate
->med_matched_value
)
7559 aggregate
->med_mismatched
= true;
7562 return !aggregate
->med_mismatched
;
7566 * Initializes and tests all routes in the aggregate address path for MED
7569 * \returns `true` if all MEDs are the same otherwise `false`.
7571 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7572 struct bgp
*bgp
, const struct prefix
*p
,
7573 afi_t afi
, safi_t safi
)
7575 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7576 const struct prefix
*dest_p
;
7577 struct bgp_dest
*dest
, *top
;
7578 struct bgp_path_info
*pi
;
7579 bool med_matched
= true;
7581 aggregate
->med_initialized
= false;
7583 top
= bgp_node_get(table
, p
);
7584 for (dest
= bgp_node_get(table
, p
); dest
;
7585 dest
= bgp_route_next_until(dest
, top
)) {
7586 dest_p
= bgp_dest_get_prefix(dest
);
7587 if (dest_p
->prefixlen
<= p
->prefixlen
)
7590 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7591 if (BGP_PATH_HOLDDOWN(pi
))
7593 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7595 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7596 med_matched
= false;
7603 bgp_dest_unlock_node(top
);
7609 * Toggles the route suppression status for this aggregate address
7612 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7613 struct bgp
*bgp
, const struct prefix
*p
,
7614 afi_t afi
, safi_t safi
, bool suppress
)
7616 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7617 const struct prefix
*dest_p
;
7618 struct bgp_dest
*dest
, *top
;
7619 struct bgp_path_info
*pi
;
7620 bool toggle_suppression
;
7622 /* We've found a different MED we must revert any suppressed routes. */
7623 top
= bgp_node_get(table
, p
);
7624 for (dest
= bgp_node_get(table
, p
); dest
;
7625 dest
= bgp_route_next_until(dest
, top
)) {
7626 dest_p
= bgp_dest_get_prefix(dest
);
7627 if (dest_p
->prefixlen
<= p
->prefixlen
)
7630 toggle_suppression
= false;
7631 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7632 if (BGP_PATH_HOLDDOWN(pi
))
7634 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7637 /* We are toggling suppression back. */
7639 /* Suppress route if not suppressed already. */
7640 if (aggr_suppress_path(aggregate
, pi
))
7641 toggle_suppression
= true;
7645 /* Install route if there is no more suppression. */
7646 if (aggr_unsuppress_path(aggregate
, pi
))
7647 toggle_suppression
= true;
7650 if (toggle_suppression
)
7651 bgp_process(bgp
, dest
, afi
, safi
);
7653 bgp_dest_unlock_node(top
);
7657 * Aggregate address MED matching incremental test: this function is called
7658 * when the initial aggregation occurred and we are only testing a single
7661 * In addition to testing and setting the MED validity it also installs back
7662 * suppressed routes (if summary is configured).
7664 * Must not be called in `bgp_aggregate_route`.
7666 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7667 struct bgp
*bgp
, const struct prefix
*p
,
7668 afi_t afi
, safi_t safi
,
7669 struct bgp_path_info
*pi
)
7671 /* MED matching disabled. */
7672 if (!aggregate
->match_med
)
7675 /* Aggregation with different MED, recheck if we have got equal MEDs
7678 if (aggregate
->med_mismatched
&&
7679 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7680 aggregate
->summary_only
)
7681 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7684 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7686 /* No mismatches, just quit. */
7687 if (!aggregate
->med_mismatched
)
7690 /* Route summarization is disabled. */
7691 if (!aggregate
->summary_only
)
7694 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7697 /* Update an aggregate as routes are added/removed from the BGP table */
7698 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7699 safi_t safi
, struct bgp_aggregate
*aggregate
)
7701 struct bgp_table
*table
;
7702 struct bgp_dest
*top
;
7703 struct bgp_dest
*dest
;
7705 struct aspath
*aspath
= NULL
;
7706 struct community
*community
= NULL
;
7707 struct ecommunity
*ecommunity
= NULL
;
7708 struct lcommunity
*lcommunity
= NULL
;
7709 struct bgp_path_info
*pi
;
7710 unsigned long match
= 0;
7711 uint8_t atomic_aggregate
= 0;
7713 /* If the bgp instance is being deleted or self peer is deleted
7714 * then do not create aggregate route
7716 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7717 || (bgp
->peer_self
== NULL
))
7720 /* Initialize and test routes for MED difference. */
7721 if (aggregate
->match_med
)
7722 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7725 * Reset aggregate count: we might've been called from route map
7726 * update so in that case we must retest all more specific routes.
7728 * \see `bgp_route_map_process_update`.
7730 aggregate
->count
= 0;
7731 aggregate
->incomplete_origin_count
= 0;
7732 aggregate
->incomplete_origin_count
= 0;
7733 aggregate
->egp_origin_count
= 0;
7735 /* ORIGIN attribute: If at least one route among routes that are
7736 aggregated has ORIGIN with the value INCOMPLETE, then the
7737 aggregated route must have the ORIGIN attribute with the value
7738 INCOMPLETE. Otherwise, if at least one route among routes that
7739 are aggregated has ORIGIN with the value EGP, then the aggregated
7740 route must have the origin attribute with the value EGP. In all
7741 other case the value of the ORIGIN attribute of the aggregated
7742 route is INTERNAL. */
7743 origin
= BGP_ORIGIN_IGP
;
7745 table
= bgp
->rib
[afi
][safi
];
7747 top
= bgp_node_get(table
, p
);
7748 for (dest
= bgp_node_get(table
, p
); dest
;
7749 dest
= bgp_route_next_until(dest
, top
)) {
7750 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7752 if (dest_p
->prefixlen
<= p
->prefixlen
)
7755 /* If suppress fib is enabled and route not installed
7756 * in FIB, skip the route
7758 if (!bgp_check_advertise(bgp
, dest
))
7763 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7764 if (BGP_PATH_HOLDDOWN(pi
))
7768 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7769 atomic_aggregate
= 1;
7771 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7775 * summary-only aggregate route suppress
7776 * aggregated route announcements.
7779 * Don't create summaries if MED didn't match
7780 * otherwise neither the specific routes and the
7781 * aggregation will be announced.
7783 if (aggregate
->summary_only
7784 && AGGREGATE_MED_VALID(aggregate
)) {
7785 if (aggr_suppress_path(aggregate
, pi
))
7790 * Suppress more specific routes that match the route
7794 * Don't suppress routes if MED matching is enabled and
7795 * it mismatched otherwise we might end up with no
7796 * routes for this path.
7798 if (aggregate
->suppress_map_name
7799 && AGGREGATE_MED_VALID(aggregate
)
7800 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7801 if (aggr_suppress_path(aggregate
, pi
))
7808 * If at least one route among routes that are
7809 * aggregated has ORIGIN with the value INCOMPLETE,
7810 * then the aggregated route MUST have the ORIGIN
7811 * attribute with the value INCOMPLETE. Otherwise, if
7812 * at least one route among routes that are aggregated
7813 * has ORIGIN with the value EGP, then the aggregated
7814 * route MUST have the ORIGIN attribute with the value
7817 switch (pi
->attr
->origin
) {
7818 case BGP_ORIGIN_INCOMPLETE
:
7819 aggregate
->incomplete_origin_count
++;
7821 case BGP_ORIGIN_EGP
:
7822 aggregate
->egp_origin_count
++;
7830 if (!aggregate
->as_set
)
7834 * as-set aggregate route generate origin, as path,
7835 * and community aggregation.
7837 /* Compute aggregate route's as-path.
7839 bgp_compute_aggregate_aspath_hash(aggregate
,
7842 /* Compute aggregate route's community.
7844 if (bgp_attr_get_community(pi
->attr
))
7845 bgp_compute_aggregate_community_hash(
7847 bgp_attr_get_community(pi
->attr
));
7849 /* Compute aggregate route's extended community.
7851 if (bgp_attr_get_ecommunity(pi
->attr
))
7852 bgp_compute_aggregate_ecommunity_hash(
7854 bgp_attr_get_ecommunity(pi
->attr
));
7856 /* Compute aggregate route's large community.
7858 if (bgp_attr_get_lcommunity(pi
->attr
))
7859 bgp_compute_aggregate_lcommunity_hash(
7861 bgp_attr_get_lcommunity(pi
->attr
));
7864 bgp_process(bgp
, dest
, afi
, safi
);
7866 if (aggregate
->as_set
) {
7867 bgp_compute_aggregate_aspath_val(aggregate
);
7868 bgp_compute_aggregate_community_val(aggregate
);
7869 bgp_compute_aggregate_ecommunity_val(aggregate
);
7870 bgp_compute_aggregate_lcommunity_val(aggregate
);
7874 bgp_dest_unlock_node(top
);
7877 if (aggregate
->incomplete_origin_count
> 0)
7878 origin
= BGP_ORIGIN_INCOMPLETE
;
7879 else if (aggregate
->egp_origin_count
> 0)
7880 origin
= BGP_ORIGIN_EGP
;
7882 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7883 origin
= aggregate
->origin
;
7885 if (aggregate
->as_set
) {
7886 if (aggregate
->aspath
)
7887 /* Retrieve aggregate route's as-path.
7889 aspath
= aspath_dup(aggregate
->aspath
);
7891 if (aggregate
->community
)
7892 /* Retrieve aggregate route's community.
7894 community
= community_dup(aggregate
->community
);
7896 if (aggregate
->ecommunity
)
7897 /* Retrieve aggregate route's ecommunity.
7899 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7901 if (aggregate
->lcommunity
)
7902 /* Retrieve aggregate route's lcommunity.
7904 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7907 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7908 ecommunity
, lcommunity
, atomic_aggregate
,
7912 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7913 safi_t safi
, struct bgp_aggregate
*aggregate
)
7915 struct bgp_table
*table
;
7916 struct bgp_dest
*top
;
7917 struct bgp_dest
*dest
;
7918 struct bgp_path_info
*pi
;
7919 unsigned long match
;
7921 table
= bgp
->rib
[afi
][safi
];
7923 /* If routes exists below this node, generate aggregate routes. */
7924 top
= bgp_node_get(table
, p
);
7925 for (dest
= bgp_node_get(table
, p
); dest
;
7926 dest
= bgp_route_next_until(dest
, top
)) {
7927 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7929 if (dest_p
->prefixlen
<= p
->prefixlen
)
7933 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7934 if (BGP_PATH_HOLDDOWN(pi
))
7937 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7941 * This route is suppressed: attempt to unsuppress it.
7943 * `aggr_unsuppress_path` will fail if this particular
7944 * aggregate route was not the suppressor.
7946 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7947 listcount(pi
->extra
->aggr_suppressors
)) {
7948 if (aggr_unsuppress_path(aggregate
, pi
))
7954 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7955 aggregate
->incomplete_origin_count
--;
7956 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7957 aggregate
->egp_origin_count
--;
7959 if (aggregate
->as_set
) {
7960 /* Remove as-path from aggregate.
7962 bgp_remove_aspath_from_aggregate_hash(
7966 if (bgp_attr_get_community(pi
->attr
))
7967 /* Remove community from aggregate.
7969 bgp_remove_comm_from_aggregate_hash(
7971 bgp_attr_get_community(
7974 if (bgp_attr_get_ecommunity(pi
->attr
))
7975 /* Remove ecommunity from aggregate.
7977 bgp_remove_ecomm_from_aggregate_hash(
7979 bgp_attr_get_ecommunity(
7982 if (bgp_attr_get_lcommunity(pi
->attr
))
7983 /* Remove lcommunity from aggregate.
7985 bgp_remove_lcomm_from_aggregate_hash(
7987 bgp_attr_get_lcommunity(
7992 /* If this node was suppressed, process the change. */
7994 bgp_process(bgp
, dest
, afi
, safi
);
7996 if (aggregate
->as_set
) {
7997 aspath_free(aggregate
->aspath
);
7998 aggregate
->aspath
= NULL
;
7999 if (aggregate
->community
)
8000 community_free(&aggregate
->community
);
8001 if (aggregate
->ecommunity
)
8002 ecommunity_free(&aggregate
->ecommunity
);
8003 if (aggregate
->lcommunity
)
8004 lcommunity_free(&aggregate
->lcommunity
);
8007 bgp_dest_unlock_node(top
);
8010 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
8011 const struct prefix
*aggr_p
,
8012 struct bgp_path_info
*pinew
, afi_t afi
,
8014 struct bgp_aggregate
*aggregate
)
8017 struct aspath
*aspath
= NULL
;
8018 uint8_t atomic_aggregate
= 0;
8019 struct community
*community
= NULL
;
8020 struct ecommunity
*ecommunity
= NULL
;
8021 struct lcommunity
*lcommunity
= NULL
;
8023 /* If the bgp instance is being deleted or self peer is deleted
8024 * then do not create aggregate route
8026 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8027 || (bgp
->peer_self
== NULL
))
8030 /* ORIGIN attribute: If at least one route among routes that are
8031 * aggregated has ORIGIN with the value INCOMPLETE, then the
8032 * aggregated route must have the ORIGIN attribute with the value
8033 * INCOMPLETE. Otherwise, if at least one route among routes that
8034 * are aggregated has ORIGIN with the value EGP, then the aggregated
8035 * route must have the origin attribute with the value EGP. In all
8036 * other case the value of the ORIGIN attribute of the aggregated
8037 * route is INTERNAL.
8039 origin
= BGP_ORIGIN_IGP
;
8044 * This must be called before `summary` check to avoid
8045 * "suppressing" twice.
8047 if (aggregate
->match_med
)
8048 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8051 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8052 aggr_suppress_path(aggregate
, pinew
);
8054 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8055 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8056 aggr_suppress_path(aggregate
, pinew
);
8058 switch (pinew
->attr
->origin
) {
8059 case BGP_ORIGIN_INCOMPLETE
:
8060 aggregate
->incomplete_origin_count
++;
8062 case BGP_ORIGIN_EGP
:
8063 aggregate
->egp_origin_count
++;
8071 if (aggregate
->incomplete_origin_count
> 0)
8072 origin
= BGP_ORIGIN_INCOMPLETE
;
8073 else if (aggregate
->egp_origin_count
> 0)
8074 origin
= BGP_ORIGIN_EGP
;
8076 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8077 origin
= aggregate
->origin
;
8079 if (aggregate
->as_set
) {
8080 /* Compute aggregate route's as-path.
8082 bgp_compute_aggregate_aspath(aggregate
,
8083 pinew
->attr
->aspath
);
8085 /* Compute aggregate route's community.
8087 if (bgp_attr_get_community(pinew
->attr
))
8088 bgp_compute_aggregate_community(
8089 aggregate
, bgp_attr_get_community(pinew
->attr
));
8091 /* Compute aggregate route's extended community.
8093 if (bgp_attr_get_ecommunity(pinew
->attr
))
8094 bgp_compute_aggregate_ecommunity(
8096 bgp_attr_get_ecommunity(pinew
->attr
));
8098 /* Compute aggregate route's large community.
8100 if (bgp_attr_get_lcommunity(pinew
->attr
))
8101 bgp_compute_aggregate_lcommunity(
8103 bgp_attr_get_lcommunity(pinew
->attr
));
8105 /* Retrieve aggregate route's as-path.
8107 if (aggregate
->aspath
)
8108 aspath
= aspath_dup(aggregate
->aspath
);
8110 /* Retrieve aggregate route's community.
8112 if (aggregate
->community
)
8113 community
= community_dup(aggregate
->community
);
8115 /* Retrieve aggregate route's ecommunity.
8117 if (aggregate
->ecommunity
)
8118 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8120 /* Retrieve aggregate route's lcommunity.
8122 if (aggregate
->lcommunity
)
8123 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8126 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8127 aspath
, community
, ecommunity
,
8128 lcommunity
, atomic_aggregate
, aggregate
);
8131 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8133 struct bgp_path_info
*pi
,
8134 struct bgp_aggregate
*aggregate
,
8135 const struct prefix
*aggr_p
)
8138 struct aspath
*aspath
= NULL
;
8139 uint8_t atomic_aggregate
= 0;
8140 struct community
*community
= NULL
;
8141 struct ecommunity
*ecommunity
= NULL
;
8142 struct lcommunity
*lcommunity
= NULL
;
8143 unsigned long match
= 0;
8145 /* If the bgp instance is being deleted or self peer is deleted
8146 * then do not create aggregate route
8148 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8149 || (bgp
->peer_self
== NULL
))
8152 if (BGP_PATH_HOLDDOWN(pi
))
8155 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8158 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8159 if (aggr_unsuppress_path(aggregate
, pi
))
8162 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8163 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8164 if (aggr_unsuppress_path(aggregate
, pi
))
8168 * This must be called after `summary`, `suppress-map` check to avoid
8169 * "unsuppressing" twice.
8171 if (aggregate
->match_med
)
8172 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8174 if (aggregate
->count
> 0)
8177 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8178 aggregate
->incomplete_origin_count
--;
8179 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8180 aggregate
->egp_origin_count
--;
8182 if (aggregate
->as_set
) {
8183 /* Remove as-path from aggregate.
8185 bgp_remove_aspath_from_aggregate(aggregate
,
8188 if (bgp_attr_get_community(pi
->attr
))
8189 /* Remove community from aggregate.
8191 bgp_remove_community_from_aggregate(
8192 aggregate
, bgp_attr_get_community(pi
->attr
));
8194 if (bgp_attr_get_ecommunity(pi
->attr
))
8195 /* Remove ecommunity from aggregate.
8197 bgp_remove_ecommunity_from_aggregate(
8198 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8200 if (bgp_attr_get_lcommunity(pi
->attr
))
8201 /* Remove lcommunity from aggregate.
8203 bgp_remove_lcommunity_from_aggregate(
8204 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8207 /* If this node was suppressed, process the change. */
8209 bgp_process(bgp
, pi
->net
, afi
, safi
);
8211 origin
= BGP_ORIGIN_IGP
;
8212 if (aggregate
->incomplete_origin_count
> 0)
8213 origin
= BGP_ORIGIN_INCOMPLETE
;
8214 else if (aggregate
->egp_origin_count
> 0)
8215 origin
= BGP_ORIGIN_EGP
;
8217 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8218 origin
= aggregate
->origin
;
8220 if (aggregate
->as_set
) {
8221 /* Retrieve aggregate route's as-path.
8223 if (aggregate
->aspath
)
8224 aspath
= aspath_dup(aggregate
->aspath
);
8226 /* Retrieve aggregate route's community.
8228 if (aggregate
->community
)
8229 community
= community_dup(aggregate
->community
);
8231 /* Retrieve aggregate route's ecommunity.
8233 if (aggregate
->ecommunity
)
8234 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8236 /* Retrieve aggregate route's lcommunity.
8238 if (aggregate
->lcommunity
)
8239 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8242 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8243 aspath
, community
, ecommunity
,
8244 lcommunity
, atomic_aggregate
, aggregate
);
8247 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8248 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8250 struct bgp_dest
*child
;
8251 struct bgp_dest
*dest
;
8252 struct bgp_aggregate
*aggregate
;
8253 struct bgp_table
*table
;
8255 table
= bgp
->aggregate
[afi
][safi
];
8257 /* No aggregates configured. */
8258 if (bgp_table_top_nolock(table
) == NULL
)
8261 if (p
->prefixlen
== 0)
8264 if (BGP_PATH_HOLDDOWN(pi
))
8267 /* If suppress fib is enabled and route not installed
8268 * in FIB, do not update the aggregate route
8270 if (!bgp_check_advertise(bgp
, pi
->net
))
8273 child
= bgp_node_get(table
, p
);
8275 /* Aggregate address configuration check. */
8276 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8277 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8279 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8280 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8281 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8285 bgp_dest_unlock_node(child
);
8288 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8289 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8291 struct bgp_dest
*child
;
8292 struct bgp_dest
*dest
;
8293 struct bgp_aggregate
*aggregate
;
8294 struct bgp_table
*table
;
8296 table
= bgp
->aggregate
[afi
][safi
];
8298 /* No aggregates configured. */
8299 if (bgp_table_top_nolock(table
) == NULL
)
8302 if (p
->prefixlen
== 0)
8305 child
= bgp_node_get(table
, p
);
8307 /* Aggregate address configuration check. */
8308 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8309 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8311 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8312 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8313 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8317 bgp_dest_unlock_node(child
);
8320 /* Aggregate route attribute. */
8321 #define AGGREGATE_SUMMARY_ONLY 1
8322 #define AGGREGATE_AS_SET 1
8323 #define AGGREGATE_AS_UNSET 0
8325 static const char *bgp_origin2str(uint8_t origin
)
8328 case BGP_ORIGIN_IGP
:
8330 case BGP_ORIGIN_EGP
:
8332 case BGP_ORIGIN_INCOMPLETE
:
8333 return "incomplete";
8338 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8341 case RPKI_NOT_BEING_USED
:
8351 assert(!"We should never get here this is a dev escape");
8355 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8356 afi_t afi
, safi_t safi
)
8358 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8361 struct bgp_dest
*dest
;
8362 struct bgp_aggregate
*aggregate
;
8364 /* Convert string to prefix structure. */
8365 ret
= str2prefix(prefix_str
, &p
);
8367 vty_out(vty
, "Malformed prefix\n");
8368 return CMD_WARNING_CONFIG_FAILED
;
8372 /* Old configuration check. */
8373 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8376 "%% There is no aggregate-address configuration.\n");
8377 return CMD_WARNING_CONFIG_FAILED
;
8380 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8381 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8382 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8383 NULL
, NULL
, 0, aggregate
);
8385 /* Unlock aggregate address configuration. */
8386 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8388 if (aggregate
->community
)
8389 community_free(&aggregate
->community
);
8391 if (aggregate
->community_hash
) {
8392 /* Delete all communities in the hash.
8394 hash_clean(aggregate
->community_hash
,
8395 bgp_aggr_community_remove
);
8396 /* Free up the community_hash.
8398 hash_free(aggregate
->community_hash
);
8401 if (aggregate
->ecommunity
)
8402 ecommunity_free(&aggregate
->ecommunity
);
8404 if (aggregate
->ecommunity_hash
) {
8405 /* Delete all ecommunities in the hash.
8407 hash_clean(aggregate
->ecommunity_hash
,
8408 bgp_aggr_ecommunity_remove
);
8409 /* Free up the ecommunity_hash.
8411 hash_free(aggregate
->ecommunity_hash
);
8414 if (aggregate
->lcommunity
)
8415 lcommunity_free(&aggregate
->lcommunity
);
8417 if (aggregate
->lcommunity_hash
) {
8418 /* Delete all lcommunities in the hash.
8420 hash_clean(aggregate
->lcommunity_hash
,
8421 bgp_aggr_lcommunity_remove
);
8422 /* Free up the lcommunity_hash.
8424 hash_free(aggregate
->lcommunity_hash
);
8427 if (aggregate
->aspath
)
8428 aspath_free(aggregate
->aspath
);
8430 if (aggregate
->aspath_hash
) {
8431 /* Delete all as-paths in the hash.
8433 hash_clean(aggregate
->aspath_hash
,
8434 bgp_aggr_aspath_remove
);
8435 /* Free up the aspath_hash.
8437 hash_free(aggregate
->aspath_hash
);
8440 bgp_aggregate_free(aggregate
);
8441 bgp_dest_unlock_node(dest
);
8442 bgp_dest_unlock_node(dest
);
8447 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8448 safi_t safi
, const char *rmap
,
8449 uint8_t summary_only
, uint8_t as_set
,
8450 uint8_t origin
, bool match_med
,
8451 const char *suppress_map
)
8453 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8456 struct bgp_dest
*dest
;
8457 struct bgp_aggregate
*aggregate
;
8458 uint8_t as_set_new
= as_set
;
8460 if (suppress_map
&& summary_only
) {
8462 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8463 return CMD_WARNING_CONFIG_FAILED
;
8466 /* Convert string to prefix structure. */
8467 ret
= str2prefix(prefix_str
, &p
);
8469 vty_out(vty
, "Malformed prefix\n");
8470 return CMD_WARNING_CONFIG_FAILED
;
8474 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8475 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8476 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8478 return CMD_WARNING_CONFIG_FAILED
;
8481 /* Old configuration check. */
8482 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8483 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8486 vty_out(vty
, "There is already same aggregate network.\n");
8487 /* try to remove the old entry */
8488 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8490 vty_out(vty
, "Error deleting aggregate.\n");
8491 bgp_dest_unlock_node(dest
);
8492 return CMD_WARNING_CONFIG_FAILED
;
8496 /* Make aggregate address structure. */
8497 aggregate
= bgp_aggregate_new();
8498 aggregate
->summary_only
= summary_only
;
8499 aggregate
->match_med
= match_med
;
8501 /* Network operators MUST NOT locally generate any new
8502 * announcements containing AS_SET or AS_CONFED_SET. If they have
8503 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8504 * SHOULD withdraw those routes and re-announce routes for the
8505 * aggregate or component prefixes (i.e., the more-specific routes
8506 * subsumed by the previously aggregated route) without AS_SET
8507 * or AS_CONFED_SET in the updates.
8509 if (bgp
->reject_as_sets
) {
8510 if (as_set
== AGGREGATE_AS_SET
) {
8511 as_set_new
= AGGREGATE_AS_UNSET
;
8513 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8516 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8520 aggregate
->as_set
= as_set_new
;
8521 aggregate
->safi
= safi
;
8522 /* Override ORIGIN attribute if defined.
8523 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8524 * to IGP which is not what rfc4271 says.
8525 * This enables the same behavior, optionally.
8527 aggregate
->origin
= origin
;
8530 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8531 route_map_counter_decrement(aggregate
->rmap
.map
);
8532 aggregate
->rmap
.name
=
8533 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8534 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8535 route_map_counter_increment(aggregate
->rmap
.map
);
8539 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8540 route_map_counter_decrement(aggregate
->suppress_map
);
8542 aggregate
->suppress_map_name
=
8543 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8544 aggregate
->suppress_map
=
8545 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8546 route_map_counter_increment(aggregate
->suppress_map
);
8549 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8551 /* Aggregate address insert into BGP routing table. */
8552 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8557 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8558 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8560 "|summary-only$summary_only"
8561 "|route-map RMAP_NAME$rmap_name"
8562 "|origin <egp|igp|incomplete>$origin_s"
8563 "|matching-MED-only$match_med"
8564 "|suppress-map RMAP_NAME$suppress_map"
8567 "Configure BGP aggregate entries\n"
8568 "Aggregate prefix\n"
8569 "Aggregate address\n"
8571 "Generate AS set path information\n"
8572 "Filter more specific routes from updates\n"
8573 "Apply route map to aggregate network\n"
8578 "Unknown heritage\n"
8579 "Only aggregate routes with matching MED\n"
8580 "Suppress the selected more specific routes\n"
8581 "Route map with the route selectors\n")
8583 const char *prefix_s
= NULL
;
8584 safi_t safi
= bgp_node_safi(vty
);
8585 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8586 int as_set
= AGGREGATE_AS_UNSET
;
8587 char prefix_buf
[PREFIX2STR_BUFFER
];
8590 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8593 vty_out(vty
, "%% Inconsistent address and mask\n");
8594 return CMD_WARNING_CONFIG_FAILED
;
8596 prefix_s
= prefix_buf
;
8598 prefix_s
= prefix_str
;
8601 if (strcmp(origin_s
, "egp") == 0)
8602 origin
= BGP_ORIGIN_EGP
;
8603 else if (strcmp(origin_s
, "igp") == 0)
8604 origin
= BGP_ORIGIN_IGP
;
8605 else if (strcmp(origin_s
, "incomplete") == 0)
8606 origin
= BGP_ORIGIN_INCOMPLETE
;
8610 as_set
= AGGREGATE_AS_SET
;
8612 /* Handle configuration removal, otherwise installation. */
8614 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8616 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8617 summary_only
!= NULL
, as_set
, origin
,
8618 match_med
!= NULL
, suppress_map
);
8621 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8622 "[no] aggregate-address X:X::X:X/M$prefix [{"
8624 "|summary-only$summary_only"
8625 "|route-map RMAP_NAME$rmap_name"
8626 "|origin <egp|igp|incomplete>$origin_s"
8627 "|matching-MED-only$match_med"
8628 "|suppress-map RMAP_NAME$suppress_map"
8631 "Configure BGP aggregate entries\n"
8632 "Aggregate prefix\n"
8633 "Generate AS set path information\n"
8634 "Filter more specific routes from updates\n"
8635 "Apply route map to aggregate network\n"
8640 "Unknown heritage\n"
8641 "Only aggregate routes with matching MED\n"
8642 "Suppress the selected more specific routes\n"
8643 "Route map with the route selectors\n")
8645 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8646 int as_set
= AGGREGATE_AS_UNSET
;
8649 if (strcmp(origin_s
, "egp") == 0)
8650 origin
= BGP_ORIGIN_EGP
;
8651 else if (strcmp(origin_s
, "igp") == 0)
8652 origin
= BGP_ORIGIN_IGP
;
8653 else if (strcmp(origin_s
, "incomplete") == 0)
8654 origin
= BGP_ORIGIN_INCOMPLETE
;
8658 as_set
= AGGREGATE_AS_SET
;
8660 /* Handle configuration removal, otherwise installation. */
8662 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8665 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8666 rmap_name
, summary_only
!= NULL
, as_set
,
8667 origin
, match_med
!= NULL
, suppress_map
);
8670 /* Redistribute route treatment. */
8671 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8672 const union g_addr
*nexthop
, ifindex_t ifindex
,
8673 enum nexthop_types_t nhtype
, uint8_t distance
,
8674 enum blackhole_type bhtype
, uint32_t metric
,
8675 uint8_t type
, unsigned short instance
,
8678 struct bgp_path_info
*new;
8679 struct bgp_path_info
*bpi
;
8680 struct bgp_path_info rmap_path
;
8681 struct bgp_dest
*bn
;
8683 struct attr
*new_attr
;
8685 route_map_result_t ret
;
8686 struct bgp_redist
*red
;
8688 /* Make default attribute. */
8689 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8691 * This must not be NULL to satisfy Coverity SA
8693 assert(attr
.aspath
);
8696 case NEXTHOP_TYPE_IFINDEX
:
8697 switch (p
->family
) {
8699 attr
.nexthop
.s_addr
= INADDR_ANY
;
8700 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8703 memset(&attr
.mp_nexthop_global
, 0,
8704 sizeof(attr
.mp_nexthop_global
));
8705 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8709 case NEXTHOP_TYPE_IPV4
:
8710 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8711 attr
.nexthop
= nexthop
->ipv4
;
8712 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8714 case NEXTHOP_TYPE_IPV6
:
8715 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8716 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8717 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8719 case NEXTHOP_TYPE_BLACKHOLE
:
8720 switch (p
->family
) {
8722 attr
.nexthop
.s_addr
= INADDR_ANY
;
8723 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8726 memset(&attr
.mp_nexthop_global
, 0,
8727 sizeof(attr
.mp_nexthop_global
));
8728 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8731 attr
.bh_type
= bhtype
;
8734 attr
.nh_type
= nhtype
;
8735 attr
.nh_ifindex
= ifindex
;
8738 attr
.distance
= distance
;
8739 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8743 bgp_attr_set_aigp_metric(&attr
, metric
);
8745 afi
= family2afi(p
->family
);
8747 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8749 struct attr attr_new
;
8751 /* Copy attribute for modification. */
8754 if (red
->redist_metric_flag
) {
8755 attr_new
.med
= red
->redist_metric
;
8756 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8759 /* Apply route-map. */
8760 if (red
->rmap
.name
) {
8761 memset(&rmap_path
, 0, sizeof(rmap_path
));
8762 rmap_path
.peer
= bgp
->peer_self
;
8763 rmap_path
.attr
= &attr_new
;
8765 SET_FLAG(bgp
->peer_self
->rmap_type
,
8766 PEER_RMAP_TYPE_REDISTRIBUTE
);
8768 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8770 bgp
->peer_self
->rmap_type
= 0;
8772 if (ret
== RMAP_DENYMATCH
) {
8773 /* Free uninterned attribute. */
8774 bgp_attr_flush(&attr_new
);
8776 /* Unintern original. */
8777 aspath_unintern(&attr
.aspath
);
8778 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8783 if (bgp_in_graceful_shutdown(bgp
))
8784 bgp_attr_add_gshut_community(&attr_new
);
8786 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8787 SAFI_UNICAST
, p
, NULL
);
8789 new_attr
= bgp_attr_intern(&attr_new
);
8791 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8792 if (bpi
->peer
== bgp
->peer_self
8793 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8797 /* Ensure the (source route) type is updated. */
8799 if (attrhash_cmp(bpi
->attr
, new_attr
)
8800 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8801 bgp_attr_unintern(&new_attr
);
8802 aspath_unintern(&attr
.aspath
);
8803 bgp_dest_unlock_node(bn
);
8806 /* The attribute is changed. */
8807 bgp_path_info_set_flag(bn
, bpi
,
8808 BGP_PATH_ATTR_CHANGED
);
8810 /* Rewrite BGP route information. */
8811 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8812 bgp_path_info_restore(bn
, bpi
);
8814 bgp_aggregate_decrement(
8815 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8816 bgp_attr_unintern(&bpi
->attr
);
8817 bpi
->attr
= new_attr
;
8818 bpi
->uptime
= monotime(NULL
);
8820 /* Process change. */
8821 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8823 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8824 bgp_dest_unlock_node(bn
);
8825 aspath_unintern(&attr
.aspath
);
8827 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8829 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8831 vpn_leak_from_vrf_update(
8832 bgp_get_default(), bgp
, bpi
);
8838 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8839 bgp
->peer_self
, new_attr
, bn
);
8840 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8842 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8843 bgp_path_info_add(bn
, new);
8844 bgp_dest_unlock_node(bn
);
8845 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8846 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8848 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8849 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8851 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8855 /* Unintern original. */
8856 aspath_unintern(&attr
.aspath
);
8859 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8860 unsigned short instance
)
8863 struct bgp_dest
*dest
;
8864 struct bgp_path_info
*pi
;
8865 struct bgp_redist
*red
;
8867 afi
= family2afi(p
->family
);
8869 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8871 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8872 SAFI_UNICAST
, p
, NULL
);
8874 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8875 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8879 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8880 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8882 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8885 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8886 bgp_path_info_delete(dest
, pi
);
8887 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8889 bgp_dest_unlock_node(dest
);
8893 /* Withdraw specified route type's route. */
8894 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8895 unsigned short instance
)
8897 struct bgp_dest
*dest
;
8898 struct bgp_path_info
*pi
;
8899 struct bgp_table
*table
;
8901 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8903 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8904 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8905 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8906 && pi
->instance
== instance
)
8910 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8911 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8913 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8916 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8917 pi
, afi
, SAFI_UNICAST
);
8918 bgp_path_info_delete(dest
, pi
);
8919 if (!CHECK_FLAG(bgp
->flags
,
8920 BGP_FLAG_DELETE_IN_PROGRESS
))
8921 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8923 bgp_path_info_reap(dest
, pi
);
8928 /* Static function to display route. */
8929 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8930 struct vty
*vty
, json_object
*json
, bool wide
)
8933 char buf
[INET6_ADDRSTRLEN
];
8935 if (p
->family
== AF_INET
) {
8937 len
= vty_out(vty
, "%pFX", p
);
8939 json_object_string_add(json
, "prefix",
8940 inet_ntop(p
->family
,
8943 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8944 json_object_string_addf(json
, "network", "%pFX", p
);
8945 json_object_int_add(json
, "version", dest
->version
);
8947 } else if (p
->family
== AF_ETHERNET
) {
8948 len
= vty_out(vty
, "%pFX", p
);
8949 } else if (p
->family
== AF_EVPN
) {
8951 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8953 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8954 } else if (p
->family
== AF_FLOWSPEC
) {
8955 route_vty_out_flowspec(vty
, p
, NULL
,
8957 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8958 NLRI_STRING_FORMAT_MIN
, json
);
8961 len
= vty_out(vty
, "%pFX", p
);
8963 json_object_string_add(json
, "prefix",
8964 inet_ntop(p
->family
,
8967 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8968 json_object_string_addf(json
, "network", "%pFX", p
);
8969 json_object_int_add(json
, "version", dest
->version
);
8974 len
= wide
? (45 - len
) : (17 - len
);
8976 vty_out(vty
, "\n%*s", 20, " ");
8978 vty_out(vty
, "%*s", len
, " ");
8982 enum bgp_display_type
{
8986 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8989 case bgp_path_selection_none
:
8990 return "Nothing to Select";
8991 case bgp_path_selection_first
:
8992 return "First path received";
8993 case bgp_path_selection_evpn_sticky_mac
:
8994 return "EVPN Sticky Mac";
8995 case bgp_path_selection_evpn_seq
:
8996 return "EVPN sequence number";
8997 case bgp_path_selection_evpn_lower_ip
:
8998 return "EVPN lower IP";
8999 case bgp_path_selection_evpn_local_path
:
9000 return "EVPN local ES path";
9001 case bgp_path_selection_evpn_non_proxy
:
9002 return "EVPN non proxy";
9003 case bgp_path_selection_weight
:
9005 case bgp_path_selection_local_pref
:
9006 return "Local Pref";
9007 case bgp_path_selection_accept_own
:
9008 return "Accept Own";
9009 case bgp_path_selection_local_route
:
9010 return "Local Route";
9011 case bgp_path_selection_aigp
:
9013 case bgp_path_selection_confed_as_path
:
9014 return "Confederation based AS Path";
9015 case bgp_path_selection_as_path
:
9017 case bgp_path_selection_origin
:
9019 case bgp_path_selection_med
:
9021 case bgp_path_selection_peer
:
9023 case bgp_path_selection_confed
:
9024 return "Confed Peer Type";
9025 case bgp_path_selection_igp_metric
:
9026 return "IGP Metric";
9027 case bgp_path_selection_older
:
9028 return "Older Path";
9029 case bgp_path_selection_router_id
:
9031 case bgp_path_selection_cluster_length
:
9032 return "Cluster length";
9033 case bgp_path_selection_stale
:
9034 return "Path Staleness";
9035 case bgp_path_selection_local_configured
:
9036 return "Locally configured route";
9037 case bgp_path_selection_neighbor_ip
:
9038 return "Neighbor IP";
9039 case bgp_path_selection_default
:
9040 return "Nothing left to compare";
9042 return "Invalid (internal error)";
9045 /* Print the short form route status for a bgp_path_info */
9046 static void route_vty_short_status_out(struct vty
*vty
,
9047 struct bgp_path_info
*path
,
9048 const struct prefix
*p
,
9049 json_object
*json_path
)
9051 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
9055 /* Route status display. */
9056 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9057 json_object_boolean_true_add(json_path
, "removed");
9059 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9060 json_object_boolean_true_add(json_path
, "stale");
9062 if (path
->extra
&& bgp_path_suppressed(path
))
9063 json_object_boolean_true_add(json_path
, "suppressed");
9065 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9066 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9067 json_object_boolean_true_add(json_path
, "valid");
9070 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9071 json_object_boolean_true_add(json_path
, "history");
9073 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9074 json_object_boolean_true_add(json_path
, "damped");
9076 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9077 json_object_boolean_true_add(json_path
, "bestpath");
9078 json_object_string_add(json_path
, "selectionReason",
9079 bgp_path_selection_reason2str(
9080 path
->net
->reason
));
9083 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9084 json_object_boolean_true_add(json_path
, "multipath");
9086 /* Internal route. */
9087 if ((path
->peer
->as
)
9088 && (path
->peer
->as
== path
->peer
->local_as
))
9089 json_object_string_add(json_path
, "pathFrom",
9092 json_object_string_add(json_path
, "pathFrom",
9098 /* RPKI validation state */
9100 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9102 if (rpki_state
== RPKI_VALID
)
9104 else if (rpki_state
== RPKI_INVALID
)
9106 else if (rpki_state
== RPKI_NOTFOUND
)
9111 /* Route status display. */
9112 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9114 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9116 else if (bgp_path_suppressed(path
))
9118 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9119 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9125 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9127 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9129 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9131 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9136 /* Internal route. */
9137 if (path
->peer
&& (path
->peer
->as
)
9138 && (path
->peer
->as
== path
->peer
->local_as
))
9144 static char *bgp_nexthop_hostname(struct peer
*peer
,
9145 struct bgp_nexthop_cache
*bnc
)
9148 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9149 return peer
->hostname
;
9153 /* called from terminal list command */
9154 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9155 struct bgp_path_info
*path
, int display
, safi_t safi
,
9156 json_object
*json_paths
, bool wide
)
9159 struct attr
*attr
= path
->attr
;
9160 json_object
*json_path
= NULL
;
9161 json_object
*json_nexthops
= NULL
;
9162 json_object
*json_nexthop_global
= NULL
;
9163 json_object
*json_nexthop_ll
= NULL
;
9164 json_object
*json_ext_community
= NULL
;
9165 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9167 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9168 bool nexthop_othervrf
= false;
9169 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9170 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9171 char *nexthop_hostname
=
9172 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9173 char esi_buf
[ESI_STR_LEN
];
9176 json_path
= json_object_new_object();
9178 /* short status lead text */
9179 route_vty_short_status_out(vty
, path
, p
, json_path
);
9182 /* print prefix and mask */
9184 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9186 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9188 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9192 * If vrf id of nexthop is different from that of prefix,
9193 * set up printable string to append
9195 if (path
->extra
&& path
->extra
->bgp_orig
) {
9196 const char *self
= "";
9201 nexthop_othervrf
= true;
9202 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9204 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9205 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9206 "@%s%s", VRFID_NONE_STR
, self
);
9208 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9209 path
->extra
->bgp_orig
->vrf_id
, self
);
9211 if (path
->extra
->bgp_orig
->inst_type
9212 != BGP_INSTANCE_TYPE_DEFAULT
)
9214 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9216 const char *self
= "";
9221 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9225 * For ENCAP and EVPN routes, nexthop address family is not
9226 * neccessarily the same as the prefix address family.
9227 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9228 * EVPN routes are also exchanged with a MP nexthop. Currently,
9230 * is only IPv4, the value will be present in either
9232 * attr->mp_nexthop_global_in
9234 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9236 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9240 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9241 &attr
->mp_nexthop_global_in
);
9244 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9245 &attr
->mp_nexthop_global
);
9248 snprintf(nexthop
, sizeof(nexthop
), "?");
9253 json_nexthop_global
= json_object_new_object();
9255 json_object_string_add(json_nexthop_global
, "ip",
9258 if (path
->peer
->hostname
)
9259 json_object_string_add(json_nexthop_global
,
9261 path
->peer
->hostname
);
9263 json_object_string_add(json_nexthop_global
, "afi",
9264 (af
== AF_INET
) ? "ipv4"
9266 json_object_boolean_true_add(json_nexthop_global
,
9269 if (nexthop_hostname
)
9270 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9271 nexthop_hostname
, vrf_id_str
);
9273 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9275 len
= wide
? (41 - len
) : (16 - len
);
9277 vty_out(vty
, "\n%*s", 36, " ");
9279 vty_out(vty
, "%*s", len
, " ");
9281 } else if (safi
== SAFI_EVPN
) {
9283 json_nexthop_global
= json_object_new_object();
9285 json_object_string_addf(json_nexthop_global
, "ip",
9287 &attr
->mp_nexthop_global_in
);
9289 if (path
->peer
->hostname
)
9290 json_object_string_add(json_nexthop_global
,
9292 path
->peer
->hostname
);
9294 json_object_string_add(json_nexthop_global
, "afi",
9296 json_object_boolean_true_add(json_nexthop_global
,
9299 if (nexthop_hostname
)
9300 len
= vty_out(vty
, "%pI4(%s)%s",
9301 &attr
->mp_nexthop_global_in
,
9302 nexthop_hostname
, vrf_id_str
);
9304 len
= vty_out(vty
, "%pI4%s",
9305 &attr
->mp_nexthop_global_in
,
9308 len
= wide
? (41 - len
) : (16 - len
);
9310 vty_out(vty
, "\n%*s", 36, " ");
9312 vty_out(vty
, "%*s", len
, " ");
9314 } else if (safi
== SAFI_FLOWSPEC
) {
9315 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9317 json_nexthop_global
= json_object_new_object();
9319 json_object_string_add(json_nexthop_global
,
9321 json_object_string_addf(json_nexthop_global
,
9325 if (path
->peer
->hostname
)
9326 json_object_string_add(
9327 json_nexthop_global
, "hostname",
9328 path
->peer
->hostname
);
9330 json_object_boolean_true_add(
9331 json_nexthop_global
,
9334 if (nexthop_hostname
)
9335 len
= vty_out(vty
, "%pI4(%s)%s",
9340 len
= vty_out(vty
, "%pI4%s",
9344 len
= wide
? (41 - len
) : (16 - len
);
9346 vty_out(vty
, "\n%*s", 36, " ");
9348 vty_out(vty
, "%*s", len
, " ");
9351 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9353 json_nexthop_global
= json_object_new_object();
9355 json_object_string_addf(json_nexthop_global
, "ip",
9356 "%pI4", &attr
->nexthop
);
9358 if (path
->peer
->hostname
)
9359 json_object_string_add(json_nexthop_global
,
9361 path
->peer
->hostname
);
9363 json_object_string_add(json_nexthop_global
, "afi",
9365 json_object_boolean_true_add(json_nexthop_global
,
9368 if (nexthop_hostname
)
9369 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9370 nexthop_hostname
, vrf_id_str
);
9372 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9375 len
= wide
? (41 - len
) : (16 - len
);
9377 vty_out(vty
, "\n%*s", 36, " ");
9379 vty_out(vty
, "%*s", len
, " ");
9384 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9386 json_nexthop_global
= json_object_new_object();
9387 json_object_string_addf(json_nexthop_global
, "ip",
9389 &attr
->mp_nexthop_global
);
9391 if (path
->peer
->hostname
)
9392 json_object_string_add(json_nexthop_global
,
9394 path
->peer
->hostname
);
9396 json_object_string_add(json_nexthop_global
, "afi",
9398 json_object_string_add(json_nexthop_global
, "scope",
9401 /* We display both LL & GL if both have been
9403 if ((attr
->mp_nexthop_len
9404 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9405 || (path
->peer
->conf_if
)) {
9406 json_nexthop_ll
= json_object_new_object();
9407 json_object_string_addf(
9408 json_nexthop_ll
, "ip", "%pI6",
9409 &attr
->mp_nexthop_local
);
9411 if (path
->peer
->hostname
)
9412 json_object_string_add(
9413 json_nexthop_ll
, "hostname",
9414 path
->peer
->hostname
);
9416 json_object_string_add(json_nexthop_ll
, "afi",
9418 json_object_string_add(json_nexthop_ll
, "scope",
9421 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9422 &attr
->mp_nexthop_local
)
9424 && !attr
->mp_nexthop_prefer_global
)
9425 json_object_boolean_true_add(
9426 json_nexthop_ll
, "used");
9428 json_object_boolean_true_add(
9429 json_nexthop_global
, "used");
9431 json_object_boolean_true_add(
9432 json_nexthop_global
, "used");
9434 /* Display LL if LL/Global both in table unless
9435 * prefer-global is set */
9436 if (((attr
->mp_nexthop_len
9437 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9438 && !attr
->mp_nexthop_prefer_global
)
9439 || (path
->peer
->conf_if
)) {
9440 if (path
->peer
->conf_if
) {
9441 len
= vty_out(vty
, "%s",
9442 path
->peer
->conf_if
);
9443 /* len of IPv6 addr + max len of def
9445 len
= wide
? (41 - len
) : (16 - len
);
9448 vty_out(vty
, "\n%*s", 36, " ");
9450 vty_out(vty
, "%*s", len
, " ");
9452 if (nexthop_hostname
)
9455 &attr
->mp_nexthop_local
,
9461 &attr
->mp_nexthop_local
,
9464 len
= wide
? (41 - len
) : (16 - len
);
9467 vty_out(vty
, "\n%*s", 36, " ");
9469 vty_out(vty
, "%*s", len
, " ");
9472 if (nexthop_hostname
)
9473 len
= vty_out(vty
, "%pI6(%s)%s",
9474 &attr
->mp_nexthop_global
,
9478 len
= vty_out(vty
, "%pI6%s",
9479 &attr
->mp_nexthop_global
,
9482 len
= wide
? (41 - len
) : (16 - len
);
9485 vty_out(vty
, "\n%*s", 36, " ");
9487 vty_out(vty
, "%*s", len
, " ");
9493 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9495 json_object_int_add(json_path
, "metric", attr
->med
);
9497 vty_out(vty
, "%7u", attr
->med
);
9499 vty_out(vty
, "%10u", attr
->med
);
9500 else if (!json_paths
) {
9502 vty_out(vty
, "%*s", 7, " ");
9504 vty_out(vty
, "%*s", 10, " ");
9508 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9510 json_object_int_add(json_path
, "locPrf",
9513 vty_out(vty
, "%7u", attr
->local_pref
);
9514 else if (!json_paths
)
9518 json_object_int_add(json_path
, "weight", attr
->weight
);
9520 vty_out(vty
, "%7u ", attr
->weight
);
9523 json_object_string_addf(json_path
, "peerId", "%pSU",
9529 json_object_string_add(json_path
, "path",
9532 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9537 json_object_string_add(json_path
, "origin",
9538 bgp_origin_long_str
[attr
->origin
]);
9540 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9543 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9544 json_object_string_add(json_path
, "esi",
9545 esi_to_str(&attr
->esi
,
9546 esi_buf
, sizeof(esi_buf
)));
9548 if (safi
== SAFI_EVPN
&&
9549 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9550 json_ext_community
= json_object_new_object();
9551 json_object_string_add(
9552 json_ext_community
, "string",
9553 bgp_attr_get_ecommunity(attr
)->str
);
9554 json_object_object_add(json_path
,
9555 "extendedCommunity",
9556 json_ext_community
);
9560 json_object_boolean_true_add(json_path
,
9561 "announceNexthopSelf");
9562 if (nexthop_othervrf
) {
9563 json_object_string_add(json_path
, "nhVrfName",
9566 json_object_int_add(json_path
, "nhVrfId",
9567 ((nexthop_vrfid
== VRF_UNKNOWN
)
9569 : (int)nexthop_vrfid
));
9574 if (json_nexthop_global
|| json_nexthop_ll
) {
9575 json_nexthops
= json_object_new_array();
9577 if (json_nexthop_global
)
9578 json_object_array_add(json_nexthops
,
9579 json_nexthop_global
);
9581 if (json_nexthop_ll
)
9582 json_object_array_add(json_nexthops
,
9585 json_object_object_add(json_path
, "nexthops",
9589 json_object_array_add(json_paths
, json_path
);
9593 if (safi
== SAFI_EVPN
) {
9594 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9595 /* XXX - add these params to the json out */
9596 vty_out(vty
, "%*s", 20, " ");
9597 vty_out(vty
, "ESI:%s",
9598 esi_to_str(&attr
->esi
, esi_buf
,
9604 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9605 vty_out(vty
, "%*s", 20, " ");
9606 vty_out(vty
, "%s\n",
9607 bgp_attr_get_ecommunity(attr
)->str
);
9611 #ifdef ENABLE_BGP_VNC
9612 /* prints an additional line, indented, with VNC info, if
9614 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9615 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9620 /* called from terminal list command */
9621 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9622 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9623 bool use_json
, json_object
*json_ar
, bool wide
)
9625 json_object
*json_status
= NULL
;
9626 json_object
*json_net
= NULL
;
9630 /* Route status display. */
9632 json_status
= json_object_new_object();
9633 json_net
= json_object_new_object();
9640 /* print prefix and mask */
9642 if (safi
== SAFI_EVPN
)
9643 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9644 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9645 json_object_string_add(
9646 json_net
, "addrPrefix",
9647 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9649 json_object_int_add(json_net
, "prefixLen",
9651 json_object_string_addf(json_net
, "network", "%pFX", p
);
9654 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9656 /* Print attribute */
9659 if (p
->family
== AF_INET
&&
9660 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9661 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9662 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9663 json_object_string_addf(
9664 json_net
, "nextHop", "%pI4",
9665 &attr
->mp_nexthop_global_in
);
9667 json_object_string_addf(
9668 json_net
, "nextHop", "%pI4",
9670 } else if (p
->family
== AF_INET6
||
9671 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9672 json_object_string_addf(
9673 json_net
, "nextHopGlobal", "%pI6",
9674 &attr
->mp_nexthop_global
);
9675 } else if (p
->family
== AF_EVPN
&&
9676 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9677 json_object_string_addf(
9678 json_net
, "nextHop", "%pI4",
9679 &attr
->mp_nexthop_global_in
);
9683 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9684 json_object_int_add(json_net
, "metric",
9687 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9688 json_object_int_add(json_net
, "locPrf",
9691 json_object_int_add(json_net
, "weight", attr
->weight
);
9695 json_object_string_add(json_net
, "path",
9699 #if CONFDATE > 20231208
9700 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9702 json_object_string_add(json_net
, "bgpOriginCode",
9703 bgp_origin_str
[attr
->origin
]);
9704 json_object_string_add(
9706 bgp_origin_long_str
[attr
->origin
]);
9708 if (p
->family
== AF_INET
&&
9709 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9710 safi
== SAFI_EVPN
||
9711 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9712 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9713 || safi
== SAFI_EVPN
)
9714 vty_out(vty
, "%-16pI4",
9715 &attr
->mp_nexthop_global_in
);
9717 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9719 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9720 } else if (p
->family
== AF_INET6
||
9721 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9722 len
= vty_out(vty
, "%pI6",
9723 &attr
->mp_nexthop_global
);
9724 len
= wide
? (41 - len
) : (16 - len
);
9726 vty_out(vty
, "\n%*s", 36, " ");
9728 vty_out(vty
, "%*s", len
, " ");
9731 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9733 vty_out(vty
, "%7u", attr
->med
);
9735 vty_out(vty
, "%10u", attr
->med
);
9741 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9742 vty_out(vty
, "%7u", attr
->local_pref
);
9746 vty_out(vty
, "%7u ", attr
->weight
);
9750 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9753 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9757 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9759 #if CONFDATE > 20231208
9760 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9762 json_object_boolean_true_add(json_status
, "*");
9763 json_object_boolean_true_add(json_status
, ">");
9764 json_object_boolean_true_add(json_net
, "valid");
9765 json_object_boolean_true_add(json_net
, "best");
9767 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9768 json_object_boolean_true_add(json_status
, "=");
9769 json_object_boolean_true_add(json_net
, "multipath");
9771 json_object_object_add(json_net
, "appliedStatusSymbols",
9773 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9778 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9779 struct bgp_path_info
*path
, int display
, safi_t safi
,
9782 json_object
*json_out
= NULL
;
9784 mpls_label_t label
= MPLS_INVALID_LABEL
;
9790 json_out
= json_object_new_object();
9792 /* short status lead text */
9793 route_vty_short_status_out(vty
, path
, p
, json_out
);
9795 /* print prefix and mask */
9798 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9800 vty_out(vty
, "%*s", 17, " ");
9803 /* Print attribute */
9805 if (((p
->family
== AF_INET
) &&
9806 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9807 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9808 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9809 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9810 || safi
== SAFI_EVPN
) {
9812 json_object_string_addf(
9813 json_out
, "mpNexthopGlobalIn", "%pI4",
9814 &attr
->mp_nexthop_global_in
);
9816 vty_out(vty
, "%-16pI4",
9817 &attr
->mp_nexthop_global_in
);
9820 json_object_string_addf(json_out
, "nexthop",
9821 "%pI4", &attr
->nexthop
);
9823 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9825 } else if (((p
->family
== AF_INET6
) &&
9826 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9827 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9828 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9831 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9833 json_object_string_addf(
9834 json_out
, "mpNexthopGlobalIn", "%pI6",
9835 &attr
->mp_nexthop_global
);
9839 &attr
->mp_nexthop_global
,
9840 buf_a
, sizeof(buf_a
)));
9841 } else if (attr
->mp_nexthop_len
9842 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9843 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9844 &attr
->mp_nexthop_global
,
9845 &attr
->mp_nexthop_local
);
9847 json_object_string_add(json_out
,
9848 "mpNexthopGlobalLocal",
9851 vty_out(vty
, "%s", buf_a
);
9855 label
= decode_label(&path
->extra
->label
[0]);
9857 if (bgp_is_valid_label(&label
)) {
9859 json_object_int_add(json_out
, "notag", label
);
9860 json_object_array_add(json
, json_out
);
9862 vty_out(vty
, "notag/%d", label
);
9869 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9870 struct bgp_path_info
*path
, int display
,
9871 json_object
*json_paths
)
9874 json_object
*json_path
= NULL
;
9875 json_object
*json_nexthop
= NULL
;
9876 json_object
*json_overlay
= NULL
;
9882 json_path
= json_object_new_object();
9883 json_overlay
= json_object_new_object();
9884 json_nexthop
= json_object_new_object();
9887 /* short status lead text */
9888 route_vty_short_status_out(vty
, path
, p
, json_path
);
9890 /* print prefix and mask */
9892 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9894 vty_out(vty
, "%*s", 17, " ");
9896 /* Print attribute */
9898 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9903 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9905 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9906 &attr
->mp_nexthop_global_in
);
9908 json_object_string_add(json_nexthop
, "afi", "ipv4");
9910 json_object_object_add(json_path
, "nexthop",
9916 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9917 &attr
->mp_nexthop_local
);
9919 json_object_string_addf(json_nexthop
, "ipv6Global",
9921 &attr
->mp_nexthop_global
);
9923 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9925 &attr
->mp_nexthop_local
);
9927 json_object_string_add(json_nexthop
, "afi", "ipv6");
9929 json_object_object_add(json_path
, "nexthop",
9937 json_object_string_add(json_nexthop
, "Error",
9938 "Unsupported address-family");
9939 json_object_string_add(json_nexthop
, "error",
9940 "Unsupported address-family");
9944 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9947 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9949 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9951 if (bgp_attr_get_ecommunity(attr
)) {
9953 struct ecommunity_val
*routermac
= ecommunity_lookup(
9954 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9955 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9958 mac
= ecom_mac2str((char *)routermac
->val
);
9961 vty_out(vty
, "/%s", mac
);
9963 json_object_string_add(json_overlay
, "rmac",
9966 XFREE(MTYPE_TMP
, mac
);
9973 json_object_object_add(json_path
, "overlay", json_overlay
);
9975 json_object_array_add(json_paths
, json_path
);
9979 /* dampening route */
9980 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9981 struct bgp_path_info
*path
, int display
,
9982 afi_t afi
, safi_t safi
, bool use_json
,
9983 json_object
*json_paths
)
9985 struct attr
*attr
= path
->attr
;
9987 char timebuf
[BGP_UPTIME_LEN
];
9988 json_object
*json_path
= NULL
;
9991 json_path
= json_object_new_object();
9993 /* short status lead text */
9994 route_vty_short_status_out(vty
, path
, p
, json_path
);
9996 /* print prefix and mask */
9999 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10001 vty_out(vty
, "%*s", 17, " ");
10003 len
= vty_out(vty
, "%s", path
->peer
->host
);
10007 vty_out(vty
, "\n%*s", 34, " ");
10009 vty_out(vty
, "%*s", len
, " ");
10011 vty_out(vty
, "%s ",
10012 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10013 BGP_UPTIME_LEN
, afi
, safi
,
10017 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
10019 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10021 vty_out(vty
, "\n");
10023 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
10024 safi
, use_json
, json_path
);
10027 json_object_string_add(json_path
, "asPath",
10028 attr
->aspath
->str
);
10030 json_object_string_add(json_path
, "origin",
10031 bgp_origin_str
[attr
->origin
]);
10032 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10034 json_object_array_add(json_paths
, json_path
);
10039 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
10040 struct bgp_path_info
*path
, int display
,
10041 afi_t afi
, safi_t safi
, bool use_json
,
10042 json_object
*json_paths
)
10044 struct attr
*attr
= path
->attr
;
10045 struct bgp_damp_info
*bdi
;
10046 char timebuf
[BGP_UPTIME_LEN
];
10048 json_object
*json_path
= NULL
;
10054 json_path
= json_object_new_object();
10056 bdi
= path
->extra
->damp_info
;
10058 /* short status lead text */
10059 route_vty_short_status_out(vty
, path
, p
, json_path
);
10063 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10065 vty_out(vty
, "%*s", 17, " ");
10067 len
= vty_out(vty
, "%s", path
->peer
->host
);
10070 vty_out(vty
, "\n%*s", 33, " ");
10072 vty_out(vty
, "%*s", len
, " ");
10074 len
= vty_out(vty
, "%d", bdi
->flap
);
10079 vty_out(vty
, "%*s", len
, " ");
10081 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10082 BGP_UPTIME_LEN
, 0, NULL
));
10084 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10085 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10086 vty_out(vty
, "%s ",
10087 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10088 BGP_UPTIME_LEN
, afi
,
10089 safi
, use_json
, NULL
));
10091 vty_out(vty
, "%*s ", 8, " ");
10094 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
10096 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10098 vty_out(vty
, "\n");
10100 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10101 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10103 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10106 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10107 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10108 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10109 BGP_UPTIME_LEN
, afi
, safi
,
10110 use_json
, json_path
);
10113 json_object_string_add(json_path
, "asPath",
10114 attr
->aspath
->str
);
10116 json_object_string_add(json_path
, "origin",
10117 bgp_origin_str
[attr
->origin
]);
10119 json_object_array_add(json_paths
, json_path
);
10123 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10124 int *first
, const char *header
,
10125 json_object
*json_adv_to
)
10127 json_object
*json_peer
= NULL
;
10130 /* 'advertised-to' is a dictionary of peers we have advertised
10132 * prefix too. The key is the peer's IP or swpX, the value is
10134 * hostname if we know it and "" if not.
10136 json_peer
= json_object_new_object();
10138 if (peer
->hostname
)
10139 json_object_string_add(json_peer
, "hostname",
10143 json_object_object_add(json_adv_to
, peer
->conf_if
,
10146 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10150 vty_out(vty
, "%s", header
);
10155 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10157 vty_out(vty
, " %s(%s)", peer
->hostname
,
10160 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10164 vty_out(vty
, " %s", peer
->conf_if
);
10166 vty_out(vty
, " %pSU", &peer
->su
);
10171 static void route_vty_out_tx_ids(struct vty
*vty
,
10172 struct bgp_addpath_info_data
*d
)
10176 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10177 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10178 d
->addpath_tx_id
[i
],
10179 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10183 static void route_vty_out_detail_es_info(struct vty
*vty
,
10184 struct bgp_path_info
*pi
,
10186 json_object
*json_path
)
10188 char esi_buf
[ESI_STR_LEN
];
10189 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10190 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10191 ATTR_ES_PEER_ROUTER
);
10192 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10193 ATTR_ES_PEER_ACTIVE
);
10194 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10195 ATTR_ES_PEER_PROXY
);
10196 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10198 json_object
*json_es_info
= NULL
;
10200 json_object_string_add(
10203 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10204 json_es_info
= json_object_new_object();
10206 json_object_boolean_true_add(
10207 json_es_info
, "localEs");
10209 json_object_boolean_true_add(
10210 json_es_info
, "peerActive");
10212 json_object_boolean_true_add(
10213 json_es_info
, "peerProxy");
10215 json_object_boolean_true_add(
10216 json_es_info
, "peerRouter");
10217 if (attr
->mm_sync_seqnum
)
10218 json_object_int_add(
10219 json_es_info
, "peerSeq",
10220 attr
->mm_sync_seqnum
);
10221 json_object_object_add(
10222 json_path
, "es_info",
10226 if (bgp_evpn_attr_is_sync(attr
))
10228 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10230 es_local
? "local-es":"",
10231 peer_proxy
? "proxy " : "",
10232 peer_active
? "active ":"",
10233 peer_router
? "router ":"",
10234 attr
->mm_sync_seqnum
);
10236 vty_out(vty
, " ESI %s %s\n",
10238 es_local
? "local-es":"");
10242 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10243 const struct prefix
*p
, struct bgp_path_info
*path
,
10244 afi_t afi
, safi_t safi
,
10245 enum rpki_states rpki_curr_state
,
10246 json_object
*json_paths
)
10248 char buf
[INET6_ADDRSTRLEN
];
10250 struct attr
*attr
= path
->attr
;
10252 json_object
*json_bestpath
= NULL
;
10253 json_object
*json_cluster_list
= NULL
;
10254 json_object
*json_cluster_list_list
= NULL
;
10255 json_object
*json_ext_community
= NULL
;
10256 json_object
*json_last_update
= NULL
;
10257 json_object
*json_pmsi
= NULL
;
10258 json_object
*json_nexthop_global
= NULL
;
10259 json_object
*json_nexthop_ll
= NULL
;
10260 json_object
*json_nexthops
= NULL
;
10261 json_object
*json_path
= NULL
;
10262 json_object
*json_peer
= NULL
;
10263 json_object
*json_string
= NULL
;
10264 json_object
*json_adv_to
= NULL
;
10266 struct listnode
*node
, *nnode
;
10268 bool addpath_capable
;
10270 unsigned int first_as
;
10271 bool nexthop_self
=
10272 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10274 char *nexthop_hostname
=
10275 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10279 mpls_label_t label
= MPLS_INVALID_LABEL
;
10281 struct bgp_path_info
*bpi_ultimate
=
10282 bgp_get_imported_bpi_ultimate(path
);
10285 json_path
= json_object_new_object();
10286 json_peer
= json_object_new_object();
10287 json_nexthop_global
= json_object_new_object();
10290 if (safi
== SAFI_EVPN
) {
10292 vty_out(vty
, " Route %pFX", p
);
10296 if (path
->extra
&& path
->extra
->num_labels
) {
10297 bgp_evpn_label2str(path
->extra
->label
,
10298 path
->extra
->num_labels
, tag_buf
,
10301 if (safi
== SAFI_EVPN
) {
10303 if (tag_buf
[0] != '\0')
10304 vty_out(vty
, " VNI %s", tag_buf
);
10307 json_object_string_add(json_path
, "VNI",
10309 json_object_string_add(json_path
, "vni",
10316 if (safi
== SAFI_EVPN
10317 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10318 char gwip_buf
[INET6_ADDRSTRLEN
];
10320 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10324 json_object_string_add(json_path
, "gatewayIP",
10327 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10330 if (safi
== SAFI_EVPN
&& !json_path
)
10331 vty_out(vty
, "\n");
10334 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10335 struct bgp_path_info
*parent_ri
;
10336 struct bgp_dest
*dest
, *pdest
;
10338 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10339 dest
= parent_ri
->net
;
10340 if (dest
&& dest
->pdest
) {
10341 pdest
= dest
->pdest
;
10342 if (is_pi_family_evpn(parent_ri
)) {
10344 " Imported from %pRD:%pFX, VNI %s",
10345 (struct prefix_rd
*)bgp_dest_get_prefix(
10347 (struct prefix_evpn
*)
10348 bgp_dest_get_prefix(dest
),
10350 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10351 vty_out(vty
, ", L3NHG %s",
10354 ATTR_ES_L3_NHG_ACTIVE
)
10357 vty_out(vty
, "\n");
10360 vty_out(vty
, " Imported from %pRD:%pFX\n",
10361 (struct prefix_rd
*)bgp_dest_get_prefix(
10363 (struct prefix_evpn
*)
10364 bgp_dest_get_prefix(dest
));
10368 /* Line1 display AS-path, Aggregator */
10369 if (attr
->aspath
) {
10371 if (!attr
->aspath
->json
)
10372 aspath_str_update(attr
->aspath
, true);
10373 json_object_lock(attr
->aspath
->json
);
10374 json_object_object_add(json_path
, "aspath",
10375 attr
->aspath
->json
);
10377 if (attr
->aspath
->segments
)
10378 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
10380 vty_out(vty
, " Local");
10384 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10386 json_object_boolean_true_add(json_path
, "removed");
10388 vty_out(vty
, ", (removed)");
10391 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10393 json_object_boolean_true_add(json_path
, "stale");
10395 vty_out(vty
, ", (stale)");
10398 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10400 json_object_int_add(json_path
, "aggregatorAs",
10401 attr
->aggregator_as
);
10402 json_object_string_addf(json_path
, "aggregatorId",
10403 "%pI4", &attr
->aggregator_addr
);
10405 vty_out(vty
, ", (aggregated by %u %pI4)",
10406 attr
->aggregator_as
, &attr
->aggregator_addr
);
10410 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10411 PEER_FLAG_REFLECTOR_CLIENT
)) {
10413 json_object_boolean_true_add(json_path
,
10414 "rxedFromRrClient");
10416 vty_out(vty
, ", (Received from a RR-client)");
10419 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10420 PEER_FLAG_RSERVER_CLIENT
)) {
10422 json_object_boolean_true_add(json_path
,
10423 "rxedFromRsClient");
10425 vty_out(vty
, ", (Received from a RS-client)");
10428 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10430 json_object_boolean_true_add(json_path
,
10431 "dampeningHistoryEntry");
10433 vty_out(vty
, ", (history entry)");
10434 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10436 json_object_boolean_true_add(json_path
,
10437 "dampeningSuppressed");
10439 vty_out(vty
, ", (suppressed due to dampening)");
10443 vty_out(vty
, "\n");
10445 /* Line2 display Next-hop, Neighbor, Router-id */
10446 /* Display the nexthop */
10448 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10449 p
->family
== AF_EVPN
) &&
10450 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10451 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10452 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10453 || safi
== SAFI_EVPN
) {
10455 json_object_string_addf(
10456 json_nexthop_global
, "ip", "%pI4",
10457 &attr
->mp_nexthop_global_in
);
10459 if (path
->peer
->hostname
)
10460 json_object_string_add(
10461 json_nexthop_global
, "hostname",
10462 path
->peer
->hostname
);
10464 if (nexthop_hostname
)
10465 vty_out(vty
, " %pI4(%s)",
10466 &attr
->mp_nexthop_global_in
,
10469 vty_out(vty
, " %pI4",
10470 &attr
->mp_nexthop_global_in
);
10474 json_object_string_addf(json_nexthop_global
,
10478 if (path
->peer
->hostname
)
10479 json_object_string_add(
10480 json_nexthop_global
, "hostname",
10481 path
->peer
->hostname
);
10483 if (nexthop_hostname
)
10484 vty_out(vty
, " %pI4(%s)",
10488 vty_out(vty
, " %pI4",
10494 json_object_string_add(json_nexthop_global
, "afi",
10498 json_object_string_addf(json_nexthop_global
, "ip",
10500 &attr
->mp_nexthop_global
);
10502 if (path
->peer
->hostname
)
10503 json_object_string_add(json_nexthop_global
,
10505 path
->peer
->hostname
);
10507 json_object_string_add(json_nexthop_global
, "afi",
10509 json_object_string_add(json_nexthop_global
, "scope",
10512 if (nexthop_hostname
)
10513 vty_out(vty
, " %pI6(%s)",
10514 &attr
->mp_nexthop_global
,
10517 vty_out(vty
, " %pI6",
10518 &attr
->mp_nexthop_global
);
10522 /* Display the IGP cost or 'inaccessible' */
10523 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10524 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10527 json_object_boolean_false_add(json_nexthop_global
,
10529 json_object_boolean_add(json_nexthop_global
,
10530 "importCheckEnabled", import
);
10532 vty_out(vty
, " (inaccessible%s)",
10533 import
? ", import-check enabled" : "");
10536 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10538 json_object_int_add(
10539 json_nexthop_global
, "metric",
10540 bpi_ultimate
->extra
->igpmetric
);
10542 vty_out(vty
, " (metric %u)",
10543 bpi_ultimate
->extra
->igpmetric
);
10546 /* IGP cost is 0, display this only for json */
10549 json_object_int_add(json_nexthop_global
,
10554 json_object_boolean_true_add(json_nexthop_global
,
10558 /* Display peer "from" output */
10559 /* This path was originated locally */
10560 if (path
->peer
== bgp
->peer_self
) {
10562 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10563 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10565 json_object_string_add(json_peer
, "peerId",
10568 vty_out(vty
, " from 0.0.0.0 ");
10571 json_object_string_add(json_peer
, "peerId",
10574 vty_out(vty
, " from :: ");
10578 json_object_string_addf(json_peer
, "routerId", "%pI4",
10581 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10584 /* We RXed this path from one of our peers */
10588 json_object_string_addf(json_peer
, "peerId", "%pSU",
10590 json_object_string_addf(json_peer
, "routerId", "%pI4",
10591 &path
->peer
->remote_id
);
10593 if (path
->peer
->hostname
)
10594 json_object_string_add(json_peer
, "hostname",
10595 path
->peer
->hostname
);
10597 if (path
->peer
->domainname
)
10598 json_object_string_add(json_peer
, "domainname",
10599 path
->peer
->domainname
);
10601 if (path
->peer
->conf_if
)
10602 json_object_string_add(json_peer
, "interface",
10603 path
->peer
->conf_if
);
10605 if (path
->peer
->conf_if
) {
10606 if (path
->peer
->hostname
10607 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10608 BGP_FLAG_SHOW_HOSTNAME
))
10609 vty_out(vty
, " from %s(%s)",
10610 path
->peer
->hostname
,
10611 path
->peer
->conf_if
);
10613 vty_out(vty
, " from %s",
10614 path
->peer
->conf_if
);
10616 if (path
->peer
->hostname
10617 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10618 BGP_FLAG_SHOW_HOSTNAME
))
10619 vty_out(vty
, " from %s(%s)",
10620 path
->peer
->hostname
,
10623 vty_out(vty
, " from %pSU",
10627 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10628 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10630 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10635 * Note when vrfid of nexthop is different from that of prefix
10637 if (path
->extra
&& path
->extra
->bgp_orig
) {
10638 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10643 if (path
->extra
->bgp_orig
->inst_type
10644 == BGP_INSTANCE_TYPE_DEFAULT
)
10645 vn
= VRF_DEFAULT_NAME
;
10647 vn
= path
->extra
->bgp_orig
->name
;
10649 json_object_string_add(json_path
, "nhVrfName", vn
);
10651 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10652 json_object_int_add(json_path
, "nhVrfId", -1);
10654 json_object_int_add(json_path
, "nhVrfId",
10655 (int)nexthop_vrfid
);
10658 if (nexthop_vrfid
== VRF_UNKNOWN
)
10659 vty_out(vty
, " vrf ?");
10663 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10664 vty_out(vty
, " vrf %s(%u)",
10665 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10670 if (nexthop_self
) {
10672 json_object_boolean_true_add(json_path
,
10673 "announceNexthopSelf");
10675 vty_out(vty
, " announce-nh-self");
10680 vty_out(vty
, "\n");
10682 /* display the link-local nexthop */
10683 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10685 json_nexthop_ll
= json_object_new_object();
10686 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10687 &attr
->mp_nexthop_local
);
10689 if (path
->peer
->hostname
)
10690 json_object_string_add(json_nexthop_ll
,
10692 path
->peer
->hostname
);
10694 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10695 json_object_string_add(json_nexthop_ll
, "scope",
10698 json_object_boolean_true_add(json_nexthop_ll
,
10701 if (!attr
->mp_nexthop_prefer_global
)
10702 json_object_boolean_true_add(json_nexthop_ll
,
10705 json_object_boolean_true_add(
10706 json_nexthop_global
, "used");
10708 vty_out(vty
, " (%s) %s\n",
10709 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10710 buf
, INET6_ADDRSTRLEN
),
10711 attr
->mp_nexthop_prefer_global
10712 ? "(prefer-global)"
10716 /* If we do not have a link-local nexthop then we must flag the
10717 global as "used" */
10720 json_object_boolean_true_add(json_nexthop_global
,
10724 if (safi
== SAFI_EVPN
&&
10725 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10726 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10729 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10730 * Int/Ext/Local, Atomic, best */
10732 json_object_string_add(json_path
, "origin",
10733 bgp_origin_long_str
[attr
->origin
]);
10735 vty_out(vty
, " Origin %s",
10736 bgp_origin_long_str
[attr
->origin
]);
10738 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10740 json_object_int_add(json_path
, "metric", attr
->med
);
10742 vty_out(vty
, ", metric %u", attr
->med
);
10745 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10747 json_object_int_add(json_path
, "locPrf",
10750 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10753 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10755 json_object_int_add(json_path
, "aigpMetric",
10756 bgp_attr_get_aigp_metric(attr
));
10758 vty_out(vty
, ", aigp-metric %" PRIu64
,
10759 bgp_attr_get_aigp_metric(attr
));
10762 if (attr
->weight
!= 0) {
10764 json_object_int_add(json_path
, "weight", attr
->weight
);
10766 vty_out(vty
, ", weight %u", attr
->weight
);
10769 if (attr
->tag
!= 0) {
10771 json_object_int_add(json_path
, "tag", attr
->tag
);
10773 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10776 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10778 json_object_boolean_false_add(json_path
, "valid");
10780 vty_out(vty
, ", invalid");
10781 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10783 json_object_boolean_true_add(json_path
, "valid");
10785 vty_out(vty
, ", valid");
10789 json_object_int_add(json_path
, "version", bn
->version
);
10791 if (path
->peer
!= bgp
->peer_self
) {
10792 if (path
->peer
->as
== path
->peer
->local_as
) {
10793 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10795 json_object_string_add(
10797 "confed-internal");
10799 vty_out(vty
, ", confed-internal");
10802 json_object_string_add(
10803 json_peer
, "type", "internal");
10805 vty_out(vty
, ", internal");
10808 if (bgp_confederation_peers_check(bgp
,
10811 json_object_string_add(
10813 "confed-external");
10815 vty_out(vty
, ", confed-external");
10818 json_object_string_add(
10819 json_peer
, "type", "external");
10821 vty_out(vty
, ", external");
10824 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10826 json_object_boolean_true_add(json_path
, "aggregated");
10827 json_object_boolean_true_add(json_path
, "local");
10829 vty_out(vty
, ", aggregated, local");
10831 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10833 json_object_boolean_true_add(json_path
, "sourced");
10835 vty_out(vty
, ", sourced");
10838 json_object_boolean_true_add(json_path
, "sourced");
10839 json_object_boolean_true_add(json_path
, "local");
10841 vty_out(vty
, ", sourced, local");
10845 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10847 json_object_boolean_true_add(json_path
,
10848 "atomicAggregate");
10850 vty_out(vty
, ", atomic-aggregate");
10853 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10855 json_object_int_add(json_path
, "otc", attr
->otc
);
10857 vty_out(vty
, ", otc %u", attr
->otc
);
10860 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10861 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10862 && bgp_path_info_mpath_count(path
))) {
10864 json_object_boolean_true_add(json_path
, "multipath");
10866 vty_out(vty
, ", multipath");
10869 // Mark the bestpath(s)
10870 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10871 first_as
= aspath_get_first_as(attr
->aspath
);
10874 if (!json_bestpath
)
10875 json_bestpath
= json_object_new_object();
10876 json_object_int_add(json_bestpath
, "bestpathFromAs",
10880 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10882 vty_out(vty
, ", bestpath-from-AS Local");
10886 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10888 if (!json_bestpath
)
10889 json_bestpath
= json_object_new_object();
10890 json_object_boolean_true_add(json_bestpath
, "overall");
10891 json_object_string_add(
10892 json_bestpath
, "selectionReason",
10893 bgp_path_selection_reason2str(bn
->reason
));
10895 vty_out(vty
, ", best");
10896 vty_out(vty
, " (%s)",
10897 bgp_path_selection_reason2str(bn
->reason
));
10901 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10903 json_object_string_add(
10904 json_path
, "rpkiValidationState",
10905 bgp_rpki_validation2str(rpki_curr_state
));
10907 vty_out(vty
, ", rpki validation-state: %s",
10908 bgp_rpki_validation2str(rpki_curr_state
));
10912 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10915 vty_out(vty
, "\n");
10917 /* Line 4 display Community */
10918 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10920 if (!bgp_attr_get_community(attr
)->json
)
10921 community_str(bgp_attr_get_community(attr
),
10923 json_object_lock(bgp_attr_get_community(attr
)->json
);
10924 json_object_object_add(
10925 json_path
, "community",
10926 bgp_attr_get_community(attr
)->json
);
10928 vty_out(vty
, " Community: %s\n",
10929 bgp_attr_get_community(attr
)->str
);
10933 /* Line 5 display Extended-community */
10934 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10936 json_ext_community
= json_object_new_object();
10937 json_object_string_add(
10938 json_ext_community
, "string",
10939 bgp_attr_get_ecommunity(attr
)->str
);
10940 json_object_object_add(json_path
, "extendedCommunity",
10941 json_ext_community
);
10943 vty_out(vty
, " Extended Community: %s\n",
10944 bgp_attr_get_ecommunity(attr
)->str
);
10948 /* Line 6 display Large community */
10949 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10951 if (!bgp_attr_get_lcommunity(attr
)->json
)
10952 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10954 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10955 json_object_object_add(
10956 json_path
, "largeCommunity",
10957 bgp_attr_get_lcommunity(attr
)->json
);
10959 vty_out(vty
, " Large Community: %s\n",
10960 bgp_attr_get_lcommunity(attr
)->str
);
10964 /* Line 7 display Originator, Cluster-id */
10965 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10966 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10967 char buf
[BUFSIZ
] = {0};
10969 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10971 json_object_string_addf(json_path
,
10972 "originatorId", "%pI4",
10973 &attr
->originator_id
);
10975 vty_out(vty
, " Originator: %pI4",
10976 &attr
->originator_id
);
10979 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10980 struct cluster_list
*cluster
=
10981 bgp_attr_get_cluster(attr
);
10985 json_cluster_list
= json_object_new_object();
10986 json_cluster_list_list
=
10987 json_object_new_array();
10989 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10990 json_string
= json_object_new_string(
10993 buf
, sizeof(buf
)));
10994 json_object_array_add(
10995 json_cluster_list_list
,
11000 * struct cluster_list does not have
11001 * "str" variable like aspath and community
11002 * do. Add this someday if someone asks
11004 * json_object_string_add(json_cluster_list,
11005 * "string", cluster->str);
11007 json_object_object_add(json_cluster_list
,
11009 json_cluster_list_list
);
11010 json_object_object_add(json_path
, "clusterList",
11011 json_cluster_list
);
11013 vty_out(vty
, ", Cluster list: ");
11015 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
11016 vty_out(vty
, "%pI4 ",
11017 &cluster
->list
[i
]);
11023 vty_out(vty
, "\n");
11026 if (path
->extra
&& path
->extra
->damp_info
)
11027 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
11030 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
11031 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
11032 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
11036 json_object_int_add(json_path
, "remoteLabel", label
);
11038 vty_out(vty
, " Remote label: %d\n", label
);
11042 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
11044 json_object_string_addf(json_path
, "remoteSid", "%pI6",
11045 &path
->extra
->sid
[0].sid
);
11047 vty_out(vty
, " Remote SID: %pI6\n",
11048 &path
->extra
->sid
[0].sid
);
11052 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
11054 json_object_int_add(json_path
, "labelIndex",
11055 attr
->label_index
);
11057 vty_out(vty
, " Label Index: %d\n",
11058 attr
->label_index
);
11061 /* Line 8 display Addpath IDs */
11062 if (path
->addpath_rx_id
11063 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11065 json_object_int_add(json_path
, "addpathRxId",
11066 path
->addpath_rx_id
);
11068 /* Keep backwards compatibility with the old API
11069 * by putting TX All's ID in the old field
11071 json_object_int_add(
11072 json_path
, "addpathTxId",
11074 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11076 /* ... but create a specific field for each
11079 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11080 json_object_int_add(
11082 bgp_addpath_names(i
)->id_json_name
,
11083 path
->tx_addpath
.addpath_tx_id
[i
]);
11086 vty_out(vty
, " AddPath ID: RX %u, ",
11087 path
->addpath_rx_id
);
11089 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11093 /* If we used addpath to TX a non-bestpath we need to display
11094 * "Advertised to" on a path-by-path basis
11096 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11099 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11101 bgp_addpath_encode_tx(peer
, afi
, safi
);
11102 has_adj
= bgp_adj_out_lookup(
11104 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11105 &path
->tx_addpath
));
11107 if ((addpath_capable
&& has_adj
)
11108 || (!addpath_capable
&& has_adj
11109 && CHECK_FLAG(path
->flags
,
11110 BGP_PATH_SELECTED
))) {
11111 if (json_path
&& !json_adv_to
)
11112 json_adv_to
= json_object_new_object();
11114 route_vty_out_advertised_to(
11116 " Advertised to:", json_adv_to
);
11122 json_object_object_add(
11123 json_path
, "advertisedTo", json_adv_to
);
11127 vty_out(vty
, "\n");
11132 /* Line 9 display Uptime */
11133 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11135 json_last_update
= json_object_new_object();
11136 json_object_int_add(json_last_update
, "epoch", tbuf
);
11137 json_object_string_add(json_last_update
, "string",
11139 json_object_object_add(json_path
, "lastUpdate",
11142 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11144 /* Line 10 display PMSI tunnel attribute, if present */
11145 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11146 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11147 bgp_attr_get_pmsi_tnl_type(attr
),
11148 PMSI_TNLTYPE_STR_DEFAULT
);
11151 json_pmsi
= json_object_new_object();
11152 json_object_string_add(json_pmsi
, "tunnelType", str
);
11153 json_object_int_add(json_pmsi
, "label",
11154 label2vni(&attr
->label
));
11155 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11157 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11158 str
, label2vni(&attr
->label
));
11161 if (path
->peer
->t_gr_restart
&&
11162 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11163 unsigned long gr_remaining
=
11164 thread_timer_remain_second(path
->peer
->t_gr_restart
);
11167 json_object_int_add(json_path
,
11168 "gracefulRestartSecondsRemaining",
11172 " Time until Graceful Restart stale route deleted: %lu\n",
11176 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11177 bgp_attr_get_community(attr
) &&
11178 community_include(bgp_attr_get_community(attr
),
11179 COMMUNITY_LLGR_STALE
)) {
11180 unsigned long llgr_remaining
= thread_timer_remain_second(
11181 path
->peer
->t_llgr_stale
[afi
][safi
]);
11184 json_object_int_add(json_path
, "llgrSecondsRemaining",
11188 " Time until Long-lived stale route deleted: %lu\n",
11192 /* Output some debug about internal state of the dest flags */
11194 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11195 json_object_boolean_true_add(json_path
, "processScheduled");
11196 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11197 json_object_boolean_true_add(json_path
, "userCleared");
11198 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11199 json_object_boolean_true_add(json_path
, "labelChanged");
11200 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11201 json_object_boolean_true_add(json_path
, "registeredForLabel");
11202 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11203 json_object_boolean_true_add(json_path
, "selectDefered");
11204 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11205 json_object_boolean_true_add(json_path
, "fibInstalled");
11206 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11207 json_object_boolean_true_add(json_path
, "fibPending");
11209 if (json_nexthop_global
|| json_nexthop_ll
) {
11210 json_nexthops
= json_object_new_array();
11212 if (json_nexthop_global
)
11213 json_object_array_add(json_nexthops
,
11214 json_nexthop_global
);
11216 if (json_nexthop_ll
)
11217 json_object_array_add(json_nexthops
,
11220 json_object_object_add(json_path
, "nexthops",
11224 json_object_object_add(json_path
, "peer", json_peer
);
11225 json_object_array_add(json_paths
, json_path
);
11229 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11230 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11231 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11233 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11234 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11236 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11237 const char *comstr
, int exact
, afi_t afi
,
11238 safi_t safi
, uint16_t show_flags
);
11240 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11241 struct bgp_table
*table
, enum bgp_show_type type
,
11242 void *output_arg
, const char *rd
, int is_last
,
11243 unsigned long *output_cum
, unsigned long *total_cum
,
11244 unsigned long *json_header_depth
, uint16_t show_flags
,
11245 enum rpki_states rpki_target_state
)
11247 struct bgp_path_info
*pi
;
11248 struct bgp_dest
*dest
;
11249 bool header
= true;
11250 bool json_detail_header
= false;
11252 unsigned long output_count
= 0;
11253 unsigned long total_count
= 0;
11255 json_object
*json_paths
= NULL
;
11257 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11258 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11259 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11260 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11261 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11263 if (output_cum
&& *output_cum
!= 0)
11266 if (use_json
&& !*json_header_depth
) {
11268 *json_header_depth
= 1;
11270 vty_out(vty
, "{\n");
11271 *json_header_depth
= 2;
11275 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11276 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11277 " \"localAS\": %u,\n \"routes\": { ",
11278 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11279 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11282 table
->version
, &bgp
->router_id
,
11283 bgp
->default_local_pref
, bgp
->as
);
11285 vty_out(vty
, " \"routeDistinguishers\" : {");
11286 ++*json_header_depth
;
11290 if (use_json
&& rd
) {
11291 vty_out(vty
, " \"%s\" : { ", rd
);
11294 /* Check for 'json detail', where we need header output once per dest */
11295 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11296 type
!= bgp_show_type_damp_neighbor
&&
11297 type
!= bgp_show_type_flap_statistics
&&
11298 type
!= bgp_show_type_flap_neighbor
)
11299 json_detail_header
= true;
11301 /* Start processing of routes. */
11302 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11303 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11304 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11305 bool json_detail
= json_detail_header
;
11307 pi
= bgp_dest_get_bgp_path_info(dest
);
11313 json_paths
= json_object_new_array();
11317 for (; pi
; pi
= pi
->next
) {
11318 struct community
*picomm
= NULL
;
11320 picomm
= bgp_attr_get_community(pi
->attr
);
11324 if (type
== bgp_show_type_prefix_version
) {
11326 strtoul(output_arg
, NULL
, 10);
11327 if (dest
->version
< version
)
11331 if (type
== bgp_show_type_community_alias
) {
11332 char *alias
= output_arg
;
11333 char **communities
;
11335 bool found
= false;
11338 frrstr_split(picomm
->str
, " ",
11339 &communities
, &num
);
11340 for (int i
= 0; i
< num
; i
++) {
11341 const char *com2alias
=
11342 bgp_community2alias(
11345 && strcmp(alias
, com2alias
)
11351 XFREE(MTYPE_TMP
, communities
);
11355 bgp_attr_get_lcommunity(pi
->attr
)) {
11356 frrstr_split(bgp_attr_get_lcommunity(
11359 " ", &communities
, &num
);
11360 for (int i
= 0; i
< num
; i
++) {
11361 const char *com2alias
=
11362 bgp_community2alias(
11365 && strcmp(alias
, com2alias
)
11371 XFREE(MTYPE_TMP
, communities
);
11378 if (type
== bgp_show_type_rpki
) {
11379 if (dest_p
->family
== AF_INET
11380 || dest_p
->family
== AF_INET6
)
11381 rpki_curr_state
= hook_call(
11382 bgp_rpki_prefix_status
,
11383 pi
->peer
, pi
->attr
, dest_p
);
11384 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11385 && rpki_curr_state
!= rpki_target_state
)
11389 if (type
== bgp_show_type_flap_statistics
11390 || type
== bgp_show_type_flap_neighbor
11391 || type
== bgp_show_type_dampend_paths
11392 || type
== bgp_show_type_damp_neighbor
) {
11393 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11396 if (type
== bgp_show_type_regexp
) {
11397 regex_t
*regex
= output_arg
;
11399 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11403 if (type
== bgp_show_type_prefix_list
) {
11404 struct prefix_list
*plist
= output_arg
;
11406 if (prefix_list_apply(plist
, dest_p
)
11410 if (type
== bgp_show_type_access_list
) {
11411 struct access_list
*alist
= output_arg
;
11413 if (access_list_apply(alist
, dest_p
) !=
11417 if (type
== bgp_show_type_filter_list
) {
11418 struct as_list
*as_list
= output_arg
;
11420 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11421 != AS_FILTER_PERMIT
)
11424 if (type
== bgp_show_type_route_map
) {
11425 struct route_map
*rmap
= output_arg
;
11426 struct bgp_path_info path
;
11427 struct bgp_path_info_extra extra
;
11428 struct attr dummy_attr
= {};
11429 route_map_result_t ret
;
11431 dummy_attr
= *pi
->attr
;
11433 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11434 pi
->peer
, &dummy_attr
);
11436 ret
= route_map_apply(rmap
, dest_p
, &path
);
11437 bgp_attr_flush(&dummy_attr
);
11438 if (ret
== RMAP_DENYMATCH
)
11441 if (type
== bgp_show_type_neighbor
11442 || type
== bgp_show_type_flap_neighbor
11443 || type
== bgp_show_type_damp_neighbor
) {
11444 union sockunion
*su
= output_arg
;
11446 if (pi
->peer
== NULL
11447 || pi
->peer
->su_remote
== NULL
11448 || !sockunion_same(pi
->peer
->su_remote
, su
))
11451 if (type
== bgp_show_type_cidr_only
) {
11452 uint32_t destination
;
11454 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11455 if (IN_CLASSC(destination
)
11456 && dest_p
->prefixlen
== 24)
11458 if (IN_CLASSB(destination
)
11459 && dest_p
->prefixlen
== 16)
11461 if (IN_CLASSA(destination
)
11462 && dest_p
->prefixlen
== 8)
11465 if (type
== bgp_show_type_prefix_longer
) {
11467 if (!prefix_match(p
, dest_p
))
11470 if (type
== bgp_show_type_community_all
) {
11474 if (type
== bgp_show_type_community
) {
11475 struct community
*com
= output_arg
;
11477 if (!picomm
|| !community_match(picomm
, com
))
11480 if (type
== bgp_show_type_community_exact
) {
11481 struct community
*com
= output_arg
;
11483 if (!picomm
|| !community_cmp(picomm
, com
))
11486 if (type
== bgp_show_type_community_list
) {
11487 struct community_list
*list
= output_arg
;
11489 if (!community_list_match(picomm
, list
))
11492 if (type
== bgp_show_type_community_list_exact
) {
11493 struct community_list
*list
= output_arg
;
11495 if (!community_list_exact_match(picomm
, list
))
11498 if (type
== bgp_show_type_lcommunity
) {
11499 struct lcommunity
*lcom
= output_arg
;
11501 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11503 bgp_attr_get_lcommunity(pi
->attr
),
11508 if (type
== bgp_show_type_lcommunity_exact
) {
11509 struct lcommunity
*lcom
= output_arg
;
11511 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11513 bgp_attr_get_lcommunity(pi
->attr
),
11517 if (type
== bgp_show_type_lcommunity_list
) {
11518 struct community_list
*list
= output_arg
;
11520 if (!lcommunity_list_match(
11521 bgp_attr_get_lcommunity(pi
->attr
),
11526 == bgp_show_type_lcommunity_list_exact
) {
11527 struct community_list
*list
= output_arg
;
11529 if (!lcommunity_list_exact_match(
11530 bgp_attr_get_lcommunity(pi
->attr
),
11534 if (type
== bgp_show_type_lcommunity_all
) {
11535 if (!bgp_attr_get_lcommunity(pi
->attr
))
11538 if (type
== bgp_show_type_dampend_paths
11539 || type
== bgp_show_type_damp_neighbor
) {
11540 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11541 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11545 if (!use_json
&& header
) {
11547 "BGP table version is %" PRIu64
11548 ", local router ID is %pI4, vrf id ",
11549 table
->version
, &bgp
->router_id
);
11550 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11551 vty_out(vty
, "%s", VRFID_NONE_STR
);
11553 vty_out(vty
, "%u", bgp
->vrf_id
);
11554 vty_out(vty
, "\n");
11555 vty_out(vty
, "Default local pref %u, ",
11556 bgp
->default_local_pref
);
11557 vty_out(vty
, "local AS %u\n", bgp
->as
);
11558 if (!detail_routes
) {
11559 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11560 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11561 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11562 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11564 if (type
== bgp_show_type_dampend_paths
11565 || type
== bgp_show_type_damp_neighbor
)
11566 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11567 else if (type
== bgp_show_type_flap_statistics
11568 || type
== bgp_show_type_flap_neighbor
)
11569 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11570 else if (!detail_routes
)
11571 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11572 : BGP_SHOW_HEADER
));
11575 } else if (json_detail
&& json_paths
!= NULL
) {
11576 const struct prefix_rd
*prd
;
11577 json_object
*jtemp
;
11579 /* Use common detail header, for most types;
11580 * need a json 'object'.
11583 jtemp
= json_object_new_object();
11584 prd
= bgp_rd_from_dest(dest
, safi
);
11586 route_vty_out_detail_header(
11588 bgp_dest_get_prefix(dest
), prd
,
11589 table
->afi
, safi
, jtemp
);
11591 json_object_array_add(json_paths
, jtemp
);
11593 json_detail
= false;
11596 if (rd
!= NULL
&& !display
&& !output_count
) {
11599 "Route Distinguisher: %s\n",
11602 if (type
== bgp_show_type_dampend_paths
11603 || type
== bgp_show_type_damp_neighbor
)
11604 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11605 AFI_IP
, safi
, use_json
,
11607 else if (type
== bgp_show_type_flap_statistics
11608 || type
== bgp_show_type_flap_neighbor
)
11609 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11610 AFI_IP
, safi
, use_json
,
11613 if (detail_routes
|| detail_json
) {
11614 const struct prefix_rd
*prd
= NULL
;
11617 prd
= bgp_rd_from_dest(
11618 dest
->pdest
, safi
);
11621 route_vty_out_detail_header(
11623 bgp_dest_get_prefix(
11625 prd
, table
->afi
, safi
,
11628 route_vty_out_detail(
11629 vty
, bgp
, dest
, dest_p
, pi
,
11630 family2afi(dest_p
->family
),
11631 safi
, RPKI_NOT_BEING_USED
,
11634 route_vty_out(vty
, dest_p
, pi
, display
,
11635 safi
, json_paths
, wide
);
11646 /* encode prefix */
11647 if (dest_p
->family
== AF_FLOWSPEC
) {
11648 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11651 bgp_fs_nlri_get_string(
11653 dest_p
->u
.prefix_flowspec
.ptr
,
11654 dest_p
->u
.prefix_flowspec
.prefixlen
,
11655 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11656 family2afi(dest_p
->u
11657 .prefix_flowspec
.family
));
11659 vty_out(vty
, "\"%s/%d\": ", retstr
,
11660 dest_p
->u
.prefix_flowspec
11663 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11664 dest_p
->u
.prefix_flowspec
11668 vty_out(vty
, "\"%pFX\": ", dest_p
);
11670 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11672 vty_json(vty
, json_paths
);
11676 json_object_free(json_paths
);
11680 output_count
+= *output_cum
;
11681 *output_cum
= output_count
;
11684 total_count
+= *total_cum
;
11685 *total_cum
= total_count
;
11689 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11693 for (i
= 0; i
< *json_header_depth
; ++i
)
11694 vty_out(vty
, " } ");
11696 vty_out(vty
, "\n");
11700 /* No route is displayed */
11701 if (output_count
== 0) {
11702 if (type
== bgp_show_type_normal
)
11704 "No BGP prefixes displayed, %ld exist\n",
11708 "\nDisplayed %ld routes and %ld total paths\n",
11709 output_count
, total_count
);
11713 return CMD_SUCCESS
;
11716 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11717 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11718 enum bgp_show_type type
, void *output_arg
,
11719 uint16_t show_flags
)
11721 struct bgp_dest
*dest
, *next
;
11722 unsigned long output_cum
= 0;
11723 unsigned long total_cum
= 0;
11724 unsigned long json_header_depth
= 0;
11725 struct bgp_table
*itable
;
11727 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11729 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11731 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11732 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11734 next
= bgp_route_next(dest
);
11735 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11738 itable
= bgp_dest_get_bgp_table_info(dest
);
11739 if (itable
!= NULL
) {
11740 struct prefix_rd prd
;
11741 char rd
[RD_ADDRSTRLEN
];
11743 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11744 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11745 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11746 rd
, next
== NULL
, &output_cum
,
11747 &total_cum
, &json_header_depth
,
11748 show_flags
, RPKI_NOT_BEING_USED
);
11754 if (output_cum
== 0)
11755 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11759 "\nDisplayed %ld routes and %ld total paths\n",
11760 output_cum
, total_cum
);
11762 if (use_json
&& output_cum
== 0)
11763 vty_out(vty
, "{}\n");
11765 return CMD_SUCCESS
;
11768 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11769 enum bgp_show_type type
, void *output_arg
,
11770 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11772 struct bgp_table
*table
;
11773 unsigned long json_header_depth
= 0;
11774 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11777 bgp
= bgp_get_default();
11782 vty_out(vty
, "No BGP process is configured\n");
11784 vty_out(vty
, "{}\n");
11785 return CMD_WARNING
;
11788 /* Labeled-unicast routes live in the unicast table. */
11789 if (safi
== SAFI_LABELED_UNICAST
)
11790 safi
= SAFI_UNICAST
;
11792 table
= bgp
->rib
[afi
][safi
];
11793 /* use MPLS and ENCAP specific shows until they are merged */
11794 if (safi
== SAFI_MPLS_VPN
) {
11795 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11796 output_arg
, show_flags
);
11799 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11800 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11801 output_arg
, use_json
,
11805 if (safi
== SAFI_EVPN
)
11806 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11808 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11809 NULL
, NULL
, &json_header_depth
, show_flags
,
11810 rpki_target_state
);
11813 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11814 safi_t safi
, uint16_t show_flags
)
11816 struct listnode
*node
, *nnode
;
11819 bool route_output
= false;
11820 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11823 vty_out(vty
, "{\n");
11825 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11826 route_output
= true;
11829 vty_out(vty
, ",\n");
11833 vty_out(vty
, "\"%s\":",
11834 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11838 vty_out(vty
, "\nInstance %s:\n",
11839 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11843 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11844 show_flags
, RPKI_NOT_BEING_USED
);
11848 vty_out(vty
, "}\n");
11849 else if (!route_output
)
11850 vty_out(vty
, "%% BGP instance not found\n");
11853 /* Header of detailed BGP route information */
11854 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11855 struct bgp_dest
*dest
, const struct prefix
*p
,
11856 const struct prefix_rd
*prd
, afi_t afi
,
11857 safi_t safi
, json_object
*json
)
11859 struct bgp_path_info
*pi
;
11861 struct listnode
*node
, *nnode
;
11862 char buf1
[RD_ADDRSTRLEN
];
11866 int accept_own
= 0;
11867 int route_filter_translated_v4
= 0;
11868 int route_filter_v4
= 0;
11869 int route_filter_translated_v6
= 0;
11870 int route_filter_v6
= 0;
11871 int llgr_stale
= 0;
11873 int accept_own_nexthop
= 0;
11876 int no_advertise
= 0;
11880 int has_valid_label
= 0;
11881 mpls_label_t label
= 0;
11882 json_object
*json_adv_to
= NULL
;
11887 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11889 has_valid_label
= bgp_is_valid_label(&label
);
11891 if (safi
== SAFI_EVPN
) {
11893 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11894 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11896 prd
? ":" : "", (struct prefix_evpn
*)p
);
11898 json_object_string_add(json
, "rd",
11899 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11901 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11906 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11908 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11909 ? prefix_rd2str(prd
, buf1
,
11912 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11916 json_object_string_addf(json
, "prefix", "%pFX", p
);
11917 json_object_int_add(json
, "version", dest
->version
);
11922 if (has_valid_label
) {
11924 json_object_int_add(json
, "localLabel", label
);
11926 vty_out(vty
, "Local label: %d\n", label
);
11930 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11931 vty_out(vty
, "not allocated\n");
11933 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11934 struct community
*picomm
= NULL
;
11936 picomm
= bgp_attr_get_community(pi
->attr
);
11939 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11941 if (bgp_path_suppressed(pi
))
11947 no_advertise
+= community_include(
11948 picomm
, COMMUNITY_NO_ADVERTISE
);
11950 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11952 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11954 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11955 route_filter_translated_v4
+= community_include(
11956 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11957 route_filter_translated_v6
+= community_include(
11958 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11959 route_filter_v4
+= community_include(
11960 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11961 route_filter_v6
+= community_include(
11962 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11964 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11965 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11966 accept_own_nexthop
+= community_include(
11967 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11969 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11970 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11975 vty_out(vty
, "Paths: (%d available", count
);
11977 vty_out(vty
, ", best #%d", best
);
11978 if (safi
== SAFI_UNICAST
) {
11979 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11980 vty_out(vty
, ", table %s",
11983 vty_out(vty
, ", vrf %s",
11987 vty_out(vty
, ", no best path");
11991 ", accept own local route exported and imported in different VRF");
11992 else if (route_filter_translated_v4
)
11994 ", mark translated RTs for VPNv4 route filtering");
11995 else if (route_filter_v4
)
11997 ", attach RT as-is for VPNv4 route filtering");
11998 else if (route_filter_translated_v6
)
12000 ", mark translated RTs for VPNv6 route filtering");
12001 else if (route_filter_v6
)
12003 ", attach RT as-is for VPNv6 route filtering");
12004 else if (llgr_stale
)
12006 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
12009 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
12010 else if (accept_own_nexthop
)
12012 ", accept local nexthop");
12013 else if (blackhole
)
12014 vty_out(vty
, ", inform peer to blackhole prefix");
12015 else if (no_export
)
12016 vty_out(vty
, ", not advertised to EBGP peer");
12017 else if (no_advertise
)
12018 vty_out(vty
, ", not advertised to any peer");
12020 vty_out(vty
, ", not advertised outside local AS");
12023 ", inform EBGP peer not to advertise to their EBGP peers");
12027 ", Advertisements suppressed by an aggregate.");
12028 vty_out(vty
, ")\n");
12031 /* If we are not using addpath then we can display Advertised to and
12033 * show what peers we advertised the bestpath to. If we are using
12035 * though then we must display Advertised to on a path-by-path basis. */
12036 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12037 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12038 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12039 if (json
&& !json_adv_to
)
12040 json_adv_to
= json_object_new_object();
12042 route_vty_out_advertised_to(
12044 " Advertised to non peer-group peers:\n ",
12051 json_object_object_add(json
, "advertisedTo",
12056 vty_out(vty
, " Not advertised to any peer");
12057 vty_out(vty
, "\n");
12062 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12063 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12064 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12065 json_object
*json
, enum bgp_path_type pathtype
,
12066 int *display
, enum rpki_states rpki_target_state
)
12068 struct bgp_path_info
*pi
;
12070 json_object
*json_header
= NULL
;
12071 json_object
*json_paths
= NULL
;
12072 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12074 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12075 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12077 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12078 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12079 pi
->peer
, pi
->attr
, p
);
12081 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12082 && rpki_curr_state
!= rpki_target_state
)
12085 if (json
&& !json_paths
) {
12086 /* Instantiate json_paths only if path is valid */
12087 json_paths
= json_object_new_array();
12089 json_header
= json_object_new_object();
12091 json_header
= json
;
12095 route_vty_out_detail_header(
12096 vty
, bgp
, bgp_node
,
12097 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12098 safi
, json_header
);
12103 if (pathtype
== BGP_PATH_SHOW_ALL
12104 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12105 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12106 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12107 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12108 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12109 route_vty_out_detail(vty
, bgp
, bgp_node
,
12110 bgp_dest_get_prefix(bgp_node
), pi
,
12111 AFI_IP
, safi
, rpki_curr_state
,
12115 if (json
&& json_paths
) {
12116 json_object_object_add(json_header
, "paths", json_paths
);
12119 json_object_object_addf(json
, json_header
, "%pRD",
12125 * Return rd based on safi
12127 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12131 case SAFI_MPLS_VPN
:
12134 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12140 /* Display specified route of BGP table. */
12141 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12142 struct bgp_table
*rib
, const char *ip_str
,
12143 afi_t afi
, safi_t safi
,
12144 enum rpki_states rpki_target_state
,
12145 struct prefix_rd
*prd
, int prefix_check
,
12146 enum bgp_path_type pathtype
, bool use_json
)
12150 struct prefix match
;
12151 struct bgp_dest
*dest
;
12152 struct bgp_dest
*rm
;
12153 struct bgp_table
*table
;
12154 json_object
*json
= NULL
;
12155 json_object
*json_paths
= NULL
;
12157 /* Check IP address argument. */
12158 ret
= str2prefix(ip_str
, &match
);
12160 vty_out(vty
, "address is malformed\n");
12161 return CMD_WARNING
;
12164 match
.family
= afi2family(afi
);
12167 json
= json_object_new_object();
12169 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12170 for (dest
= bgp_table_top(rib
); dest
;
12171 dest
= bgp_route_next(dest
)) {
12172 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12174 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12176 table
= bgp_dest_get_bgp_table_info(dest
);
12180 rm
= bgp_node_match(table
, &match
);
12184 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12186 && rm_p
->prefixlen
!= match
.prefixlen
) {
12187 bgp_dest_unlock_node(rm
);
12191 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12192 bgp
, afi
, safi
, json
, pathtype
,
12193 &display
, rpki_target_state
);
12195 bgp_dest_unlock_node(rm
);
12197 } else if (safi
== SAFI_EVPN
) {
12198 struct bgp_dest
*longest_pfx
;
12199 bool is_exact_pfxlen_match
= false;
12201 for (dest
= bgp_table_top(rib
); dest
;
12202 dest
= bgp_route_next(dest
)) {
12203 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12205 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12207 table
= bgp_dest_get_bgp_table_info(dest
);
12211 longest_pfx
= NULL
;
12212 is_exact_pfxlen_match
= false;
12214 * Search through all the prefixes for a match. The
12215 * pfx's are enumerated in ascending order of pfxlens.
12216 * So, the last pfx match is the longest match. Set
12217 * is_exact_pfxlen_match when we get exact pfxlen match
12219 for (rm
= bgp_table_top(table
); rm
;
12220 rm
= bgp_route_next(rm
)) {
12221 const struct prefix
*rm_p
=
12222 bgp_dest_get_prefix(rm
);
12224 * Get prefixlen of the ip-prefix within type5
12227 if (evpn_type5_prefix_match(rm_p
, &match
)
12231 bgp_evpn_get_type5_prefixlen(
12233 if (type5_pfxlen
== match
.prefixlen
) {
12234 is_exact_pfxlen_match
= true;
12235 bgp_dest_unlock_node(rm
);
12244 if (prefix_check
&& !is_exact_pfxlen_match
)
12248 bgp_dest_lock_node(rm
);
12250 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12251 bgp
, afi
, safi
, json
, pathtype
,
12252 &display
, rpki_target_state
);
12254 bgp_dest_unlock_node(rm
);
12256 } else if (safi
== SAFI_FLOWSPEC
) {
12258 json_paths
= json_object_new_array();
12260 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12261 &match
, prefix_check
,
12267 json_object_object_add(json
, "paths",
12270 json_object_free(json_paths
);
12273 dest
= bgp_node_match(rib
, &match
);
12274 if (dest
!= NULL
) {
12275 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12277 || dest_p
->prefixlen
== match
.prefixlen
) {
12278 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12279 safi
, json
, pathtype
,
12280 &display
, rpki_target_state
);
12283 bgp_dest_unlock_node(dest
);
12288 vty_json(vty
, json
);
12291 vty_out(vty
, "%% Network not in table\n");
12292 return CMD_WARNING
;
12296 return CMD_SUCCESS
;
12299 /* Display specified route of Main RIB */
12300 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12301 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12302 int prefix_check
, enum bgp_path_type pathtype
,
12303 enum rpki_states rpki_target_state
, bool use_json
)
12306 bgp
= bgp_get_default();
12309 vty_out(vty
, "No BGP process is configured\n");
12311 vty_out(vty
, "{}\n");
12312 return CMD_WARNING
;
12316 /* labeled-unicast routes live in the unicast table */
12317 if (safi
== SAFI_LABELED_UNICAST
)
12318 safi
= SAFI_UNICAST
;
12320 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12321 afi
, safi
, rpki_target_state
, prd
,
12322 prefix_check
, pathtype
, use_json
);
12325 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12326 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12327 safi_t safi
, bool uj
)
12329 struct lcommunity
*lcom
;
12334 uint16_t show_flags
= 0;
12338 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12340 b
= buffer_new(1024);
12341 for (i
= 0; i
< argc
; i
++) {
12343 buffer_putc(b
, ' ');
12345 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12347 buffer_putstr(b
, argv
[i
]->arg
);
12351 buffer_putc(b
, '\0');
12353 str
= buffer_getstr(b
);
12356 lcom
= lcommunity_str2com(str
);
12357 XFREE(MTYPE_TMP
, str
);
12359 vty_out(vty
, "%% Large-community malformed\n");
12360 return CMD_WARNING
;
12363 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12364 (exact
? bgp_show_type_lcommunity_exact
12365 : bgp_show_type_lcommunity
),
12366 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12368 lcommunity_free(&lcom
);
12372 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12373 const char *lcom
, bool exact
, afi_t afi
,
12374 safi_t safi
, bool uj
)
12376 struct community_list
*list
;
12377 uint16_t show_flags
= 0;
12380 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12383 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12384 LARGE_COMMUNITY_LIST_MASTER
);
12385 if (list
== NULL
) {
12386 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12388 return CMD_WARNING
;
12391 return bgp_show(vty
, bgp
, afi
, safi
,
12392 (exact
? bgp_show_type_lcommunity_list_exact
12393 : bgp_show_type_lcommunity_list
),
12394 list
, show_flags
, RPKI_NOT_BEING_USED
);
12397 DEFUN (show_ip_bgp_large_community_list
,
12398 show_ip_bgp_large_community_list_cmd
,
12399 "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]",
12403 BGP_INSTANCE_HELP_STR
12405 BGP_SAFI_WITH_LABEL_HELP_STR
12406 "Display routes matching the large-community-list\n"
12407 "large-community-list number\n"
12408 "large-community-list name\n"
12409 "Exact match of the large-communities\n"
12412 afi_t afi
= AFI_IP6
;
12413 safi_t safi
= SAFI_UNICAST
;
12415 bool exact_match
= 0;
12416 struct bgp
*bgp
= NULL
;
12417 bool uj
= use_json(argc
, argv
);
12422 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12425 return CMD_WARNING
;
12427 argv_find(argv
, argc
, "large-community-list", &idx
);
12429 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12431 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12434 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12435 exact_match
, afi
, safi
, uj
);
12437 DEFUN (show_ip_bgp_large_community
,
12438 show_ip_bgp_large_community_cmd
,
12439 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12443 BGP_INSTANCE_HELP_STR
12445 BGP_SAFI_WITH_LABEL_HELP_STR
12446 "Display routes matching the large-communities\n"
12447 "List of large-community numbers\n"
12448 "Exact match of the large-communities\n"
12451 afi_t afi
= AFI_IP6
;
12452 safi_t safi
= SAFI_UNICAST
;
12454 bool exact_match
= 0;
12455 struct bgp
*bgp
= NULL
;
12456 bool uj
= use_json(argc
, argv
);
12457 uint16_t show_flags
= 0;
12461 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12464 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12467 return CMD_WARNING
;
12469 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12470 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12474 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12475 exact_match
, afi
, safi
, uj
);
12477 return bgp_show(vty
, bgp
, afi
, safi
,
12478 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12479 RPKI_NOT_BEING_USED
);
12482 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12483 safi_t safi
, struct json_object
*json_array
);
12484 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12485 safi_t safi
, struct json_object
*json
);
12488 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12489 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12490 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12491 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12493 bool uj
= use_json(argc
, argv
);
12494 struct bgp
*bgp
= NULL
;
12495 safi_t safi
= SAFI_UNICAST
;
12496 afi_t afi
= AFI_IP6
;
12498 struct json_object
*json_all
= NULL
;
12499 struct json_object
*json_afi_safi
= NULL
;
12501 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12504 return CMD_WARNING
;
12507 json_all
= json_object_new_object();
12509 FOREACH_AFI_SAFI (afi
, safi
) {
12511 * So limit output to those afi/safi pairs that
12512 * actually have something interesting in them
12514 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12519 json_afi_safi
= json_object_new_array();
12520 json_object_object_add(
12522 get_afi_safi_str(afi
, safi
, true),
12525 json_afi_safi
= NULL
;
12528 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12532 vty_json(vty
, json_all
);
12534 return CMD_SUCCESS
;
12537 /* BGP route print out function without JSON */
12538 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12539 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12540 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12544 BGP_INSTANCE_HELP_STR
12547 "BGP RIB advertisement statistics\n"
12550 afi_t afi
= AFI_IP6
;
12551 safi_t safi
= SAFI_UNICAST
;
12552 struct bgp
*bgp
= NULL
;
12554 bool uj
= use_json(argc
, argv
);
12555 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12557 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12560 return CMD_WARNING
;
12563 json_afi_safi
= json_object_new_array();
12565 json_afi_safi
= NULL
;
12567 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12570 json
= json_object_new_object();
12571 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12573 vty_json(vty
, json
);
12578 /* BGP route print out function without JSON */
12579 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12580 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12581 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12583 statistics [json]",
12584 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12585 BGP_SAFI_WITH_LABEL_HELP_STR
12586 "BGP RIB advertisement statistics\n" JSON_STR
)
12588 afi_t afi
= AFI_IP6
;
12589 safi_t safi
= SAFI_UNICAST
;
12590 struct bgp
*bgp
= NULL
;
12592 bool uj
= use_json(argc
, argv
);
12593 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12595 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12598 return CMD_WARNING
;
12601 json_afi_safi
= json_object_new_array();
12603 json_afi_safi
= NULL
;
12605 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12608 json
= json_object_new_object();
12609 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12611 vty_json(vty
, json
);
12616 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12617 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12618 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12619 "]] [all$all] dampening parameters [json]",
12620 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12621 BGP_SAFI_WITH_LABEL_HELP_STR
12622 "Display the entries for all address families\n"
12623 "Display detailed information about dampening\n"
12624 "Display detail of configured dampening parameters\n"
12627 afi_t afi
= AFI_IP6
;
12628 safi_t safi
= SAFI_UNICAST
;
12629 struct bgp
*bgp
= NULL
;
12631 uint16_t show_flags
= 0;
12632 bool uj
= use_json(argc
, argv
);
12636 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12639 /* [<ipv4|ipv6> [all]] */
12641 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12642 if (argv_find(argv
, argc
, "ipv4", &idx
))
12643 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12645 if (argv_find(argv
, argc
, "ipv6", &idx
))
12646 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12649 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12652 return CMD_WARNING
;
12654 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12657 /* BGP route print out function */
12658 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12659 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12660 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12664 |dampening <flap-statistics|dampened-paths>\
12665 |community [AA:NN|local-AS|no-advertise|no-export\
12666 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12667 |accept-own|accept-own-nexthop|route-filter-v6\
12668 |route-filter-v4|route-filter-translated-v6\
12669 |route-filter-translated-v4] [exact-match]\
12670 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12671 |filter-list AS_PATH_FILTER_NAME\
12673 |access-list ACCESSLIST_NAME\
12674 |route-map RMAP_NAME\
12675 |rpki <invalid|valid|notfound>\
12676 |version (1-4294967295)\
12678 |A.B.C.D/M longer-prefixes\
12679 |X:X::X:X/M longer-prefixes\
12680 |optimal-route-reflection [WORD$orr_group_name]\
12681 |detail-routes$detail_routes\
12682 ] [json$uj [detail$detail_json] | wide$wide]",
12683 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12684 BGP_SAFI_WITH_LABEL_HELP_STR
12685 "Display the entries for all address families\n"
12686 "Display only routes with non-natural netmasks\n"
12687 "Display detailed information about dampening\n"
12688 "Display flap statistics of routes\n"
12689 "Display paths suppressed due to dampening\n"
12690 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12691 "Do not send outside local AS (well-known community)\n"
12692 "Do not advertise to any peer (well-known community)\n"
12693 "Do not export to next AS (well-known community)\n"
12694 "Graceful shutdown (well-known community)\n"
12695 "Do not export to any peer (well-known community)\n"
12696 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12697 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12698 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12699 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12700 "Should accept VPN route with local nexthop (well-known community)\n"
12701 "RT VPNv6 route filtering (well-known community)\n"
12702 "RT VPNv4 route filtering (well-known community)\n"
12703 "RT translated VPNv6 route filtering (well-known community)\n"
12704 "RT translated VPNv4 route filtering (well-known community)\n"
12705 "Exact match of the communities\n"
12706 "Community-list number\n"
12707 "Community-list name\n"
12708 "Display routes matching the community-list\n"
12709 "Exact match of the communities\n"
12710 "Display routes conforming to the filter-list\n"
12711 "Regular expression access list name\n"
12712 "Display routes conforming to the prefix-list\n"
12713 "Prefix-list name\n"
12714 "Display routes conforming to the access-list\n"
12715 "Access-list name\n"
12716 "Display routes matching the route-map\n"
12717 "A route-map to match on\n"
12718 "RPKI route types\n"
12719 "A valid path as determined by rpki\n"
12720 "A invalid path as determined by rpki\n"
12721 "A path that has no rpki data\n"
12722 "Display prefixes with matching version numbers\n"
12723 "Version number and above\n"
12724 "Display prefixes with matching BGP community alias\n"
12725 "BGP community alias\n"
12727 "Display route and more specific routes\n"
12729 "Display route and more specific routes\n"
12730 "Display Optimal Route Reflection RR Clients\n"
12732 "Display detailed version of all routes\n"
12734 "Display detailed version of JSON output\n"
12735 "Increase table width for longer prefixes\n")
12737 afi_t afi
= AFI_IP6
;
12738 safi_t safi
= SAFI_UNICAST
;
12739 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12740 void *output_arg
= NULL
;
12741 struct bgp
*bgp
= NULL
;
12743 int exact_match
= 0;
12744 char *community
= NULL
;
12746 uint16_t show_flags
= 0;
12747 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12749 bool orr_group
= false;
12753 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12757 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12760 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12762 /* [<ipv4|ipv6> [all]] */
12764 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12766 if (argv_find(argv
, argc
, "ipv4", &idx
))
12767 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12769 if (argv_find(argv
, argc
, "ipv6", &idx
))
12770 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12774 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12776 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12779 return CMD_WARNING
;
12781 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12782 sh_type
= bgp_show_type_cidr_only
;
12784 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12785 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12786 sh_type
= bgp_show_type_dampend_paths
;
12787 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12788 sh_type
= bgp_show_type_flap_statistics
;
12791 if (argv_find(argv
, argc
, "community", &idx
)) {
12792 char *maybecomm
= NULL
;
12794 if (idx
+ 1 < argc
) {
12795 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12796 maybecomm
= argv
[idx
+ 1]->arg
;
12798 maybecomm
= argv
[idx
+ 1]->text
;
12801 if (maybecomm
&& !strmatch(maybecomm
, "json")
12802 && !strmatch(maybecomm
, "exact-match"))
12803 community
= maybecomm
;
12805 if (argv_find(argv
, argc
, "exact-match", &idx
))
12809 sh_type
= bgp_show_type_community_all
;
12812 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12813 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12814 struct community_list
*list
;
12816 if (argv_find(argv
, argc
, "exact-match", &idx
))
12819 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12820 COMMUNITY_LIST_MASTER
);
12821 if (list
== NULL
) {
12822 vty_out(vty
, "%% %s community-list not found\n",
12823 clist_number_or_name
);
12824 return CMD_WARNING
;
12828 sh_type
= bgp_show_type_community_list_exact
;
12830 sh_type
= bgp_show_type_community_list
;
12834 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12835 const char *filter
= argv
[++idx
]->arg
;
12836 struct as_list
*as_list
;
12838 as_list
= as_list_lookup(filter
);
12839 if (as_list
== NULL
) {
12840 vty_out(vty
, "%% %s AS-path access-list not found\n",
12842 return CMD_WARNING
;
12845 sh_type
= bgp_show_type_filter_list
;
12846 output_arg
= as_list
;
12849 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12850 const char *prefix_list_str
= argv
[++idx
]->arg
;
12851 struct prefix_list
*plist
;
12853 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12854 if (plist
== NULL
) {
12855 vty_out(vty
, "%% %s prefix-list not found\n",
12857 return CMD_WARNING
;
12860 sh_type
= bgp_show_type_prefix_list
;
12861 output_arg
= plist
;
12864 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12865 const char *access_list_str
= argv
[++idx
]->arg
;
12866 struct access_list
*alist
;
12868 alist
= access_list_lookup(afi
, access_list_str
);
12870 vty_out(vty
, "%% %s access-list not found\n",
12872 return CMD_WARNING
;
12875 sh_type
= bgp_show_type_access_list
;
12876 output_arg
= alist
;
12879 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12880 const char *rmap_str
= argv
[++idx
]->arg
;
12881 struct route_map
*rmap
;
12883 rmap
= route_map_lookup_by_name(rmap_str
);
12885 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12886 return CMD_WARNING
;
12889 sh_type
= bgp_show_type_route_map
;
12893 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12894 sh_type
= bgp_show_type_rpki
;
12895 if (argv_find(argv
, argc
, "valid", &idx
))
12896 rpki_target_state
= RPKI_VALID
;
12897 else if (argv_find(argv
, argc
, "invalid", &idx
))
12898 rpki_target_state
= RPKI_INVALID
;
12901 /* Display prefixes with matching version numbers */
12902 if (argv_find(argv
, argc
, "version", &idx
)) {
12903 sh_type
= bgp_show_type_prefix_version
;
12904 output_arg
= argv
[idx
+ 1]->arg
;
12907 /* Display prefixes with matching BGP community alias */
12908 if (argv_find(argv
, argc
, "alias", &idx
)) {
12909 sh_type
= bgp_show_type_community_alias
;
12910 output_arg
= argv
[idx
+ 1]->arg
;
12913 /* prefix-longer */
12914 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12915 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12916 const char *prefix_str
= argv
[idx
]->arg
;
12918 if (!str2prefix(prefix_str
, &p
)) {
12919 vty_out(vty
, "%% Malformed Prefix\n");
12920 return CMD_WARNING
;
12923 sh_type
= bgp_show_type_prefix_longer
;
12927 if (argv_find(argv
, argc
, "optimal-route-reflection", &idx
))
12931 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12933 return bgp_show_community(vty
, bgp
, community
,
12934 exact_match
, afi
, safi
,
12936 else if (orr_group
)
12937 return bgp_show_orr(vty
, bgp
, afi
, safi
, orr_group_name
,
12940 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12941 output_arg
, show_flags
,
12942 rpki_target_state
);
12944 struct listnode
*node
;
12946 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12950 vty_out(vty
, "{\n");
12952 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12953 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12954 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12957 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12958 FOREACH_SAFI (safi
) {
12959 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12967 vty_out(vty
, ",\n");
12968 vty_out(vty
, "\"%s\":{\n",
12969 get_afi_safi_str(afi
,
12974 "\nFor address family: %s\n",
12980 bgp_show_community(
12981 vty
, abgp
, community
,
12982 exact_match
, afi
, safi
,
12984 else if (orr_group
)
12985 bgp_show_orr(vty
, bgp
, afi
,
12990 bgp_show(vty
, abgp
, afi
, safi
,
12991 sh_type
, output_arg
,
12993 rpki_target_state
);
12995 vty_out(vty
, "}\n");
12999 /* show <ip> bgp all: for each AFI and SAFI*/
13000 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
13001 FOREACH_AFI_SAFI (afi
, safi
) {
13002 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
13010 vty_out(vty
, ",\n");
13012 vty_out(vty
, "\"%s\":{\n",
13013 get_afi_safi_str(afi
,
13018 "\nFor address family: %s\n",
13024 bgp_show_community(
13025 vty
, abgp
, community
,
13026 exact_match
, afi
, safi
,
13028 else if (orr_group
)
13029 bgp_show_orr(vty
, bgp
, afi
,
13034 bgp_show(vty
, abgp
, afi
, safi
,
13035 sh_type
, output_arg
,
13037 rpki_target_state
);
13039 vty_out(vty
, "}\n");
13044 vty_out(vty
, "}\n");
13046 return CMD_SUCCESS
;
13049 DEFUN (show_ip_bgp_route
,
13050 show_ip_bgp_route_cmd
,
13051 "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]",
13055 BGP_INSTANCE_HELP_STR
13057 BGP_SAFI_WITH_LABEL_HELP_STR
13058 "Network in the BGP routing table to display\n"
13060 "Network in the BGP routing table to display\n"
13062 "Display only the bestpath\n"
13063 "Display only multipaths\n"
13064 "Display only paths that match the specified rpki state\n"
13065 "A valid path as determined by rpki\n"
13066 "A invalid path as determined by rpki\n"
13067 "A path that has no rpki data\n"
13070 int prefix_check
= 0;
13072 afi_t afi
= AFI_IP6
;
13073 safi_t safi
= SAFI_UNICAST
;
13074 char *prefix
= NULL
;
13075 struct bgp
*bgp
= NULL
;
13076 enum bgp_path_type path_type
;
13077 bool uj
= use_json(argc
, argv
);
13081 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13084 return CMD_WARNING
;
13088 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13089 return CMD_WARNING
;
13092 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13093 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13094 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13096 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13097 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13100 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13101 && afi
!= AFI_IP6
) {
13103 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13104 return CMD_WARNING
;
13106 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13107 && afi
!= AFI_IP
) {
13109 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13110 return CMD_WARNING
;
13113 prefix
= argv
[idx
]->arg
;
13115 /* [<bestpath|multipath>] */
13116 if (argv_find(argv
, argc
, "bestpath", &idx
))
13117 path_type
= BGP_PATH_SHOW_BESTPATH
;
13118 else if (argv_find(argv
, argc
, "multipath", &idx
))
13119 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13121 path_type
= BGP_PATH_SHOW_ALL
;
13123 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13124 path_type
, RPKI_NOT_BEING_USED
, uj
);
13127 DEFUN (show_ip_bgp_regexp
,
13128 show_ip_bgp_regexp_cmd
,
13129 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13133 BGP_INSTANCE_HELP_STR
13135 BGP_SAFI_WITH_LABEL_HELP_STR
13136 "Display routes matching the AS path regular expression\n"
13137 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13140 afi_t afi
= AFI_IP6
;
13141 safi_t safi
= SAFI_UNICAST
;
13142 struct bgp
*bgp
= NULL
;
13143 bool uj
= use_json(argc
, argv
);
13144 char *regstr
= NULL
;
13147 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13150 return CMD_WARNING
;
13152 // get index of regex
13153 if (argv_find(argv
, argc
, "REGEX", &idx
))
13154 regstr
= argv
[idx
]->arg
;
13157 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13158 bgp_show_type_regexp
, uj
);
13161 DEFPY (show_ip_bgp_instance_all
,
13162 show_ip_bgp_instance_all_cmd
,
13163 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13167 BGP_INSTANCE_ALL_HELP_STR
13169 BGP_SAFI_WITH_LABEL_HELP_STR
13171 "Increase table width for longer prefixes\n")
13173 afi_t afi
= AFI_IP6
;
13174 safi_t safi
= SAFI_UNICAST
;
13175 struct bgp
*bgp
= NULL
;
13177 uint16_t show_flags
= 0;
13181 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13185 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13187 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13190 return CMD_WARNING
;
13192 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13193 return CMD_SUCCESS
;
13196 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13197 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13202 uint16_t show_flags
= 0;
13205 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13207 if (!config_bgp_aspath_validate(regstr
)) {
13208 vty_out(vty
, "Invalid character in REGEX %s\n",
13210 return CMD_WARNING_CONFIG_FAILED
;
13213 regex
= bgp_regcomp(regstr
);
13215 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13216 return CMD_WARNING
;
13219 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13220 RPKI_NOT_BEING_USED
);
13221 bgp_regex_free(regex
);
13225 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13226 const char *comstr
, int exact
, afi_t afi
,
13227 safi_t safi
, uint16_t show_flags
)
13229 struct community
*com
;
13232 com
= community_str2com(comstr
);
13234 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13235 return CMD_WARNING
;
13238 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13239 (exact
? bgp_show_type_community_exact
13240 : bgp_show_type_community
),
13241 com
, show_flags
, RPKI_NOT_BEING_USED
);
13242 community_free(&com
);
13248 BGP_STATS_MAXBITLEN
= 0,
13250 BGP_STATS_PREFIXES
,
13252 BGP_STATS_UNAGGREGATEABLE
,
13253 BGP_STATS_MAX_AGGREGATEABLE
,
13254 BGP_STATS_AGGREGATES
,
13256 BGP_STATS_ASPATH_COUNT
,
13257 BGP_STATS_ASPATH_MAXHOPS
,
13258 BGP_STATS_ASPATH_TOTHOPS
,
13259 BGP_STATS_ASPATH_MAXSIZE
,
13260 BGP_STATS_ASPATH_TOTSIZE
,
13261 BGP_STATS_ASN_HIGHEST
,
13265 #define TABLE_STATS_IDX_VTY 0
13266 #define TABLE_STATS_IDX_JSON 1
13268 static const char *table_stats_strs
[][2] = {
13269 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13270 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13271 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13272 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13273 "unaggregateablePrefixes"},
13274 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13275 "maximumAggregateablePrefixes"},
13276 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13277 "bgpAggregateAdvertisements"},
13278 [BGP_STATS_SPACE
] = {"Address space advertised",
13279 "addressSpaceAdvertised"},
13280 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13281 "advertisementsWithPaths"},
13282 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13284 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13286 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13287 "averageAsPathLengthHops"},
13288 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13289 "averageAsPathSizeBytes"},
13290 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13291 [BGP_STATS_MAX
] = {NULL
, NULL
}
13294 struct bgp_table_stats
{
13295 struct bgp_table
*table
;
13296 unsigned long long counts
[BGP_STATS_MAX
];
13299 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13302 double total_space
;
13305 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13306 struct bgp_table_stats
*ts
, unsigned int space
)
13308 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13309 struct bgp_path_info
*pi
;
13310 const struct prefix
*rn_p
;
13312 if (!bgp_dest_has_bgp_path_info_data(dest
))
13315 rn_p
= bgp_dest_get_prefix(dest
);
13316 ts
->counts
[BGP_STATS_PREFIXES
]++;
13317 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13319 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13320 /* check if the prefix is included by any other announcements */
13321 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13322 pdest
= bgp_dest_parent_nolock(pdest
);
13324 if (pdest
== NULL
|| pdest
== top
) {
13325 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13326 /* announced address space */
13328 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13329 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13330 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13333 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13334 ts
->counts
[BGP_STATS_RIB
]++;
13336 if (CHECK_FLAG(pi
->attr
->flag
,
13337 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13338 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13340 /* as-path stats */
13341 if (pi
->attr
->aspath
) {
13342 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13343 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13344 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13346 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13348 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13349 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13351 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13352 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13354 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13355 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13356 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13357 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13362 static void bgp_table_stats_walker(struct thread
*t
)
13364 struct bgp_dest
*dest
, *ndest
;
13365 struct bgp_dest
*top
;
13366 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13367 unsigned int space
= 0;
13369 if (!(top
= bgp_table_top(ts
->table
)))
13372 switch (ts
->table
->afi
) {
13374 space
= IPV4_MAX_BITLEN
;
13377 space
= IPV6_MAX_BITLEN
;
13380 space
= EVPN_ROUTE_PREFIXLEN
;
13386 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13388 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13389 if (ts
->table
->safi
== SAFI_MPLS_VPN
13390 || ts
->table
->safi
== SAFI_ENCAP
13391 || ts
->table
->safi
== SAFI_EVPN
) {
13392 struct bgp_table
*table
;
13394 table
= bgp_dest_get_bgp_table_info(dest
);
13398 top
= bgp_table_top(table
);
13399 for (ndest
= bgp_table_top(table
); ndest
;
13400 ndest
= bgp_route_next(ndest
))
13401 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13403 bgp_table_stats_rn(dest
, top
, ts
, space
);
13408 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13409 struct json_object
*json_array
)
13411 struct listnode
*node
, *nnode
;
13414 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13415 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13418 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13419 safi_t safi
, struct json_object
*json_array
)
13421 struct bgp_table_stats ts
;
13423 int ret
= CMD_SUCCESS
;
13425 struct json_object
*json
= NULL
;
13426 uint32_t bitlen
= 0;
13427 struct json_object
*json_bitlen
;
13430 json
= json_object_new_object();
13432 if (!bgp
->rib
[afi
][safi
]) {
13433 char warning_msg
[50];
13435 snprintf(warning_msg
, sizeof(warning_msg
),
13436 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13440 vty_out(vty
, "%s\n", warning_msg
);
13442 json_object_string_add(json
, "warning", warning_msg
);
13445 goto end_table_stats
;
13449 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13450 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13452 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13454 /* labeled-unicast routes live in the unicast table */
13455 if (safi
== SAFI_LABELED_UNICAST
)
13456 safi
= SAFI_UNICAST
;
13458 memset(&ts
, 0, sizeof(ts
));
13459 ts
.table
= bgp
->rib
[afi
][safi
];
13460 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13462 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13463 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13464 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13468 case BGP_STATS_ASPATH_TOTHOPS
:
13469 case BGP_STATS_ASPATH_TOTSIZE
:
13472 temp_buf
, sizeof(temp_buf
), "%12.2f",
13474 ? (float)ts
.counts
[i
]
13476 [BGP_STATS_ASPATH_COUNT
]
13478 vty_out(vty
, "%-30s: %s",
13479 table_stats_strs
[i
]
13480 [TABLE_STATS_IDX_VTY
],
13483 json_object_double_add(
13485 table_stats_strs
[i
]
13486 [TABLE_STATS_IDX_JSON
],
13488 ? (double)ts
.counts
[i
]
13489 / (double)ts
.counts
13490 [BGP_STATS_ASPATH_COUNT
]
13494 case BGP_STATS_TOTPLEN
:
13497 temp_buf
, sizeof(temp_buf
), "%12.2f",
13499 ? (float)ts
.counts
[i
]
13501 [BGP_STATS_PREFIXES
]
13503 vty_out(vty
, "%-30s: %s",
13504 table_stats_strs
[i
]
13505 [TABLE_STATS_IDX_VTY
],
13508 json_object_double_add(
13510 table_stats_strs
[i
]
13511 [TABLE_STATS_IDX_JSON
],
13513 ? (double)ts
.counts
[i
]
13514 / (double)ts
.counts
13515 [BGP_STATS_PREFIXES
]
13519 case BGP_STATS_SPACE
:
13521 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13523 vty_out(vty
, "%-30s: %s\n",
13524 table_stats_strs
[i
]
13525 [TABLE_STATS_IDX_VTY
],
13528 json_object_double_add(
13530 table_stats_strs
[i
]
13531 [TABLE_STATS_IDX_JSON
],
13532 (double)ts
.total_space
);
13534 if (afi
== AFI_IP6
) {
13536 snprintf(temp_buf
, sizeof(temp_buf
),
13539 * pow(2.0, -128 + 32));
13540 vty_out(vty
, "%30s: %s\n",
13541 "/32 equivalent %s\n",
13544 json_object_double_add(
13545 json
, "/32equivalent",
13546 (double)(ts
.total_space
13551 snprintf(temp_buf
, sizeof(temp_buf
),
13554 * pow(2.0, -128 + 48));
13555 vty_out(vty
, "%30s: %s\n",
13556 "/48 equivalent %s\n",
13559 json_object_double_add(
13560 json
, "/48equivalent",
13561 (double)(ts
.total_space
13567 snprintf(temp_buf
, sizeof(temp_buf
),
13569 ts
.total_space
* 100.
13571 vty_out(vty
, "%30s: %s\n",
13572 "% announced ", temp_buf
);
13574 json_object_double_add(
13575 json
, "%announced",
13576 (double)(ts
.total_space
* 100.
13580 snprintf(temp_buf
, sizeof(temp_buf
),
13583 * pow(2.0, -32 + 8));
13584 vty_out(vty
, "%30s: %s\n",
13585 "/8 equivalent ", temp_buf
);
13587 json_object_double_add(
13588 json
, "/8equivalent",
13589 (double)(ts
.total_space
13590 * pow(2.0, -32 + 8)));
13593 snprintf(temp_buf
, sizeof(temp_buf
),
13596 * pow(2.0, -32 + 24));
13597 vty_out(vty
, "%30s: %s\n",
13598 "/24 equivalent ", temp_buf
);
13600 json_object_double_add(
13601 json
, "/24equivalent",
13602 (double)(ts
.total_space
13603 * pow(2.0, -32 + 24)));
13609 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13611 vty_out(vty
, "%-30s: %s",
13612 table_stats_strs
[i
]
13613 [TABLE_STATS_IDX_VTY
],
13616 json_object_int_add(
13618 table_stats_strs
[i
]
13619 [TABLE_STATS_IDX_JSON
],
13624 vty_out(vty
, "\n");
13629 bitlen
= IPV4_MAX_BITLEN
;
13632 bitlen
= IPV6_MAX_BITLEN
;
13635 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13642 json_bitlen
= json_object_new_array();
13644 for (i
= 0; i
<= bitlen
; i
++) {
13645 struct json_object
*ind_bit
= json_object_new_object();
13647 if (!ts
.prefix_len_count
[i
])
13650 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13651 json_object_int_add(ind_bit
, temp_buf
,
13652 ts
.prefix_len_count
[i
]);
13653 json_object_array_add(json_bitlen
, ind_bit
);
13655 json_object_object_add(json
, "prefixLength", json_bitlen
);
13660 json_object_array_add(json_array
, json
);
13664 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13665 safi_t safi
, struct json_object
*json_array
)
13668 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13669 return CMD_SUCCESS
;
13672 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13684 PCOUNT_BPATH_SELECTED
,
13685 PCOUNT_PFCNT
, /* the figure we display to users */
13689 static const char *const pcount_strs
[] = {
13690 [PCOUNT_ADJ_IN
] = "Adj-in",
13691 [PCOUNT_DAMPED
] = "Damped",
13692 [PCOUNT_REMOVED
] = "Removed",
13693 [PCOUNT_HISTORY
] = "History",
13694 [PCOUNT_STALE
] = "Stale",
13695 [PCOUNT_VALID
] = "Valid",
13696 [PCOUNT_ALL
] = "All RIB",
13697 [PCOUNT_COUNTED
] = "PfxCt counted",
13698 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13699 [PCOUNT_PFCNT
] = "Useable",
13700 [PCOUNT_MAX
] = NULL
,
13703 struct peer_pcounts
{
13704 unsigned int count
[PCOUNT_MAX
];
13705 const struct peer
*peer
;
13706 const struct bgp_table
*table
;
13710 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13712 const struct bgp_adj_in
*ain
;
13713 const struct bgp_path_info
*pi
;
13714 const struct peer
*peer
= pc
->peer
;
13716 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13717 if (ain
->peer
== peer
)
13718 pc
->count
[PCOUNT_ADJ_IN
]++;
13720 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13722 if (pi
->peer
!= peer
)
13725 pc
->count
[PCOUNT_ALL
]++;
13727 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13728 pc
->count
[PCOUNT_DAMPED
]++;
13729 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13730 pc
->count
[PCOUNT_HISTORY
]++;
13731 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13732 pc
->count
[PCOUNT_REMOVED
]++;
13733 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13734 pc
->count
[PCOUNT_STALE
]++;
13735 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13736 pc
->count
[PCOUNT_VALID
]++;
13737 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13738 pc
->count
[PCOUNT_PFCNT
]++;
13739 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13740 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13742 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13743 pc
->count
[PCOUNT_COUNTED
]++;
13744 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13746 EC_LIB_DEVELOPMENT
,
13747 "Attempting to count but flags say it is unusable");
13749 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13751 EC_LIB_DEVELOPMENT
,
13752 "Not counted but flags say we should");
13757 static void bgp_peer_count_walker(struct thread
*t
)
13759 struct bgp_dest
*rn
, *rm
;
13760 const struct bgp_table
*table
;
13761 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13763 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13764 || pc
->safi
== SAFI_EVPN
) {
13765 /* Special handling for 2-level routing tables. */
13766 for (rn
= bgp_table_top(pc
->table
); rn
;
13767 rn
= bgp_route_next(rn
)) {
13768 table
= bgp_dest_get_bgp_table_info(rn
);
13770 for (rm
= bgp_table_top(table
); rm
;
13771 rm
= bgp_route_next(rm
))
13772 bgp_peer_count_proc(rm
, pc
);
13775 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13776 bgp_peer_count_proc(rn
, pc
);
13779 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13780 safi_t safi
, bool use_json
)
13782 struct peer_pcounts pcounts
= {.peer
= peer
};
13784 json_object
*json
= NULL
;
13785 json_object
*json_loop
= NULL
;
13788 json
= json_object_new_object();
13789 json_loop
= json_object_new_object();
13792 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13793 || !peer
->bgp
->rib
[afi
][safi
]) {
13795 json_object_string_add(
13797 "No such neighbor or address family");
13798 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13799 json_object_free(json
);
13800 json_object_free(json_loop
);
13802 vty_out(vty
, "%% No such neighbor or address family\n");
13804 return CMD_WARNING
;
13807 memset(&pcounts
, 0, sizeof(pcounts
));
13808 pcounts
.peer
= peer
;
13809 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13810 pcounts
.safi
= safi
;
13812 /* in-place call via thread subsystem so as to record execution time
13813 * stats for the thread-walk (i.e. ensure this can't be blamed on
13814 * on just vty_read()).
13816 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13819 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13820 json_object_string_add(json
, "multiProtocol",
13821 get_afi_safi_str(afi
, safi
, true));
13822 json_object_int_add(json
, "pfxCounter",
13823 peer
->pcount
[afi
][safi
]);
13825 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13826 json_object_int_add(json_loop
, pcount_strs
[i
],
13829 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13831 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13832 json_object_string_add(json
, "pfxctDriftFor",
13834 json_object_string_add(
13835 json
, "recommended",
13836 "Please report this bug, with the above command output");
13838 vty_json(vty
, json
);
13842 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13843 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13844 peer
->hostname
, peer
->host
,
13845 get_afi_safi_str(afi
, safi
, false));
13847 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13848 get_afi_safi_str(afi
, safi
, false));
13851 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13852 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13854 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13855 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13858 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13859 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13861 "Please report this bug, with the above command output\n");
13865 return CMD_SUCCESS
;
13868 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13869 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13870 "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]",
13874 BGP_INSTANCE_HELP_STR
13877 "Detailed information on TCP and BGP neighbor connections\n"
13878 "Neighbor to display information about\n"
13879 "Neighbor to display information about\n"
13880 "Neighbor on BGP configured interface\n"
13881 "Display detailed prefix count information\n"
13884 afi_t afi
= AFI_IP6
;
13885 safi_t safi
= SAFI_UNICAST
;
13888 struct bgp
*bgp
= NULL
;
13889 bool uj
= use_json(argc
, argv
);
13894 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13897 return CMD_WARNING
;
13899 argv_find(argv
, argc
, "neighbors", &idx
);
13900 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13902 return CMD_WARNING
;
13904 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13907 #ifdef KEEP_OLD_VPN_COMMANDS
13908 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13909 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13910 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13915 "Display information about all VPNv4 NLRIs\n"
13916 "Detailed information on TCP and BGP neighbor connections\n"
13917 "Neighbor to display information about\n"
13918 "Neighbor to display information about\n"
13919 "Neighbor on BGP configured interface\n"
13920 "Display detailed prefix count information\n"
13925 bool uj
= use_json(argc
, argv
);
13927 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13929 return CMD_WARNING
;
13931 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13934 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13935 show_ip_bgp_vpn_all_route_prefix_cmd
,
13936 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13941 "Display information about all VPNv4 NLRIs\n"
13942 "Network in the BGP routing table to display\n"
13943 "Network in the BGP routing table to display\n"
13947 char *network
= NULL
;
13948 struct bgp
*bgp
= bgp_get_default();
13950 vty_out(vty
, "Can't find default instance\n");
13951 return CMD_WARNING
;
13954 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13955 network
= argv
[idx
]->arg
;
13956 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13957 network
= argv
[idx
]->arg
;
13959 vty_out(vty
, "Unable to figure out Network\n");
13960 return CMD_WARNING
;
13963 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13964 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13965 use_json(argc
, argv
));
13967 #endif /* KEEP_OLD_VPN_COMMANDS */
13969 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13970 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13971 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13976 "Network in the BGP routing table to display\n"
13977 "Network in the BGP routing table to display\n"
13978 "Network in the BGP routing table to display\n"
13979 "Network in the BGP routing table to display\n"
13983 char *network
= NULL
;
13984 int prefix_check
= 0;
13986 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13987 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13988 network
= argv
[idx
]->arg
;
13989 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13990 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13991 network
= argv
[idx
]->arg
;
13994 vty_out(vty
, "Unable to figure out Network\n");
13995 return CMD_WARNING
;
13997 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13998 prefix_check
, BGP_PATH_SHOW_ALL
,
13999 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
14002 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
14003 struct bgp_table
*table
, int *header1
,
14004 int *header2
, json_object
*json
,
14005 json_object
*json_scode
,
14006 json_object
*json_ocode
, bool wide
,
14009 uint64_t version
= table
? table
->version
: 0;
14013 json_object_int_add(json
, "bgpTableVersion", version
);
14014 json_object_string_addf(json
, "bgpLocalRouterId",
14015 "%pI4", &peer
->bgp
->router_id
);
14016 json_object_int_add(json
, "defaultLocPrf",
14017 peer
->bgp
->default_local_pref
);
14018 json_object_int_add(json
, "localAS",
14019 peer
->change_local_as
14020 ? peer
->change_local_as
14022 json_object_object_add(json
, "bgpStatusCodes",
14024 json_object_object_add(json
, "bgpOriginCodes",
14028 "BGP table version is %" PRIu64
14029 ", local router ID is %pI4, vrf id ",
14030 version
, &peer
->bgp
->router_id
);
14031 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
14032 vty_out(vty
, "%s", VRFID_NONE_STR
);
14034 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
14035 vty_out(vty
, "\n");
14036 vty_out(vty
, "Default local pref %u, ",
14037 peer
->bgp
->default_local_pref
);
14038 vty_out(vty
, "local AS %u\n",
14039 peer
->change_local_as
? peer
->change_local_as
14042 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14043 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14044 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14045 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14051 if (!json
&& !detail
)
14052 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14053 : BGP_SHOW_HEADER
));
14059 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14060 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14061 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14062 json_object
*json_scode
, json_object
*json_ocode
,
14063 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14064 unsigned long *output_count
, unsigned long *filtered_count
)
14066 struct bgp_adj_in
*ain
;
14067 struct bgp_adj_out
*adj
;
14068 struct bgp_dest
*dest
;
14072 struct update_subgroup
*subgrp
;
14073 struct peer_af
*paf
;
14074 bool route_filtered
;
14075 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14076 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14077 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14078 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14079 || (safi
== SAFI_EVPN
))
14083 json_object
*json_net
= NULL
;
14087 subgrp
= peer_subgroup(peer
, afi
, safi
);
14089 if (type
== bgp_show_adj_route_advertised
&& subgrp
14090 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14092 json_object_int_add(json
, "bgpTableVersion",
14094 json_object_string_addf(json
, "bgpLocalRouterId",
14095 "%pI4", &bgp
->router_id
);
14096 json_object_int_add(json
, "defaultLocPrf",
14097 bgp
->default_local_pref
);
14098 json_object_int_add(json
, "localAS",
14099 peer
->change_local_as
14100 ? peer
->change_local_as
14102 json_object_object_add(json
, "bgpStatusCodes",
14104 json_object_object_add(json
, "bgpOriginCodes",
14106 json_object_string_add(
14107 json
, "bgpOriginatingDefaultNetwork",
14108 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14111 "BGP table version is %" PRIu64
14112 ", local router ID is %pI4, vrf id ",
14113 table
->version
, &bgp
->router_id
);
14114 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14115 vty_out(vty
, "%s", VRFID_NONE_STR
);
14117 vty_out(vty
, "%u", bgp
->vrf_id
);
14118 vty_out(vty
, "\n");
14119 vty_out(vty
, "Default local pref %u, ",
14120 bgp
->default_local_pref
);
14121 vty_out(vty
, "local AS %u\n",
14122 peer
->change_local_as
? peer
->change_local_as
14125 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14126 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14127 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14128 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14131 vty_out(vty
, "Originating default network %s\n\n",
14132 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14138 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14139 if (type
== bgp_show_adj_route_received
14140 || type
== bgp_show_adj_route_filtered
) {
14141 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14142 if (ain
->peer
!= peer
)
14145 show_adj_route_header(vty
, peer
, table
, header1
,
14146 header2
, json
, json_scode
,
14147 json_ocode
, wide
, detail
);
14149 if ((safi
== SAFI_MPLS_VPN
)
14150 || (safi
== SAFI_ENCAP
)
14151 || (safi
== SAFI_EVPN
)) {
14153 json_object_string_add(
14154 json_ar
, "rd", rd_str
);
14155 else if (show_rd
&& rd_str
) {
14157 "Route Distinguisher: %s\n",
14164 route_filtered
= false;
14166 /* Filter prefix using distribute list,
14167 * filter list or prefix list
14169 const struct prefix
*rn_p
=
14170 bgp_dest_get_prefix(dest
);
14171 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14174 route_filtered
= true;
14176 /* Filter prefix using route-map */
14177 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14178 safi
, rmap_name
, NULL
,
14181 if (type
== bgp_show_adj_route_filtered
&&
14182 !route_filtered
&& ret
!= RMAP_DENY
) {
14183 bgp_attr_flush(&attr
);
14187 if (type
== bgp_show_adj_route_received
14188 && (route_filtered
|| ret
== RMAP_DENY
))
14189 (*filtered_count
)++;
14194 json_object_new_object();
14195 bgp_show_path_info(
14196 NULL
/* prefix_rd */, dest
, vty
,
14197 bgp
, afi
, safi
, json_net
,
14198 BGP_PATH_SHOW_ALL
, &display
,
14199 RPKI_NOT_BEING_USED
);
14201 json_object_object_addf(
14205 route_vty_out_tmp(vty
, dest
, rn_p
,
14206 &attr
, safi
, use_json
,
14208 bgp_attr_flush(&attr
);
14211 } else if (type
== bgp_show_adj_route_advertised
) {
14212 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14213 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14214 if (paf
->peer
!= peer
|| !adj
->attr
)
14217 show_adj_route_header(
14218 vty
, peer
, table
, header1
,
14219 header2
, json
, json_scode
,
14220 json_ocode
, wide
, detail
);
14222 const struct prefix
*rn_p
=
14223 bgp_dest_get_prefix(dest
);
14226 ret
= bgp_output_modifier(
14227 peer
, rn_p
, &attr
, afi
, safi
,
14230 if (ret
!= RMAP_DENY
) {
14231 if ((safi
== SAFI_MPLS_VPN
)
14232 || (safi
== SAFI_ENCAP
)
14233 || (safi
== SAFI_EVPN
)) {
14235 json_object_string_add(
14242 "Route Distinguisher: %s\n",
14250 json_object_new_object();
14251 bgp_show_path_info(
14260 RPKI_NOT_BEING_USED
);
14262 json_object_object_addf(
14275 (*filtered_count
)++;
14278 bgp_attr_flush(&attr
);
14280 } else if (type
== bgp_show_adj_route_bestpath
) {
14281 struct bgp_path_info
*pi
;
14283 show_adj_route_header(vty
, peer
, table
, header1
,
14284 header2
, json
, json_scode
,
14285 json_ocode
, wide
, detail
);
14287 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14289 if (pi
->peer
!= peer
)
14292 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14295 route_vty_out_tmp(vty
, dest
,
14296 bgp_dest_get_prefix(dest
),
14297 pi
->attr
, safi
, use_json
,
14305 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14306 safi_t safi
, enum bgp_show_adj_route_type type
,
14307 const char *rmap_name
, uint16_t show_flags
)
14310 struct bgp_table
*table
;
14311 json_object
*json
= NULL
;
14312 json_object
*json_scode
= NULL
;
14313 json_object
*json_ocode
= NULL
;
14314 json_object
*json_ar
= NULL
;
14315 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14317 /* Init BGP headers here so they're only displayed once
14318 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14324 * Initialize variables for each RD
14325 * All prefixes under an RD is aggregated within "json_routes"
14327 char rd_str
[BUFSIZ
] = {0};
14328 json_object
*json_routes
= NULL
;
14331 /* For 2-tier tables, prefix counts need to be
14332 * maintained across multiple runs of show_adj_route()
14334 unsigned long output_count_per_rd
;
14335 unsigned long filtered_count_per_rd
;
14336 unsigned long output_count
= 0;
14337 unsigned long filtered_count
= 0;
14340 json
= json_object_new_object();
14341 json_ar
= json_object_new_object();
14342 json_scode
= json_object_new_object();
14343 json_ocode
= json_object_new_object();
14344 #if CONFDATE > 20231208
14345 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14347 json_object_string_add(json_scode
, "suppressed", "s");
14348 json_object_string_add(json_scode
, "damped", "d");
14349 json_object_string_add(json_scode
, "history", "h");
14350 json_object_string_add(json_scode
, "valid", "*");
14351 json_object_string_add(json_scode
, "best", ">");
14352 json_object_string_add(json_scode
, "multipath", "=");
14353 json_object_string_add(json_scode
, "internal", "i");
14354 json_object_string_add(json_scode
, "ribFailure", "r");
14355 json_object_string_add(json_scode
, "stale", "S");
14356 json_object_string_add(json_scode
, "removed", "R");
14358 #if CONFDATE > 20231208
14359 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14361 json_object_string_add(json_ocode
, "igp", "i");
14362 json_object_string_add(json_ocode
, "egp", "e");
14363 json_object_string_add(json_ocode
, "incomplete", "?");
14366 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14368 json_object_string_add(
14370 "No such neighbor or address family");
14371 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14372 json_object_free(json
);
14373 json_object_free(json_ar
);
14374 json_object_free(json_scode
);
14375 json_object_free(json_ocode
);
14377 vty_out(vty
, "%% No such neighbor or address family\n");
14379 return CMD_WARNING
;
14382 if ((type
== bgp_show_adj_route_received
14383 || type
== bgp_show_adj_route_filtered
)
14384 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14385 PEER_FLAG_SOFT_RECONFIG
)) {
14387 json_object_string_add(
14389 "Inbound soft reconfiguration not enabled");
14390 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14391 json_object_free(json
);
14392 json_object_free(json_ar
);
14393 json_object_free(json_scode
);
14394 json_object_free(json_ocode
);
14397 "%% Inbound soft reconfiguration not enabled\n");
14399 return CMD_WARNING
;
14404 /* labeled-unicast routes live in the unicast table */
14405 if (safi
== SAFI_LABELED_UNICAST
)
14406 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14408 table
= bgp
->rib
[afi
][safi
];
14410 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14411 || (safi
== SAFI_EVPN
)) {
14413 struct bgp_dest
*dest
;
14415 for (dest
= bgp_table_top(table
); dest
;
14416 dest
= bgp_route_next(dest
)) {
14417 table
= bgp_dest_get_bgp_table_info(dest
);
14421 output_count_per_rd
= 0;
14422 filtered_count_per_rd
= 0;
14425 json_routes
= json_object_new_object();
14427 const struct prefix_rd
*prd
;
14428 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14431 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
14433 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
14434 rmap_name
, json
, json_routes
, json_scode
,
14435 json_ocode
, show_flags
, &header1
,
14436 &header2
, rd_str
, &output_count_per_rd
,
14437 &filtered_count_per_rd
);
14439 /* Don't include an empty RD in the output! */
14440 if (json_routes
&& (output_count_per_rd
> 0))
14441 json_object_object_add(json_ar
, rd_str
,
14444 output_count
+= output_count_per_rd
;
14445 filtered_count
+= filtered_count_per_rd
;
14448 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14449 json
, json_ar
, json_scode
, json_ocode
,
14450 show_flags
, &header1
, &header2
, rd_str
,
14451 &output_count
, &filtered_count
);
14454 if (type
== bgp_show_adj_route_advertised
)
14455 json_object_object_add(json
, "advertisedRoutes",
14458 json_object_object_add(json
, "receivedRoutes", json_ar
);
14459 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14460 json_object_int_add(json
, "filteredPrefixCounter",
14464 * These fields only give up ownership to `json` when `header1`
14465 * is used (set to zero). See code in `show_adj_route` and
14466 * `show_adj_route_header`.
14468 if (header1
== 1) {
14469 json_object_free(json_scode
);
14470 json_object_free(json_ocode
);
14473 vty_json(vty
, json
);
14474 } else if (output_count
> 0) {
14475 if (filtered_count
> 0)
14477 "\nTotal number of prefixes %ld (%ld filtered)\n",
14478 output_count
, filtered_count
);
14480 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14484 return CMD_SUCCESS
;
14487 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14488 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14489 "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]",
14493 BGP_INSTANCE_HELP_STR
14495 BGP_SAFI_WITH_LABEL_HELP_STR
14496 "Detailed information on TCP and BGP neighbor connections\n"
14497 "Neighbor to display information about\n"
14498 "Neighbor to display information about\n"
14499 "Neighbor on BGP configured interface\n"
14500 "Display the routes selected by best path\n"
14502 "Increase table width for longer prefixes\n")
14504 afi_t afi
= AFI_IP6
;
14505 safi_t safi
= SAFI_UNICAST
;
14506 char *rmap_name
= NULL
;
14507 char *peerstr
= NULL
;
14508 struct bgp
*bgp
= NULL
;
14510 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14512 uint16_t show_flags
= 0;
14515 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14518 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14520 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14524 return CMD_WARNING
;
14526 argv_find(argv
, argc
, "neighbors", &idx
);
14527 peerstr
= argv
[++idx
]->arg
;
14529 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14531 return CMD_WARNING
;
14533 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14537 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14538 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14539 "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] [detail$detail] [json$uj | wide$wide]",
14543 BGP_INSTANCE_HELP_STR
14545 BGP_SAFI_WITH_LABEL_HELP_STR
14546 "Display the entries for all address families\n"
14547 "Detailed information on TCP and BGP neighbor connections\n"
14548 "Neighbor to display information about\n"
14549 "Neighbor to display information about\n"
14550 "Neighbor on BGP configured interface\n"
14551 "Display the routes advertised to a BGP neighbor\n"
14552 "Display the received routes from neighbor\n"
14553 "Display the filtered routes received from neighbor\n"
14554 "Route-map to modify the attributes\n"
14555 "Name of the route map\n"
14556 "Display detailed version of routes\n"
14558 "Increase table width for longer prefixes\n")
14560 afi_t afi
= AFI_IP6
;
14561 safi_t safi
= SAFI_UNICAST
;
14562 char *peerstr
= NULL
;
14563 struct bgp
*bgp
= NULL
;
14565 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14568 uint16_t show_flags
= 0;
14569 struct listnode
*node
;
14573 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14577 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14581 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14582 if (argv_find(argv
, argc
, "ipv4", &idx
))
14583 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14585 if (argv_find(argv
, argc
, "ipv6", &idx
))
14586 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14590 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14592 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14595 return CMD_WARNING
;
14597 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14598 argv_find(argv
, argc
, "neighbors", &idx
);
14599 peerstr
= argv
[++idx
]->arg
;
14601 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14603 return CMD_WARNING
;
14605 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14606 type
= bgp_show_adj_route_advertised
;
14607 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14608 type
= bgp_show_adj_route_received
;
14609 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14610 type
= bgp_show_adj_route_filtered
;
14613 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14616 vty_out(vty
, "{\n");
14618 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14619 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14620 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14622 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14623 FOREACH_SAFI (safi
) {
14624 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14631 vty_out(vty
, ",\n");
14632 vty_out(vty
, "\"%s\":",
14633 get_afi_safi_str(afi
, safi
,
14637 "\nFor address family: %s\n",
14638 get_afi_safi_str(afi
, safi
,
14641 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14642 route_map
, show_flags
);
14646 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14647 FOREACH_AFI_SAFI (afi
, safi
) {
14648 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14655 vty_out(vty
, ",\n");
14656 vty_out(vty
, "\"%s\":",
14657 get_afi_safi_str(afi
, safi
,
14661 "\nFor address family: %s\n",
14662 get_afi_safi_str(afi
, safi
,
14665 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14666 route_map
, show_flags
);
14671 vty_out(vty
, "}\n");
14673 return CMD_SUCCESS
;
14676 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14677 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14678 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14682 BGP_INSTANCE_HELP_STR
14685 BGP_AF_MODIFIER_STR
14686 "Detailed information on TCP and BGP neighbor connections\n"
14687 "Neighbor to display information about\n"
14688 "Neighbor to display information about\n"
14689 "Neighbor on BGP configured interface\n"
14690 "Display information received from a BGP neighbor\n"
14691 "Display the prefixlist filter\n"
14694 afi_t afi
= AFI_IP6
;
14695 safi_t safi
= SAFI_UNICAST
;
14696 char *peerstr
= NULL
;
14701 struct bgp
*bgp
= NULL
;
14702 bool uj
= use_json(argc
, argv
);
14707 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14710 return CMD_WARNING
;
14712 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14713 argv_find(argv
, argc
, "neighbors", &idx
);
14714 peerstr
= argv
[++idx
]->arg
;
14716 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14718 return CMD_WARNING
;
14720 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14721 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14724 vty_out(vty
, "Address Family: %s\n",
14725 get_afi_safi_str(afi
, safi
, false));
14726 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14729 vty_out(vty
, "{}\n");
14731 vty_out(vty
, "No functional output\n");
14734 return CMD_SUCCESS
;
14737 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14738 afi_t afi
, safi_t safi
,
14739 enum bgp_show_type type
, bool use_json
)
14741 uint16_t show_flags
= 0;
14744 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14746 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14748 json_object
*json_no
= NULL
;
14749 json_no
= json_object_new_object();
14750 json_object_string_add(
14751 json_no
, "warning",
14752 "No such neighbor or address family");
14753 vty_out(vty
, "%s\n",
14754 json_object_to_json_string(json_no
));
14755 json_object_free(json_no
);
14757 vty_out(vty
, "%% No such neighbor or address family\n");
14758 return CMD_WARNING
;
14761 /* labeled-unicast routes live in the unicast table */
14762 if (safi
== SAFI_LABELED_UNICAST
)
14763 safi
= SAFI_UNICAST
;
14765 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14766 RPKI_NOT_BEING_USED
);
14769 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14770 show_ip_bgp_flowspec_routes_detailed_cmd
,
14771 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14775 BGP_INSTANCE_HELP_STR
14778 "Detailed information on flowspec entries\n"
14781 afi_t afi
= AFI_IP6
;
14782 safi_t safi
= SAFI_UNICAST
;
14783 struct bgp
*bgp
= NULL
;
14785 bool uj
= use_json(argc
, argv
);
14786 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14790 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14793 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14796 return CMD_WARNING
;
14798 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14799 show_flags
, RPKI_NOT_BEING_USED
);
14802 DEFUN (show_ip_bgp_neighbor_routes
,
14803 show_ip_bgp_neighbor_routes_cmd
,
14804 "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]",
14808 BGP_INSTANCE_HELP_STR
14810 BGP_SAFI_WITH_LABEL_HELP_STR
14811 "Detailed information on TCP and BGP neighbor connections\n"
14812 "Neighbor to display information about\n"
14813 "Neighbor to display information about\n"
14814 "Neighbor on BGP configured interface\n"
14815 "Display flap statistics of the routes learned from neighbor\n"
14816 "Display the dampened routes received from neighbor\n"
14817 "Display routes learned from neighbor\n"
14820 char *peerstr
= NULL
;
14821 struct bgp
*bgp
= NULL
;
14822 afi_t afi
= AFI_IP6
;
14823 safi_t safi
= SAFI_UNICAST
;
14825 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14827 bool uj
= use_json(argc
, argv
);
14832 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14835 return CMD_WARNING
;
14837 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14838 argv_find(argv
, argc
, "neighbors", &idx
);
14839 peerstr
= argv
[++idx
]->arg
;
14841 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14843 return CMD_WARNING
;
14845 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14846 sh_type
= bgp_show_type_flap_neighbor
;
14847 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14848 sh_type
= bgp_show_type_damp_neighbor
;
14849 else if (argv_find(argv
, argc
, "routes", &idx
))
14850 sh_type
= bgp_show_type_neighbor
;
14852 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14855 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14857 struct bgp_distance
{
14858 /* Distance value for the IP source prefix. */
14861 /* Name of the access-list to be matched. */
14865 DEFUN (show_bgp_afi_vpn_rd_route
,
14866 show_bgp_afi_vpn_rd_route_cmd
,
14867 "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]",
14871 BGP_AF_MODIFIER_STR
14872 "Display information for a route distinguisher\n"
14873 "Route Distinguisher\n"
14874 "All Route Distinguishers\n"
14875 "Network in the BGP routing table to display\n"
14876 "Network in the BGP routing table to display\n"
14880 struct prefix_rd prd
;
14881 afi_t afi
= AFI_MAX
;
14884 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14885 vty_out(vty
, "%% Malformed Address Family\n");
14886 return CMD_WARNING
;
14889 if (!strcmp(argv
[5]->arg
, "all"))
14890 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14891 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14892 RPKI_NOT_BEING_USED
,
14893 use_json(argc
, argv
));
14895 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14897 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14898 return CMD_WARNING
;
14901 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14902 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14903 use_json(argc
, argv
));
14906 static struct bgp_distance
*bgp_distance_new(void)
14908 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14911 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14913 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14916 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14917 const char *ip_str
, const char *access_list_str
)
14924 struct bgp_dest
*dest
;
14925 struct bgp_distance
*bdistance
;
14927 afi
= bgp_node_afi(vty
);
14928 safi
= bgp_node_safi(vty
);
14930 ret
= str2prefix(ip_str
, &p
);
14932 vty_out(vty
, "Malformed prefix\n");
14933 return CMD_WARNING_CONFIG_FAILED
;
14936 distance
= atoi(distance_str
);
14938 /* Get BGP distance node. */
14939 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14940 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14942 bgp_dest_unlock_node(dest
);
14944 bdistance
= bgp_distance_new();
14945 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14948 /* Set distance value. */
14949 bdistance
->distance
= distance
;
14951 /* Reset access-list configuration. */
14952 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14953 if (access_list_str
)
14954 bdistance
->access_list
=
14955 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14957 return CMD_SUCCESS
;
14960 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14961 const char *ip_str
, const char *access_list_str
)
14968 struct bgp_dest
*dest
;
14969 struct bgp_distance
*bdistance
;
14971 afi
= bgp_node_afi(vty
);
14972 safi
= bgp_node_safi(vty
);
14974 ret
= str2prefix(ip_str
, &p
);
14976 vty_out(vty
, "Malformed prefix\n");
14977 return CMD_WARNING_CONFIG_FAILED
;
14980 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14982 vty_out(vty
, "Can't find specified prefix\n");
14983 return CMD_WARNING_CONFIG_FAILED
;
14986 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14987 distance
= atoi(distance_str
);
14989 if (bdistance
->distance
!= distance
) {
14990 vty_out(vty
, "Distance does not match configured\n");
14991 bgp_dest_unlock_node(dest
);
14992 return CMD_WARNING_CONFIG_FAILED
;
14995 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14996 bgp_distance_free(bdistance
);
14998 bgp_dest_set_bgp_path_info(dest
, NULL
);
14999 bgp_dest_unlock_node(dest
);
15000 bgp_dest_unlock_node(dest
);
15002 return CMD_SUCCESS
;
15005 /* Apply BGP information to distance method. */
15006 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
15007 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
15009 struct bgp_dest
*dest
;
15010 struct prefix q
= {0};
15012 struct bgp_distance
*bdistance
;
15013 struct access_list
*alist
;
15014 struct bgp_static
*bgp_static
;
15019 peer
= pinfo
->peer
;
15021 if (pinfo
->attr
->distance
)
15022 return pinfo
->attr
->distance
;
15024 /* Check source address.
15025 * Note: for aggregate route, peer can have unspec af type.
15027 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
15028 && !sockunion2hostprefix(&peer
->su
, &q
))
15031 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
15033 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15034 bgp_dest_unlock_node(dest
);
15036 if (bdistance
->access_list
) {
15037 alist
= access_list_lookup(afi
, bdistance
->access_list
);
15039 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
15040 return bdistance
->distance
;
15042 return bdistance
->distance
;
15045 /* Backdoor check. */
15046 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
15048 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15049 bgp_dest_unlock_node(dest
);
15051 if (bgp_static
->backdoor
) {
15052 if (bgp
->distance_local
[afi
][safi
])
15053 return bgp
->distance_local
[afi
][safi
];
15055 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15059 if (peer
->sort
== BGP_PEER_EBGP
) {
15060 if (bgp
->distance_ebgp
[afi
][safi
])
15061 return bgp
->distance_ebgp
[afi
][safi
];
15062 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15063 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15064 if (bgp
->distance_ibgp
[afi
][safi
])
15065 return bgp
->distance_ibgp
[afi
][safi
];
15066 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15068 if (bgp
->distance_local
[afi
][safi
])
15069 return bgp
->distance_local
[afi
][safi
];
15070 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15074 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15075 * we should tell ZEBRA update the routes for a specific
15076 * AFI/SAFI to reflect changes in RIB.
15078 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15080 safi_t update_safi
)
15085 FOREACH_AFI_SAFI (afi
, safi
) {
15086 if (!bgp_fibupd_safi(safi
))
15089 if (afi
!= update_afi
&& safi
!= update_safi
)
15092 if (BGP_DEBUG(zebra
, ZEBRA
))
15094 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15095 __func__
, afi
, safi
);
15096 bgp_zebra_announce_table(bgp
, afi
, safi
);
15100 DEFUN (bgp_distance
,
15102 "distance bgp (1-255) (1-255) (1-255)",
15103 "Define an administrative distance\n"
15105 "Distance for routes external to the AS\n"
15106 "Distance for routes internal to the AS\n"
15107 "Distance for local routes\n")
15109 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15110 int idx_number
= 2;
15111 int idx_number_2
= 3;
15112 int idx_number_3
= 4;
15113 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15114 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15115 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15119 afi
= bgp_node_afi(vty
);
15120 safi
= bgp_node_safi(vty
);
15122 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15123 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15124 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15125 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15126 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15127 bgp
->distance_local
[afi
][safi
] = distance_local
;
15128 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15130 return CMD_SUCCESS
;
15133 DEFUN (no_bgp_distance
,
15134 no_bgp_distance_cmd
,
15135 "no distance bgp [(1-255) (1-255) (1-255)]",
15137 "Define an administrative distance\n"
15139 "Distance for routes external to the AS\n"
15140 "Distance for routes internal to the AS\n"
15141 "Distance for local routes\n")
15143 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15147 afi
= bgp_node_afi(vty
);
15148 safi
= bgp_node_safi(vty
);
15150 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15151 || bgp
->distance_ibgp
[afi
][safi
] != 0
15152 || bgp
->distance_local
[afi
][safi
] != 0) {
15153 bgp
->distance_ebgp
[afi
][safi
] = 0;
15154 bgp
->distance_ibgp
[afi
][safi
] = 0;
15155 bgp
->distance_local
[afi
][safi
] = 0;
15156 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15158 return CMD_SUCCESS
;
15162 DEFUN (bgp_distance_source
,
15163 bgp_distance_source_cmd
,
15164 "distance (1-255) A.B.C.D/M",
15165 "Define an administrative distance\n"
15166 "Administrative distance\n"
15167 "IP source prefix\n")
15169 int idx_number
= 1;
15170 int idx_ipv4_prefixlen
= 2;
15171 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15172 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15173 return CMD_SUCCESS
;
15176 DEFUN (no_bgp_distance_source
,
15177 no_bgp_distance_source_cmd
,
15178 "no distance (1-255) A.B.C.D/M",
15180 "Define an administrative distance\n"
15181 "Administrative distance\n"
15182 "IP source prefix\n")
15184 int idx_number
= 2;
15185 int idx_ipv4_prefixlen
= 3;
15186 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15187 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15188 return CMD_SUCCESS
;
15191 DEFUN (bgp_distance_source_access_list
,
15192 bgp_distance_source_access_list_cmd
,
15193 "distance (1-255) A.B.C.D/M WORD",
15194 "Define an administrative distance\n"
15195 "Administrative distance\n"
15196 "IP source prefix\n"
15197 "Access list name\n")
15199 int idx_number
= 1;
15200 int idx_ipv4_prefixlen
= 2;
15202 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15203 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15204 return CMD_SUCCESS
;
15207 DEFUN (no_bgp_distance_source_access_list
,
15208 no_bgp_distance_source_access_list_cmd
,
15209 "no distance (1-255) A.B.C.D/M WORD",
15211 "Define an administrative distance\n"
15212 "Administrative distance\n"
15213 "IP source prefix\n"
15214 "Access list name\n")
15216 int idx_number
= 2;
15217 int idx_ipv4_prefixlen
= 3;
15219 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15220 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15221 return CMD_SUCCESS
;
15224 DEFUN (ipv6_bgp_distance_source
,
15225 ipv6_bgp_distance_source_cmd
,
15226 "distance (1-255) X:X::X:X/M",
15227 "Define an administrative distance\n"
15228 "Administrative distance\n"
15229 "IP source prefix\n")
15231 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15232 return CMD_SUCCESS
;
15235 DEFUN (no_ipv6_bgp_distance_source
,
15236 no_ipv6_bgp_distance_source_cmd
,
15237 "no distance (1-255) X:X::X:X/M",
15239 "Define an administrative distance\n"
15240 "Administrative distance\n"
15241 "IP source prefix\n")
15243 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15244 return CMD_SUCCESS
;
15247 DEFUN (ipv6_bgp_distance_source_access_list
,
15248 ipv6_bgp_distance_source_access_list_cmd
,
15249 "distance (1-255) X:X::X:X/M WORD",
15250 "Define an administrative distance\n"
15251 "Administrative distance\n"
15252 "IP source prefix\n"
15253 "Access list name\n")
15255 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15256 return CMD_SUCCESS
;
15259 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15260 no_ipv6_bgp_distance_source_access_list_cmd
,
15261 "no distance (1-255) X:X::X:X/M WORD",
15263 "Define an administrative distance\n"
15264 "Administrative distance\n"
15265 "IP source prefix\n"
15266 "Access list name\n")
15268 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15269 return CMD_SUCCESS
;
15272 DEFUN (bgp_damp_set
,
15274 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15275 "BGP Specific commands\n"
15276 "Enable route-flap dampening\n"
15277 "Half-life time for the penalty\n"
15278 "Value to start reusing a route\n"
15279 "Value to start suppressing a route\n"
15280 "Maximum duration to suppress a stable route\n")
15282 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15283 int idx_half_life
= 2;
15285 int idx_suppress
= 4;
15286 int idx_max_suppress
= 5;
15287 int half
= DEFAULT_HALF_LIFE
* 60;
15288 int reuse
= DEFAULT_REUSE
;
15289 int suppress
= DEFAULT_SUPPRESS
;
15290 int max
= 4 * half
;
15293 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15294 reuse
= atoi(argv
[idx_reuse
]->arg
);
15295 suppress
= atoi(argv
[idx_suppress
]->arg
);
15296 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15297 } else if (argc
== 3) {
15298 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15303 * These can't be 0 but our SA doesn't understand the
15304 * way our cli is constructed
15308 if (suppress
< reuse
) {
15310 "Suppress value cannot be less than reuse value \n");
15314 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15315 reuse
, suppress
, max
);
15318 DEFUN (bgp_damp_unset
,
15319 bgp_damp_unset_cmd
,
15320 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15322 "BGP Specific commands\n"
15323 "Enable route-flap dampening\n"
15324 "Half-life time for the penalty\n"
15325 "Value to start reusing a route\n"
15326 "Value to start suppressing a route\n"
15327 "Maximum duration to suppress a stable route\n")
15329 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15330 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15333 /* Display specified route of BGP table. */
15334 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15335 const char *ip_str
, afi_t afi
, safi_t safi
,
15336 struct prefix_rd
*prd
, int prefix_check
)
15339 struct prefix match
;
15340 struct bgp_dest
*dest
;
15341 struct bgp_dest
*rm
;
15342 struct bgp_path_info
*pi
;
15343 struct bgp_path_info
*pi_temp
;
15345 struct bgp_table
*table
;
15347 /* BGP structure lookup. */
15349 bgp
= bgp_lookup_by_name(view_name
);
15351 vty_out(vty
, "%% Can't find BGP instance %s\n",
15353 return CMD_WARNING
;
15356 bgp
= bgp_get_default();
15358 vty_out(vty
, "%% No BGP process is configured\n");
15359 return CMD_WARNING
;
15363 /* Check IP address argument. */
15364 ret
= str2prefix(ip_str
, &match
);
15366 vty_out(vty
, "%% address is malformed\n");
15367 return CMD_WARNING
;
15370 match
.family
= afi2family(afi
);
15372 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15373 || (safi
== SAFI_EVPN
)) {
15374 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15375 dest
= bgp_route_next(dest
)) {
15376 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15378 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15380 table
= bgp_dest_get_bgp_table_info(dest
);
15383 rm
= bgp_node_match(table
, &match
);
15387 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15390 || rm_p
->prefixlen
== match
.prefixlen
) {
15391 pi
= bgp_dest_get_bgp_path_info(rm
);
15393 if (pi
->extra
&& pi
->extra
->damp_info
) {
15394 pi_temp
= pi
->next
;
15395 bgp_damp_info_free(
15396 pi
->extra
->damp_info
,
15404 bgp_dest_unlock_node(rm
);
15407 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15408 if (dest
!= NULL
) {
15409 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15412 || dest_p
->prefixlen
== match
.prefixlen
) {
15413 pi
= bgp_dest_get_bgp_path_info(dest
);
15415 if (pi
->extra
&& pi
->extra
->damp_info
) {
15416 pi_temp
= pi
->next
;
15417 bgp_damp_info_free(
15418 pi
->extra
->damp_info
,
15426 bgp_dest_unlock_node(dest
);
15430 return CMD_SUCCESS
;
15433 DEFUN (clear_ip_bgp_dampening
,
15434 clear_ip_bgp_dampening_cmd
,
15435 "clear ip bgp dampening",
15439 "Clear route flap dampening information\n")
15441 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15442 return CMD_SUCCESS
;
15445 DEFUN (clear_ip_bgp_dampening_prefix
,
15446 clear_ip_bgp_dampening_prefix_cmd
,
15447 "clear ip bgp dampening A.B.C.D/M",
15451 "Clear route flap dampening information\n"
15454 int idx_ipv4_prefixlen
= 4;
15455 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15456 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15459 DEFUN (clear_ip_bgp_dampening_address
,
15460 clear_ip_bgp_dampening_address_cmd
,
15461 "clear ip bgp dampening A.B.C.D",
15465 "Clear route flap dampening information\n"
15466 "Network to clear damping information\n")
15469 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15470 SAFI_UNICAST
, NULL
, 0);
15473 DEFUN (clear_ip_bgp_dampening_address_mask
,
15474 clear_ip_bgp_dampening_address_mask_cmd
,
15475 "clear ip bgp dampening A.B.C.D A.B.C.D",
15479 "Clear route flap dampening information\n"
15480 "Network to clear damping information\n"
15484 int idx_ipv4_2
= 5;
15486 char prefix_str
[BUFSIZ
];
15488 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15489 prefix_str
, sizeof(prefix_str
));
15491 vty_out(vty
, "%% Inconsistent address and mask\n");
15492 return CMD_WARNING
;
15495 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15499 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15501 struct vty
*vty
= arg
;
15502 struct peer
*peer
= bucket
->data
;
15504 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15507 DEFUN (show_bgp_listeners
,
15508 show_bgp_listeners_cmd
,
15509 "show bgp listeners",
15512 "Display Listen Sockets and who created them\n")
15514 bgp_dump_listener_info(vty
);
15516 return CMD_SUCCESS
;
15519 DEFUN (show_bgp_peerhash
,
15520 show_bgp_peerhash_cmd
,
15521 "show bgp peerhash",
15524 "Display information about the BGP peerhash\n")
15526 struct list
*instances
= bm
->bgp
;
15527 struct listnode
*node
;
15530 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15531 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15532 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15536 return CMD_SUCCESS
;
15539 /* also used for encap safi */
15540 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15541 afi_t afi
, safi_t safi
)
15543 struct bgp_dest
*pdest
;
15544 struct bgp_dest
*dest
;
15545 struct bgp_table
*table
;
15546 const struct prefix
*p
;
15547 const struct prefix_rd
*prd
;
15548 struct bgp_static
*bgp_static
;
15549 mpls_label_t label
;
15551 /* Network configuration. */
15552 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15553 pdest
= bgp_route_next(pdest
)) {
15554 table
= bgp_dest_get_bgp_table_info(pdest
);
15558 for (dest
= bgp_table_top(table
); dest
;
15559 dest
= bgp_route_next(dest
)) {
15560 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15561 if (bgp_static
== NULL
)
15564 p
= bgp_dest_get_prefix(dest
);
15565 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
15568 /* "network" configuration display. */
15569 label
= decode_label(&bgp_static
->label
);
15571 vty_out(vty
, " network %pFX rd %pRD", p
, prd
);
15572 if (safi
== SAFI_MPLS_VPN
)
15573 vty_out(vty
, " label %u", label
);
15575 if (bgp_static
->rmap
.name
)
15576 vty_out(vty
, " route-map %s",
15577 bgp_static
->rmap
.name
);
15579 if (bgp_static
->backdoor
)
15580 vty_out(vty
, " backdoor");
15582 vty_out(vty
, "\n");
15587 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15588 afi_t afi
, safi_t safi
)
15590 struct bgp_dest
*pdest
;
15591 struct bgp_dest
*dest
;
15592 struct bgp_table
*table
;
15593 const struct prefix
*p
;
15594 const struct prefix_rd
*prd
;
15595 struct bgp_static
*bgp_static
;
15596 char buf
[PREFIX_STRLEN
* 2];
15597 char buf2
[SU_ADDRSTRLEN
];
15598 char esi_buf
[ESI_STR_LEN
];
15600 /* Network configuration. */
15601 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15602 pdest
= bgp_route_next(pdest
)) {
15603 table
= bgp_dest_get_bgp_table_info(pdest
);
15607 for (dest
= bgp_table_top(table
); dest
;
15608 dest
= bgp_route_next(dest
)) {
15609 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15610 if (bgp_static
== NULL
)
15613 char *macrouter
= NULL
;
15615 if (bgp_static
->router_mac
)
15616 macrouter
= prefix_mac2str(
15617 bgp_static
->router_mac
, NULL
, 0);
15618 if (bgp_static
->eth_s_id
)
15619 esi_to_str(bgp_static
->eth_s_id
,
15620 esi_buf
, sizeof(esi_buf
));
15621 p
= bgp_dest_get_prefix(dest
);
15622 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15624 /* "network" configuration display. */
15625 if (p
->u
.prefix_evpn
.route_type
== 5) {
15626 char local_buf
[PREFIX_STRLEN
];
15628 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15629 struct prefix_evpn
*)p
)
15633 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15635 local_buf
, sizeof(local_buf
));
15636 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15637 p
->u
.prefix_evpn
.prefix_addr
15638 .ip_prefix_length
);
15640 prefix2str(p
, buf
, sizeof(buf
));
15643 if (bgp_static
->gatewayIp
.family
== AF_INET
15644 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15645 inet_ntop(bgp_static
->gatewayIp
.family
,
15646 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15649 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15650 buf
, prd
, p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15651 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15654 XFREE(MTYPE_TMP
, macrouter
);
15659 /* Configuration of static route announcement and aggregate
15661 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15664 struct bgp_dest
*dest
;
15665 const struct prefix
*p
;
15666 struct bgp_static
*bgp_static
;
15667 struct bgp_aggregate
*bgp_aggregate
;
15669 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15670 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15674 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15675 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15679 /* Network configuration. */
15680 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15681 dest
= bgp_route_next(dest
)) {
15682 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15683 if (bgp_static
== NULL
)
15686 p
= bgp_dest_get_prefix(dest
);
15688 vty_out(vty
, " network %pFX", p
);
15690 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15691 vty_out(vty
, " label-index %u",
15692 bgp_static
->label_index
);
15694 if (bgp_static
->rmap
.name
)
15695 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15697 if (bgp_static
->backdoor
)
15698 vty_out(vty
, " backdoor");
15700 vty_out(vty
, "\n");
15703 /* Aggregate-address configuration. */
15704 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15705 dest
= bgp_route_next(dest
)) {
15706 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15707 if (bgp_aggregate
== NULL
)
15710 p
= bgp_dest_get_prefix(dest
);
15712 vty_out(vty
, " aggregate-address %pFX", p
);
15714 if (bgp_aggregate
->as_set
)
15715 vty_out(vty
, " as-set");
15717 if (bgp_aggregate
->summary_only
)
15718 vty_out(vty
, " summary-only");
15720 if (bgp_aggregate
->rmap
.name
)
15721 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15723 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15724 vty_out(vty
, " origin %s",
15725 bgp_origin2str(bgp_aggregate
->origin
));
15727 if (bgp_aggregate
->match_med
)
15728 vty_out(vty
, " matching-MED-only");
15730 if (bgp_aggregate
->suppress_map_name
)
15731 vty_out(vty
, " suppress-map %s",
15732 bgp_aggregate
->suppress_map_name
);
15734 vty_out(vty
, "\n");
15738 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15741 struct bgp_dest
*dest
;
15742 struct bgp_distance
*bdistance
;
15744 /* Distance configuration. */
15745 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15746 && bgp
->distance_local
[afi
][safi
]
15747 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15748 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15749 || bgp
->distance_local
[afi
][safi
]
15750 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15751 vty_out(vty
, " distance bgp %d %d %d\n",
15752 bgp
->distance_ebgp
[afi
][safi
],
15753 bgp
->distance_ibgp
[afi
][safi
],
15754 bgp
->distance_local
[afi
][safi
]);
15757 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15758 dest
= bgp_route_next(dest
)) {
15759 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15760 if (bdistance
!= NULL
)
15761 vty_out(vty
, " distance %d %pBD %s\n",
15762 bdistance
->distance
, dest
,
15763 bdistance
->access_list
? bdistance
->access_list
15768 /* Allocate routing table structure and install commands. */
15769 void bgp_route_init(void)
15774 /* Init BGP distance table. */
15775 FOREACH_AFI_SAFI (afi
, safi
)
15776 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15778 /* IPv4 BGP commands. */
15779 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15780 install_element(BGP_NODE
, &bgp_network_cmd
);
15781 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15783 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15785 /* IPv4 unicast configuration. */
15786 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15787 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15788 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15790 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15792 /* IPv4 multicast configuration. */
15793 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15794 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15795 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15796 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15798 /* IPv4 labeled-unicast configuration. */
15799 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15800 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15802 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15803 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15804 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15805 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15806 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15807 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15808 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15809 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15811 install_element(VIEW_NODE
,
15812 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15813 install_element(VIEW_NODE
,
15814 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15815 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15816 install_element(VIEW_NODE
,
15817 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15818 #ifdef KEEP_OLD_VPN_COMMANDS
15819 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15820 #endif /* KEEP_OLD_VPN_COMMANDS */
15821 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15822 install_element(VIEW_NODE
,
15823 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15825 /* BGP dampening clear commands */
15826 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15827 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15829 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15830 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15833 install_element(ENABLE_NODE
,
15834 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15835 #ifdef KEEP_OLD_VPN_COMMANDS
15836 install_element(ENABLE_NODE
,
15837 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15838 #endif /* KEEP_OLD_VPN_COMMANDS */
15840 /* New config IPv6 BGP commands. */
15841 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15842 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15843 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15845 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15847 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15849 /* IPv6 labeled unicast address family. */
15850 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15851 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15853 install_element(BGP_NODE
, &bgp_distance_cmd
);
15854 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15855 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15856 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15857 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15858 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15859 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15860 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15861 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15862 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15863 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15864 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15865 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15866 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15867 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15868 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15869 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15870 install_element(BGP_IPV4M_NODE
,
15871 &no_bgp_distance_source_access_list_cmd
);
15872 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15873 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15874 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15875 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15876 install_element(BGP_IPV6_NODE
,
15877 &ipv6_bgp_distance_source_access_list_cmd
);
15878 install_element(BGP_IPV6_NODE
,
15879 &no_ipv6_bgp_distance_source_access_list_cmd
);
15880 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15881 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15882 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15883 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15884 install_element(BGP_IPV6M_NODE
,
15885 &ipv6_bgp_distance_source_access_list_cmd
);
15886 install_element(BGP_IPV6M_NODE
,
15887 &no_ipv6_bgp_distance_source_access_list_cmd
);
15889 /* BGP dampening */
15890 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15891 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15892 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15893 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15894 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15895 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15896 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15897 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15898 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15899 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15900 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15901 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15902 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15903 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15905 /* Large Communities */
15906 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15907 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15909 /* show bgp ipv4 flowspec detailed */
15910 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15912 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15913 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15916 void bgp_route_finish(void)
15921 FOREACH_AFI_SAFI (afi
, safi
) {
15922 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15923 bgp_distance_table
[afi
][safi
] = NULL
;