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(2, 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;
4412 /* Received Logging. */
4413 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4414 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4415 num_labels
, addpath_id
? 1 : 0,
4416 addpath_id
, evpn
, pfx_buf
,
4418 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4421 /* graceful restart STALE flag unset. */
4422 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4423 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4424 bgp_dest_set_defer_flag(dest
, false);
4427 /* The attribute is changed. */
4428 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4430 /* implicit withdraw, decrement aggregate and pcount here.
4431 * only if update is accepted, they'll increment below.
4433 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4435 /* Update bgp route dampening information. */
4436 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4437 && peer
->sort
== BGP_PEER_EBGP
) {
4438 /* This is implicit withdraw so we should update
4441 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4442 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4444 #ifdef ENABLE_BGP_VNC
4445 if (safi
== SAFI_MPLS_VPN
) {
4446 struct bgp_dest
*pdest
= NULL
;
4447 struct bgp_table
*table
= NULL
;
4449 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4450 (struct prefix
*)prd
);
4451 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4452 table
= bgp_dest_get_bgp_table_info(pdest
);
4454 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4455 bgp
, prd
, table
, p
, pi
);
4457 bgp_dest_unlock_node(pdest
);
4459 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4460 && (safi
== SAFI_UNICAST
)) {
4461 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4463 * Implicit withdraw case.
4465 ++vnc_implicit_withdraw
;
4466 vnc_import_bgp_del_route(bgp
, p
, pi
);
4467 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4472 /* Special handling for EVPN update of an existing route. If the
4473 * extended community attribute has changed, we need to
4475 * the route using its existing extended community. It will be
4476 * subsequently processed for import with the new extended
4479 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4482 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4484 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4487 cmp
= ecommunity_cmp(
4488 bgp_attr_get_ecommunity(pi
->attr
),
4489 bgp_attr_get_ecommunity(attr_new
));
4491 if (bgp_debug_update(peer
, p
, NULL
, 1))
4493 "Change in EXT-COMM, existing %s new %s",
4495 bgp_attr_get_ecommunity(
4498 bgp_attr_get_ecommunity(
4500 if (safi
== SAFI_EVPN
)
4501 bgp_evpn_unimport_route(
4502 bgp
, afi
, safi
, p
, pi
);
4503 else /* SAFI_MPLS_VPN */
4504 vpn_leak_to_vrf_withdraw(bgp
,
4510 /* Update to new attribute. */
4511 bgp_attr_unintern(&pi
->attr
);
4512 pi
->attr
= attr_new
;
4514 /* Update MPLS label */
4515 if (has_valid_label
) {
4516 extra
= bgp_path_info_extra_get(pi
);
4517 if (extra
->label
!= label
) {
4518 memcpy(&extra
->label
, label
,
4519 num_labels
* sizeof(mpls_label_t
));
4520 extra
->num_labels
= num_labels
;
4522 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4523 bgp_set_valid_label(&extra
->label
[0]);
4526 /* Update SRv6 SID */
4527 if (attr
->srv6_l3vpn
) {
4528 extra
= bgp_path_info_extra_get(pi
);
4529 if (sid_diff(&extra
->sid
[0].sid
,
4530 &attr
->srv6_l3vpn
->sid
)) {
4531 sid_copy(&extra
->sid
[0].sid
,
4532 &attr
->srv6_l3vpn
->sid
);
4533 extra
->num_sids
= 1;
4535 extra
->sid
[0].loc_block_len
= 0;
4536 extra
->sid
[0].loc_node_len
= 0;
4537 extra
->sid
[0].func_len
= 0;
4538 extra
->sid
[0].arg_len
= 0;
4539 extra
->sid
[0].transposition_len
= 0;
4540 extra
->sid
[0].transposition_offset
= 0;
4542 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4543 extra
->sid
[0].loc_block_len
=
4544 attr
->srv6_l3vpn
->loc_block_len
;
4545 extra
->sid
[0].loc_node_len
=
4546 attr
->srv6_l3vpn
->loc_node_len
;
4547 extra
->sid
[0].func_len
=
4548 attr
->srv6_l3vpn
->func_len
;
4549 extra
->sid
[0].arg_len
=
4550 attr
->srv6_l3vpn
->arg_len
;
4551 extra
->sid
[0].transposition_len
=
4553 ->transposition_len
;
4554 extra
->sid
[0].transposition_offset
=
4556 ->transposition_offset
;
4559 } else if (attr
->srv6_vpn
) {
4560 extra
= bgp_path_info_extra_get(pi
);
4561 if (sid_diff(&extra
->sid
[0].sid
,
4562 &attr
->srv6_vpn
->sid
)) {
4563 sid_copy(&extra
->sid
[0].sid
,
4564 &attr
->srv6_vpn
->sid
);
4565 extra
->num_sids
= 1;
4569 #ifdef ENABLE_BGP_VNC
4570 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4571 && (safi
== SAFI_UNICAST
)) {
4572 if (vnc_implicit_withdraw
) {
4574 * Add back the route with its new attributes
4576 * The route is still selected, until the route
4578 * queued by bgp_process actually runs. We have
4580 * update to the VNC side immediately to avoid
4582 * configuration changes (e.g., route-map
4584 * trigger re-importation of the entire RIB.
4586 vnc_import_bgp_add_route(bgp
, p
, pi
);
4587 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4592 /* Update bgp route dampening information. */
4593 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4594 && peer
->sort
== BGP_PEER_EBGP
) {
4595 /* Now we do normal update dampening. */
4596 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4597 if (ret
== BGP_DAMP_SUPPRESSED
) {
4598 bgp_dest_unlock_node(dest
);
4603 /* Nexthop reachability check - for unicast and
4604 * labeled-unicast.. */
4605 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4606 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4607 || (safi
== SAFI_EVPN
&&
4608 bgp_evpn_is_prefix_nht_supported(p
))) {
4609 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4610 && peer
->ttl
== BGP_DEFAULT_TTL
4611 && !CHECK_FLAG(peer
->flags
,
4612 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4613 && !CHECK_FLAG(bgp
->flags
,
4614 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4619 struct bgp
*bgp_nexthop
= bgp
;
4621 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4622 bgp_nexthop
= pi
->extra
->bgp_orig
;
4624 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4626 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4627 safi
, pi
, NULL
, connected
,
4628 bgp_nht_param_prefix
) ||
4629 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4630 bgp_path_info_set_flag(dest
, pi
,
4633 if (BGP_DEBUG(nht
, NHT
)) {
4634 zlog_debug("%s(%pI4): NH unresolved",
4636 (in_addr_t
*)&attr_new
->nexthop
);
4638 bgp_path_info_unset_flag(dest
, pi
,
4643 bgp_path_info_set_flag(dest
, pi
,
4644 BGP_PATH_ACCEPT_OWN
);
4646 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4649 #ifdef ENABLE_BGP_VNC
4650 if (safi
== SAFI_MPLS_VPN
) {
4651 struct bgp_dest
*pdest
= NULL
;
4652 struct bgp_table
*table
= NULL
;
4654 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4655 (struct prefix
*)prd
);
4656 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4657 table
= bgp_dest_get_bgp_table_info(pdest
);
4659 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4660 bgp
, prd
, table
, p
, pi
);
4662 bgp_dest_unlock_node(pdest
);
4666 /* If this is an EVPN route and some attribute has changed,
4667 * or we are explicitly told to perform a route import, process
4668 * route for import. If the extended community has changed, we
4670 * have done the un-import earlier and the import would result
4672 * route getting injected into appropriate L2 VNIs. If it is
4674 * some other attribute change, the import will result in
4676 * the attributes for the route in the VNI(s).
4678 if (safi
== SAFI_EVPN
&&
4679 (!same_attr
|| force_evpn_import
) &&
4680 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4681 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4683 /* Process change. */
4684 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4686 bgp_process(bgp
, dest
, afi
, safi
);
4687 bgp_dest_unlock_node(dest
);
4689 if (SAFI_UNICAST
== safi
4690 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4691 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4693 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4695 if ((SAFI_MPLS_VPN
== safi
)
4696 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4697 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4700 #ifdef ENABLE_BGP_VNC
4701 if (SAFI_MPLS_VPN
== safi
) {
4702 mpls_label_t label_decoded
= decode_label(label
);
4704 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4705 type
, sub_type
, &label_decoded
);
4707 if (SAFI_ENCAP
== safi
) {
4708 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4709 type
, sub_type
, NULL
);
4712 if ((safi
== SAFI_MPLS_VPN
) &&
4713 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4714 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4716 bgp_unlink_nexthop(pi
);
4717 bgp_path_info_delete(dest
, pi
);
4720 } // End of implicit withdraw
4722 /* Received Logging. */
4723 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4724 if (!peer
->rcvd_attr_printed
) {
4725 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4726 peer
->rcvd_attr_str
);
4727 peer
->rcvd_attr_printed
= 1;
4730 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4731 addpath_id
? 1 : 0, addpath_id
, evpn
,
4732 pfx_buf
, sizeof(pfx_buf
));
4733 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4736 /* Make new BGP info. */
4737 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4739 /* Update MPLS label */
4740 if (has_valid_label
) {
4741 extra
= bgp_path_info_extra_get(new);
4742 if (extra
->label
!= label
) {
4743 memcpy(&extra
->label
, label
,
4744 num_labels
* sizeof(mpls_label_t
));
4745 extra
->num_labels
= num_labels
;
4747 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4748 bgp_set_valid_label(&extra
->label
[0]);
4751 /* Update SRv6 SID */
4752 if (safi
== SAFI_MPLS_VPN
) {
4753 extra
= bgp_path_info_extra_get(new);
4754 if (attr
->srv6_l3vpn
) {
4755 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4756 extra
->num_sids
= 1;
4758 extra
->sid
[0].loc_block_len
=
4759 attr
->srv6_l3vpn
->loc_block_len
;
4760 extra
->sid
[0].loc_node_len
=
4761 attr
->srv6_l3vpn
->loc_node_len
;
4762 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4763 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4764 extra
->sid
[0].transposition_len
=
4765 attr
->srv6_l3vpn
->transposition_len
;
4766 extra
->sid
[0].transposition_offset
=
4767 attr
->srv6_l3vpn
->transposition_offset
;
4768 } else if (attr
->srv6_vpn
) {
4769 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4770 extra
->num_sids
= 1;
4774 /* Nexthop reachability check. */
4775 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4776 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4777 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4778 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4779 && peer
->ttl
== BGP_DEFAULT_TTL
4780 && !CHECK_FLAG(peer
->flags
,
4781 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4782 && !CHECK_FLAG(bgp
->flags
,
4783 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4788 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4790 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4791 connected
, bgp_nht_param_prefix
) ||
4792 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4793 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4795 if (BGP_DEBUG(nht
, NHT
))
4796 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4797 &attr_new
->nexthop
);
4798 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4802 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4804 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4807 /* If maximum prefix count is configured and current prefix
4810 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4811 reason
= "maximum-prefix overflow";
4812 bgp_attr_flush(&new_attr
);
4817 new->addpath_rx_id
= addpath_id
;
4819 /* Increment prefix */
4820 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4822 /* Register new BGP information. */
4823 bgp_path_info_add(dest
, new);
4825 /* route_node_get lock */
4826 bgp_dest_unlock_node(dest
);
4828 #ifdef ENABLE_BGP_VNC
4829 if (safi
== SAFI_MPLS_VPN
) {
4830 struct bgp_dest
*pdest
= NULL
;
4831 struct bgp_table
*table
= NULL
;
4833 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4834 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4835 table
= bgp_dest_get_bgp_table_info(pdest
);
4837 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4838 bgp
, prd
, table
, p
, new);
4840 bgp_dest_unlock_node(pdest
);
4844 /* If this is an EVPN route, process for import. */
4845 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4846 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4848 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4850 /* Process change. */
4851 bgp_process(bgp
, dest
, afi
, safi
);
4853 if (SAFI_UNICAST
== safi
4854 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4855 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4856 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4858 if ((SAFI_MPLS_VPN
== safi
)
4859 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4860 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4862 #ifdef ENABLE_BGP_VNC
4863 if (SAFI_MPLS_VPN
== safi
) {
4864 mpls_label_t label_decoded
= decode_label(label
);
4866 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4867 sub_type
, &label_decoded
);
4869 if (SAFI_ENCAP
== safi
) {
4870 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4874 if ((safi
== SAFI_MPLS_VPN
) &&
4875 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4876 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4878 bgp_unlink_nexthop(new);
4879 bgp_path_info_delete(dest
, new);
4884 /* This BGP update is filtered. Log the reason then update BGP
4888 bgp_unlink_nexthop(new);
4889 bgp_path_info_delete(dest
, new);
4890 bgp_path_info_extra_free(&new->extra
);
4891 XFREE(MTYPE_BGP_ROUTE
, new);
4894 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4896 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4897 if (!peer
->rcvd_attr_printed
) {
4898 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4899 peer
->rcvd_attr_str
);
4900 peer
->rcvd_attr_printed
= 1;
4903 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4904 addpath_id
? 1 : 0, addpath_id
, evpn
,
4905 pfx_buf
, sizeof(pfx_buf
));
4906 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4907 peer
, pfx_buf
, reason
);
4911 /* If this is an EVPN route, un-import it as it is now filtered.
4913 if (safi
== SAFI_EVPN
)
4914 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4916 if (SAFI_UNICAST
== safi
4917 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4918 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4920 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4922 if ((SAFI_MPLS_VPN
== safi
)
4923 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4925 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4928 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4931 bgp_dest_unlock_node(dest
);
4933 #ifdef ENABLE_BGP_VNC
4935 * Filtered update is treated as an implicit withdrawal (see
4937 * a few lines above)
4939 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4940 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4948 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4949 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4950 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4951 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4954 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4955 struct bgp_dest
*dest
;
4956 struct bgp_path_info
*pi
;
4958 #ifdef ENABLE_BGP_VNC
4959 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4960 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4968 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4970 /* If peer is soft reconfiguration enabled. Record input packet for
4971 * further calculation.
4973 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4974 * routes that are filtered. This tanks out Quagga RS pretty badly due
4976 * the iteration over all RS clients.
4977 * Since we need to remove the entry from adj_in anyway, do that first
4979 * if there was no entry, we don't need to do anything more.
4981 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4982 && peer
!= bgp
->peer_self
)
4983 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4984 peer
->stat_pfx_dup_withdraw
++;
4986 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4987 bgp_debug_rdpfxpath2str(
4988 afi
, safi
, prd
, p
, label
, num_labels
,
4989 addpath_id
? 1 : 0, addpath_id
, NULL
,
4990 pfx_buf
, sizeof(pfx_buf
));
4992 "%s withdrawing route %s not in adj-in",
4993 peer
->host
, pfx_buf
);
4995 bgp_dest_unlock_node(dest
);
4999 /* Lookup withdrawn route. */
5000 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5001 if (pi
->peer
== peer
&& pi
->type
== type
5002 && pi
->sub_type
== sub_type
5003 && pi
->addpath_rx_id
== addpath_id
)
5007 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5008 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5009 addpath_id
? 1 : 0, addpath_id
, NULL
,
5010 pfx_buf
, sizeof(pfx_buf
));
5011 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
5015 /* Withdraw specified route from routing table. */
5016 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
5017 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
5018 if (SAFI_UNICAST
== safi
5019 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5020 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5021 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5023 if ((SAFI_MPLS_VPN
== safi
)
5024 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5026 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5028 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5029 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5030 addpath_id
? 1 : 0, addpath_id
, NULL
,
5031 pfx_buf
, sizeof(pfx_buf
));
5032 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
5035 /* Unlock bgp_node_get() lock. */
5036 bgp_dest_unlock_node(dest
);
5041 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
5044 struct update_subgroup
*subgrp
;
5045 subgrp
= peer_subgroup(peer
, afi
, safi
);
5046 subgroup_default_originate(subgrp
, withdraw
);
5051 * bgp_stop_announce_route_timer
5053 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5055 if (!paf
->t_announce_route
)
5058 THREAD_OFF(paf
->t_announce_route
);
5062 * bgp_announce_route_timer_expired
5064 * Callback that is invoked when the route announcement timer for a
5067 static void bgp_announce_route_timer_expired(struct thread
*t
)
5069 struct peer_af
*paf
;
5072 paf
= THREAD_ARG(t
);
5075 if (!peer_established(peer
))
5078 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5081 peer_af_announce_route(paf
, 1);
5083 /* Notify BGP conditional advertisement scanner percess */
5084 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5088 * bgp_announce_route
5090 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5092 * if force is true we will force an update even if the update
5093 * limiting code is attempted to kick in.
5095 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5097 struct peer_af
*paf
;
5098 struct update_subgroup
*subgrp
;
5100 paf
= peer_af_find(peer
, afi
, safi
);
5103 subgrp
= PAF_SUBGRP(paf
);
5106 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5107 * or a refresh has already been triggered.
5109 if (!subgrp
|| paf
->t_announce_route
)
5113 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5116 * Start a timer to stagger/delay the announce. This serves
5117 * two purposes - announcement can potentially be combined for
5118 * multiple peers and the announcement doesn't happen in the
5121 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5122 (subgrp
->peer_count
== 1)
5123 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5124 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5125 &paf
->t_announce_route
);
5129 * Announce routes from all AF tables to a peer.
5131 * This should ONLY be called when there is a need to refresh the
5132 * routes to the peer based on a policy change for this peer alone
5133 * or a route refresh request received from the peer.
5134 * The operation will result in splitting the peer from its existing
5135 * subgroups and putting it in new subgroups.
5137 void bgp_announce_route_all(struct peer
*peer
)
5142 FOREACH_AFI_SAFI (afi
, safi
)
5143 bgp_announce_route(peer
, afi
, safi
, false);
5146 /* Flag or unflag bgp_dest to determine whether it should be treated by
5147 * bgp_soft_reconfig_table_task.
5148 * Flag if flag is true. Unflag if flag is false.
5150 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5152 struct bgp_dest
*dest
;
5153 struct bgp_adj_in
*ain
;
5158 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5159 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5160 if (ain
->peer
!= NULL
)
5163 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5164 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5166 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5170 static int bgp_soft_reconfig_table_update(struct peer
*peer
,
5171 struct bgp_dest
*dest
,
5172 struct bgp_adj_in
*ain
, afi_t afi
,
5173 safi_t safi
, struct prefix_rd
*prd
)
5175 struct bgp_path_info
*pi
;
5176 uint32_t num_labels
= 0;
5177 mpls_label_t
*label_pnt
= NULL
;
5178 struct bgp_route_evpn evpn
;
5180 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5181 if (pi
->peer
== peer
)
5184 if (pi
&& pi
->extra
)
5185 num_labels
= pi
->extra
->num_labels
;
5187 label_pnt
= &pi
->extra
->label
[0];
5189 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5192 memset(&evpn
, 0, sizeof(evpn
));
5194 return bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5195 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
5196 BGP_ROUTE_NORMAL
, prd
, label_pnt
, num_labels
, 1,
5200 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5201 struct bgp_table
*table
,
5202 struct prefix_rd
*prd
)
5205 struct bgp_dest
*dest
;
5206 struct bgp_adj_in
*ain
;
5209 table
= peer
->bgp
->rib
[afi
][safi
];
5211 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5212 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5213 if (ain
->peer
!= peer
)
5216 ret
= bgp_soft_reconfig_table_update(peer
, dest
, ain
,
5220 bgp_dest_unlock_node(dest
);
5226 /* Do soft reconfig table per bgp table.
5227 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5228 * when BGP_NODE_SOFT_RECONFIG is set,
5229 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5230 * Schedule a new thread to continue the job.
5231 * Without splitting the full job into several part,
5232 * vtysh waits for the job to finish before responding to a BGP command
5234 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
5236 uint32_t iter
, max_iter
;
5238 struct bgp_dest
*dest
;
5239 struct bgp_adj_in
*ain
;
5241 struct bgp_table
*table
;
5242 struct prefix_rd
*prd
;
5243 struct listnode
*node
, *nnode
;
5245 table
= THREAD_ARG(thread
);
5248 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5249 if (table
->soft_reconfig_init
) {
5250 /* first call of the function with a new srta structure.
5251 * Don't do any treatment this time on nodes
5252 * in order vtysh to respond quickly
5257 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5258 dest
= bgp_route_next(dest
)) {
5259 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5262 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5264 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5265 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5267 if (ain
->peer
!= peer
)
5270 ret
= bgp_soft_reconfig_table_update(
5271 peer
, dest
, ain
, table
->afi
,
5276 bgp_dest_unlock_node(dest
);
5278 table
->soft_reconfig_peers
,
5280 bgp_announce_route(peer
, table
->afi
,
5281 table
->safi
, false);
5283 table
->soft_reconfig_peers
)) {
5285 &table
->soft_reconfig_peers
);
5286 bgp_soft_reconfig_table_flag(
5295 /* we're either starting the initial iteration,
5296 * or we're going to continue an ongoing iteration
5298 if (dest
|| table
->soft_reconfig_init
) {
5299 table
->soft_reconfig_init
= false;
5300 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
5301 table
, 0, &table
->soft_reconfig_thread
);
5304 /* we're done, clean up the background iteration context info and
5305 schedule route annoucement
5307 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5308 listnode_delete(table
->soft_reconfig_peers
, peer
);
5309 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5312 list_delete(&table
->soft_reconfig_peers
);
5316 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5318 * - bgp cannot be NULL
5319 * - if table and peer are NULL, cancel all threads within the bgp instance
5320 * - if table is NULL and peer is not,
5321 * remove peer in all threads within the bgp instance
5322 * - if peer is NULL, cancel all threads matching table within the bgp instance
5324 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5325 const struct bgp_table
*table
,
5326 const struct peer
*peer
)
5329 struct listnode
*node
, *nnode
;
5331 struct bgp_table
*ntable
;
5336 FOREACH_AFI_SAFI (afi
, safi
) {
5337 ntable
= bgp
->rib
[afi
][safi
];
5340 if (table
&& table
!= ntable
)
5343 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5345 if (peer
&& peer
!= npeer
)
5347 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5350 if (!ntable
->soft_reconfig_peers
5351 || !list_isempty(ntable
->soft_reconfig_peers
))
5354 list_delete(&ntable
->soft_reconfig_peers
);
5355 bgp_soft_reconfig_table_flag(ntable
, false);
5356 THREAD_OFF(ntable
->soft_reconfig_thread
);
5361 * Returns false if the peer is not configured for soft reconfig in
5363 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5365 struct bgp_dest
*dest
;
5366 struct bgp_table
*table
;
5367 struct listnode
*node
, *nnode
;
5369 struct peer_af
*paf
;
5371 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5374 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5375 && (safi
!= SAFI_EVPN
)) {
5376 table
= peer
->bgp
->rib
[afi
][safi
];
5380 table
->soft_reconfig_init
= true;
5382 if (!table
->soft_reconfig_peers
)
5383 table
->soft_reconfig_peers
= list_new();
5385 /* add peer to the table soft_reconfig_peers if not already
5388 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5394 listnode_add(table
->soft_reconfig_peers
, peer
);
5396 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5397 * on table would start back at the beginning.
5399 bgp_soft_reconfig_table_flag(table
, true);
5401 if (!table
->soft_reconfig_thread
)
5402 thread_add_event(bm
->master
,
5403 bgp_soft_reconfig_table_task
, table
, 0,
5404 &table
->soft_reconfig_thread
);
5405 /* Cancel bgp_announce_route_timer_expired threads.
5406 * bgp_announce_route_timer_expired threads have been scheduled
5407 * to announce routes as soon as the soft_reconfigure process
5409 * In this case, soft_reconfigure is also scheduled by using
5410 * a thread but is planned after the
5411 * bgp_announce_route_timer_expired threads. It means that,
5412 * without cancelling the threads, the route announcement task
5413 * would run before the soft reconfiguration one. That would
5414 * useless and would block vtysh during several seconds. Route
5415 * announcements are rescheduled as soon as the soft_reconfigure
5418 paf
= peer_af_find(peer
, afi
, safi
);
5420 bgp_stop_announce_route_timer(paf
);
5422 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5423 dest
= bgp_route_next(dest
)) {
5424 table
= bgp_dest_get_bgp_table_info(dest
);
5429 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5430 struct prefix_rd prd
;
5432 prd
.family
= AF_UNSPEC
;
5434 memcpy(&prd
.val
, p
->u
.val
, 8);
5436 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5443 struct bgp_clear_node_queue
{
5444 struct bgp_dest
*dest
;
5447 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5449 struct bgp_clear_node_queue
*cnq
= data
;
5450 struct bgp_dest
*dest
= cnq
->dest
;
5451 struct peer
*peer
= wq
->spec
.data
;
5452 struct bgp_path_info
*pi
;
5454 afi_t afi
= bgp_dest_table(dest
)->afi
;
5455 safi_t safi
= bgp_dest_table(dest
)->safi
;
5457 assert(dest
&& peer
);
5460 /* It is possible that we have multiple paths for a prefix from a peer
5461 * if that peer is using AddPath.
5463 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5464 if (pi
->peer
!= peer
)
5467 /* graceful restart STALE flag set. */
5468 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5469 && peer
->nsf
[afi
][safi
])
5470 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5471 PEER_STATUS_ENHANCED_REFRESH
))
5472 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5473 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5474 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5476 /* If this is an EVPN route, process for
5478 if (safi
== SAFI_EVPN
)
5479 bgp_evpn_unimport_route(
5481 bgp_dest_get_prefix(dest
), pi
);
5482 /* Handle withdraw for VRF route-leaking and L3VPN */
5483 if (SAFI_UNICAST
== safi
5484 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5485 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5486 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5489 if (SAFI_MPLS_VPN
== safi
&&
5490 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5491 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5494 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5500 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5502 struct bgp_clear_node_queue
*cnq
= data
;
5503 struct bgp_dest
*dest
= cnq
->dest
;
5504 struct bgp_table
*table
= bgp_dest_table(dest
);
5506 bgp_dest_unlock_node(dest
);
5507 bgp_table_unlock(table
);
5508 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5511 static void bgp_clear_node_complete(struct work_queue
*wq
)
5513 struct peer
*peer
= wq
->spec
.data
;
5515 /* Tickle FSM to start moving again */
5516 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5518 peer_unlock(peer
); /* bgp_clear_route */
5521 static void bgp_clear_node_queue_init(struct peer
*peer
)
5523 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5525 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5526 #undef CLEAR_QUEUE_NAME_LEN
5528 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5529 peer
->clear_node_queue
->spec
.hold
= 10;
5530 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5531 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5532 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5533 peer
->clear_node_queue
->spec
.max_retries
= 0;
5535 /* we only 'lock' this peer reference when the queue is actually active
5537 peer
->clear_node_queue
->spec
.data
= peer
;
5540 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5541 struct bgp_table
*table
)
5543 struct bgp_dest
*dest
;
5544 int force
= peer
->bgp
->process_queue
? 0 : 1;
5547 table
= peer
->bgp
->rib
[afi
][safi
];
5549 /* If still no table => afi/safi isn't configured at all or smth. */
5553 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5554 struct bgp_path_info
*pi
, *next
;
5555 struct bgp_adj_in
*ain
;
5556 struct bgp_adj_in
*ain_next
;
5558 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5559 * queued for every clearing peer, regardless of whether it is
5560 * relevant to the peer at hand.
5562 * Overview: There are 3 different indices which need to be
5563 * scrubbed, potentially, when a peer is removed:
5565 * 1 peer's routes visible via the RIB (ie accepted routes)
5566 * 2 peer's routes visible by the (optional) peer's adj-in index
5567 * 3 other routes visible by the peer's adj-out index
5569 * 3 there is no hurry in scrubbing, once the struct peer is
5570 * removed from bgp->peer, we could just GC such deleted peer's
5571 * adj-outs at our leisure.
5573 * 1 and 2 must be 'scrubbed' in some way, at least made
5574 * invisible via RIB index before peer session is allowed to be
5575 * brought back up. So one needs to know when such a 'search' is
5580 * - there'd be a single global queue or a single RIB walker
5581 * - rather than tracking which route_nodes still need to be
5582 * examined on a peer basis, we'd track which peers still
5585 * Given that our per-peer prefix-counts now should be reliable,
5586 * this may actually be achievable. It doesn't seem to be a huge
5587 * problem at this time,
5589 * It is possible that we have multiple paths for a prefix from
5591 * if that peer is using AddPath.
5595 ain_next
= ain
->next
;
5597 if (ain
->peer
== peer
)
5598 bgp_adj_in_remove(dest
, ain
);
5603 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5605 if (pi
->peer
!= peer
)
5609 bgp_path_info_reap(dest
, pi
);
5611 struct bgp_clear_node_queue
*cnq
;
5613 /* both unlocked in bgp_clear_node_queue_del */
5614 bgp_table_lock(bgp_dest_table(dest
));
5615 bgp_dest_lock_node(dest
);
5617 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5618 sizeof(struct bgp_clear_node_queue
));
5620 work_queue_add(peer
->clear_node_queue
, cnq
);
5628 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5630 struct bgp_dest
*dest
;
5631 struct bgp_table
*table
;
5633 if (peer
->clear_node_queue
== NULL
)
5634 bgp_clear_node_queue_init(peer
);
5636 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5637 * Idle until it receives a Clearing_Completed event. This protects
5638 * against peers which flap faster than we can we clear, which could
5641 * a) race with routes from the new session being installed before
5642 * clear_route_node visits the node (to delete the route of that
5644 * b) resource exhaustion, clear_route_node likely leads to an entry
5645 * on the process_main queue. Fast-flapping could cause that queue
5649 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5650 * the unlock will happen upon work-queue completion; other wise, the
5651 * unlock happens at the end of this function.
5653 if (!peer
->clear_node_queue
->thread
)
5656 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5657 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5659 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5660 dest
= bgp_route_next(dest
)) {
5661 table
= bgp_dest_get_bgp_table_info(dest
);
5665 bgp_clear_route_table(peer
, afi
, safi
, table
);
5668 /* unlock if no nodes got added to the clear-node-queue. */
5669 if (!peer
->clear_node_queue
->thread
)
5673 void bgp_clear_route_all(struct peer
*peer
)
5678 FOREACH_AFI_SAFI (afi
, safi
)
5679 bgp_clear_route(peer
, afi
, safi
);
5681 #ifdef ENABLE_BGP_VNC
5682 rfapiProcessPeerDown(peer
);
5686 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5688 struct bgp_table
*table
;
5689 struct bgp_dest
*dest
;
5690 struct bgp_adj_in
*ain
;
5691 struct bgp_adj_in
*ain_next
;
5693 table
= peer
->bgp
->rib
[afi
][safi
];
5695 /* It is possible that we have multiple paths for a prefix from a peer
5696 * if that peer is using AddPath.
5698 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5702 ain_next
= ain
->next
;
5704 if (ain
->peer
== peer
)
5705 bgp_adj_in_remove(dest
, ain
);
5712 /* If any of the routes from the peer have been marked with the NO_LLGR
5713 * community, either as sent by the peer, or as the result of a configured
5714 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5715 * operation of [RFC4271].
5717 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5719 struct bgp_dest
*dest
;
5720 struct bgp_path_info
*pi
;
5721 struct bgp_table
*table
;
5723 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5724 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5725 dest
= bgp_route_next(dest
)) {
5726 struct bgp_dest
*rm
;
5728 /* look for neighbor in tables */
5729 table
= bgp_dest_get_bgp_table_info(dest
);
5733 for (rm
= bgp_table_top(table
); rm
;
5734 rm
= bgp_route_next(rm
))
5735 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5737 if (pi
->peer
!= peer
)
5740 peer
->af_sflags
[afi
][safi
],
5741 PEER_STATUS_LLGR_WAIT
) &&
5742 bgp_attr_get_community(pi
->attr
) &&
5744 bgp_attr_get_community(
5748 if (!CHECK_FLAG(pi
->flags
,
5753 * If this is VRF leaked route
5754 * process for withdraw.
5757 BGP_ROUTE_IMPORTED
&&
5758 peer
->bgp
->inst_type
==
5759 BGP_INSTANCE_TYPE_DEFAULT
)
5760 vpn_leak_to_vrf_withdraw(
5763 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5768 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5769 dest
= bgp_route_next(dest
))
5770 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5772 if (pi
->peer
!= peer
)
5774 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5775 PEER_STATUS_LLGR_WAIT
) &&
5776 bgp_attr_get_community(pi
->attr
) &&
5778 bgp_attr_get_community(pi
->attr
),
5781 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5783 if (safi
== SAFI_UNICAST
&&
5784 (peer
->bgp
->inst_type
==
5785 BGP_INSTANCE_TYPE_VRF
||
5786 peer
->bgp
->inst_type
==
5787 BGP_INSTANCE_TYPE_DEFAULT
))
5788 vpn_leak_from_vrf_withdraw(
5789 bgp_get_default(), peer
->bgp
,
5792 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5798 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5800 struct bgp_dest
*dest
, *ndest
;
5801 struct bgp_path_info
*pi
;
5802 struct bgp_table
*table
;
5804 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5805 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5806 dest
= bgp_route_next(dest
)) {
5807 table
= bgp_dest_get_bgp_table_info(dest
);
5811 for (ndest
= bgp_table_top(table
); ndest
;
5812 ndest
= bgp_route_next(ndest
)) {
5813 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5815 if (pi
->peer
!= peer
)
5819 peer
->af_sflags
[afi
][safi
],
5820 PEER_STATUS_ENHANCED_REFRESH
))
5821 && !CHECK_FLAG(pi
->flags
,
5825 BGP_PATH_UNUSEABLE
)) {
5826 if (bgp_debug_neighbor_events(
5829 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5833 bgp_dest_get_prefix(
5836 bgp_path_info_set_flag(
5844 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5845 dest
= bgp_route_next(dest
)) {
5846 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5848 if (pi
->peer
!= peer
)
5851 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5852 PEER_STATUS_ENHANCED_REFRESH
))
5853 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5854 && !CHECK_FLAG(pi
->flags
,
5855 BGP_PATH_UNUSEABLE
)) {
5856 if (bgp_debug_neighbor_events(peer
))
5858 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5861 bgp_dest_get_prefix(
5864 bgp_path_info_set_flag(dest
, pi
,
5872 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5874 if (peer
->sort
== BGP_PEER_IBGP
)
5877 if (peer
->sort
== BGP_PEER_EBGP
5878 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5879 || FILTER_LIST_OUT_NAME(filter
)
5880 || DISTRIBUTE_OUT_NAME(filter
)))
5885 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5887 if (peer
->sort
== BGP_PEER_IBGP
)
5890 if (peer
->sort
== BGP_PEER_EBGP
5891 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5892 || FILTER_LIST_IN_NAME(filter
)
5893 || DISTRIBUTE_IN_NAME(filter
)))
5898 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5901 struct bgp_dest
*dest
;
5902 struct bgp_path_info
*pi
;
5903 struct bgp_path_info
*next
;
5905 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5906 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5907 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5911 /* Unimport EVPN routes from VRFs */
5912 if (safi
== SAFI_EVPN
)
5913 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5916 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5917 && pi
->type
== ZEBRA_ROUTE_BGP
5918 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5919 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5920 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5922 if (bgp_fibupd_safi(safi
))
5923 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5926 bgp_path_info_reap(dest
, pi
);
5930 /* Delete all kernel routes. */
5931 void bgp_cleanup_routes(struct bgp
*bgp
)
5934 struct bgp_dest
*dest
;
5935 struct bgp_table
*table
;
5937 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5938 if (afi
== AFI_L2VPN
)
5940 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5943 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5945 if (afi
!= AFI_L2VPN
) {
5947 safi
= SAFI_MPLS_VPN
;
5948 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5949 dest
= bgp_route_next(dest
)) {
5950 table
= bgp_dest_get_bgp_table_info(dest
);
5951 if (table
!= NULL
) {
5952 bgp_cleanup_table(bgp
, table
, safi
);
5953 bgp_table_finish(&table
);
5954 bgp_dest_set_bgp_table_info(dest
, NULL
);
5955 bgp_dest_unlock_node(dest
);
5959 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5960 dest
= bgp_route_next(dest
)) {
5961 table
= bgp_dest_get_bgp_table_info(dest
);
5962 if (table
!= NULL
) {
5963 bgp_cleanup_table(bgp
, table
, safi
);
5964 bgp_table_finish(&table
);
5965 bgp_dest_set_bgp_table_info(dest
, NULL
);
5966 bgp_dest_unlock_node(dest
);
5971 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5972 dest
= bgp_route_next(dest
)) {
5973 table
= bgp_dest_get_bgp_table_info(dest
);
5974 if (table
!= NULL
) {
5975 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5976 bgp_table_finish(&table
);
5977 bgp_dest_set_bgp_table_info(dest
, NULL
);
5978 bgp_dest_unlock_node(dest
);
5983 void bgp_reset(void)
5986 bgp_zclient_reset();
5987 access_list_reset();
5988 prefix_list_reset();
5991 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5993 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5994 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5995 PEER_CAP_ADDPATH_AF_TX_RCV
));
5998 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
6000 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
6001 struct bgp_nlri
*packet
)
6010 bool addpath_capable
;
6011 uint32_t addpath_id
;
6014 lim
= pnt
+ packet
->length
;
6016 safi
= packet
->safi
;
6018 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
6020 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6021 syntactic validity. If the field is syntactically incorrect,
6022 then the Error Subcode is set to Invalid Network Field. */
6023 for (; pnt
< lim
; pnt
+= psize
) {
6024 /* Clear prefix structure. */
6025 memset(&p
, 0, sizeof(p
));
6027 if (addpath_capable
) {
6029 /* When packet overflow occurs return immediately. */
6030 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
6031 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6033 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
6034 addpath_id
= ntohl(addpath_id
);
6035 pnt
+= BGP_ADDPATH_ID_LEN
;
6038 /* Fetch prefix length. */
6039 p
.prefixlen
= *pnt
++;
6040 /* afi/safi validity already verified by caller,
6041 * bgp_update_receive */
6042 p
.family
= afi2family(afi
);
6044 /* Prefix length check. */
6045 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
6048 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
6049 peer
->host
, p
.prefixlen
, packet
->afi
);
6050 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
6053 /* Packet size overflow check. */
6054 psize
= PSIZE(p
.prefixlen
);
6056 /* When packet overflow occur return immediately. */
6057 if (pnt
+ psize
> lim
) {
6060 "%s [Error] Update packet error (prefix length %d overflows packet)",
6061 peer
->host
, p
.prefixlen
);
6062 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6065 /* Defensive coding, double-check the psize fits in a struct
6066 * prefix for the v4 and v6 afi's and unicast/multicast */
6067 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6070 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6071 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6072 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6075 /* Fetch prefix from NLRI packet. */
6076 memcpy(p
.u
.val
, pnt
, psize
);
6078 /* Check address. */
6079 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6080 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6081 /* From RFC4271 Section 6.3:
6083 * If a prefix in the NLRI field is semantically
6085 * (e.g., an unexpected multicast IP address),
6087 * be logged locally, and the prefix SHOULD be
6092 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6093 peer
->host
, &p
.u
.prefix4
);
6098 /* Check address. */
6099 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6100 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6103 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6104 peer
->host
, &p
.u
.prefix6
);
6108 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6111 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6112 peer
->host
, &p
.u
.prefix6
);
6118 /* Normal process. */
6120 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6121 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
6122 NULL
, NULL
, 0, 0, NULL
);
6124 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
6125 safi
, ZEBRA_ROUTE_BGP
,
6126 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
6129 /* Do not send BGP notification twice when maximum-prefix count
6131 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6132 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6134 /* Address family configuration mismatch. */
6136 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
6139 /* Packet length consistency check. */
6143 "%s [Error] Update packet error (prefix length mismatch with total length)",
6145 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6148 return BGP_NLRI_PARSE_OK
;
6151 static struct bgp_static
*bgp_static_new(void)
6153 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6156 static void bgp_static_free(struct bgp_static
*bgp_static
)
6158 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6159 route_map_counter_decrement(bgp_static
->rmap
.map
);
6161 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6162 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6165 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6166 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6168 struct bgp_dest
*dest
;
6169 struct bgp_path_info
*pi
;
6170 struct bgp_path_info
*new;
6171 struct bgp_path_info rmap_path
;
6173 struct attr
*attr_new
;
6174 route_map_result_t ret
;
6175 #ifdef ENABLE_BGP_VNC
6176 int vnc_implicit_withdraw
= 0;
6181 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6183 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6185 attr
.nexthop
= bgp_static
->igpnexthop
;
6186 attr
.med
= bgp_static
->igpmetric
;
6187 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6190 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6192 if (bgp_static
->igpmetric
)
6193 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6195 if (bgp_static
->atomic
)
6196 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6198 /* Store label index, if required. */
6199 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6200 attr
.label_index
= bgp_static
->label_index
;
6201 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6204 /* Apply route-map. */
6205 if (bgp_static
->rmap
.name
) {
6206 struct attr attr_tmp
= attr
;
6208 memset(&rmap_path
, 0, sizeof(rmap_path
));
6209 rmap_path
.peer
= bgp
->peer_self
;
6210 rmap_path
.attr
= &attr_tmp
;
6212 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6214 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6216 bgp
->peer_self
->rmap_type
= 0;
6218 if (ret
== RMAP_DENYMATCH
) {
6219 /* Free uninterned attribute. */
6220 bgp_attr_flush(&attr_tmp
);
6222 /* Unintern original. */
6223 aspath_unintern(&attr
.aspath
);
6224 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6225 bgp_dest_unlock_node(dest
);
6229 if (bgp_in_graceful_shutdown(bgp
))
6230 bgp_attr_add_gshut_community(&attr_tmp
);
6232 attr_new
= bgp_attr_intern(&attr_tmp
);
6235 if (bgp_in_graceful_shutdown(bgp
))
6236 bgp_attr_add_gshut_community(&attr
);
6238 attr_new
= bgp_attr_intern(&attr
);
6241 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6242 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6243 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6247 if (attrhash_cmp(pi
->attr
, attr_new
)
6248 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6249 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6250 bgp_dest_unlock_node(dest
);
6251 bgp_attr_unintern(&attr_new
);
6252 aspath_unintern(&attr
.aspath
);
6255 /* The attribute is changed. */
6256 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6258 /* Rewrite BGP route information. */
6259 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6260 bgp_path_info_restore(dest
, pi
);
6262 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6263 #ifdef ENABLE_BGP_VNC
6264 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6265 && (safi
== SAFI_UNICAST
)) {
6266 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6268 * Implicit withdraw case.
6269 * We have to do this before pi is
6272 ++vnc_implicit_withdraw
;
6273 vnc_import_bgp_del_route(bgp
, p
, pi
);
6274 vnc_import_bgp_exterior_del_route(
6279 bgp_attr_unintern(&pi
->attr
);
6280 pi
->attr
= attr_new
;
6281 pi
->uptime
= monotime(NULL
);
6282 #ifdef ENABLE_BGP_VNC
6283 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6284 && (safi
== SAFI_UNICAST
)) {
6285 if (vnc_implicit_withdraw
) {
6286 vnc_import_bgp_add_route(bgp
, p
, pi
);
6287 vnc_import_bgp_exterior_add_route(
6293 /* Nexthop reachability check. */
6294 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6295 && (safi
== SAFI_UNICAST
6296 || safi
== SAFI_LABELED_UNICAST
)) {
6298 struct bgp
*bgp_nexthop
= bgp
;
6300 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6301 bgp_nexthop
= pi
->extra
->bgp_orig
;
6303 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6304 afi
, safi
, pi
, NULL
,
6306 bgp_path_info_set_flag(dest
, pi
,
6309 if (BGP_DEBUG(nht
, NHT
)) {
6310 char buf1
[INET6_ADDRSTRLEN
];
6311 inet_ntop(p
->family
,
6315 "%s(%s): Route not in table, not advertising",
6318 bgp_path_info_unset_flag(
6319 dest
, pi
, BGP_PATH_VALID
);
6322 /* Delete the NHT structure if any, if we're
6324 * enabling/disabling import check. We
6325 * deregister the route
6326 * from NHT to avoid overloading NHT and the
6327 * process interaction
6329 bgp_unlink_nexthop(pi
);
6330 bgp_path_info_set_flag(dest
, pi
,
6333 /* Process change. */
6334 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6335 bgp_process(bgp
, dest
, afi
, safi
);
6337 if (SAFI_UNICAST
== safi
6338 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6340 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6341 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6345 bgp_dest_unlock_node(dest
);
6346 aspath_unintern(&attr
.aspath
);
6351 /* Make new BGP info. */
6352 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6354 /* Nexthop reachability check. */
6355 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6356 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6357 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6359 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6361 if (BGP_DEBUG(nht
, NHT
)) {
6362 char buf1
[INET6_ADDRSTRLEN
];
6364 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6367 "%s(%s): Route not in table, not advertising",
6370 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6373 /* Delete the NHT structure if any, if we're toggling between
6374 * enabling/disabling import check. We deregister the route
6375 * from NHT to avoid overloading NHT and the process interaction
6377 bgp_unlink_nexthop(new);
6379 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6382 /* Aggregate address increment. */
6383 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6385 /* Register new BGP information. */
6386 bgp_path_info_add(dest
, new);
6388 /* route_node_get lock */
6389 bgp_dest_unlock_node(dest
);
6391 /* Process change. */
6392 bgp_process(bgp
, dest
, afi
, safi
);
6394 if (SAFI_UNICAST
== safi
6395 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6396 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6397 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6400 /* Unintern original. */
6401 aspath_unintern(&attr
.aspath
);
6404 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6407 struct bgp_dest
*dest
;
6408 struct bgp_path_info
*pi
;
6410 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6412 /* Check selected route and self inserted route. */
6413 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6414 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6415 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6418 /* Withdraw static BGP route from routing table. */
6420 if (SAFI_UNICAST
== safi
6421 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6422 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6423 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6425 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6426 bgp_unlink_nexthop(pi
);
6427 bgp_path_info_delete(dest
, pi
);
6428 bgp_process(bgp
, dest
, afi
, safi
);
6431 /* Unlock bgp_node_lookup. */
6432 bgp_dest_unlock_node(dest
);
6436 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6438 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6439 afi_t afi
, safi_t safi
,
6440 struct prefix_rd
*prd
)
6442 struct bgp_dest
*dest
;
6443 struct bgp_path_info
*pi
;
6445 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6447 /* Check selected route and self inserted route. */
6448 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6449 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6450 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6453 /* Withdraw static BGP route from routing table. */
6455 #ifdef ENABLE_BGP_VNC
6456 rfapiProcessWithdraw(
6457 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6458 1); /* Kill, since it is an administrative change */
6460 if (SAFI_MPLS_VPN
== safi
6461 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6462 vpn_leak_to_vrf_withdraw(bgp
, pi
);
6464 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6465 bgp_path_info_delete(dest
, pi
);
6466 bgp_process(bgp
, dest
, afi
, safi
);
6469 /* Unlock bgp_node_lookup. */
6470 bgp_dest_unlock_node(dest
);
6473 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6474 struct bgp_static
*bgp_static
, afi_t afi
,
6477 struct bgp_dest
*dest
;
6478 struct bgp_path_info
*new;
6479 struct attr
*attr_new
;
6480 struct attr attr
= {0};
6481 struct bgp_path_info
*pi
;
6482 #ifdef ENABLE_BGP_VNC
6483 mpls_label_t label
= 0;
6485 uint32_t num_labels
= 0;
6489 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6491 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6494 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6496 attr
.nexthop
= bgp_static
->igpnexthop
;
6497 attr
.med
= bgp_static
->igpmetric
;
6498 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6500 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6501 || (safi
== SAFI_ENCAP
)) {
6502 if (afi
== AFI_IP
) {
6503 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6504 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6507 if (afi
== AFI_L2VPN
) {
6508 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6509 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6510 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6511 &bgp_static
->gatewayIp
.u
.prefix4
,
6513 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6514 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6515 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6516 &bgp_static
->gatewayIp
.u
.prefix6
,
6519 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6520 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6521 struct bgp_encap_type_vxlan bet
;
6522 memset(&bet
, 0, sizeof(bet
));
6523 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6524 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6526 if (bgp_static
->router_mac
) {
6527 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6530 /* Apply route-map. */
6531 if (bgp_static
->rmap
.name
) {
6532 struct attr attr_tmp
= attr
;
6533 struct bgp_path_info rmap_path
;
6534 route_map_result_t ret
;
6536 rmap_path
.peer
= bgp
->peer_self
;
6537 rmap_path
.attr
= &attr_tmp
;
6539 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6541 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6543 bgp
->peer_self
->rmap_type
= 0;
6545 if (ret
== RMAP_DENYMATCH
) {
6546 /* Free uninterned attribute. */
6547 bgp_attr_flush(&attr_tmp
);
6549 /* Unintern original. */
6550 aspath_unintern(&attr
.aspath
);
6551 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6553 bgp_dest_unlock_node(dest
);
6557 attr_new
= bgp_attr_intern(&attr_tmp
);
6559 attr_new
= bgp_attr_intern(&attr
);
6562 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6563 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6564 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6568 if (attrhash_cmp(pi
->attr
, attr_new
)
6569 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6570 bgp_dest_unlock_node(dest
);
6571 bgp_attr_unintern(&attr_new
);
6572 aspath_unintern(&attr
.aspath
);
6575 /* The attribute is changed. */
6576 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6578 /* Rewrite BGP route information. */
6579 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6580 bgp_path_info_restore(dest
, pi
);
6582 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6583 bgp_attr_unintern(&pi
->attr
);
6584 pi
->attr
= attr_new
;
6585 pi
->uptime
= monotime(NULL
);
6586 #ifdef ENABLE_BGP_VNC
6588 label
= decode_label(&pi
->extra
->label
[0]);
6591 /* Process change. */
6592 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6593 bgp_process(bgp
, dest
, afi
, safi
);
6595 if (SAFI_MPLS_VPN
== safi
6596 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6597 vpn_leak_to_vrf_update(bgp
, pi
,
6600 #ifdef ENABLE_BGP_VNC
6601 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6602 pi
->attr
, afi
, safi
, pi
->type
,
6603 pi
->sub_type
, &label
);
6605 bgp_dest_unlock_node(dest
);
6606 aspath_unintern(&attr
.aspath
);
6612 /* Make new BGP info. */
6613 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6615 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6616 bgp_path_info_extra_get(new);
6618 new->extra
->label
[0] = bgp_static
->label
;
6619 new->extra
->num_labels
= num_labels
;
6621 #ifdef ENABLE_BGP_VNC
6622 label
= decode_label(&bgp_static
->label
);
6625 /* Aggregate address increment. */
6626 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6628 /* Register new BGP information. */
6629 bgp_path_info_add(dest
, new);
6630 /* route_node_get lock */
6631 bgp_dest_unlock_node(dest
);
6633 /* Process change. */
6634 bgp_process(bgp
, dest
, afi
, safi
);
6636 if (SAFI_MPLS_VPN
== safi
6637 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6638 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6640 #ifdef ENABLE_BGP_VNC
6641 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6642 safi
, new->type
, new->sub_type
, &label
);
6645 /* Unintern original. */
6646 aspath_unintern(&attr
.aspath
);
6649 /* Configure static BGP network. When user don't run zebra, static
6650 route should be installed as valid. */
6651 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6652 const char *ip_str
, afi_t afi
, safi_t safi
,
6653 const char *rmap
, int backdoor
, uint32_t label_index
)
6655 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6658 struct bgp_static
*bgp_static
;
6659 struct bgp_dest
*dest
;
6660 uint8_t need_update
= 0;
6662 /* Convert IP prefix string to struct prefix. */
6663 ret
= str2prefix(ip_str
, &p
);
6665 vty_out(vty
, "%% Malformed prefix\n");
6666 return CMD_WARNING_CONFIG_FAILED
;
6668 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6669 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6670 return CMD_WARNING_CONFIG_FAILED
;
6677 /* Set BGP static route configuration. */
6678 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6681 vty_out(vty
, "%% Can't find static route specified\n");
6682 return CMD_WARNING_CONFIG_FAILED
;
6685 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6687 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6688 && (label_index
!= bgp_static
->label_index
)) {
6690 "%% label-index doesn't match static route\n");
6691 bgp_dest_unlock_node(dest
);
6692 return CMD_WARNING_CONFIG_FAILED
;
6695 if ((rmap
&& bgp_static
->rmap
.name
)
6696 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6698 "%% route-map name doesn't match static route\n");
6699 bgp_dest_unlock_node(dest
);
6700 return CMD_WARNING_CONFIG_FAILED
;
6703 /* Update BGP RIB. */
6704 if (!bgp_static
->backdoor
)
6705 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6707 /* Clear configuration. */
6708 bgp_static_free(bgp_static
);
6709 bgp_dest_set_bgp_static_info(dest
, NULL
);
6710 bgp_dest_unlock_node(dest
);
6711 bgp_dest_unlock_node(dest
);
6714 /* Set BGP static route configuration. */
6715 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6716 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6718 /* Configuration change. */
6719 /* Label index cannot be changed. */
6720 if (bgp_static
->label_index
!= label_index
) {
6721 vty_out(vty
, "%% cannot change label-index\n");
6722 bgp_dest_unlock_node(dest
);
6723 return CMD_WARNING_CONFIG_FAILED
;
6726 /* Check previous routes are installed into BGP. */
6727 if (bgp_static
->valid
6728 && bgp_static
->backdoor
!= backdoor
)
6731 bgp_static
->backdoor
= backdoor
;
6734 XFREE(MTYPE_ROUTE_MAP_NAME
,
6735 bgp_static
->rmap
.name
);
6736 route_map_counter_decrement(
6737 bgp_static
->rmap
.map
);
6738 bgp_static
->rmap
.name
=
6739 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6740 bgp_static
->rmap
.map
=
6741 route_map_lookup_by_name(rmap
);
6742 route_map_counter_increment(
6743 bgp_static
->rmap
.map
);
6745 XFREE(MTYPE_ROUTE_MAP_NAME
,
6746 bgp_static
->rmap
.name
);
6747 route_map_counter_decrement(
6748 bgp_static
->rmap
.map
);
6749 bgp_static
->rmap
.map
= NULL
;
6750 bgp_static
->valid
= 0;
6752 bgp_dest_unlock_node(dest
);
6754 /* New configuration. */
6755 bgp_static
= bgp_static_new();
6756 bgp_static
->backdoor
= backdoor
;
6757 bgp_static
->valid
= 0;
6758 bgp_static
->igpmetric
= 0;
6759 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6760 bgp_static
->label_index
= label_index
;
6763 XFREE(MTYPE_ROUTE_MAP_NAME
,
6764 bgp_static
->rmap
.name
);
6765 route_map_counter_decrement(
6766 bgp_static
->rmap
.map
);
6767 bgp_static
->rmap
.name
=
6768 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6769 bgp_static
->rmap
.map
=
6770 route_map_lookup_by_name(rmap
);
6771 route_map_counter_increment(
6772 bgp_static
->rmap
.map
);
6774 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6777 bgp_static
->valid
= 1;
6779 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6781 if (!bgp_static
->backdoor
)
6782 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6788 void bgp_static_add(struct bgp
*bgp
)
6792 struct bgp_dest
*dest
;
6793 struct bgp_dest
*rm
;
6794 struct bgp_table
*table
;
6795 struct bgp_static
*bgp_static
;
6797 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6798 FOREACH_AFI_SAFI (afi
, safi
)
6799 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6800 dest
= bgp_route_next(dest
)) {
6801 if (!bgp_dest_has_bgp_path_info_data(dest
))
6804 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6805 || (safi
== SAFI_EVPN
)) {
6806 table
= bgp_dest_get_bgp_table_info(dest
);
6808 for (rm
= bgp_table_top(table
); rm
;
6809 rm
= bgp_route_next(rm
)) {
6811 bgp_dest_get_bgp_static_info(
6813 bgp_static_update_safi(
6814 bgp
, bgp_dest_get_prefix(rm
),
6815 bgp_static
, afi
, safi
);
6819 bgp
, bgp_dest_get_prefix(dest
),
6820 bgp_dest_get_bgp_static_info(dest
), afi
,
6824 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6827 /* Called from bgp_delete(). Delete all static routes from the BGP
6829 void bgp_static_delete(struct bgp
*bgp
)
6833 struct bgp_dest
*dest
;
6834 struct bgp_dest
*rm
;
6835 struct bgp_table
*table
;
6836 struct bgp_static
*bgp_static
;
6838 FOREACH_AFI_SAFI (afi
, safi
)
6839 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6840 dest
= bgp_route_next(dest
)) {
6841 if (!bgp_dest_has_bgp_path_info_data(dest
))
6844 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6845 || (safi
== SAFI_EVPN
)) {
6846 table
= bgp_dest_get_bgp_table_info(dest
);
6848 for (rm
= bgp_table_top(table
); rm
;
6849 rm
= bgp_route_next(rm
)) {
6851 bgp_dest_get_bgp_static_info(
6856 bgp_static_withdraw_safi(
6857 bgp
, bgp_dest_get_prefix(rm
),
6859 (struct prefix_rd
*)
6860 bgp_dest_get_prefix(
6862 bgp_static_free(bgp_static
);
6863 bgp_dest_set_bgp_static_info(rm
,
6865 bgp_dest_unlock_node(rm
);
6868 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6869 bgp_static_withdraw(bgp
,
6870 bgp_dest_get_prefix(dest
),
6872 bgp_static_free(bgp_static
);
6873 bgp_dest_set_bgp_static_info(dest
, NULL
);
6874 bgp_dest_unlock_node(dest
);
6879 void bgp_static_redo_import_check(struct bgp
*bgp
)
6883 struct bgp_dest
*dest
;
6884 struct bgp_dest
*rm
;
6885 struct bgp_table
*table
;
6886 struct bgp_static
*bgp_static
;
6888 /* Use this flag to force reprocessing of the route */
6889 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6890 FOREACH_AFI_SAFI (afi
, safi
) {
6891 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6892 dest
= bgp_route_next(dest
)) {
6893 if (!bgp_dest_has_bgp_path_info_data(dest
))
6896 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6897 || (safi
== SAFI_EVPN
)) {
6898 table
= bgp_dest_get_bgp_table_info(dest
);
6900 for (rm
= bgp_table_top(table
); rm
;
6901 rm
= bgp_route_next(rm
)) {
6903 bgp_dest_get_bgp_static_info(
6905 bgp_static_update_safi(
6906 bgp
, bgp_dest_get_prefix(rm
),
6907 bgp_static
, afi
, safi
);
6910 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6911 bgp_static_update(bgp
,
6912 bgp_dest_get_prefix(dest
),
6913 bgp_static
, afi
, safi
);
6917 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6920 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6923 struct bgp_table
*table
;
6924 struct bgp_dest
*dest
;
6925 struct bgp_path_info
*pi
;
6927 /* Do not install the aggregate route if BGP is in the
6928 * process of termination.
6930 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6931 || (bgp
->peer_self
== NULL
))
6934 table
= bgp
->rib
[afi
][safi
];
6935 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6936 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6937 if (pi
->peer
== bgp
->peer_self
6938 && ((pi
->type
== ZEBRA_ROUTE_BGP
6939 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6940 || (pi
->type
!= ZEBRA_ROUTE_BGP
6942 == BGP_ROUTE_REDISTRIBUTE
))) {
6943 bgp_aggregate_decrement(
6944 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6946 bgp_unlink_nexthop(pi
);
6947 bgp_path_info_delete(dest
, pi
);
6948 bgp_process(bgp
, dest
, afi
, safi
);
6955 * Purge all networks and redistributed routes from routing table.
6956 * Invoked upon the instance going down.
6958 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6963 FOREACH_AFI_SAFI (afi
, safi
)
6964 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6969 * Currently this is used to set static routes for VPN and ENCAP.
6970 * I think it can probably be factored with bgp_static_set.
6972 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6973 const char *ip_str
, const char *rd_str
,
6974 const char *label_str
, const char *rmap_str
,
6975 int evpn_type
, const char *esi
, const char *gwip
,
6976 const char *ethtag
, const char *routermac
)
6978 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6981 struct prefix_rd prd
;
6982 struct bgp_dest
*pdest
;
6983 struct bgp_dest
*dest
;
6984 struct bgp_table
*table
;
6985 struct bgp_static
*bgp_static
;
6986 mpls_label_t label
= MPLS_INVALID_LABEL
;
6987 struct prefix gw_ip
;
6989 /* validate ip prefix */
6990 ret
= str2prefix(ip_str
, &p
);
6992 vty_out(vty
, "%% Malformed prefix\n");
6993 return CMD_WARNING_CONFIG_FAILED
;
6996 if ((afi
== AFI_L2VPN
)
6997 && (bgp_build_evpn_prefix(evpn_type
,
6998 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6999 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7000 return CMD_WARNING_CONFIG_FAILED
;
7003 ret
= str2prefix_rd(rd_str
, &prd
);
7005 vty_out(vty
, "%% Malformed rd\n");
7006 return CMD_WARNING_CONFIG_FAILED
;
7010 unsigned long label_val
;
7011 label_val
= strtoul(label_str
, NULL
, 10);
7012 encode_label(label_val
, &label
);
7015 if (safi
== SAFI_EVPN
) {
7016 if (esi
&& str2esi(esi
, NULL
) == 0) {
7017 vty_out(vty
, "%% Malformed ESI\n");
7018 return CMD_WARNING_CONFIG_FAILED
;
7020 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
7021 vty_out(vty
, "%% Malformed Router MAC\n");
7022 return CMD_WARNING_CONFIG_FAILED
;
7025 memset(&gw_ip
, 0, sizeof(gw_ip
));
7026 ret
= str2prefix(gwip
, &gw_ip
);
7028 vty_out(vty
, "%% Malformed GatewayIp\n");
7029 return CMD_WARNING_CONFIG_FAILED
;
7031 if ((gw_ip
.family
== AF_INET
7032 && is_evpn_prefix_ipaddr_v6(
7033 (struct prefix_evpn
*)&p
))
7034 || (gw_ip
.family
== AF_INET6
7035 && is_evpn_prefix_ipaddr_v4(
7036 (struct prefix_evpn
*)&p
))) {
7038 "%% GatewayIp family differs with IP prefix\n");
7039 return CMD_WARNING_CONFIG_FAILED
;
7043 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7044 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7045 bgp_dest_set_bgp_table_info(pdest
,
7046 bgp_table_init(bgp
, afi
, safi
));
7047 table
= bgp_dest_get_bgp_table_info(pdest
);
7049 dest
= bgp_node_get(table
, &p
);
7051 if (bgp_dest_has_bgp_path_info_data(dest
)) {
7052 vty_out(vty
, "%% Same network configuration exists\n");
7053 bgp_dest_unlock_node(dest
);
7055 /* New configuration. */
7056 bgp_static
= bgp_static_new();
7057 bgp_static
->backdoor
= 0;
7058 bgp_static
->valid
= 0;
7059 bgp_static
->igpmetric
= 0;
7060 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7061 bgp_static
->label
= label
;
7062 bgp_static
->prd
= prd
;
7065 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7066 route_map_counter_decrement(bgp_static
->rmap
.map
);
7067 bgp_static
->rmap
.name
=
7068 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7069 bgp_static
->rmap
.map
=
7070 route_map_lookup_by_name(rmap_str
);
7071 route_map_counter_increment(bgp_static
->rmap
.map
);
7074 if (safi
== SAFI_EVPN
) {
7076 bgp_static
->eth_s_id
=
7079 str2esi(esi
, bgp_static
->eth_s_id
);
7082 bgp_static
->router_mac
=
7083 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7084 (void)prefix_str2mac(routermac
,
7085 bgp_static
->router_mac
);
7088 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7090 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7092 bgp_static
->valid
= 1;
7093 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7099 /* Configure static BGP network. */
7100 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7101 const char *ip_str
, const char *rd_str
,
7102 const char *label_str
, int evpn_type
, const char *esi
,
7103 const char *gwip
, const char *ethtag
)
7105 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7108 struct prefix_rd prd
;
7109 struct bgp_dest
*pdest
;
7110 struct bgp_dest
*dest
;
7111 struct bgp_table
*table
;
7112 struct bgp_static
*bgp_static
;
7113 mpls_label_t label
= MPLS_INVALID_LABEL
;
7115 /* Convert IP prefix string to struct prefix. */
7116 ret
= str2prefix(ip_str
, &p
);
7118 vty_out(vty
, "%% Malformed prefix\n");
7119 return CMD_WARNING_CONFIG_FAILED
;
7122 if ((afi
== AFI_L2VPN
)
7123 && (bgp_build_evpn_prefix(evpn_type
,
7124 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7125 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7126 return CMD_WARNING_CONFIG_FAILED
;
7128 ret
= str2prefix_rd(rd_str
, &prd
);
7130 vty_out(vty
, "%% Malformed rd\n");
7131 return CMD_WARNING_CONFIG_FAILED
;
7135 unsigned long label_val
;
7136 label_val
= strtoul(label_str
, NULL
, 10);
7137 encode_label(label_val
, &label
);
7140 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7141 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7142 bgp_dest_set_bgp_table_info(pdest
,
7143 bgp_table_init(bgp
, afi
, safi
));
7145 bgp_dest_unlock_node(pdest
);
7146 table
= bgp_dest_get_bgp_table_info(pdest
);
7148 dest
= bgp_node_lookup(table
, &p
);
7151 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7153 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7154 bgp_static_free(bgp_static
);
7155 bgp_dest_set_bgp_static_info(dest
, NULL
);
7156 bgp_dest_unlock_node(dest
);
7157 bgp_dest_unlock_node(dest
);
7159 vty_out(vty
, "%% Can't find the route\n");
7164 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7165 const char *rmap_name
)
7167 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7168 struct bgp_rmap
*rmap
;
7170 rmap
= &bgp
->table_map
[afi
][safi
];
7172 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7173 route_map_counter_decrement(rmap
->map
);
7174 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7175 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7176 route_map_counter_increment(rmap
->map
);
7178 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7179 route_map_counter_decrement(rmap
->map
);
7183 if (bgp_fibupd_safi(safi
))
7184 bgp_zebra_announce_table(bgp
, afi
, safi
);
7189 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7190 const char *rmap_name
)
7192 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7193 struct bgp_rmap
*rmap
;
7195 rmap
= &bgp
->table_map
[afi
][safi
];
7196 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7197 route_map_counter_decrement(rmap
->map
);
7200 if (bgp_fibupd_safi(safi
))
7201 bgp_zebra_announce_table(bgp
, afi
, safi
);
7206 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7209 if (bgp
->table_map
[afi
][safi
].name
) {
7210 vty_out(vty
, " table-map %s\n",
7211 bgp
->table_map
[afi
][safi
].name
);
7215 DEFUN (bgp_table_map
,
7218 "BGP table to RIB route download filter\n"
7219 "Name of the route map\n")
7222 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7223 argv
[idx_word
]->arg
);
7225 DEFUN (no_bgp_table_map
,
7226 no_bgp_table_map_cmd
,
7227 "no table-map WORD",
7229 "BGP table to RIB route download filter\n"
7230 "Name of the route map\n")
7233 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7234 argv
[idx_word
]->arg
);
7240 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7241 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7242 backdoor$backdoor}]",
7244 "Specify a network to announce via BGP\n"
7249 "Route-map to modify the attributes\n"
7250 "Name of the route map\n"
7251 "Label index to associate with the prefix\n"
7252 "Label index value\n"
7253 "Specify a BGP backdoor route\n")
7255 char addr_prefix_str
[BUFSIZ
];
7260 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7262 sizeof(addr_prefix_str
));
7264 vty_out(vty
, "%% Inconsistent address and mask\n");
7265 return CMD_WARNING_CONFIG_FAILED
;
7269 return bgp_static_set(
7270 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7271 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7272 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7275 DEFPY(ipv6_bgp_network
,
7276 ipv6_bgp_network_cmd
,
7277 "[no] network X:X::X:X/M$prefix \
7278 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7280 "Specify a network to announce via BGP\n"
7282 "Route-map to modify the attributes\n"
7283 "Name of the route map\n"
7284 "Label index to associate with the prefix\n"
7285 "Label index value\n")
7287 return bgp_static_set(
7288 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7289 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7292 static struct bgp_aggregate
*bgp_aggregate_new(void)
7294 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7297 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7299 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7300 route_map_counter_decrement(aggregate
->suppress_map
);
7301 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7302 route_map_counter_decrement(aggregate
->rmap
.map
);
7303 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7307 * Helper function to avoid repeated code: prepare variables for a
7308 * `route_map_apply` call.
7310 * \returns `true` on route map match, otherwise `false`.
7312 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7313 struct bgp_aggregate
*aggregate
,
7314 struct bgp_path_info
*pi
)
7316 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7317 route_map_result_t rmr
= RMAP_DENYMATCH
;
7318 struct bgp_path_info rmap_path
= {};
7319 struct attr attr
= {};
7321 /* No route map entries created, just don't match. */
7322 if (aggregate
->suppress_map
== NULL
)
7325 /* Call route map matching and return result. */
7326 attr
.aspath
= aspath_empty();
7327 rmap_path
.peer
= bgp
->peer_self
;
7328 rmap_path
.attr
= &attr
;
7330 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7331 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7332 bgp
->peer_self
->rmap_type
= 0;
7334 bgp_attr_flush(&attr
);
7335 aspath_unintern(&attr
.aspath
);
7337 return rmr
== RMAP_PERMITMATCH
;
7340 /** Test whether the aggregation has suppressed this path or not. */
7341 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7342 struct bgp_path_info
*pi
)
7344 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7347 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7351 * Suppress this path and keep the reference.
7353 * \returns `true` if needs processing otherwise `false`.
7355 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7356 struct bgp_path_info
*pi
)
7358 struct bgp_path_info_extra
*pie
;
7360 /* Path is already suppressed by this aggregation. */
7361 if (aggr_suppress_exists(aggregate
, pi
))
7364 pie
= bgp_path_info_extra_get(pi
);
7366 /* This is the first suppression, allocate memory and list it. */
7367 if (pie
->aggr_suppressors
== NULL
)
7368 pie
->aggr_suppressors
= list_new();
7370 listnode_add(pie
->aggr_suppressors
, aggregate
);
7372 /* Only mark for processing if suppressed. */
7373 if (listcount(pie
->aggr_suppressors
) == 1) {
7374 if (BGP_DEBUG(update
, UPDATE_OUT
))
7375 zlog_debug("aggregate-address suppressing: %pFX",
7376 bgp_dest_get_prefix(pi
->net
));
7378 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7386 * Unsuppress this path and remove the reference.
7388 * \returns `true` if needs processing otherwise `false`.
7390 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7391 struct bgp_path_info
*pi
)
7393 /* Path wasn't suppressed. */
7394 if (!aggr_suppress_exists(aggregate
, pi
))
7397 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7399 /* Unsuppress and free extra memory if last item. */
7400 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7401 if (BGP_DEBUG(update
, UPDATE_OUT
))
7402 zlog_debug("aggregate-address unsuppressing: %pFX",
7403 bgp_dest_get_prefix(pi
->net
));
7405 list_delete(&pi
->extra
->aggr_suppressors
);
7406 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7413 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7414 struct aspath
*aspath
,
7415 struct community
*comm
,
7416 struct ecommunity
*ecomm
,
7417 struct lcommunity
*lcomm
)
7419 static struct aspath
*ae
= NULL
;
7422 ae
= aspath_empty();
7427 if (origin
!= pi
->attr
->origin
)
7430 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7433 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7436 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7439 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7442 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7448 static void bgp_aggregate_install(
7449 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7450 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7451 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7452 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7454 struct bgp_dest
*dest
;
7455 struct bgp_table
*table
;
7456 struct bgp_path_info
*pi
, *orig
, *new;
7459 table
= bgp
->rib
[afi
][safi
];
7461 dest
= bgp_node_get(table
, p
);
7463 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7464 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7465 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7469 * If we have paths with different MEDs, then don't install
7470 * (or uninstall) the aggregate route.
7472 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7473 goto uninstall_aggregate_route
;
7475 if (aggregate
->count
> 0) {
7477 * If the aggregate information has not changed
7478 * no need to re-install it again.
7480 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7481 ecommunity
, lcommunity
)) {
7482 bgp_dest_unlock_node(dest
);
7485 aspath_free(aspath
);
7487 community_free(&community
);
7489 ecommunity_free(&ecommunity
);
7491 lcommunity_free(&lcommunity
);
7497 * Mark the old as unusable
7500 bgp_path_info_delete(dest
, pi
);
7502 attr
= bgp_attr_aggregate_intern(
7503 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7504 aggregate
, atomic_aggregate
, p
);
7507 bgp_dest_unlock_node(dest
);
7508 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7509 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7510 zlog_debug("%s: %pFX null attribute", __func__
,
7515 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7516 bgp
->peer_self
, attr
, dest
);
7518 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7520 bgp_path_info_add(dest
, new);
7521 bgp_process(bgp
, dest
, afi
, safi
);
7523 uninstall_aggregate_route
:
7524 for (pi
= orig
; pi
; pi
= pi
->next
)
7525 if (pi
->peer
== bgp
->peer_self
7526 && pi
->type
== ZEBRA_ROUTE_BGP
7527 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7530 /* Withdraw static BGP route from routing table. */
7532 bgp_path_info_delete(dest
, pi
);
7533 bgp_process(bgp
, dest
, afi
, safi
);
7537 bgp_dest_unlock_node(dest
);
7541 * Check if the current path has different MED than other known paths.
7543 * \returns `true` if the MED matched the others else `false`.
7545 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7546 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7548 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7550 /* This is the first route being analyzed. */
7551 if (!aggregate
->med_initialized
) {
7552 aggregate
->med_initialized
= true;
7553 aggregate
->med_mismatched
= false;
7554 aggregate
->med_matched_value
= cur_med
;
7556 /* Check if routes with different MED showed up. */
7557 if (cur_med
!= aggregate
->med_matched_value
)
7558 aggregate
->med_mismatched
= true;
7561 return !aggregate
->med_mismatched
;
7565 * Initializes and tests all routes in the aggregate address path for MED
7568 * \returns `true` if all MEDs are the same otherwise `false`.
7570 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7571 struct bgp
*bgp
, const struct prefix
*p
,
7572 afi_t afi
, safi_t safi
)
7574 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7575 const struct prefix
*dest_p
;
7576 struct bgp_dest
*dest
, *top
;
7577 struct bgp_path_info
*pi
;
7578 bool med_matched
= true;
7580 aggregate
->med_initialized
= false;
7582 top
= bgp_node_get(table
, p
);
7583 for (dest
= bgp_node_get(table
, p
); dest
;
7584 dest
= bgp_route_next_until(dest
, top
)) {
7585 dest_p
= bgp_dest_get_prefix(dest
);
7586 if (dest_p
->prefixlen
<= p
->prefixlen
)
7589 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7590 if (BGP_PATH_HOLDDOWN(pi
))
7592 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7594 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7595 med_matched
= false;
7602 bgp_dest_unlock_node(top
);
7608 * Toggles the route suppression status for this aggregate address
7611 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7612 struct bgp
*bgp
, const struct prefix
*p
,
7613 afi_t afi
, safi_t safi
, bool suppress
)
7615 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7616 const struct prefix
*dest_p
;
7617 struct bgp_dest
*dest
, *top
;
7618 struct bgp_path_info
*pi
;
7619 bool toggle_suppression
;
7621 /* We've found a different MED we must revert any suppressed routes. */
7622 top
= bgp_node_get(table
, p
);
7623 for (dest
= bgp_node_get(table
, p
); dest
;
7624 dest
= bgp_route_next_until(dest
, top
)) {
7625 dest_p
= bgp_dest_get_prefix(dest
);
7626 if (dest_p
->prefixlen
<= p
->prefixlen
)
7629 toggle_suppression
= false;
7630 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7631 if (BGP_PATH_HOLDDOWN(pi
))
7633 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7636 /* We are toggling suppression back. */
7638 /* Suppress route if not suppressed already. */
7639 if (aggr_suppress_path(aggregate
, pi
))
7640 toggle_suppression
= true;
7644 /* Install route if there is no more suppression. */
7645 if (aggr_unsuppress_path(aggregate
, pi
))
7646 toggle_suppression
= true;
7649 if (toggle_suppression
)
7650 bgp_process(bgp
, dest
, afi
, safi
);
7652 bgp_dest_unlock_node(top
);
7656 * Aggregate address MED matching incremental test: this function is called
7657 * when the initial aggregation occurred and we are only testing a single
7660 * In addition to testing and setting the MED validity it also installs back
7661 * suppressed routes (if summary is configured).
7663 * Must not be called in `bgp_aggregate_route`.
7665 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7666 struct bgp
*bgp
, const struct prefix
*p
,
7667 afi_t afi
, safi_t safi
,
7668 struct bgp_path_info
*pi
)
7670 /* MED matching disabled. */
7671 if (!aggregate
->match_med
)
7674 /* Aggregation with different MED, recheck if we have got equal MEDs
7677 if (aggregate
->med_mismatched
&&
7678 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7679 aggregate
->summary_only
)
7680 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7683 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7685 /* No mismatches, just quit. */
7686 if (!aggregate
->med_mismatched
)
7689 /* Route summarization is disabled. */
7690 if (!aggregate
->summary_only
)
7693 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7696 /* Update an aggregate as routes are added/removed from the BGP table */
7697 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7698 safi_t safi
, struct bgp_aggregate
*aggregate
)
7700 struct bgp_table
*table
;
7701 struct bgp_dest
*top
;
7702 struct bgp_dest
*dest
;
7704 struct aspath
*aspath
= NULL
;
7705 struct community
*community
= NULL
;
7706 struct ecommunity
*ecommunity
= NULL
;
7707 struct lcommunity
*lcommunity
= NULL
;
7708 struct bgp_path_info
*pi
;
7709 unsigned long match
= 0;
7710 uint8_t atomic_aggregate
= 0;
7712 /* If the bgp instance is being deleted or self peer is deleted
7713 * then do not create aggregate route
7715 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7716 || (bgp
->peer_self
== NULL
))
7719 /* Initialize and test routes for MED difference. */
7720 if (aggregate
->match_med
)
7721 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7724 * Reset aggregate count: we might've been called from route map
7725 * update so in that case we must retest all more specific routes.
7727 * \see `bgp_route_map_process_update`.
7729 aggregate
->count
= 0;
7730 aggregate
->incomplete_origin_count
= 0;
7731 aggregate
->incomplete_origin_count
= 0;
7732 aggregate
->egp_origin_count
= 0;
7734 /* ORIGIN attribute: If at least one route among routes that are
7735 aggregated has ORIGIN with the value INCOMPLETE, then the
7736 aggregated route must have the ORIGIN attribute with the value
7737 INCOMPLETE. Otherwise, if at least one route among routes that
7738 are aggregated has ORIGIN with the value EGP, then the aggregated
7739 route must have the origin attribute with the value EGP. In all
7740 other case the value of the ORIGIN attribute of the aggregated
7741 route is INTERNAL. */
7742 origin
= BGP_ORIGIN_IGP
;
7744 table
= bgp
->rib
[afi
][safi
];
7746 top
= bgp_node_get(table
, p
);
7747 for (dest
= bgp_node_get(table
, p
); dest
;
7748 dest
= bgp_route_next_until(dest
, top
)) {
7749 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7751 if (dest_p
->prefixlen
<= p
->prefixlen
)
7754 /* If suppress fib is enabled and route not installed
7755 * in FIB, skip the route
7757 if (!bgp_check_advertise(bgp
, dest
))
7762 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7763 if (BGP_PATH_HOLDDOWN(pi
))
7767 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7768 atomic_aggregate
= 1;
7770 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7774 * summary-only aggregate route suppress
7775 * aggregated route announcements.
7778 * Don't create summaries if MED didn't match
7779 * otherwise neither the specific routes and the
7780 * aggregation will be announced.
7782 if (aggregate
->summary_only
7783 && AGGREGATE_MED_VALID(aggregate
)) {
7784 if (aggr_suppress_path(aggregate
, pi
))
7789 * Suppress more specific routes that match the route
7793 * Don't suppress routes if MED matching is enabled and
7794 * it mismatched otherwise we might end up with no
7795 * routes for this path.
7797 if (aggregate
->suppress_map_name
7798 && AGGREGATE_MED_VALID(aggregate
)
7799 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7800 if (aggr_suppress_path(aggregate
, pi
))
7807 * If at least one route among routes that are
7808 * aggregated has ORIGIN with the value INCOMPLETE,
7809 * then the aggregated route MUST have the ORIGIN
7810 * attribute with the value INCOMPLETE. Otherwise, if
7811 * at least one route among routes that are aggregated
7812 * has ORIGIN with the value EGP, then the aggregated
7813 * route MUST have the ORIGIN attribute with the value
7816 switch (pi
->attr
->origin
) {
7817 case BGP_ORIGIN_INCOMPLETE
:
7818 aggregate
->incomplete_origin_count
++;
7820 case BGP_ORIGIN_EGP
:
7821 aggregate
->egp_origin_count
++;
7829 if (!aggregate
->as_set
)
7833 * as-set aggregate route generate origin, as path,
7834 * and community aggregation.
7836 /* Compute aggregate route's as-path.
7838 bgp_compute_aggregate_aspath_hash(aggregate
,
7841 /* Compute aggregate route's community.
7843 if (bgp_attr_get_community(pi
->attr
))
7844 bgp_compute_aggregate_community_hash(
7846 bgp_attr_get_community(pi
->attr
));
7848 /* Compute aggregate route's extended community.
7850 if (bgp_attr_get_ecommunity(pi
->attr
))
7851 bgp_compute_aggregate_ecommunity_hash(
7853 bgp_attr_get_ecommunity(pi
->attr
));
7855 /* Compute aggregate route's large community.
7857 if (bgp_attr_get_lcommunity(pi
->attr
))
7858 bgp_compute_aggregate_lcommunity_hash(
7860 bgp_attr_get_lcommunity(pi
->attr
));
7863 bgp_process(bgp
, dest
, afi
, safi
);
7865 if (aggregate
->as_set
) {
7866 bgp_compute_aggregate_aspath_val(aggregate
);
7867 bgp_compute_aggregate_community_val(aggregate
);
7868 bgp_compute_aggregate_ecommunity_val(aggregate
);
7869 bgp_compute_aggregate_lcommunity_val(aggregate
);
7873 bgp_dest_unlock_node(top
);
7876 if (aggregate
->incomplete_origin_count
> 0)
7877 origin
= BGP_ORIGIN_INCOMPLETE
;
7878 else if (aggregate
->egp_origin_count
> 0)
7879 origin
= BGP_ORIGIN_EGP
;
7881 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7882 origin
= aggregate
->origin
;
7884 if (aggregate
->as_set
) {
7885 if (aggregate
->aspath
)
7886 /* Retrieve aggregate route's as-path.
7888 aspath
= aspath_dup(aggregate
->aspath
);
7890 if (aggregate
->community
)
7891 /* Retrieve aggregate route's community.
7893 community
= community_dup(aggregate
->community
);
7895 if (aggregate
->ecommunity
)
7896 /* Retrieve aggregate route's ecommunity.
7898 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7900 if (aggregate
->lcommunity
)
7901 /* Retrieve aggregate route's lcommunity.
7903 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7906 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7907 ecommunity
, lcommunity
, atomic_aggregate
,
7911 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7912 safi_t safi
, struct bgp_aggregate
*aggregate
)
7914 struct bgp_table
*table
;
7915 struct bgp_dest
*top
;
7916 struct bgp_dest
*dest
;
7917 struct bgp_path_info
*pi
;
7918 unsigned long match
;
7920 table
= bgp
->rib
[afi
][safi
];
7922 /* If routes exists below this node, generate aggregate routes. */
7923 top
= bgp_node_get(table
, p
);
7924 for (dest
= bgp_node_get(table
, p
); dest
;
7925 dest
= bgp_route_next_until(dest
, top
)) {
7926 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7928 if (dest_p
->prefixlen
<= p
->prefixlen
)
7932 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7933 if (BGP_PATH_HOLDDOWN(pi
))
7936 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7940 * This route is suppressed: attempt to unsuppress it.
7942 * `aggr_unsuppress_path` will fail if this particular
7943 * aggregate route was not the suppressor.
7945 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7946 listcount(pi
->extra
->aggr_suppressors
)) {
7947 if (aggr_unsuppress_path(aggregate
, pi
))
7953 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7954 aggregate
->incomplete_origin_count
--;
7955 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7956 aggregate
->egp_origin_count
--;
7958 if (aggregate
->as_set
) {
7959 /* Remove as-path from aggregate.
7961 bgp_remove_aspath_from_aggregate_hash(
7965 if (bgp_attr_get_community(pi
->attr
))
7966 /* Remove community from aggregate.
7968 bgp_remove_comm_from_aggregate_hash(
7970 bgp_attr_get_community(
7973 if (bgp_attr_get_ecommunity(pi
->attr
))
7974 /* Remove ecommunity from aggregate.
7976 bgp_remove_ecomm_from_aggregate_hash(
7978 bgp_attr_get_ecommunity(
7981 if (bgp_attr_get_lcommunity(pi
->attr
))
7982 /* Remove lcommunity from aggregate.
7984 bgp_remove_lcomm_from_aggregate_hash(
7986 bgp_attr_get_lcommunity(
7991 /* If this node was suppressed, process the change. */
7993 bgp_process(bgp
, dest
, afi
, safi
);
7995 if (aggregate
->as_set
) {
7996 aspath_free(aggregate
->aspath
);
7997 aggregate
->aspath
= NULL
;
7998 if (aggregate
->community
)
7999 community_free(&aggregate
->community
);
8000 if (aggregate
->ecommunity
)
8001 ecommunity_free(&aggregate
->ecommunity
);
8002 if (aggregate
->lcommunity
)
8003 lcommunity_free(&aggregate
->lcommunity
);
8006 bgp_dest_unlock_node(top
);
8009 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
8010 const struct prefix
*aggr_p
,
8011 struct bgp_path_info
*pinew
, afi_t afi
,
8013 struct bgp_aggregate
*aggregate
)
8016 struct aspath
*aspath
= NULL
;
8017 uint8_t atomic_aggregate
= 0;
8018 struct community
*community
= NULL
;
8019 struct ecommunity
*ecommunity
= NULL
;
8020 struct lcommunity
*lcommunity
= NULL
;
8022 /* If the bgp instance is being deleted or self peer is deleted
8023 * then do not create aggregate route
8025 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8026 || (bgp
->peer_self
== NULL
))
8029 /* ORIGIN attribute: If at least one route among routes that are
8030 * aggregated has ORIGIN with the value INCOMPLETE, then the
8031 * aggregated route must have the ORIGIN attribute with the value
8032 * INCOMPLETE. Otherwise, if at least one route among routes that
8033 * are aggregated has ORIGIN with the value EGP, then the aggregated
8034 * route must have the origin attribute with the value EGP. In all
8035 * other case the value of the ORIGIN attribute of the aggregated
8036 * route is INTERNAL.
8038 origin
= BGP_ORIGIN_IGP
;
8043 * This must be called before `summary` check to avoid
8044 * "suppressing" twice.
8046 if (aggregate
->match_med
)
8047 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8050 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8051 aggr_suppress_path(aggregate
, pinew
);
8053 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8054 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8055 aggr_suppress_path(aggregate
, pinew
);
8057 switch (pinew
->attr
->origin
) {
8058 case BGP_ORIGIN_INCOMPLETE
:
8059 aggregate
->incomplete_origin_count
++;
8061 case BGP_ORIGIN_EGP
:
8062 aggregate
->egp_origin_count
++;
8070 if (aggregate
->incomplete_origin_count
> 0)
8071 origin
= BGP_ORIGIN_INCOMPLETE
;
8072 else if (aggregate
->egp_origin_count
> 0)
8073 origin
= BGP_ORIGIN_EGP
;
8075 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8076 origin
= aggregate
->origin
;
8078 if (aggregate
->as_set
) {
8079 /* Compute aggregate route's as-path.
8081 bgp_compute_aggregate_aspath(aggregate
,
8082 pinew
->attr
->aspath
);
8084 /* Compute aggregate route's community.
8086 if (bgp_attr_get_community(pinew
->attr
))
8087 bgp_compute_aggregate_community(
8088 aggregate
, bgp_attr_get_community(pinew
->attr
));
8090 /* Compute aggregate route's extended community.
8092 if (bgp_attr_get_ecommunity(pinew
->attr
))
8093 bgp_compute_aggregate_ecommunity(
8095 bgp_attr_get_ecommunity(pinew
->attr
));
8097 /* Compute aggregate route's large community.
8099 if (bgp_attr_get_lcommunity(pinew
->attr
))
8100 bgp_compute_aggregate_lcommunity(
8102 bgp_attr_get_lcommunity(pinew
->attr
));
8104 /* Retrieve aggregate route's as-path.
8106 if (aggregate
->aspath
)
8107 aspath
= aspath_dup(aggregate
->aspath
);
8109 /* Retrieve aggregate route's community.
8111 if (aggregate
->community
)
8112 community
= community_dup(aggregate
->community
);
8114 /* Retrieve aggregate route's ecommunity.
8116 if (aggregate
->ecommunity
)
8117 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8119 /* Retrieve aggregate route's lcommunity.
8121 if (aggregate
->lcommunity
)
8122 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8125 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8126 aspath
, community
, ecommunity
,
8127 lcommunity
, atomic_aggregate
, aggregate
);
8130 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8132 struct bgp_path_info
*pi
,
8133 struct bgp_aggregate
*aggregate
,
8134 const struct prefix
*aggr_p
)
8137 struct aspath
*aspath
= NULL
;
8138 uint8_t atomic_aggregate
= 0;
8139 struct community
*community
= NULL
;
8140 struct ecommunity
*ecommunity
= NULL
;
8141 struct lcommunity
*lcommunity
= NULL
;
8142 unsigned long match
= 0;
8144 /* If the bgp instance is being deleted or self peer is deleted
8145 * then do not create aggregate route
8147 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8148 || (bgp
->peer_self
== NULL
))
8151 if (BGP_PATH_HOLDDOWN(pi
))
8154 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8157 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8158 if (aggr_unsuppress_path(aggregate
, pi
))
8161 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8162 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8163 if (aggr_unsuppress_path(aggregate
, pi
))
8167 * This must be called after `summary`, `suppress-map` check to avoid
8168 * "unsuppressing" twice.
8170 if (aggregate
->match_med
)
8171 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8173 if (aggregate
->count
> 0)
8176 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8177 aggregate
->incomplete_origin_count
--;
8178 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8179 aggregate
->egp_origin_count
--;
8181 if (aggregate
->as_set
) {
8182 /* Remove as-path from aggregate.
8184 bgp_remove_aspath_from_aggregate(aggregate
,
8187 if (bgp_attr_get_community(pi
->attr
))
8188 /* Remove community from aggregate.
8190 bgp_remove_community_from_aggregate(
8191 aggregate
, bgp_attr_get_community(pi
->attr
));
8193 if (bgp_attr_get_ecommunity(pi
->attr
))
8194 /* Remove ecommunity from aggregate.
8196 bgp_remove_ecommunity_from_aggregate(
8197 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8199 if (bgp_attr_get_lcommunity(pi
->attr
))
8200 /* Remove lcommunity from aggregate.
8202 bgp_remove_lcommunity_from_aggregate(
8203 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8206 /* If this node was suppressed, process the change. */
8208 bgp_process(bgp
, pi
->net
, afi
, safi
);
8210 origin
= BGP_ORIGIN_IGP
;
8211 if (aggregate
->incomplete_origin_count
> 0)
8212 origin
= BGP_ORIGIN_INCOMPLETE
;
8213 else if (aggregate
->egp_origin_count
> 0)
8214 origin
= BGP_ORIGIN_EGP
;
8216 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8217 origin
= aggregate
->origin
;
8219 if (aggregate
->as_set
) {
8220 /* Retrieve aggregate route's as-path.
8222 if (aggregate
->aspath
)
8223 aspath
= aspath_dup(aggregate
->aspath
);
8225 /* Retrieve aggregate route's community.
8227 if (aggregate
->community
)
8228 community
= community_dup(aggregate
->community
);
8230 /* Retrieve aggregate route's ecommunity.
8232 if (aggregate
->ecommunity
)
8233 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8235 /* Retrieve aggregate route's lcommunity.
8237 if (aggregate
->lcommunity
)
8238 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8241 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8242 aspath
, community
, ecommunity
,
8243 lcommunity
, atomic_aggregate
, aggregate
);
8246 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8247 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8249 struct bgp_dest
*child
;
8250 struct bgp_dest
*dest
;
8251 struct bgp_aggregate
*aggregate
;
8252 struct bgp_table
*table
;
8254 table
= bgp
->aggregate
[afi
][safi
];
8256 /* No aggregates configured. */
8257 if (bgp_table_top_nolock(table
) == NULL
)
8260 if (p
->prefixlen
== 0)
8263 if (BGP_PATH_HOLDDOWN(pi
))
8266 /* If suppress fib is enabled and route not installed
8267 * in FIB, do not update the aggregate route
8269 if (!bgp_check_advertise(bgp
, pi
->net
))
8272 child
= bgp_node_get(table
, p
);
8274 /* Aggregate address configuration check. */
8275 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8276 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8278 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8279 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8280 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8284 bgp_dest_unlock_node(child
);
8287 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8288 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8290 struct bgp_dest
*child
;
8291 struct bgp_dest
*dest
;
8292 struct bgp_aggregate
*aggregate
;
8293 struct bgp_table
*table
;
8295 table
= bgp
->aggregate
[afi
][safi
];
8297 /* No aggregates configured. */
8298 if (bgp_table_top_nolock(table
) == NULL
)
8301 if (p
->prefixlen
== 0)
8304 child
= bgp_node_get(table
, p
);
8306 /* Aggregate address configuration check. */
8307 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8308 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8310 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8311 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8312 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8316 bgp_dest_unlock_node(child
);
8319 /* Aggregate route attribute. */
8320 #define AGGREGATE_SUMMARY_ONLY 1
8321 #define AGGREGATE_AS_SET 1
8322 #define AGGREGATE_AS_UNSET 0
8324 static const char *bgp_origin2str(uint8_t origin
)
8327 case BGP_ORIGIN_IGP
:
8329 case BGP_ORIGIN_EGP
:
8331 case BGP_ORIGIN_INCOMPLETE
:
8332 return "incomplete";
8337 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8340 case RPKI_NOT_BEING_USED
:
8350 assert(!"We should never get here this is a dev escape");
8354 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8355 afi_t afi
, safi_t safi
)
8357 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8360 struct bgp_dest
*dest
;
8361 struct bgp_aggregate
*aggregate
;
8363 /* Convert string to prefix structure. */
8364 ret
= str2prefix(prefix_str
, &p
);
8366 vty_out(vty
, "Malformed prefix\n");
8367 return CMD_WARNING_CONFIG_FAILED
;
8371 /* Old configuration check. */
8372 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8375 "%% There is no aggregate-address configuration.\n");
8376 return CMD_WARNING_CONFIG_FAILED
;
8379 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8380 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8381 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8382 NULL
, NULL
, 0, aggregate
);
8384 /* Unlock aggregate address configuration. */
8385 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8387 if (aggregate
->community
)
8388 community_free(&aggregate
->community
);
8390 if (aggregate
->community_hash
) {
8391 /* Delete all communities in the hash.
8393 hash_clean(aggregate
->community_hash
,
8394 bgp_aggr_community_remove
);
8395 /* Free up the community_hash.
8397 hash_free(aggregate
->community_hash
);
8400 if (aggregate
->ecommunity
)
8401 ecommunity_free(&aggregate
->ecommunity
);
8403 if (aggregate
->ecommunity_hash
) {
8404 /* Delete all ecommunities in the hash.
8406 hash_clean(aggregate
->ecommunity_hash
,
8407 bgp_aggr_ecommunity_remove
);
8408 /* Free up the ecommunity_hash.
8410 hash_free(aggregate
->ecommunity_hash
);
8413 if (aggregate
->lcommunity
)
8414 lcommunity_free(&aggregate
->lcommunity
);
8416 if (aggregate
->lcommunity_hash
) {
8417 /* Delete all lcommunities in the hash.
8419 hash_clean(aggregate
->lcommunity_hash
,
8420 bgp_aggr_lcommunity_remove
);
8421 /* Free up the lcommunity_hash.
8423 hash_free(aggregate
->lcommunity_hash
);
8426 if (aggregate
->aspath
)
8427 aspath_free(aggregate
->aspath
);
8429 if (aggregate
->aspath_hash
) {
8430 /* Delete all as-paths in the hash.
8432 hash_clean(aggregate
->aspath_hash
,
8433 bgp_aggr_aspath_remove
);
8434 /* Free up the aspath_hash.
8436 hash_free(aggregate
->aspath_hash
);
8439 bgp_aggregate_free(aggregate
);
8440 bgp_dest_unlock_node(dest
);
8441 bgp_dest_unlock_node(dest
);
8446 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8447 safi_t safi
, const char *rmap
,
8448 uint8_t summary_only
, uint8_t as_set
,
8449 uint8_t origin
, bool match_med
,
8450 const char *suppress_map
)
8452 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8455 struct bgp_dest
*dest
;
8456 struct bgp_aggregate
*aggregate
;
8457 uint8_t as_set_new
= as_set
;
8459 if (suppress_map
&& summary_only
) {
8461 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8462 return CMD_WARNING_CONFIG_FAILED
;
8465 /* Convert string to prefix structure. */
8466 ret
= str2prefix(prefix_str
, &p
);
8468 vty_out(vty
, "Malformed prefix\n");
8469 return CMD_WARNING_CONFIG_FAILED
;
8473 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8474 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8475 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8477 return CMD_WARNING_CONFIG_FAILED
;
8480 /* Old configuration check. */
8481 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8482 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8485 vty_out(vty
, "There is already same aggregate network.\n");
8486 /* try to remove the old entry */
8487 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8489 vty_out(vty
, "Error deleting aggregate.\n");
8490 bgp_dest_unlock_node(dest
);
8491 return CMD_WARNING_CONFIG_FAILED
;
8495 /* Make aggregate address structure. */
8496 aggregate
= bgp_aggregate_new();
8497 aggregate
->summary_only
= summary_only
;
8498 aggregate
->match_med
= match_med
;
8500 /* Network operators MUST NOT locally generate any new
8501 * announcements containing AS_SET or AS_CONFED_SET. If they have
8502 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8503 * SHOULD withdraw those routes and re-announce routes for the
8504 * aggregate or component prefixes (i.e., the more-specific routes
8505 * subsumed by the previously aggregated route) without AS_SET
8506 * or AS_CONFED_SET in the updates.
8508 if (bgp
->reject_as_sets
) {
8509 if (as_set
== AGGREGATE_AS_SET
) {
8510 as_set_new
= AGGREGATE_AS_UNSET
;
8512 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8515 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8519 aggregate
->as_set
= as_set_new
;
8520 aggregate
->safi
= safi
;
8521 /* Override ORIGIN attribute if defined.
8522 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8523 * to IGP which is not what rfc4271 says.
8524 * This enables the same behavior, optionally.
8526 aggregate
->origin
= origin
;
8529 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8530 route_map_counter_decrement(aggregate
->rmap
.map
);
8531 aggregate
->rmap
.name
=
8532 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8533 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8534 route_map_counter_increment(aggregate
->rmap
.map
);
8538 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8539 route_map_counter_decrement(aggregate
->suppress_map
);
8541 aggregate
->suppress_map_name
=
8542 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8543 aggregate
->suppress_map
=
8544 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8545 route_map_counter_increment(aggregate
->suppress_map
);
8548 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8550 /* Aggregate address insert into BGP routing table. */
8551 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8556 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8557 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8559 "|summary-only$summary_only"
8560 "|route-map RMAP_NAME$rmap_name"
8561 "|origin <egp|igp|incomplete>$origin_s"
8562 "|matching-MED-only$match_med"
8563 "|suppress-map RMAP_NAME$suppress_map"
8566 "Configure BGP aggregate entries\n"
8567 "Aggregate prefix\n"
8568 "Aggregate address\n"
8570 "Generate AS set path information\n"
8571 "Filter more specific routes from updates\n"
8572 "Apply route map to aggregate network\n"
8577 "Unknown heritage\n"
8578 "Only aggregate routes with matching MED\n"
8579 "Suppress the selected more specific routes\n"
8580 "Route map with the route selectors\n")
8582 const char *prefix_s
= NULL
;
8583 safi_t safi
= bgp_node_safi(vty
);
8584 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8585 int as_set
= AGGREGATE_AS_UNSET
;
8586 char prefix_buf
[PREFIX2STR_BUFFER
];
8589 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8592 vty_out(vty
, "%% Inconsistent address and mask\n");
8593 return CMD_WARNING_CONFIG_FAILED
;
8595 prefix_s
= prefix_buf
;
8597 prefix_s
= prefix_str
;
8600 if (strcmp(origin_s
, "egp") == 0)
8601 origin
= BGP_ORIGIN_EGP
;
8602 else if (strcmp(origin_s
, "igp") == 0)
8603 origin
= BGP_ORIGIN_IGP
;
8604 else if (strcmp(origin_s
, "incomplete") == 0)
8605 origin
= BGP_ORIGIN_INCOMPLETE
;
8609 as_set
= AGGREGATE_AS_SET
;
8611 /* Handle configuration removal, otherwise installation. */
8613 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8615 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8616 summary_only
!= NULL
, as_set
, origin
,
8617 match_med
!= NULL
, suppress_map
);
8620 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8621 "[no] aggregate-address X:X::X:X/M$prefix [{"
8623 "|summary-only$summary_only"
8624 "|route-map RMAP_NAME$rmap_name"
8625 "|origin <egp|igp|incomplete>$origin_s"
8626 "|matching-MED-only$match_med"
8627 "|suppress-map RMAP_NAME$suppress_map"
8630 "Configure BGP aggregate entries\n"
8631 "Aggregate prefix\n"
8632 "Generate AS set path information\n"
8633 "Filter more specific routes from updates\n"
8634 "Apply route map to aggregate network\n"
8639 "Unknown heritage\n"
8640 "Only aggregate routes with matching MED\n"
8641 "Suppress the selected more specific routes\n"
8642 "Route map with the route selectors\n")
8644 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8645 int as_set
= AGGREGATE_AS_UNSET
;
8648 if (strcmp(origin_s
, "egp") == 0)
8649 origin
= BGP_ORIGIN_EGP
;
8650 else if (strcmp(origin_s
, "igp") == 0)
8651 origin
= BGP_ORIGIN_IGP
;
8652 else if (strcmp(origin_s
, "incomplete") == 0)
8653 origin
= BGP_ORIGIN_INCOMPLETE
;
8657 as_set
= AGGREGATE_AS_SET
;
8659 /* Handle configuration removal, otherwise installation. */
8661 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8664 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8665 rmap_name
, summary_only
!= NULL
, as_set
,
8666 origin
, match_med
!= NULL
, suppress_map
);
8669 /* Redistribute route treatment. */
8670 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8671 const union g_addr
*nexthop
, ifindex_t ifindex
,
8672 enum nexthop_types_t nhtype
, uint8_t distance
,
8673 enum blackhole_type bhtype
, uint32_t metric
,
8674 uint8_t type
, unsigned short instance
,
8677 struct bgp_path_info
*new;
8678 struct bgp_path_info
*bpi
;
8679 struct bgp_path_info rmap_path
;
8680 struct bgp_dest
*bn
;
8682 struct attr
*new_attr
;
8684 route_map_result_t ret
;
8685 struct bgp_redist
*red
;
8687 /* Make default attribute. */
8688 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8690 * This must not be NULL to satisfy Coverity SA
8692 assert(attr
.aspath
);
8695 case NEXTHOP_TYPE_IFINDEX
:
8696 switch (p
->family
) {
8698 attr
.nexthop
.s_addr
= INADDR_ANY
;
8699 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8702 memset(&attr
.mp_nexthop_global
, 0,
8703 sizeof(attr
.mp_nexthop_global
));
8704 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8708 case NEXTHOP_TYPE_IPV4
:
8709 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8710 attr
.nexthop
= nexthop
->ipv4
;
8711 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8713 case NEXTHOP_TYPE_IPV6
:
8714 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8715 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8716 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8718 case NEXTHOP_TYPE_BLACKHOLE
:
8719 switch (p
->family
) {
8721 attr
.nexthop
.s_addr
= INADDR_ANY
;
8722 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8725 memset(&attr
.mp_nexthop_global
, 0,
8726 sizeof(attr
.mp_nexthop_global
));
8727 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8730 attr
.bh_type
= bhtype
;
8733 attr
.nh_type
= nhtype
;
8734 attr
.nh_ifindex
= ifindex
;
8737 attr
.distance
= distance
;
8738 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8742 bgp_attr_set_aigp_metric(&attr
, metric
);
8744 afi
= family2afi(p
->family
);
8746 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8748 struct attr attr_new
;
8750 /* Copy attribute for modification. */
8753 if (red
->redist_metric_flag
) {
8754 attr_new
.med
= red
->redist_metric
;
8755 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8758 /* Apply route-map. */
8759 if (red
->rmap
.name
) {
8760 memset(&rmap_path
, 0, sizeof(rmap_path
));
8761 rmap_path
.peer
= bgp
->peer_self
;
8762 rmap_path
.attr
= &attr_new
;
8764 SET_FLAG(bgp
->peer_self
->rmap_type
,
8765 PEER_RMAP_TYPE_REDISTRIBUTE
);
8767 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8769 bgp
->peer_self
->rmap_type
= 0;
8771 if (ret
== RMAP_DENYMATCH
) {
8772 /* Free uninterned attribute. */
8773 bgp_attr_flush(&attr_new
);
8775 /* Unintern original. */
8776 aspath_unintern(&attr
.aspath
);
8777 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8782 if (bgp_in_graceful_shutdown(bgp
))
8783 bgp_attr_add_gshut_community(&attr_new
);
8785 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8786 SAFI_UNICAST
, p
, NULL
);
8788 new_attr
= bgp_attr_intern(&attr_new
);
8790 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8791 if (bpi
->peer
== bgp
->peer_self
8792 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8796 /* Ensure the (source route) type is updated. */
8798 if (attrhash_cmp(bpi
->attr
, new_attr
)
8799 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8800 bgp_attr_unintern(&new_attr
);
8801 aspath_unintern(&attr
.aspath
);
8802 bgp_dest_unlock_node(bn
);
8805 /* The attribute is changed. */
8806 bgp_path_info_set_flag(bn
, bpi
,
8807 BGP_PATH_ATTR_CHANGED
);
8809 /* Rewrite BGP route information. */
8810 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8811 bgp_path_info_restore(bn
, bpi
);
8813 bgp_aggregate_decrement(
8814 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8815 bgp_attr_unintern(&bpi
->attr
);
8816 bpi
->attr
= new_attr
;
8817 bpi
->uptime
= monotime(NULL
);
8819 /* Process change. */
8820 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8822 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8823 bgp_dest_unlock_node(bn
);
8824 aspath_unintern(&attr
.aspath
);
8826 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8828 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8830 vpn_leak_from_vrf_update(
8831 bgp_get_default(), bgp
, bpi
);
8837 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8838 bgp
->peer_self
, new_attr
, bn
);
8839 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8841 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8842 bgp_path_info_add(bn
, new);
8843 bgp_dest_unlock_node(bn
);
8844 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8845 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8847 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8848 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8850 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8854 /* Unintern original. */
8855 aspath_unintern(&attr
.aspath
);
8858 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8859 unsigned short instance
)
8862 struct bgp_dest
*dest
;
8863 struct bgp_path_info
*pi
;
8864 struct bgp_redist
*red
;
8866 afi
= family2afi(p
->family
);
8868 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8870 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8871 SAFI_UNICAST
, p
, NULL
);
8873 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8874 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8878 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8879 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8881 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8884 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8885 bgp_path_info_delete(dest
, pi
);
8886 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8888 bgp_dest_unlock_node(dest
);
8892 /* Withdraw specified route type's route. */
8893 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8894 unsigned short instance
)
8896 struct bgp_dest
*dest
;
8897 struct bgp_path_info
*pi
;
8898 struct bgp_table
*table
;
8900 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8902 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8903 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8904 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8905 && pi
->instance
== instance
)
8909 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8910 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8912 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8915 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8916 pi
, afi
, SAFI_UNICAST
);
8917 bgp_path_info_delete(dest
, pi
);
8918 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8923 /* Static function to display route. */
8924 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8925 struct vty
*vty
, json_object
*json
, bool wide
)
8928 char buf
[INET6_ADDRSTRLEN
];
8930 if (p
->family
== AF_INET
) {
8932 len
= vty_out(vty
, "%pFX", p
);
8934 json_object_string_add(json
, "prefix",
8935 inet_ntop(p
->family
,
8938 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8939 json_object_string_addf(json
, "network", "%pFX", p
);
8940 json_object_int_add(json
, "version", dest
->version
);
8942 } else if (p
->family
== AF_ETHERNET
) {
8943 len
= vty_out(vty
, "%pFX", p
);
8944 } else if (p
->family
== AF_EVPN
) {
8946 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8948 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8949 } else if (p
->family
== AF_FLOWSPEC
) {
8950 route_vty_out_flowspec(vty
, p
, NULL
,
8952 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8953 NLRI_STRING_FORMAT_MIN
, json
);
8956 len
= vty_out(vty
, "%pFX", p
);
8958 json_object_string_add(json
, "prefix",
8959 inet_ntop(p
->family
,
8962 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8963 json_object_string_addf(json
, "network", "%pFX", p
);
8964 json_object_int_add(json
, "version", dest
->version
);
8969 len
= wide
? (45 - len
) : (17 - len
);
8971 vty_out(vty
, "\n%*s", 20, " ");
8973 vty_out(vty
, "%*s", len
, " ");
8977 enum bgp_display_type
{
8981 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8984 case bgp_path_selection_none
:
8985 return "Nothing to Select";
8986 case bgp_path_selection_first
:
8987 return "First path received";
8988 case bgp_path_selection_evpn_sticky_mac
:
8989 return "EVPN Sticky Mac";
8990 case bgp_path_selection_evpn_seq
:
8991 return "EVPN sequence number";
8992 case bgp_path_selection_evpn_lower_ip
:
8993 return "EVPN lower IP";
8994 case bgp_path_selection_evpn_local_path
:
8995 return "EVPN local ES path";
8996 case bgp_path_selection_evpn_non_proxy
:
8997 return "EVPN non proxy";
8998 case bgp_path_selection_weight
:
9000 case bgp_path_selection_local_pref
:
9001 return "Local Pref";
9002 case bgp_path_selection_accept_own
:
9003 return "Accept Own";
9004 case bgp_path_selection_local_route
:
9005 return "Local Route";
9006 case bgp_path_selection_aigp
:
9008 case bgp_path_selection_confed_as_path
:
9009 return "Confederation based AS Path";
9010 case bgp_path_selection_as_path
:
9012 case bgp_path_selection_origin
:
9014 case bgp_path_selection_med
:
9016 case bgp_path_selection_peer
:
9018 case bgp_path_selection_confed
:
9019 return "Confed Peer Type";
9020 case bgp_path_selection_igp_metric
:
9021 return "IGP Metric";
9022 case bgp_path_selection_older
:
9023 return "Older Path";
9024 case bgp_path_selection_router_id
:
9026 case bgp_path_selection_cluster_length
:
9027 return "Cluster length";
9028 case bgp_path_selection_stale
:
9029 return "Path Staleness";
9030 case bgp_path_selection_local_configured
:
9031 return "Locally configured route";
9032 case bgp_path_selection_neighbor_ip
:
9033 return "Neighbor IP";
9034 case bgp_path_selection_default
:
9035 return "Nothing left to compare";
9037 return "Invalid (internal error)";
9040 /* Print the short form route status for a bgp_path_info */
9041 static void route_vty_short_status_out(struct vty
*vty
,
9042 struct bgp_path_info
*path
,
9043 const struct prefix
*p
,
9044 json_object
*json_path
)
9046 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
9050 /* Route status display. */
9051 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9052 json_object_boolean_true_add(json_path
, "removed");
9054 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9055 json_object_boolean_true_add(json_path
, "stale");
9057 if (path
->extra
&& bgp_path_suppressed(path
))
9058 json_object_boolean_true_add(json_path
, "suppressed");
9060 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9061 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9062 json_object_boolean_true_add(json_path
, "valid");
9065 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9066 json_object_boolean_true_add(json_path
, "history");
9068 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9069 json_object_boolean_true_add(json_path
, "damped");
9071 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9072 json_object_boolean_true_add(json_path
, "bestpath");
9073 json_object_string_add(json_path
, "selectionReason",
9074 bgp_path_selection_reason2str(
9075 path
->net
->reason
));
9078 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9079 json_object_boolean_true_add(json_path
, "multipath");
9081 /* Internal route. */
9082 if ((path
->peer
->as
)
9083 && (path
->peer
->as
== path
->peer
->local_as
))
9084 json_object_string_add(json_path
, "pathFrom",
9087 json_object_string_add(json_path
, "pathFrom",
9093 /* RPKI validation state */
9095 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9097 if (rpki_state
== RPKI_VALID
)
9099 else if (rpki_state
== RPKI_INVALID
)
9101 else if (rpki_state
== RPKI_NOTFOUND
)
9106 /* Route status display. */
9107 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9109 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9111 else if (bgp_path_suppressed(path
))
9113 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9114 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9120 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9122 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9124 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9126 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9131 /* Internal route. */
9132 if (path
->peer
&& (path
->peer
->as
)
9133 && (path
->peer
->as
== path
->peer
->local_as
))
9139 static char *bgp_nexthop_hostname(struct peer
*peer
,
9140 struct bgp_nexthop_cache
*bnc
)
9143 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9144 return peer
->hostname
;
9148 /* called from terminal list command */
9149 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9150 struct bgp_path_info
*path
, int display
, safi_t safi
,
9151 json_object
*json_paths
, bool wide
)
9154 struct attr
*attr
= path
->attr
;
9155 json_object
*json_path
= NULL
;
9156 json_object
*json_nexthops
= NULL
;
9157 json_object
*json_nexthop_global
= NULL
;
9158 json_object
*json_nexthop_ll
= NULL
;
9159 json_object
*json_ext_community
= NULL
;
9160 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9162 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9163 bool nexthop_othervrf
= false;
9164 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9165 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9166 char *nexthop_hostname
=
9167 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9168 char esi_buf
[ESI_STR_LEN
];
9171 json_path
= json_object_new_object();
9173 /* short status lead text */
9174 route_vty_short_status_out(vty
, path
, p
, json_path
);
9177 /* print prefix and mask */
9179 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9181 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9183 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9187 * If vrf id of nexthop is different from that of prefix,
9188 * set up printable string to append
9190 if (path
->extra
&& path
->extra
->bgp_orig
) {
9191 const char *self
= "";
9196 nexthop_othervrf
= true;
9197 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9199 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9200 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9201 "@%s%s", VRFID_NONE_STR
, self
);
9203 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9204 path
->extra
->bgp_orig
->vrf_id
, self
);
9206 if (path
->extra
->bgp_orig
->inst_type
9207 != BGP_INSTANCE_TYPE_DEFAULT
)
9209 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9211 const char *self
= "";
9216 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9220 * For ENCAP and EVPN routes, nexthop address family is not
9221 * neccessarily the same as the prefix address family.
9222 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9223 * EVPN routes are also exchanged with a MP nexthop. Currently,
9225 * is only IPv4, the value will be present in either
9227 * attr->mp_nexthop_global_in
9229 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9231 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9235 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9236 &attr
->mp_nexthop_global_in
);
9239 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9240 &attr
->mp_nexthop_global
);
9243 snprintf(nexthop
, sizeof(nexthop
), "?");
9248 json_nexthop_global
= json_object_new_object();
9250 json_object_string_add(json_nexthop_global
, "ip",
9253 if (path
->peer
->hostname
)
9254 json_object_string_add(json_nexthop_global
,
9256 path
->peer
->hostname
);
9258 json_object_string_add(json_nexthop_global
, "afi",
9259 (af
== AF_INET
) ? "ipv4"
9261 json_object_boolean_true_add(json_nexthop_global
,
9264 if (nexthop_hostname
)
9265 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9266 nexthop_hostname
, vrf_id_str
);
9268 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9270 len
= wide
? (41 - len
) : (16 - len
);
9272 vty_out(vty
, "\n%*s", 36, " ");
9274 vty_out(vty
, "%*s", len
, " ");
9276 } else if (safi
== SAFI_EVPN
) {
9278 json_nexthop_global
= json_object_new_object();
9280 json_object_string_addf(json_nexthop_global
, "ip",
9282 &attr
->mp_nexthop_global_in
);
9284 if (path
->peer
->hostname
)
9285 json_object_string_add(json_nexthop_global
,
9287 path
->peer
->hostname
);
9289 json_object_string_add(json_nexthop_global
, "afi",
9291 json_object_boolean_true_add(json_nexthop_global
,
9294 if (nexthop_hostname
)
9295 len
= vty_out(vty
, "%pI4(%s)%s",
9296 &attr
->mp_nexthop_global_in
,
9297 nexthop_hostname
, vrf_id_str
);
9299 len
= vty_out(vty
, "%pI4%s",
9300 &attr
->mp_nexthop_global_in
,
9303 len
= wide
? (41 - len
) : (16 - len
);
9305 vty_out(vty
, "\n%*s", 36, " ");
9307 vty_out(vty
, "%*s", len
, " ");
9309 } else if (safi
== SAFI_FLOWSPEC
) {
9310 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9312 json_nexthop_global
= json_object_new_object();
9314 json_object_string_add(json_nexthop_global
,
9316 json_object_string_addf(json_nexthop_global
,
9320 if (path
->peer
->hostname
)
9321 json_object_string_add(
9322 json_nexthop_global
, "hostname",
9323 path
->peer
->hostname
);
9325 json_object_boolean_true_add(
9326 json_nexthop_global
,
9329 if (nexthop_hostname
)
9330 len
= vty_out(vty
, "%pI4(%s)%s",
9335 len
= vty_out(vty
, "%pI4%s",
9339 len
= wide
? (41 - len
) : (16 - len
);
9341 vty_out(vty
, "\n%*s", 36, " ");
9343 vty_out(vty
, "%*s", len
, " ");
9346 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9348 json_nexthop_global
= json_object_new_object();
9350 json_object_string_addf(json_nexthop_global
, "ip",
9351 "%pI4", &attr
->nexthop
);
9353 if (path
->peer
->hostname
)
9354 json_object_string_add(json_nexthop_global
,
9356 path
->peer
->hostname
);
9358 json_object_string_add(json_nexthop_global
, "afi",
9360 json_object_boolean_true_add(json_nexthop_global
,
9363 if (nexthop_hostname
)
9364 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9365 nexthop_hostname
, vrf_id_str
);
9367 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9370 len
= wide
? (41 - len
) : (16 - len
);
9372 vty_out(vty
, "\n%*s", 36, " ");
9374 vty_out(vty
, "%*s", len
, " ");
9379 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9381 json_nexthop_global
= json_object_new_object();
9382 json_object_string_addf(json_nexthop_global
, "ip",
9384 &attr
->mp_nexthop_global
);
9386 if (path
->peer
->hostname
)
9387 json_object_string_add(json_nexthop_global
,
9389 path
->peer
->hostname
);
9391 json_object_string_add(json_nexthop_global
, "afi",
9393 json_object_string_add(json_nexthop_global
, "scope",
9396 /* We display both LL & GL if both have been
9398 if ((attr
->mp_nexthop_len
9399 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9400 || (path
->peer
->conf_if
)) {
9401 json_nexthop_ll
= json_object_new_object();
9402 json_object_string_addf(
9403 json_nexthop_ll
, "ip", "%pI6",
9404 &attr
->mp_nexthop_local
);
9406 if (path
->peer
->hostname
)
9407 json_object_string_add(
9408 json_nexthop_ll
, "hostname",
9409 path
->peer
->hostname
);
9411 json_object_string_add(json_nexthop_ll
, "afi",
9413 json_object_string_add(json_nexthop_ll
, "scope",
9416 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9417 &attr
->mp_nexthop_local
)
9419 && !attr
->mp_nexthop_prefer_global
)
9420 json_object_boolean_true_add(
9421 json_nexthop_ll
, "used");
9423 json_object_boolean_true_add(
9424 json_nexthop_global
, "used");
9426 json_object_boolean_true_add(
9427 json_nexthop_global
, "used");
9429 /* Display LL if LL/Global both in table unless
9430 * prefer-global is set */
9431 if (((attr
->mp_nexthop_len
9432 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9433 && !attr
->mp_nexthop_prefer_global
)
9434 || (path
->peer
->conf_if
)) {
9435 if (path
->peer
->conf_if
) {
9436 len
= vty_out(vty
, "%s",
9437 path
->peer
->conf_if
);
9438 /* len of IPv6 addr + max len of def
9440 len
= wide
? (41 - len
) : (16 - len
);
9443 vty_out(vty
, "\n%*s", 36, " ");
9445 vty_out(vty
, "%*s", len
, " ");
9447 if (nexthop_hostname
)
9450 &attr
->mp_nexthop_local
,
9456 &attr
->mp_nexthop_local
,
9459 len
= wide
? (41 - len
) : (16 - len
);
9462 vty_out(vty
, "\n%*s", 36, " ");
9464 vty_out(vty
, "%*s", len
, " ");
9467 if (nexthop_hostname
)
9468 len
= vty_out(vty
, "%pI6(%s)%s",
9469 &attr
->mp_nexthop_global
,
9473 len
= vty_out(vty
, "%pI6%s",
9474 &attr
->mp_nexthop_global
,
9477 len
= wide
? (41 - len
) : (16 - len
);
9480 vty_out(vty
, "\n%*s", 36, " ");
9482 vty_out(vty
, "%*s", len
, " ");
9488 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9490 json_object_int_add(json_path
, "metric", attr
->med
);
9492 vty_out(vty
, "%7u", attr
->med
);
9494 vty_out(vty
, "%10u", attr
->med
);
9495 else if (!json_paths
) {
9497 vty_out(vty
, "%*s", 7, " ");
9499 vty_out(vty
, "%*s", 10, " ");
9503 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9505 json_object_int_add(json_path
, "locPrf",
9508 vty_out(vty
, "%7u", attr
->local_pref
);
9509 else if (!json_paths
)
9513 json_object_int_add(json_path
, "weight", attr
->weight
);
9515 vty_out(vty
, "%7u ", attr
->weight
);
9518 json_object_string_addf(json_path
, "peerId", "%pSU",
9524 json_object_string_add(json_path
, "path",
9527 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9532 json_object_string_add(json_path
, "origin",
9533 bgp_origin_long_str
[attr
->origin
]);
9535 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9538 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9539 json_object_string_add(json_path
, "esi",
9540 esi_to_str(&attr
->esi
,
9541 esi_buf
, sizeof(esi_buf
)));
9543 if (safi
== SAFI_EVPN
&&
9544 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9545 json_ext_community
= json_object_new_object();
9546 json_object_string_add(
9547 json_ext_community
, "string",
9548 bgp_attr_get_ecommunity(attr
)->str
);
9549 json_object_object_add(json_path
,
9550 "extendedCommunity",
9551 json_ext_community
);
9555 json_object_boolean_true_add(json_path
,
9556 "announceNexthopSelf");
9557 if (nexthop_othervrf
) {
9558 json_object_string_add(json_path
, "nhVrfName",
9561 json_object_int_add(json_path
, "nhVrfId",
9562 ((nexthop_vrfid
== VRF_UNKNOWN
)
9564 : (int)nexthop_vrfid
));
9569 if (json_nexthop_global
|| json_nexthop_ll
) {
9570 json_nexthops
= json_object_new_array();
9572 if (json_nexthop_global
)
9573 json_object_array_add(json_nexthops
,
9574 json_nexthop_global
);
9576 if (json_nexthop_ll
)
9577 json_object_array_add(json_nexthops
,
9580 json_object_object_add(json_path
, "nexthops",
9584 json_object_array_add(json_paths
, json_path
);
9588 if (safi
== SAFI_EVPN
) {
9589 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9590 /* XXX - add these params to the json out */
9591 vty_out(vty
, "%*s", 20, " ");
9592 vty_out(vty
, "ESI:%s",
9593 esi_to_str(&attr
->esi
, esi_buf
,
9599 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9600 vty_out(vty
, "%*s", 20, " ");
9601 vty_out(vty
, "%s\n",
9602 bgp_attr_get_ecommunity(attr
)->str
);
9606 #ifdef ENABLE_BGP_VNC
9607 /* prints an additional line, indented, with VNC info, if
9609 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9610 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9615 /* called from terminal list command */
9616 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9617 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9618 bool use_json
, json_object
*json_ar
, bool wide
)
9620 json_object
*json_status
= NULL
;
9621 json_object
*json_net
= NULL
;
9625 /* Route status display. */
9627 json_status
= json_object_new_object();
9628 json_net
= json_object_new_object();
9635 /* print prefix and mask */
9637 if (safi
== SAFI_EVPN
)
9638 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9639 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9640 json_object_string_add(
9641 json_net
, "addrPrefix",
9642 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9644 json_object_int_add(json_net
, "prefixLen",
9646 json_object_string_addf(json_net
, "network", "%pFX", p
);
9649 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9651 /* Print attribute */
9654 if (p
->family
== AF_INET
&&
9655 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9656 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9657 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9658 json_object_string_addf(
9659 json_net
, "nextHop", "%pI4",
9660 &attr
->mp_nexthop_global_in
);
9662 json_object_string_addf(
9663 json_net
, "nextHop", "%pI4",
9665 } else if (p
->family
== AF_INET6
||
9666 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9667 json_object_string_addf(
9668 json_net
, "nextHopGlobal", "%pI6",
9669 &attr
->mp_nexthop_global
);
9670 } else if (p
->family
== AF_EVPN
&&
9671 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9672 json_object_string_addf(
9673 json_net
, "nextHop", "%pI4",
9674 &attr
->mp_nexthop_global_in
);
9678 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9679 json_object_int_add(json_net
, "metric",
9682 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9683 json_object_int_add(json_net
, "locPrf",
9686 json_object_int_add(json_net
, "weight", attr
->weight
);
9690 json_object_string_add(json_net
, "path",
9694 #if CONFDATE > 20231208
9695 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9697 json_object_string_add(json_net
, "bgpOriginCode",
9698 bgp_origin_str
[attr
->origin
]);
9699 json_object_string_add(
9701 bgp_origin_long_str
[attr
->origin
]);
9703 if (p
->family
== AF_INET
&&
9704 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9705 safi
== SAFI_EVPN
||
9706 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9707 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9708 || safi
== SAFI_EVPN
)
9709 vty_out(vty
, "%-16pI4",
9710 &attr
->mp_nexthop_global_in
);
9712 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9714 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9715 } else if (p
->family
== AF_INET6
||
9716 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9717 len
= vty_out(vty
, "%pI6",
9718 &attr
->mp_nexthop_global
);
9719 len
= wide
? (41 - len
) : (16 - len
);
9721 vty_out(vty
, "\n%*s", 36, " ");
9723 vty_out(vty
, "%*s", len
, " ");
9726 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9728 vty_out(vty
, "%7u", attr
->med
);
9730 vty_out(vty
, "%10u", attr
->med
);
9736 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9737 vty_out(vty
, "%7u", attr
->local_pref
);
9741 vty_out(vty
, "%7u ", attr
->weight
);
9745 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9748 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9752 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9754 #if CONFDATE > 20231208
9755 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9757 json_object_boolean_true_add(json_status
, "*");
9758 json_object_boolean_true_add(json_status
, ">");
9759 json_object_boolean_true_add(json_net
, "valid");
9760 json_object_boolean_true_add(json_net
, "best");
9762 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9763 json_object_boolean_true_add(json_status
, "=");
9764 json_object_boolean_true_add(json_net
, "multipath");
9766 json_object_object_add(json_net
, "appliedStatusSymbols",
9768 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9773 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9774 struct bgp_path_info
*path
, int display
, safi_t safi
,
9777 json_object
*json_out
= NULL
;
9779 mpls_label_t label
= MPLS_INVALID_LABEL
;
9785 json_out
= json_object_new_object();
9787 /* short status lead text */
9788 route_vty_short_status_out(vty
, path
, p
, json_out
);
9790 /* print prefix and mask */
9793 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9795 vty_out(vty
, "%*s", 17, " ");
9798 /* Print attribute */
9800 if (((p
->family
== AF_INET
) &&
9801 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9802 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9803 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9804 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9805 || safi
== SAFI_EVPN
) {
9807 json_object_string_addf(
9808 json_out
, "mpNexthopGlobalIn", "%pI4",
9809 &attr
->mp_nexthop_global_in
);
9811 vty_out(vty
, "%-16pI4",
9812 &attr
->mp_nexthop_global_in
);
9815 json_object_string_addf(json_out
, "nexthop",
9816 "%pI4", &attr
->nexthop
);
9818 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9820 } else if (((p
->family
== AF_INET6
) &&
9821 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9822 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9823 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9826 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9828 json_object_string_addf(
9829 json_out
, "mpNexthopGlobalIn", "%pI6",
9830 &attr
->mp_nexthop_global
);
9834 &attr
->mp_nexthop_global
,
9835 buf_a
, sizeof(buf_a
)));
9836 } else if (attr
->mp_nexthop_len
9837 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9838 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9839 &attr
->mp_nexthop_global
,
9840 &attr
->mp_nexthop_local
);
9842 json_object_string_add(json_out
,
9843 "mpNexthopGlobalLocal",
9846 vty_out(vty
, "%s", buf_a
);
9850 label
= decode_label(&path
->extra
->label
[0]);
9852 if (bgp_is_valid_label(&label
)) {
9854 json_object_int_add(json_out
, "notag", label
);
9855 json_object_array_add(json
, json_out
);
9857 vty_out(vty
, "notag/%d", label
);
9864 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9865 struct bgp_path_info
*path
, int display
,
9866 json_object
*json_paths
)
9869 json_object
*json_path
= NULL
;
9870 json_object
*json_nexthop
= NULL
;
9871 json_object
*json_overlay
= NULL
;
9877 json_path
= json_object_new_object();
9878 json_overlay
= json_object_new_object();
9879 json_nexthop
= json_object_new_object();
9882 /* short status lead text */
9883 route_vty_short_status_out(vty
, path
, p
, json_path
);
9885 /* print prefix and mask */
9887 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9889 vty_out(vty
, "%*s", 17, " ");
9891 /* Print attribute */
9893 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9898 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9900 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9901 &attr
->mp_nexthop_global_in
);
9903 json_object_string_add(json_nexthop
, "afi", "ipv4");
9905 json_object_object_add(json_path
, "nexthop",
9911 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9912 &attr
->mp_nexthop_local
);
9914 json_object_string_addf(json_nexthop
, "ipv6Global",
9916 &attr
->mp_nexthop_global
);
9918 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9920 &attr
->mp_nexthop_local
);
9922 json_object_string_add(json_nexthop
, "afi", "ipv6");
9924 json_object_object_add(json_path
, "nexthop",
9932 json_object_string_add(json_nexthop
, "Error",
9933 "Unsupported address-family");
9934 json_object_string_add(json_nexthop
, "error",
9935 "Unsupported address-family");
9939 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9942 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9944 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9946 if (bgp_attr_get_ecommunity(attr
)) {
9948 struct ecommunity_val
*routermac
= ecommunity_lookup(
9949 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9950 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9953 mac
= ecom_mac2str((char *)routermac
->val
);
9956 vty_out(vty
, "/%s", mac
);
9958 json_object_string_add(json_overlay
, "rmac",
9961 XFREE(MTYPE_TMP
, mac
);
9968 json_object_object_add(json_path
, "overlay", json_overlay
);
9970 json_object_array_add(json_paths
, json_path
);
9974 /* dampening route */
9975 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9976 struct bgp_path_info
*path
, int display
,
9977 afi_t afi
, safi_t safi
, bool use_json
,
9978 json_object
*json_paths
)
9980 struct attr
*attr
= path
->attr
;
9982 char timebuf
[BGP_UPTIME_LEN
];
9983 json_object
*json_path
= NULL
;
9986 json_path
= json_object_new_object();
9988 /* short status lead text */
9989 route_vty_short_status_out(vty
, path
, p
, json_path
);
9991 /* print prefix and mask */
9994 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9996 vty_out(vty
, "%*s", 17, " ");
9998 len
= vty_out(vty
, "%s", path
->peer
->host
);
10002 vty_out(vty
, "\n%*s", 34, " ");
10004 vty_out(vty
, "%*s", len
, " ");
10006 vty_out(vty
, "%s ",
10007 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10008 BGP_UPTIME_LEN
, afi
, safi
,
10012 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
10014 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10016 vty_out(vty
, "\n");
10018 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
10019 safi
, use_json
, json_path
);
10022 json_object_string_add(json_path
, "asPath",
10023 attr
->aspath
->str
);
10025 json_object_string_add(json_path
, "origin",
10026 bgp_origin_str
[attr
->origin
]);
10027 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10029 json_object_array_add(json_paths
, json_path
);
10034 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
10035 struct bgp_path_info
*path
, int display
,
10036 afi_t afi
, safi_t safi
, bool use_json
,
10037 json_object
*json_paths
)
10039 struct attr
*attr
= path
->attr
;
10040 struct bgp_damp_info
*bdi
;
10041 char timebuf
[BGP_UPTIME_LEN
];
10043 json_object
*json_path
= NULL
;
10049 json_path
= json_object_new_object();
10051 bdi
= path
->extra
->damp_info
;
10053 /* short status lead text */
10054 route_vty_short_status_out(vty
, path
, p
, json_path
);
10058 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10060 vty_out(vty
, "%*s", 17, " ");
10062 len
= vty_out(vty
, "%s", path
->peer
->host
);
10065 vty_out(vty
, "\n%*s", 33, " ");
10067 vty_out(vty
, "%*s", len
, " ");
10069 len
= vty_out(vty
, "%d", bdi
->flap
);
10074 vty_out(vty
, "%*s", len
, " ");
10076 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10077 BGP_UPTIME_LEN
, 0, NULL
));
10079 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10080 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10081 vty_out(vty
, "%s ",
10082 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10083 BGP_UPTIME_LEN
, afi
,
10084 safi
, use_json
, NULL
));
10086 vty_out(vty
, "%*s ", 8, " ");
10089 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
10091 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10093 vty_out(vty
, "\n");
10095 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10096 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10098 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10101 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10102 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10103 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10104 BGP_UPTIME_LEN
, afi
, safi
,
10105 use_json
, json_path
);
10108 json_object_string_add(json_path
, "asPath",
10109 attr
->aspath
->str
);
10111 json_object_string_add(json_path
, "origin",
10112 bgp_origin_str
[attr
->origin
]);
10114 json_object_array_add(json_paths
, json_path
);
10118 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10119 int *first
, const char *header
,
10120 json_object
*json_adv_to
)
10122 json_object
*json_peer
= NULL
;
10125 /* 'advertised-to' is a dictionary of peers we have advertised
10127 * prefix too. The key is the peer's IP or swpX, the value is
10129 * hostname if we know it and "" if not.
10131 json_peer
= json_object_new_object();
10133 if (peer
->hostname
)
10134 json_object_string_add(json_peer
, "hostname",
10138 json_object_object_add(json_adv_to
, peer
->conf_if
,
10141 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10145 vty_out(vty
, "%s", header
);
10150 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10152 vty_out(vty
, " %s(%s)", peer
->hostname
,
10155 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10159 vty_out(vty
, " %s", peer
->conf_if
);
10161 vty_out(vty
, " %pSU", &peer
->su
);
10166 static void route_vty_out_tx_ids(struct vty
*vty
,
10167 struct bgp_addpath_info_data
*d
)
10171 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10172 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10173 d
->addpath_tx_id
[i
],
10174 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10178 static void route_vty_out_detail_es_info(struct vty
*vty
,
10179 struct bgp_path_info
*pi
,
10181 json_object
*json_path
)
10183 char esi_buf
[ESI_STR_LEN
];
10184 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10185 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10186 ATTR_ES_PEER_ROUTER
);
10187 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10188 ATTR_ES_PEER_ACTIVE
);
10189 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10190 ATTR_ES_PEER_PROXY
);
10191 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10193 json_object
*json_es_info
= NULL
;
10195 json_object_string_add(
10198 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10199 json_es_info
= json_object_new_object();
10201 json_object_boolean_true_add(
10202 json_es_info
, "localEs");
10204 json_object_boolean_true_add(
10205 json_es_info
, "peerActive");
10207 json_object_boolean_true_add(
10208 json_es_info
, "peerProxy");
10210 json_object_boolean_true_add(
10211 json_es_info
, "peerRouter");
10212 if (attr
->mm_sync_seqnum
)
10213 json_object_int_add(
10214 json_es_info
, "peerSeq",
10215 attr
->mm_sync_seqnum
);
10216 json_object_object_add(
10217 json_path
, "es_info",
10221 if (bgp_evpn_attr_is_sync(attr
))
10223 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10225 es_local
? "local-es":"",
10226 peer_proxy
? "proxy " : "",
10227 peer_active
? "active ":"",
10228 peer_router
? "router ":"",
10229 attr
->mm_sync_seqnum
);
10231 vty_out(vty
, " ESI %s %s\n",
10233 es_local
? "local-es":"");
10237 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10238 const struct prefix
*p
, struct bgp_path_info
*path
,
10239 afi_t afi
, safi_t safi
,
10240 enum rpki_states rpki_curr_state
,
10241 json_object
*json_paths
)
10243 char buf
[INET6_ADDRSTRLEN
];
10245 struct attr
*attr
= path
->attr
;
10247 json_object
*json_bestpath
= NULL
;
10248 json_object
*json_cluster_list
= NULL
;
10249 json_object
*json_cluster_list_list
= NULL
;
10250 json_object
*json_ext_community
= NULL
;
10251 json_object
*json_last_update
= NULL
;
10252 json_object
*json_pmsi
= NULL
;
10253 json_object
*json_nexthop_global
= NULL
;
10254 json_object
*json_nexthop_ll
= NULL
;
10255 json_object
*json_nexthops
= NULL
;
10256 json_object
*json_path
= NULL
;
10257 json_object
*json_peer
= NULL
;
10258 json_object
*json_string
= NULL
;
10259 json_object
*json_adv_to
= NULL
;
10261 struct listnode
*node
, *nnode
;
10263 bool addpath_capable
;
10265 unsigned int first_as
;
10266 bool nexthop_self
=
10267 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10269 char *nexthop_hostname
=
10270 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10274 mpls_label_t label
= MPLS_INVALID_LABEL
;
10276 struct bgp_path_info
*bpi_ultimate
=
10277 bgp_get_imported_bpi_ultimate(path
);
10280 json_path
= json_object_new_object();
10281 json_peer
= json_object_new_object();
10282 json_nexthop_global
= json_object_new_object();
10285 if (safi
== SAFI_EVPN
) {
10287 vty_out(vty
, " Route %pFX", p
);
10291 if (path
->extra
&& path
->extra
->num_labels
) {
10292 bgp_evpn_label2str(path
->extra
->label
,
10293 path
->extra
->num_labels
, tag_buf
,
10296 if (safi
== SAFI_EVPN
) {
10298 if (tag_buf
[0] != '\0')
10299 vty_out(vty
, " VNI %s", tag_buf
);
10302 json_object_string_add(json_path
, "VNI",
10304 json_object_string_add(json_path
, "vni",
10311 if (safi
== SAFI_EVPN
10312 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10313 char gwip_buf
[INET6_ADDRSTRLEN
];
10315 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10319 json_object_string_add(json_path
, "gatewayIP",
10322 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10325 if (safi
== SAFI_EVPN
&& !json_path
)
10326 vty_out(vty
, "\n");
10329 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10330 struct bgp_path_info
*parent_ri
;
10331 struct bgp_dest
*dest
, *pdest
;
10333 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10334 dest
= parent_ri
->net
;
10335 if (dest
&& dest
->pdest
) {
10336 pdest
= dest
->pdest
;
10337 if (is_pi_family_evpn(parent_ri
)) {
10339 " Imported from %pRD:%pFX, VNI %s",
10340 (struct prefix_rd
*)bgp_dest_get_prefix(
10342 (struct prefix_evpn
*)
10343 bgp_dest_get_prefix(dest
),
10345 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10346 vty_out(vty
, ", L3NHG %s",
10349 ATTR_ES_L3_NHG_ACTIVE
)
10352 vty_out(vty
, "\n");
10355 vty_out(vty
, " Imported from %pRD:%pFX\n",
10356 (struct prefix_rd
*)bgp_dest_get_prefix(
10358 (struct prefix_evpn
*)
10359 bgp_dest_get_prefix(dest
));
10363 /* Line1 display AS-path, Aggregator */
10364 if (attr
->aspath
) {
10366 if (!attr
->aspath
->json
)
10367 aspath_str_update(attr
->aspath
, true);
10368 json_object_lock(attr
->aspath
->json
);
10369 json_object_object_add(json_path
, "aspath",
10370 attr
->aspath
->json
);
10372 if (attr
->aspath
->segments
)
10373 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
10375 vty_out(vty
, " Local");
10379 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10381 json_object_boolean_true_add(json_path
, "removed");
10383 vty_out(vty
, ", (removed)");
10386 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10388 json_object_boolean_true_add(json_path
, "stale");
10390 vty_out(vty
, ", (stale)");
10393 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10395 json_object_int_add(json_path
, "aggregatorAs",
10396 attr
->aggregator_as
);
10397 json_object_string_addf(json_path
, "aggregatorId",
10398 "%pI4", &attr
->aggregator_addr
);
10400 vty_out(vty
, ", (aggregated by %u %pI4)",
10401 attr
->aggregator_as
, &attr
->aggregator_addr
);
10405 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10406 PEER_FLAG_REFLECTOR_CLIENT
)) {
10408 json_object_boolean_true_add(json_path
,
10409 "rxedFromRrClient");
10411 vty_out(vty
, ", (Received from a RR-client)");
10414 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10415 PEER_FLAG_RSERVER_CLIENT
)) {
10417 json_object_boolean_true_add(json_path
,
10418 "rxedFromRsClient");
10420 vty_out(vty
, ", (Received from a RS-client)");
10423 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10425 json_object_boolean_true_add(json_path
,
10426 "dampeningHistoryEntry");
10428 vty_out(vty
, ", (history entry)");
10429 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10431 json_object_boolean_true_add(json_path
,
10432 "dampeningSuppressed");
10434 vty_out(vty
, ", (suppressed due to dampening)");
10438 vty_out(vty
, "\n");
10440 /* Line2 display Next-hop, Neighbor, Router-id */
10441 /* Display the nexthop */
10443 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10444 p
->family
== AF_EVPN
) &&
10445 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10446 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10447 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10448 || safi
== SAFI_EVPN
) {
10450 json_object_string_addf(
10451 json_nexthop_global
, "ip", "%pI4",
10452 &attr
->mp_nexthop_global_in
);
10454 if (path
->peer
->hostname
)
10455 json_object_string_add(
10456 json_nexthop_global
, "hostname",
10457 path
->peer
->hostname
);
10459 if (nexthop_hostname
)
10460 vty_out(vty
, " %pI4(%s)",
10461 &attr
->mp_nexthop_global_in
,
10464 vty_out(vty
, " %pI4",
10465 &attr
->mp_nexthop_global_in
);
10469 json_object_string_addf(json_nexthop_global
,
10473 if (path
->peer
->hostname
)
10474 json_object_string_add(
10475 json_nexthop_global
, "hostname",
10476 path
->peer
->hostname
);
10478 if (nexthop_hostname
)
10479 vty_out(vty
, " %pI4(%s)",
10483 vty_out(vty
, " %pI4",
10489 json_object_string_add(json_nexthop_global
, "afi",
10493 json_object_string_addf(json_nexthop_global
, "ip",
10495 &attr
->mp_nexthop_global
);
10497 if (path
->peer
->hostname
)
10498 json_object_string_add(json_nexthop_global
,
10500 path
->peer
->hostname
);
10502 json_object_string_add(json_nexthop_global
, "afi",
10504 json_object_string_add(json_nexthop_global
, "scope",
10507 if (nexthop_hostname
)
10508 vty_out(vty
, " %pI6(%s)",
10509 &attr
->mp_nexthop_global
,
10512 vty_out(vty
, " %pI6",
10513 &attr
->mp_nexthop_global
);
10517 /* Display the IGP cost or 'inaccessible' */
10518 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10519 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10522 json_object_boolean_false_add(json_nexthop_global
,
10524 json_object_boolean_add(json_nexthop_global
,
10525 "importCheckEnabled", import
);
10527 vty_out(vty
, " (inaccessible%s)",
10528 import
? ", import-check enabled" : "");
10531 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10533 json_object_int_add(
10534 json_nexthop_global
, "metric",
10535 bpi_ultimate
->extra
->igpmetric
);
10537 vty_out(vty
, " (metric %u)",
10538 bpi_ultimate
->extra
->igpmetric
);
10541 /* IGP cost is 0, display this only for json */
10544 json_object_int_add(json_nexthop_global
,
10549 json_object_boolean_true_add(json_nexthop_global
,
10553 /* Display peer "from" output */
10554 /* This path was originated locally */
10555 if (path
->peer
== bgp
->peer_self
) {
10557 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10558 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10560 json_object_string_add(json_peer
, "peerId",
10563 vty_out(vty
, " from 0.0.0.0 ");
10566 json_object_string_add(json_peer
, "peerId",
10569 vty_out(vty
, " from :: ");
10573 json_object_string_addf(json_peer
, "routerId", "%pI4",
10576 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10579 /* We RXed this path from one of our peers */
10583 json_object_string_addf(json_peer
, "peerId", "%pSU",
10585 json_object_string_addf(json_peer
, "routerId", "%pI4",
10586 &path
->peer
->remote_id
);
10588 if (path
->peer
->hostname
)
10589 json_object_string_add(json_peer
, "hostname",
10590 path
->peer
->hostname
);
10592 if (path
->peer
->domainname
)
10593 json_object_string_add(json_peer
, "domainname",
10594 path
->peer
->domainname
);
10596 if (path
->peer
->conf_if
)
10597 json_object_string_add(json_peer
, "interface",
10598 path
->peer
->conf_if
);
10600 if (path
->peer
->conf_if
) {
10601 if (path
->peer
->hostname
10602 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10603 BGP_FLAG_SHOW_HOSTNAME
))
10604 vty_out(vty
, " from %s(%s)",
10605 path
->peer
->hostname
,
10606 path
->peer
->conf_if
);
10608 vty_out(vty
, " from %s",
10609 path
->peer
->conf_if
);
10611 if (path
->peer
->hostname
10612 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10613 BGP_FLAG_SHOW_HOSTNAME
))
10614 vty_out(vty
, " from %s(%s)",
10615 path
->peer
->hostname
,
10618 vty_out(vty
, " from %pSU",
10622 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10623 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10625 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10630 * Note when vrfid of nexthop is different from that of prefix
10632 if (path
->extra
&& path
->extra
->bgp_orig
) {
10633 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10638 if (path
->extra
->bgp_orig
->inst_type
10639 == BGP_INSTANCE_TYPE_DEFAULT
)
10640 vn
= VRF_DEFAULT_NAME
;
10642 vn
= path
->extra
->bgp_orig
->name
;
10644 json_object_string_add(json_path
, "nhVrfName", vn
);
10646 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10647 json_object_int_add(json_path
, "nhVrfId", -1);
10649 json_object_int_add(json_path
, "nhVrfId",
10650 (int)nexthop_vrfid
);
10653 if (nexthop_vrfid
== VRF_UNKNOWN
)
10654 vty_out(vty
, " vrf ?");
10658 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10659 vty_out(vty
, " vrf %s(%u)",
10660 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10665 if (nexthop_self
) {
10667 json_object_boolean_true_add(json_path
,
10668 "announceNexthopSelf");
10670 vty_out(vty
, " announce-nh-self");
10675 vty_out(vty
, "\n");
10677 /* display the link-local nexthop */
10678 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10680 json_nexthop_ll
= json_object_new_object();
10681 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10682 &attr
->mp_nexthop_local
);
10684 if (path
->peer
->hostname
)
10685 json_object_string_add(json_nexthop_ll
,
10687 path
->peer
->hostname
);
10689 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10690 json_object_string_add(json_nexthop_ll
, "scope",
10693 json_object_boolean_true_add(json_nexthop_ll
,
10696 if (!attr
->mp_nexthop_prefer_global
)
10697 json_object_boolean_true_add(json_nexthop_ll
,
10700 json_object_boolean_true_add(
10701 json_nexthop_global
, "used");
10703 vty_out(vty
, " (%s) %s\n",
10704 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10705 buf
, INET6_ADDRSTRLEN
),
10706 attr
->mp_nexthop_prefer_global
10707 ? "(prefer-global)"
10711 /* If we do not have a link-local nexthop then we must flag the
10712 global as "used" */
10715 json_object_boolean_true_add(json_nexthop_global
,
10719 if (safi
== SAFI_EVPN
&&
10720 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10721 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10724 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10725 * Int/Ext/Local, Atomic, best */
10727 json_object_string_add(json_path
, "origin",
10728 bgp_origin_long_str
[attr
->origin
]);
10730 vty_out(vty
, " Origin %s",
10731 bgp_origin_long_str
[attr
->origin
]);
10733 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10735 json_object_int_add(json_path
, "metric", attr
->med
);
10737 vty_out(vty
, ", metric %u", attr
->med
);
10740 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10742 json_object_int_add(json_path
, "locPrf",
10745 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10748 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10750 json_object_int_add(json_path
, "aigpMetric",
10751 bgp_attr_get_aigp_metric(attr
));
10753 vty_out(vty
, ", aigp-metric %" PRIu64
,
10754 bgp_attr_get_aigp_metric(attr
));
10757 if (attr
->weight
!= 0) {
10759 json_object_int_add(json_path
, "weight", attr
->weight
);
10761 vty_out(vty
, ", weight %u", attr
->weight
);
10764 if (attr
->tag
!= 0) {
10766 json_object_int_add(json_path
, "tag", attr
->tag
);
10768 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10771 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10773 json_object_boolean_false_add(json_path
, "valid");
10775 vty_out(vty
, ", invalid");
10776 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10778 json_object_boolean_true_add(json_path
, "valid");
10780 vty_out(vty
, ", valid");
10784 json_object_int_add(json_path
, "version", bn
->version
);
10786 if (path
->peer
!= bgp
->peer_self
) {
10787 if (path
->peer
->as
== path
->peer
->local_as
) {
10788 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10790 json_object_string_add(
10792 "confed-internal");
10794 vty_out(vty
, ", confed-internal");
10797 json_object_string_add(
10798 json_peer
, "type", "internal");
10800 vty_out(vty
, ", internal");
10803 if (bgp_confederation_peers_check(bgp
,
10806 json_object_string_add(
10808 "confed-external");
10810 vty_out(vty
, ", confed-external");
10813 json_object_string_add(
10814 json_peer
, "type", "external");
10816 vty_out(vty
, ", external");
10819 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10821 json_object_boolean_true_add(json_path
, "aggregated");
10822 json_object_boolean_true_add(json_path
, "local");
10824 vty_out(vty
, ", aggregated, local");
10826 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10828 json_object_boolean_true_add(json_path
, "sourced");
10830 vty_out(vty
, ", sourced");
10833 json_object_boolean_true_add(json_path
, "sourced");
10834 json_object_boolean_true_add(json_path
, "local");
10836 vty_out(vty
, ", sourced, local");
10840 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10842 json_object_boolean_true_add(json_path
,
10843 "atomicAggregate");
10845 vty_out(vty
, ", atomic-aggregate");
10848 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10850 json_object_int_add(json_path
, "otc", attr
->otc
);
10852 vty_out(vty
, ", otc %u", attr
->otc
);
10855 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10856 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10857 && bgp_path_info_mpath_count(path
))) {
10859 json_object_boolean_true_add(json_path
, "multipath");
10861 vty_out(vty
, ", multipath");
10864 // Mark the bestpath(s)
10865 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10866 first_as
= aspath_get_first_as(attr
->aspath
);
10869 if (!json_bestpath
)
10870 json_bestpath
= json_object_new_object();
10871 json_object_int_add(json_bestpath
, "bestpathFromAs",
10875 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10877 vty_out(vty
, ", bestpath-from-AS Local");
10881 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10883 if (!json_bestpath
)
10884 json_bestpath
= json_object_new_object();
10885 json_object_boolean_true_add(json_bestpath
, "overall");
10886 json_object_string_add(
10887 json_bestpath
, "selectionReason",
10888 bgp_path_selection_reason2str(bn
->reason
));
10890 vty_out(vty
, ", best");
10891 vty_out(vty
, " (%s)",
10892 bgp_path_selection_reason2str(bn
->reason
));
10896 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10898 json_object_string_add(
10899 json_path
, "rpkiValidationState",
10900 bgp_rpki_validation2str(rpki_curr_state
));
10902 vty_out(vty
, ", rpki validation-state: %s",
10903 bgp_rpki_validation2str(rpki_curr_state
));
10907 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10910 vty_out(vty
, "\n");
10912 /* Line 4 display Community */
10913 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10915 if (!bgp_attr_get_community(attr
)->json
)
10916 community_str(bgp_attr_get_community(attr
),
10918 json_object_lock(bgp_attr_get_community(attr
)->json
);
10919 json_object_object_add(
10920 json_path
, "community",
10921 bgp_attr_get_community(attr
)->json
);
10923 vty_out(vty
, " Community: %s\n",
10924 bgp_attr_get_community(attr
)->str
);
10928 /* Line 5 display Extended-community */
10929 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10931 json_ext_community
= json_object_new_object();
10932 json_object_string_add(
10933 json_ext_community
, "string",
10934 bgp_attr_get_ecommunity(attr
)->str
);
10935 json_object_object_add(json_path
, "extendedCommunity",
10936 json_ext_community
);
10938 vty_out(vty
, " Extended Community: %s\n",
10939 bgp_attr_get_ecommunity(attr
)->str
);
10943 /* Line 6 display Large community */
10944 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10946 if (!bgp_attr_get_lcommunity(attr
)->json
)
10947 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10949 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10950 json_object_object_add(
10951 json_path
, "largeCommunity",
10952 bgp_attr_get_lcommunity(attr
)->json
);
10954 vty_out(vty
, " Large Community: %s\n",
10955 bgp_attr_get_lcommunity(attr
)->str
);
10959 /* Line 7 display Originator, Cluster-id */
10960 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10961 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10962 char buf
[BUFSIZ
] = {0};
10964 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10966 json_object_string_addf(json_path
,
10967 "originatorId", "%pI4",
10968 &attr
->originator_id
);
10970 vty_out(vty
, " Originator: %pI4",
10971 &attr
->originator_id
);
10974 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10975 struct cluster_list
*cluster
=
10976 bgp_attr_get_cluster(attr
);
10980 json_cluster_list
= json_object_new_object();
10981 json_cluster_list_list
=
10982 json_object_new_array();
10984 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10985 json_string
= json_object_new_string(
10988 buf
, sizeof(buf
)));
10989 json_object_array_add(
10990 json_cluster_list_list
,
10995 * struct cluster_list does not have
10996 * "str" variable like aspath and community
10997 * do. Add this someday if someone asks
10999 * json_object_string_add(json_cluster_list,
11000 * "string", cluster->str);
11002 json_object_object_add(json_cluster_list
,
11004 json_cluster_list_list
);
11005 json_object_object_add(json_path
, "clusterList",
11006 json_cluster_list
);
11008 vty_out(vty
, ", Cluster list: ");
11010 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
11011 vty_out(vty
, "%pI4 ",
11012 &cluster
->list
[i
]);
11018 vty_out(vty
, "\n");
11021 if (path
->extra
&& path
->extra
->damp_info
)
11022 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
11025 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
11026 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
11027 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
11031 json_object_int_add(json_path
, "remoteLabel", label
);
11033 vty_out(vty
, " Remote label: %d\n", label
);
11037 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
11039 json_object_string_addf(json_path
, "remoteSid", "%pI6",
11040 &path
->extra
->sid
[0].sid
);
11042 vty_out(vty
, " Remote SID: %pI6\n",
11043 &path
->extra
->sid
[0].sid
);
11047 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
11049 json_object_int_add(json_path
, "labelIndex",
11050 attr
->label_index
);
11052 vty_out(vty
, " Label Index: %d\n",
11053 attr
->label_index
);
11056 /* Line 8 display Addpath IDs */
11057 if (path
->addpath_rx_id
11058 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11060 json_object_int_add(json_path
, "addpathRxId",
11061 path
->addpath_rx_id
);
11063 /* Keep backwards compatibility with the old API
11064 * by putting TX All's ID in the old field
11066 json_object_int_add(
11067 json_path
, "addpathTxId",
11069 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11071 /* ... but create a specific field for each
11074 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11075 json_object_int_add(
11077 bgp_addpath_names(i
)->id_json_name
,
11078 path
->tx_addpath
.addpath_tx_id
[i
]);
11081 vty_out(vty
, " AddPath ID: RX %u, ",
11082 path
->addpath_rx_id
);
11084 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11088 /* If we used addpath to TX a non-bestpath we need to display
11089 * "Advertised to" on a path-by-path basis
11091 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11094 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11096 bgp_addpath_encode_tx(peer
, afi
, safi
);
11097 has_adj
= bgp_adj_out_lookup(
11099 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11100 &path
->tx_addpath
));
11102 if ((addpath_capable
&& has_adj
)
11103 || (!addpath_capable
&& has_adj
11104 && CHECK_FLAG(path
->flags
,
11105 BGP_PATH_SELECTED
))) {
11106 if (json_path
&& !json_adv_to
)
11107 json_adv_to
= json_object_new_object();
11109 route_vty_out_advertised_to(
11111 " Advertised to:", json_adv_to
);
11117 json_object_object_add(
11118 json_path
, "advertisedTo", json_adv_to
);
11122 vty_out(vty
, "\n");
11127 /* Line 9 display Uptime */
11128 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11130 json_last_update
= json_object_new_object();
11131 json_object_int_add(json_last_update
, "epoch", tbuf
);
11132 json_object_string_add(json_last_update
, "string",
11134 json_object_object_add(json_path
, "lastUpdate",
11137 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11139 /* Line 10 display PMSI tunnel attribute, if present */
11140 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11141 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11142 bgp_attr_get_pmsi_tnl_type(attr
),
11143 PMSI_TNLTYPE_STR_DEFAULT
);
11146 json_pmsi
= json_object_new_object();
11147 json_object_string_add(json_pmsi
, "tunnelType", str
);
11148 json_object_int_add(json_pmsi
, "label",
11149 label2vni(&attr
->label
));
11150 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11152 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11153 str
, label2vni(&attr
->label
));
11156 if (path
->peer
->t_gr_restart
&&
11157 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11158 unsigned long gr_remaining
=
11159 thread_timer_remain_second(path
->peer
->t_gr_restart
);
11162 json_object_int_add(json_path
,
11163 "gracefulRestartSecondsRemaining",
11167 " Time until Graceful Restart stale route deleted: %lu\n",
11171 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11172 bgp_attr_get_community(attr
) &&
11173 community_include(bgp_attr_get_community(attr
),
11174 COMMUNITY_LLGR_STALE
)) {
11175 unsigned long llgr_remaining
= thread_timer_remain_second(
11176 path
->peer
->t_llgr_stale
[afi
][safi
]);
11179 json_object_int_add(json_path
, "llgrSecondsRemaining",
11183 " Time until Long-lived stale route deleted: %lu\n",
11187 /* Output some debug about internal state of the dest flags */
11189 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11190 json_object_boolean_true_add(json_path
, "processScheduled");
11191 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11192 json_object_boolean_true_add(json_path
, "userCleared");
11193 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11194 json_object_boolean_true_add(json_path
, "labelChanged");
11195 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11196 json_object_boolean_true_add(json_path
, "registeredForLabel");
11197 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11198 json_object_boolean_true_add(json_path
, "selectDefered");
11199 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11200 json_object_boolean_true_add(json_path
, "fibInstalled");
11201 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11202 json_object_boolean_true_add(json_path
, "fibPending");
11204 if (json_nexthop_global
|| json_nexthop_ll
) {
11205 json_nexthops
= json_object_new_array();
11207 if (json_nexthop_global
)
11208 json_object_array_add(json_nexthops
,
11209 json_nexthop_global
);
11211 if (json_nexthop_ll
)
11212 json_object_array_add(json_nexthops
,
11215 json_object_object_add(json_path
, "nexthops",
11219 json_object_object_add(json_path
, "peer", json_peer
);
11220 json_object_array_add(json_paths
, json_path
);
11224 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11225 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11226 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11228 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11229 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11231 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11232 const char *comstr
, int exact
, afi_t afi
,
11233 safi_t safi
, uint16_t show_flags
);
11235 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11236 struct bgp_table
*table
, enum bgp_show_type type
,
11237 void *output_arg
, const char *rd
, int is_last
,
11238 unsigned long *output_cum
, unsigned long *total_cum
,
11239 unsigned long *json_header_depth
, uint16_t show_flags
,
11240 enum rpki_states rpki_target_state
)
11242 struct bgp_path_info
*pi
;
11243 struct bgp_dest
*dest
;
11244 bool header
= true;
11245 bool json_detail_header
= false;
11247 unsigned long output_count
= 0;
11248 unsigned long total_count
= 0;
11250 json_object
*json_paths
= NULL
;
11252 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11253 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11254 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11256 if (output_cum
&& *output_cum
!= 0)
11259 if (use_json
&& !*json_header_depth
) {
11261 *json_header_depth
= 1;
11263 vty_out(vty
, "{\n");
11264 *json_header_depth
= 2;
11268 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11269 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11270 " \"localAS\": %u,\n \"routes\": { ",
11271 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11272 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11275 table
->version
, &bgp
->router_id
,
11276 bgp
->default_local_pref
, bgp
->as
);
11278 vty_out(vty
, " \"routeDistinguishers\" : {");
11279 ++*json_header_depth
;
11283 if (use_json
&& rd
) {
11284 vty_out(vty
, " \"%s\" : { ", rd
);
11287 /* Check for 'json detail', where we need header output once per dest */
11288 if (use_json
&& CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
) &&
11289 type
!= bgp_show_type_dampend_paths
&&
11290 type
!= bgp_show_type_damp_neighbor
&&
11291 type
!= bgp_show_type_flap_statistics
&&
11292 type
!= bgp_show_type_flap_neighbor
)
11293 json_detail_header
= true;
11295 /* Start processing of routes. */
11296 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11297 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11298 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11299 bool json_detail
= json_detail_header
;
11301 pi
= bgp_dest_get_bgp_path_info(dest
);
11307 json_paths
= json_object_new_array();
11311 for (; pi
; pi
= pi
->next
) {
11312 struct community
*picomm
= NULL
;
11314 picomm
= bgp_attr_get_community(pi
->attr
);
11318 if (type
== bgp_show_type_prefix_version
) {
11320 strtoul(output_arg
, NULL
, 10);
11321 if (dest
->version
< version
)
11325 if (type
== bgp_show_type_community_alias
) {
11326 char *alias
= output_arg
;
11327 char **communities
;
11329 bool found
= false;
11332 frrstr_split(picomm
->str
, " ",
11333 &communities
, &num
);
11334 for (int i
= 0; i
< num
; i
++) {
11335 const char *com2alias
=
11336 bgp_community2alias(
11339 && strcmp(alias
, com2alias
)
11345 XFREE(MTYPE_TMP
, communities
);
11349 bgp_attr_get_lcommunity(pi
->attr
)) {
11350 frrstr_split(bgp_attr_get_lcommunity(
11353 " ", &communities
, &num
);
11354 for (int i
= 0; i
< num
; i
++) {
11355 const char *com2alias
=
11356 bgp_community2alias(
11359 && strcmp(alias
, com2alias
)
11365 XFREE(MTYPE_TMP
, communities
);
11372 if (type
== bgp_show_type_rpki
) {
11373 if (dest_p
->family
== AF_INET
11374 || dest_p
->family
== AF_INET6
)
11375 rpki_curr_state
= hook_call(
11376 bgp_rpki_prefix_status
,
11377 pi
->peer
, pi
->attr
, dest_p
);
11378 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11379 && rpki_curr_state
!= rpki_target_state
)
11383 if (type
== bgp_show_type_flap_statistics
11384 || type
== bgp_show_type_flap_neighbor
11385 || type
== bgp_show_type_dampend_paths
11386 || type
== bgp_show_type_damp_neighbor
) {
11387 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11390 if (type
== bgp_show_type_regexp
) {
11391 regex_t
*regex
= output_arg
;
11393 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11397 if (type
== bgp_show_type_prefix_list
) {
11398 struct prefix_list
*plist
= output_arg
;
11400 if (prefix_list_apply(plist
, dest_p
)
11404 if (type
== bgp_show_type_access_list
) {
11405 struct access_list
*alist
= output_arg
;
11407 if (access_list_apply(alist
, dest_p
) !=
11411 if (type
== bgp_show_type_filter_list
) {
11412 struct as_list
*as_list
= output_arg
;
11414 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11415 != AS_FILTER_PERMIT
)
11418 if (type
== bgp_show_type_route_map
) {
11419 struct route_map
*rmap
= output_arg
;
11420 struct bgp_path_info path
;
11421 struct bgp_path_info_extra extra
;
11422 struct attr dummy_attr
= {};
11423 route_map_result_t ret
;
11425 dummy_attr
= *pi
->attr
;
11427 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11428 pi
->peer
, &dummy_attr
);
11430 ret
= route_map_apply(rmap
, dest_p
, &path
);
11431 bgp_attr_flush(&dummy_attr
);
11432 if (ret
== RMAP_DENYMATCH
)
11435 if (type
== bgp_show_type_neighbor
11436 || type
== bgp_show_type_flap_neighbor
11437 || type
== bgp_show_type_damp_neighbor
) {
11438 union sockunion
*su
= output_arg
;
11440 if (pi
->peer
== NULL
11441 || pi
->peer
->su_remote
== NULL
11442 || !sockunion_same(pi
->peer
->su_remote
, su
))
11445 if (type
== bgp_show_type_cidr_only
) {
11446 uint32_t destination
;
11448 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11449 if (IN_CLASSC(destination
)
11450 && dest_p
->prefixlen
== 24)
11452 if (IN_CLASSB(destination
)
11453 && dest_p
->prefixlen
== 16)
11455 if (IN_CLASSA(destination
)
11456 && dest_p
->prefixlen
== 8)
11459 if (type
== bgp_show_type_prefix_longer
) {
11461 if (!prefix_match(p
, dest_p
))
11464 if (type
== bgp_show_type_community_all
) {
11468 if (type
== bgp_show_type_community
) {
11469 struct community
*com
= output_arg
;
11471 if (!picomm
|| !community_match(picomm
, com
))
11474 if (type
== bgp_show_type_community_exact
) {
11475 struct community
*com
= output_arg
;
11477 if (!picomm
|| !community_cmp(picomm
, com
))
11480 if (type
== bgp_show_type_community_list
) {
11481 struct community_list
*list
= output_arg
;
11483 if (!community_list_match(picomm
, list
))
11486 if (type
== bgp_show_type_community_list_exact
) {
11487 struct community_list
*list
= output_arg
;
11489 if (!community_list_exact_match(picomm
, list
))
11492 if (type
== bgp_show_type_lcommunity
) {
11493 struct lcommunity
*lcom
= output_arg
;
11495 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11497 bgp_attr_get_lcommunity(pi
->attr
),
11502 if (type
== bgp_show_type_lcommunity_exact
) {
11503 struct lcommunity
*lcom
= output_arg
;
11505 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11507 bgp_attr_get_lcommunity(pi
->attr
),
11511 if (type
== bgp_show_type_lcommunity_list
) {
11512 struct community_list
*list
= output_arg
;
11514 if (!lcommunity_list_match(
11515 bgp_attr_get_lcommunity(pi
->attr
),
11520 == bgp_show_type_lcommunity_list_exact
) {
11521 struct community_list
*list
= output_arg
;
11523 if (!lcommunity_list_exact_match(
11524 bgp_attr_get_lcommunity(pi
->attr
),
11528 if (type
== bgp_show_type_lcommunity_all
) {
11529 if (!bgp_attr_get_lcommunity(pi
->attr
))
11532 if (type
== bgp_show_type_dampend_paths
11533 || type
== bgp_show_type_damp_neighbor
) {
11534 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11535 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11539 if (!use_json
&& header
) {
11541 "BGP table version is %" PRIu64
11542 ", local router ID is %pI4, vrf id ",
11543 table
->version
, &bgp
->router_id
);
11544 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11545 vty_out(vty
, "%s", VRFID_NONE_STR
);
11547 vty_out(vty
, "%u", bgp
->vrf_id
);
11548 vty_out(vty
, "\n");
11549 vty_out(vty
, "Default local pref %u, ",
11550 bgp
->default_local_pref
);
11551 vty_out(vty
, "local AS %u\n", bgp
->as
);
11552 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11553 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11554 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11555 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11556 if (type
== bgp_show_type_dampend_paths
11557 || type
== bgp_show_type_damp_neighbor
)
11558 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11559 else if (type
== bgp_show_type_flap_statistics
11560 || type
== bgp_show_type_flap_neighbor
)
11561 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11563 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11564 : BGP_SHOW_HEADER
));
11567 } else if (json_detail
&& json_paths
!= NULL
) {
11568 const struct prefix_rd
*prd
;
11569 json_object
*jtemp
;
11571 /* Use common detail header, for most types;
11572 * need a json 'object'.
11575 jtemp
= json_object_new_object();
11576 prd
= bgp_rd_from_dest(dest
, safi
);
11578 route_vty_out_detail_header(
11580 bgp_dest_get_prefix(dest
), prd
,
11581 table
->afi
, safi
, jtemp
);
11583 json_object_array_add(json_paths
, jtemp
);
11585 json_detail
= false;
11588 if (rd
!= NULL
&& !display
&& !output_count
) {
11591 "Route Distinguisher: %s\n",
11594 if (type
== bgp_show_type_dampend_paths
11595 || type
== bgp_show_type_damp_neighbor
)
11596 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11597 AFI_IP
, safi
, use_json
,
11599 else if (type
== bgp_show_type_flap_statistics
11600 || type
== bgp_show_type_flap_neighbor
)
11601 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11602 AFI_IP
, safi
, use_json
,
11605 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
))
11606 route_vty_out_detail(
11608 bgp_dest_get_prefix(dest
), pi
,
11609 family2afi(dest_p
->family
),
11610 safi
, RPKI_NOT_BEING_USED
,
11613 route_vty_out(vty
, dest_p
, pi
, display
,
11614 safi
, json_paths
, wide
);
11624 /* encode prefix */
11625 if (dest_p
->family
== AF_FLOWSPEC
) {
11626 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11629 bgp_fs_nlri_get_string(
11631 dest_p
->u
.prefix_flowspec
.ptr
,
11632 dest_p
->u
.prefix_flowspec
.prefixlen
,
11633 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11634 family2afi(dest_p
->u
11635 .prefix_flowspec
.family
));
11637 vty_out(vty
, "\"%s/%d\": ", retstr
,
11638 dest_p
->u
.prefix_flowspec
11641 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11642 dest_p
->u
.prefix_flowspec
11646 vty_out(vty
, "\"%pFX\": ", dest_p
);
11648 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11650 vty_json(vty
, json_paths
);
11654 json_object_free(json_paths
);
11658 output_count
+= *output_cum
;
11659 *output_cum
= output_count
;
11662 total_count
+= *total_cum
;
11663 *total_cum
= total_count
;
11667 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11671 for (i
= 0; i
< *json_header_depth
; ++i
)
11672 vty_out(vty
, " } ");
11674 vty_out(vty
, "\n");
11678 /* No route is displayed */
11679 if (output_count
== 0) {
11680 if (type
== bgp_show_type_normal
)
11682 "No BGP prefixes displayed, %ld exist\n",
11686 "\nDisplayed %ld routes and %ld total paths\n",
11687 output_count
, total_count
);
11691 return CMD_SUCCESS
;
11694 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11695 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11696 enum bgp_show_type type
, void *output_arg
, bool use_json
)
11698 struct bgp_dest
*dest
, *next
;
11699 unsigned long output_cum
= 0;
11700 unsigned long total_cum
= 0;
11701 unsigned long json_header_depth
= 0;
11702 struct bgp_table
*itable
;
11704 uint16_t show_flags
= 0;
11706 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11709 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11711 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11712 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11714 next
= bgp_route_next(dest
);
11715 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11718 itable
= bgp_dest_get_bgp_table_info(dest
);
11719 if (itable
!= NULL
) {
11720 struct prefix_rd prd
;
11721 char rd
[RD_ADDRSTRLEN
];
11723 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11724 prefix_rd2str(&prd
, rd
, sizeof(rd
));
11725 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11726 rd
, next
== NULL
, &output_cum
,
11727 &total_cum
, &json_header_depth
,
11728 show_flags
, RPKI_NOT_BEING_USED
);
11734 if (output_cum
== 0)
11735 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11739 "\nDisplayed %ld routes and %ld total paths\n",
11740 output_cum
, total_cum
);
11742 if (use_json
&& output_cum
== 0)
11743 vty_out(vty
, "{}\n");
11745 return CMD_SUCCESS
;
11748 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11749 enum bgp_show_type type
, void *output_arg
,
11750 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11752 struct bgp_table
*table
;
11753 unsigned long json_header_depth
= 0;
11754 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11757 bgp
= bgp_get_default();
11762 vty_out(vty
, "No BGP process is configured\n");
11764 vty_out(vty
, "{}\n");
11765 return CMD_WARNING
;
11768 /* Labeled-unicast routes live in the unicast table. */
11769 if (safi
== SAFI_LABELED_UNICAST
)
11770 safi
= SAFI_UNICAST
;
11772 table
= bgp
->rib
[afi
][safi
];
11773 /* use MPLS and ENCAP specific shows until they are merged */
11774 if (safi
== SAFI_MPLS_VPN
) {
11775 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11776 output_arg
, use_json
);
11779 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11780 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11781 output_arg
, use_json
,
11785 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11786 NULL
, NULL
, &json_header_depth
, show_flags
,
11787 rpki_target_state
);
11790 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11791 safi_t safi
, uint16_t show_flags
)
11793 struct listnode
*node
, *nnode
;
11796 bool route_output
= false;
11797 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11800 vty_out(vty
, "{\n");
11802 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11803 route_output
= true;
11806 vty_out(vty
, ",\n");
11810 vty_out(vty
, "\"%s\":",
11811 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11815 vty_out(vty
, "\nInstance %s:\n",
11816 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11820 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11821 show_flags
, RPKI_NOT_BEING_USED
);
11825 vty_out(vty
, "}\n");
11826 else if (!route_output
)
11827 vty_out(vty
, "%% BGP instance not found\n");
11830 /* Header of detailed BGP route information */
11831 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11832 struct bgp_dest
*dest
, const struct prefix
*p
,
11833 const struct prefix_rd
*prd
, afi_t afi
,
11834 safi_t safi
, json_object
*json
)
11836 struct bgp_path_info
*pi
;
11838 struct listnode
*node
, *nnode
;
11839 char buf1
[RD_ADDRSTRLEN
];
11843 int accept_own
= 0;
11844 int route_filter_translated_v4
= 0;
11845 int route_filter_v4
= 0;
11846 int route_filter_translated_v6
= 0;
11847 int route_filter_v6
= 0;
11848 int llgr_stale
= 0;
11850 int accept_own_nexthop
= 0;
11853 int no_advertise
= 0;
11857 int has_valid_label
= 0;
11858 mpls_label_t label
= 0;
11859 json_object
*json_adv_to
= NULL
;
11864 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11866 has_valid_label
= bgp_is_valid_label(&label
);
11868 if (safi
== SAFI_EVPN
) {
11870 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11871 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11873 prd
? ":" : "", (struct prefix_evpn
*)p
);
11875 json_object_string_add(json
, "rd",
11876 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11878 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11883 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11885 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11886 ? prefix_rd2str(prd
, buf1
,
11889 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11893 json_object_string_addf(json
, "prefix", "%pFX", p
);
11894 json_object_int_add(json
, "version", dest
->version
);
11899 if (has_valid_label
) {
11901 json_object_int_add(json
, "localLabel", label
);
11903 vty_out(vty
, "Local label: %d\n", label
);
11907 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11908 vty_out(vty
, "not allocated\n");
11910 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11911 struct community
*picomm
= NULL
;
11913 picomm
= bgp_attr_get_community(pi
->attr
);
11916 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11918 if (bgp_path_suppressed(pi
))
11924 no_advertise
+= community_include(
11925 picomm
, COMMUNITY_NO_ADVERTISE
);
11927 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11929 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11931 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11932 route_filter_translated_v4
+= community_include(
11933 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11934 route_filter_translated_v6
+= community_include(
11935 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11936 route_filter_v4
+= community_include(
11937 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11938 route_filter_v6
+= community_include(
11939 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11941 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11942 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11943 accept_own_nexthop
+= community_include(
11944 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11946 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11947 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11952 vty_out(vty
, "Paths: (%d available", count
);
11954 vty_out(vty
, ", best #%d", best
);
11955 if (safi
== SAFI_UNICAST
) {
11956 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11957 vty_out(vty
, ", table %s",
11960 vty_out(vty
, ", vrf %s",
11964 vty_out(vty
, ", no best path");
11968 ", accept own local route exported and imported in different VRF");
11969 else if (route_filter_translated_v4
)
11971 ", mark translated RTs for VPNv4 route filtering");
11972 else if (route_filter_v4
)
11974 ", attach RT as-is for VPNv4 route filtering");
11975 else if (route_filter_translated_v6
)
11977 ", mark translated RTs for VPNv6 route filtering");
11978 else if (route_filter_v6
)
11980 ", attach RT as-is for VPNv6 route filtering");
11981 else if (llgr_stale
)
11983 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11986 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11987 else if (accept_own_nexthop
)
11989 ", accept local nexthop");
11990 else if (blackhole
)
11991 vty_out(vty
, ", inform peer to blackhole prefix");
11992 else if (no_export
)
11993 vty_out(vty
, ", not advertised to EBGP peer");
11994 else if (no_advertise
)
11995 vty_out(vty
, ", not advertised to any peer");
11997 vty_out(vty
, ", not advertised outside local AS");
12000 ", inform EBGP peer not to advertise to their EBGP peers");
12004 ", Advertisements suppressed by an aggregate.");
12005 vty_out(vty
, ")\n");
12008 /* If we are not using addpath then we can display Advertised to and
12010 * show what peers we advertised the bestpath to. If we are using
12012 * though then we must display Advertised to on a path-by-path basis. */
12013 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12014 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12015 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12016 if (json
&& !json_adv_to
)
12017 json_adv_to
= json_object_new_object();
12019 route_vty_out_advertised_to(
12021 " Advertised to non peer-group peers:\n ",
12028 json_object_object_add(json
, "advertisedTo",
12033 vty_out(vty
, " Not advertised to any peer");
12034 vty_out(vty
, "\n");
12039 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12040 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12041 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12042 json_object
*json
, enum bgp_path_type pathtype
,
12043 int *display
, enum rpki_states rpki_target_state
)
12045 struct bgp_path_info
*pi
;
12047 json_object
*json_header
= NULL
;
12048 json_object
*json_paths
= NULL
;
12049 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12051 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12052 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12054 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12055 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12056 pi
->peer
, pi
->attr
, p
);
12058 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12059 && rpki_curr_state
!= rpki_target_state
)
12062 if (json
&& !json_paths
) {
12063 /* Instantiate json_paths only if path is valid */
12064 json_paths
= json_object_new_array();
12066 json_header
= json_object_new_object();
12068 json_header
= json
;
12072 route_vty_out_detail_header(
12073 vty
, bgp
, bgp_node
,
12074 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12075 safi
, json_header
);
12080 if (pathtype
== BGP_PATH_SHOW_ALL
12081 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12082 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12083 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12084 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12085 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12086 route_vty_out_detail(vty
, bgp
, bgp_node
,
12087 bgp_dest_get_prefix(bgp_node
), pi
,
12088 AFI_IP
, safi
, rpki_curr_state
,
12092 if (json
&& json_paths
) {
12093 json_object_object_add(json_header
, "paths", json_paths
);
12096 json_object_object_addf(json
, json_header
, "%pRD",
12102 * Return rd based on safi
12104 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12108 case SAFI_MPLS_VPN
:
12111 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12117 /* Display specified route of BGP table. */
12118 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12119 struct bgp_table
*rib
, const char *ip_str
,
12120 afi_t afi
, safi_t safi
,
12121 enum rpki_states rpki_target_state
,
12122 struct prefix_rd
*prd
, int prefix_check
,
12123 enum bgp_path_type pathtype
, bool use_json
)
12127 struct prefix match
;
12128 struct bgp_dest
*dest
;
12129 struct bgp_dest
*rm
;
12130 struct bgp_table
*table
;
12131 json_object
*json
= NULL
;
12132 json_object
*json_paths
= NULL
;
12134 /* Check IP address argument. */
12135 ret
= str2prefix(ip_str
, &match
);
12137 vty_out(vty
, "address is malformed\n");
12138 return CMD_WARNING
;
12141 match
.family
= afi2family(afi
);
12144 json
= json_object_new_object();
12146 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12147 for (dest
= bgp_table_top(rib
); dest
;
12148 dest
= bgp_route_next(dest
)) {
12149 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12151 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12153 table
= bgp_dest_get_bgp_table_info(dest
);
12157 rm
= bgp_node_match(table
, &match
);
12161 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12163 && rm_p
->prefixlen
!= match
.prefixlen
) {
12164 bgp_dest_unlock_node(rm
);
12168 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12169 bgp
, afi
, safi
, json
, pathtype
,
12170 &display
, rpki_target_state
);
12172 bgp_dest_unlock_node(rm
);
12174 } else if (safi
== SAFI_EVPN
) {
12175 struct bgp_dest
*longest_pfx
;
12176 bool is_exact_pfxlen_match
= false;
12178 for (dest
= bgp_table_top(rib
); dest
;
12179 dest
= bgp_route_next(dest
)) {
12180 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12182 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12184 table
= bgp_dest_get_bgp_table_info(dest
);
12188 longest_pfx
= NULL
;
12189 is_exact_pfxlen_match
= false;
12191 * Search through all the prefixes for a match. The
12192 * pfx's are enumerated in ascending order of pfxlens.
12193 * So, the last pfx match is the longest match. Set
12194 * is_exact_pfxlen_match when we get exact pfxlen match
12196 for (rm
= bgp_table_top(table
); rm
;
12197 rm
= bgp_route_next(rm
)) {
12198 const struct prefix
*rm_p
=
12199 bgp_dest_get_prefix(rm
);
12201 * Get prefixlen of the ip-prefix within type5
12204 if (evpn_type5_prefix_match(rm_p
, &match
)
12208 bgp_evpn_get_type5_prefixlen(
12210 if (type5_pfxlen
== match
.prefixlen
) {
12211 is_exact_pfxlen_match
= true;
12212 bgp_dest_unlock_node(rm
);
12221 if (prefix_check
&& !is_exact_pfxlen_match
)
12225 bgp_dest_lock_node(rm
);
12227 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12228 bgp
, afi
, safi
, json
, pathtype
,
12229 &display
, rpki_target_state
);
12231 bgp_dest_unlock_node(rm
);
12233 } else if (safi
== SAFI_FLOWSPEC
) {
12235 json_paths
= json_object_new_array();
12237 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12238 &match
, prefix_check
,
12244 json_object_object_add(json
, "paths",
12247 json_object_free(json_paths
);
12250 dest
= bgp_node_match(rib
, &match
);
12251 if (dest
!= NULL
) {
12252 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12254 || dest_p
->prefixlen
== match
.prefixlen
) {
12255 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12256 safi
, json
, pathtype
,
12257 &display
, rpki_target_state
);
12260 bgp_dest_unlock_node(dest
);
12265 vty_json(vty
, json
);
12268 vty_out(vty
, "%% Network not in table\n");
12269 return CMD_WARNING
;
12273 return CMD_SUCCESS
;
12276 /* Display specified route of Main RIB */
12277 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12278 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12279 int prefix_check
, enum bgp_path_type pathtype
,
12280 enum rpki_states rpki_target_state
, bool use_json
)
12283 bgp
= bgp_get_default();
12286 vty_out(vty
, "No BGP process is configured\n");
12288 vty_out(vty
, "{}\n");
12289 return CMD_WARNING
;
12293 /* labeled-unicast routes live in the unicast table */
12294 if (safi
== SAFI_LABELED_UNICAST
)
12295 safi
= SAFI_UNICAST
;
12297 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12298 afi
, safi
, rpki_target_state
, prd
,
12299 prefix_check
, pathtype
, use_json
);
12302 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12303 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12304 safi_t safi
, bool uj
)
12306 struct lcommunity
*lcom
;
12311 uint16_t show_flags
= 0;
12315 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12317 b
= buffer_new(1024);
12318 for (i
= 0; i
< argc
; i
++) {
12320 buffer_putc(b
, ' ');
12322 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12324 buffer_putstr(b
, argv
[i
]->arg
);
12328 buffer_putc(b
, '\0');
12330 str
= buffer_getstr(b
);
12333 lcom
= lcommunity_str2com(str
);
12334 XFREE(MTYPE_TMP
, str
);
12336 vty_out(vty
, "%% Large-community malformed\n");
12337 return CMD_WARNING
;
12340 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12341 (exact
? bgp_show_type_lcommunity_exact
12342 : bgp_show_type_lcommunity
),
12343 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12345 lcommunity_free(&lcom
);
12349 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12350 const char *lcom
, bool exact
, afi_t afi
,
12351 safi_t safi
, bool uj
)
12353 struct community_list
*list
;
12354 uint16_t show_flags
= 0;
12357 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12360 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12361 LARGE_COMMUNITY_LIST_MASTER
);
12362 if (list
== NULL
) {
12363 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12365 return CMD_WARNING
;
12368 return bgp_show(vty
, bgp
, afi
, safi
,
12369 (exact
? bgp_show_type_lcommunity_list_exact
12370 : bgp_show_type_lcommunity_list
),
12371 list
, show_flags
, RPKI_NOT_BEING_USED
);
12374 DEFUN (show_ip_bgp_large_community_list
,
12375 show_ip_bgp_large_community_list_cmd
,
12376 "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]",
12380 BGP_INSTANCE_HELP_STR
12382 BGP_SAFI_WITH_LABEL_HELP_STR
12383 "Display routes matching the large-community-list\n"
12384 "large-community-list number\n"
12385 "large-community-list name\n"
12386 "Exact match of the large-communities\n"
12389 afi_t afi
= AFI_IP6
;
12390 safi_t safi
= SAFI_UNICAST
;
12392 bool exact_match
= 0;
12393 struct bgp
*bgp
= NULL
;
12394 bool uj
= use_json(argc
, argv
);
12399 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12402 return CMD_WARNING
;
12404 argv_find(argv
, argc
, "large-community-list", &idx
);
12406 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12408 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12411 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12412 exact_match
, afi
, safi
, uj
);
12414 DEFUN (show_ip_bgp_large_community
,
12415 show_ip_bgp_large_community_cmd
,
12416 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12420 BGP_INSTANCE_HELP_STR
12422 BGP_SAFI_WITH_LABEL_HELP_STR
12423 "Display routes matching the large-communities\n"
12424 "List of large-community numbers\n"
12425 "Exact match of the large-communities\n"
12428 afi_t afi
= AFI_IP6
;
12429 safi_t safi
= SAFI_UNICAST
;
12431 bool exact_match
= 0;
12432 struct bgp
*bgp
= NULL
;
12433 bool uj
= use_json(argc
, argv
);
12434 uint16_t show_flags
= 0;
12438 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12441 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12444 return CMD_WARNING
;
12446 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12447 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12451 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12452 exact_match
, afi
, safi
, uj
);
12454 return bgp_show(vty
, bgp
, afi
, safi
,
12455 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12456 RPKI_NOT_BEING_USED
);
12459 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12460 safi_t safi
, struct json_object
*json_array
);
12461 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12462 safi_t safi
, struct json_object
*json
);
12465 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12466 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12467 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12468 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12470 bool uj
= use_json(argc
, argv
);
12471 struct bgp
*bgp
= NULL
;
12472 safi_t safi
= SAFI_UNICAST
;
12473 afi_t afi
= AFI_IP6
;
12475 struct json_object
*json_all
= NULL
;
12476 struct json_object
*json_afi_safi
= NULL
;
12478 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12481 return CMD_WARNING
;
12484 json_all
= json_object_new_object();
12486 FOREACH_AFI_SAFI (afi
, safi
) {
12488 * So limit output to those afi/safi pairs that
12489 * actually have something interesting in them
12491 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12496 json_afi_safi
= json_object_new_array();
12497 json_object_object_add(
12499 get_afi_safi_str(afi
, safi
, true),
12502 json_afi_safi
= NULL
;
12505 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12509 vty_json(vty
, json_all
);
12511 return CMD_SUCCESS
;
12514 /* BGP route print out function without JSON */
12515 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12516 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12517 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12521 BGP_INSTANCE_HELP_STR
12524 "BGP RIB advertisement statistics\n"
12527 afi_t afi
= AFI_IP6
;
12528 safi_t safi
= SAFI_UNICAST
;
12529 struct bgp
*bgp
= NULL
;
12531 bool uj
= use_json(argc
, argv
);
12532 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12534 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12537 return CMD_WARNING
;
12540 json_afi_safi
= json_object_new_array();
12542 json_afi_safi
= NULL
;
12544 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12547 json
= json_object_new_object();
12548 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12550 vty_json(vty
, json
);
12555 /* BGP route print out function without JSON */
12556 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12557 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12558 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12560 statistics [json]",
12561 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12562 BGP_SAFI_WITH_LABEL_HELP_STR
12563 "BGP RIB advertisement statistics\n" JSON_STR
)
12565 afi_t afi
= AFI_IP6
;
12566 safi_t safi
= SAFI_UNICAST
;
12567 struct bgp
*bgp
= NULL
;
12569 bool uj
= use_json(argc
, argv
);
12570 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12572 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12575 return CMD_WARNING
;
12578 json_afi_safi
= json_object_new_array();
12580 json_afi_safi
= NULL
;
12582 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12585 json
= json_object_new_object();
12586 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12588 vty_json(vty
, json
);
12593 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12594 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12595 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12596 "]] [all$all] dampening parameters [json]",
12597 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12598 BGP_SAFI_WITH_LABEL_HELP_STR
12599 "Display the entries for all address families\n"
12600 "Display detailed information about dampening\n"
12601 "Display detail of configured dampening parameters\n"
12604 afi_t afi
= AFI_IP6
;
12605 safi_t safi
= SAFI_UNICAST
;
12606 struct bgp
*bgp
= NULL
;
12608 uint16_t show_flags
= 0;
12609 bool uj
= use_json(argc
, argv
);
12613 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12616 /* [<ipv4|ipv6> [all]] */
12618 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12619 if (argv_find(argv
, argc
, "ipv4", &idx
))
12620 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12622 if (argv_find(argv
, argc
, "ipv6", &idx
))
12623 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12626 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12629 return CMD_WARNING
;
12631 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12634 /* BGP route print out function */
12635 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12636 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12637 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12641 |dampening <flap-statistics|dampened-paths>\
12642 |community [AA:NN|local-AS|no-advertise|no-export\
12643 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12644 |accept-own|accept-own-nexthop|route-filter-v6\
12645 |route-filter-v4|route-filter-translated-v6\
12646 |route-filter-translated-v4] [exact-match]\
12647 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12648 |filter-list AS_PATH_FILTER_NAME\
12650 |access-list ACCESSLIST_NAME\
12651 |route-map RMAP_NAME\
12652 |rpki <invalid|valid|notfound>\
12653 |version (1-4294967295)\
12655 |A.B.C.D/M longer-prefixes\
12656 |X:X::X:X/M longer-prefixes\
12657 |optimal-route-reflection [WORD$orr_group_name]\
12658 ] [json$uj [detail$detail] | wide$wide]",
12659 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12660 BGP_SAFI_WITH_LABEL_HELP_STR
12661 "Display the entries for all address families\n"
12662 "Display only routes with non-natural netmasks\n"
12663 "Display detailed information about dampening\n"
12664 "Display flap statistics of routes\n"
12665 "Display paths suppressed due to dampening\n"
12666 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12667 "Do not send outside local AS (well-known community)\n"
12668 "Do not advertise to any peer (well-known community)\n"
12669 "Do not export to next AS (well-known community)\n"
12670 "Graceful shutdown (well-known community)\n"
12671 "Do not export to any peer (well-known community)\n"
12672 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12673 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12674 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12675 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12676 "Should accept VPN route with local nexthop (well-known community)\n"
12677 "RT VPNv6 route filtering (well-known community)\n"
12678 "RT VPNv4 route filtering (well-known community)\n"
12679 "RT translated VPNv6 route filtering (well-known community)\n"
12680 "RT translated VPNv4 route filtering (well-known community)\n"
12681 "Exact match of the communities\n"
12682 "Community-list number\n"
12683 "Community-list name\n"
12684 "Display routes matching the community-list\n"
12685 "Exact match of the communities\n"
12686 "Display routes conforming to the filter-list\n"
12687 "Regular expression access list name\n"
12688 "Display routes conforming to the prefix-list\n"
12689 "Prefix-list name\n"
12690 "Display routes conforming to the access-list\n"
12691 "Access-list name\n"
12692 "Display routes matching the route-map\n"
12693 "A route-map to match on\n"
12694 "RPKI route types\n"
12695 "A valid path as determined by rpki\n"
12696 "A invalid path as determined by rpki\n"
12697 "A path that has no rpki data\n"
12698 "Display prefixes with matching version numbers\n"
12699 "Version number and above\n"
12700 "Display prefixes with matching BGP community alias\n"
12701 "BGP community alias\n"
12703 "Display route and more specific routes\n"
12705 "Display route and more specific routes\n"
12706 "Display Optimal Route Reflection RR Clients\n"
12709 "Display detailed version of JSON output\n"
12710 "Increase table width for longer prefixes\n")
12712 afi_t afi
= AFI_IP6
;
12713 safi_t safi
= SAFI_UNICAST
;
12714 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12715 void *output_arg
= NULL
;
12716 struct bgp
*bgp
= NULL
;
12718 int exact_match
= 0;
12719 char *community
= NULL
;
12721 uint16_t show_flags
= 0;
12722 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12724 bool orr_group
= false;
12728 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12732 SET_FLAG(show_flags
, BGP_SHOW_OPT_DETAIL
);
12734 /* [<ipv4|ipv6> [all]] */
12736 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12738 if (argv_find(argv
, argc
, "ipv4", &idx
))
12739 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12741 if (argv_find(argv
, argc
, "ipv6", &idx
))
12742 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12746 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12748 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12751 return CMD_WARNING
;
12753 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12754 sh_type
= bgp_show_type_cidr_only
;
12756 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12757 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12758 sh_type
= bgp_show_type_dampend_paths
;
12759 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12760 sh_type
= bgp_show_type_flap_statistics
;
12763 if (argv_find(argv
, argc
, "community", &idx
)) {
12764 char *maybecomm
= NULL
;
12766 if (idx
+ 1 < argc
) {
12767 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12768 maybecomm
= argv
[idx
+ 1]->arg
;
12770 maybecomm
= argv
[idx
+ 1]->text
;
12773 if (maybecomm
&& !strmatch(maybecomm
, "json")
12774 && !strmatch(maybecomm
, "exact-match"))
12775 community
= maybecomm
;
12777 if (argv_find(argv
, argc
, "exact-match", &idx
))
12781 sh_type
= bgp_show_type_community_all
;
12784 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12785 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12786 struct community_list
*list
;
12788 if (argv_find(argv
, argc
, "exact-match", &idx
))
12791 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12792 COMMUNITY_LIST_MASTER
);
12793 if (list
== NULL
) {
12794 vty_out(vty
, "%% %s community-list not found\n",
12795 clist_number_or_name
);
12796 return CMD_WARNING
;
12800 sh_type
= bgp_show_type_community_list_exact
;
12802 sh_type
= bgp_show_type_community_list
;
12806 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12807 const char *filter
= argv
[++idx
]->arg
;
12808 struct as_list
*as_list
;
12810 as_list
= as_list_lookup(filter
);
12811 if (as_list
== NULL
) {
12812 vty_out(vty
, "%% %s AS-path access-list not found\n",
12814 return CMD_WARNING
;
12817 sh_type
= bgp_show_type_filter_list
;
12818 output_arg
= as_list
;
12821 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12822 const char *prefix_list_str
= argv
[++idx
]->arg
;
12823 struct prefix_list
*plist
;
12825 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12826 if (plist
== NULL
) {
12827 vty_out(vty
, "%% %s prefix-list not found\n",
12829 return CMD_WARNING
;
12832 sh_type
= bgp_show_type_prefix_list
;
12833 output_arg
= plist
;
12836 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12837 const char *access_list_str
= argv
[++idx
]->arg
;
12838 struct access_list
*alist
;
12840 alist
= access_list_lookup(afi
, access_list_str
);
12842 vty_out(vty
, "%% %s access-list not found\n",
12844 return CMD_WARNING
;
12847 sh_type
= bgp_show_type_access_list
;
12848 output_arg
= alist
;
12851 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12852 const char *rmap_str
= argv
[++idx
]->arg
;
12853 struct route_map
*rmap
;
12855 rmap
= route_map_lookup_by_name(rmap_str
);
12857 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12858 return CMD_WARNING
;
12861 sh_type
= bgp_show_type_route_map
;
12865 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12866 sh_type
= bgp_show_type_rpki
;
12867 if (argv_find(argv
, argc
, "valid", &idx
))
12868 rpki_target_state
= RPKI_VALID
;
12869 else if (argv_find(argv
, argc
, "invalid", &idx
))
12870 rpki_target_state
= RPKI_INVALID
;
12873 /* Display prefixes with matching version numbers */
12874 if (argv_find(argv
, argc
, "version", &idx
)) {
12875 sh_type
= bgp_show_type_prefix_version
;
12876 output_arg
= argv
[idx
+ 1]->arg
;
12879 /* Display prefixes with matching BGP community alias */
12880 if (argv_find(argv
, argc
, "alias", &idx
)) {
12881 sh_type
= bgp_show_type_community_alias
;
12882 output_arg
= argv
[idx
+ 1]->arg
;
12885 /* prefix-longer */
12886 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12887 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12888 const char *prefix_str
= argv
[idx
]->arg
;
12890 if (!str2prefix(prefix_str
, &p
)) {
12891 vty_out(vty
, "%% Malformed Prefix\n");
12892 return CMD_WARNING
;
12895 sh_type
= bgp_show_type_prefix_longer
;
12899 if (argv_find(argv
, argc
, "optimal-route-reflection", &idx
))
12903 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12905 return bgp_show_community(vty
, bgp
, community
,
12906 exact_match
, afi
, safi
,
12908 else if (orr_group
)
12909 return bgp_show_orr(vty
, bgp
, afi
, safi
, orr_group_name
,
12912 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12913 output_arg
, show_flags
,
12914 rpki_target_state
);
12916 struct listnode
*node
;
12918 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12922 vty_out(vty
, "{\n");
12924 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12925 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12926 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12929 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12930 FOREACH_SAFI (safi
) {
12931 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12939 vty_out(vty
, ",\n");
12940 vty_out(vty
, "\"%s\":{\n",
12941 get_afi_safi_str(afi
,
12946 "\nFor address family: %s\n",
12952 bgp_show_community(
12953 vty
, abgp
, community
,
12954 exact_match
, afi
, safi
,
12956 else if (orr_group
)
12957 bgp_show_orr(vty
, bgp
, afi
,
12962 bgp_show(vty
, abgp
, afi
, safi
,
12963 sh_type
, output_arg
,
12965 rpki_target_state
);
12967 vty_out(vty
, "}\n");
12971 /* show <ip> bgp all: for each AFI and SAFI*/
12972 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12973 FOREACH_AFI_SAFI (afi
, safi
) {
12974 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12982 vty_out(vty
, ",\n");
12984 vty_out(vty
, "\"%s\":{\n",
12985 get_afi_safi_str(afi
,
12990 "\nFor address family: %s\n",
12996 bgp_show_community(
12997 vty
, abgp
, community
,
12998 exact_match
, afi
, safi
,
13000 else if (orr_group
)
13001 bgp_show_orr(vty
, bgp
, afi
,
13006 bgp_show(vty
, abgp
, afi
, safi
,
13007 sh_type
, output_arg
,
13009 rpki_target_state
);
13011 vty_out(vty
, "}\n");
13016 vty_out(vty
, "}\n");
13018 return CMD_SUCCESS
;
13021 DEFUN (show_ip_bgp_route
,
13022 show_ip_bgp_route_cmd
,
13023 "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]",
13027 BGP_INSTANCE_HELP_STR
13029 BGP_SAFI_WITH_LABEL_HELP_STR
13030 "Network in the BGP routing table to display\n"
13032 "Network in the BGP routing table to display\n"
13034 "Display only the bestpath\n"
13035 "Display only multipaths\n"
13036 "Display only paths that match the specified rpki state\n"
13037 "A valid path as determined by rpki\n"
13038 "A invalid path as determined by rpki\n"
13039 "A path that has no rpki data\n"
13042 int prefix_check
= 0;
13044 afi_t afi
= AFI_IP6
;
13045 safi_t safi
= SAFI_UNICAST
;
13046 char *prefix
= NULL
;
13047 struct bgp
*bgp
= NULL
;
13048 enum bgp_path_type path_type
;
13049 bool uj
= use_json(argc
, argv
);
13053 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13056 return CMD_WARNING
;
13060 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13061 return CMD_WARNING
;
13064 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13065 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13066 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13068 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13069 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13072 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13073 && afi
!= AFI_IP6
) {
13075 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13076 return CMD_WARNING
;
13078 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13079 && afi
!= AFI_IP
) {
13081 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13082 return CMD_WARNING
;
13085 prefix
= argv
[idx
]->arg
;
13087 /* [<bestpath|multipath>] */
13088 if (argv_find(argv
, argc
, "bestpath", &idx
))
13089 path_type
= BGP_PATH_SHOW_BESTPATH
;
13090 else if (argv_find(argv
, argc
, "multipath", &idx
))
13091 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13093 path_type
= BGP_PATH_SHOW_ALL
;
13095 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13096 path_type
, RPKI_NOT_BEING_USED
, uj
);
13099 DEFUN (show_ip_bgp_regexp
,
13100 show_ip_bgp_regexp_cmd
,
13101 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13105 BGP_INSTANCE_HELP_STR
13107 BGP_SAFI_WITH_LABEL_HELP_STR
13108 "Display routes matching the AS path regular expression\n"
13109 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13112 afi_t afi
= AFI_IP6
;
13113 safi_t safi
= SAFI_UNICAST
;
13114 struct bgp
*bgp
= NULL
;
13115 bool uj
= use_json(argc
, argv
);
13116 char *regstr
= NULL
;
13119 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13122 return CMD_WARNING
;
13124 // get index of regex
13125 if (argv_find(argv
, argc
, "REGEX", &idx
))
13126 regstr
= argv
[idx
]->arg
;
13129 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13130 bgp_show_type_regexp
, uj
);
13133 DEFPY (show_ip_bgp_instance_all
,
13134 show_ip_bgp_instance_all_cmd
,
13135 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13139 BGP_INSTANCE_ALL_HELP_STR
13141 BGP_SAFI_WITH_LABEL_HELP_STR
13143 "Increase table width for longer prefixes\n")
13145 afi_t afi
= AFI_IP6
;
13146 safi_t safi
= SAFI_UNICAST
;
13147 struct bgp
*bgp
= NULL
;
13149 uint16_t show_flags
= 0;
13153 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13157 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13159 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13162 return CMD_WARNING
;
13164 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13165 return CMD_SUCCESS
;
13168 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13169 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13174 uint16_t show_flags
= 0;
13177 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13179 if (!config_bgp_aspath_validate(regstr
)) {
13180 vty_out(vty
, "Invalid character in REGEX %s\n",
13182 return CMD_WARNING_CONFIG_FAILED
;
13185 regex
= bgp_regcomp(regstr
);
13187 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13188 return CMD_WARNING
;
13191 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13192 RPKI_NOT_BEING_USED
);
13193 bgp_regex_free(regex
);
13197 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13198 const char *comstr
, int exact
, afi_t afi
,
13199 safi_t safi
, uint16_t show_flags
)
13201 struct community
*com
;
13204 com
= community_str2com(comstr
);
13206 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13207 return CMD_WARNING
;
13210 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13211 (exact
? bgp_show_type_community_exact
13212 : bgp_show_type_community
),
13213 com
, show_flags
, RPKI_NOT_BEING_USED
);
13214 community_free(&com
);
13220 BGP_STATS_MAXBITLEN
= 0,
13222 BGP_STATS_PREFIXES
,
13224 BGP_STATS_UNAGGREGATEABLE
,
13225 BGP_STATS_MAX_AGGREGATEABLE
,
13226 BGP_STATS_AGGREGATES
,
13228 BGP_STATS_ASPATH_COUNT
,
13229 BGP_STATS_ASPATH_MAXHOPS
,
13230 BGP_STATS_ASPATH_TOTHOPS
,
13231 BGP_STATS_ASPATH_MAXSIZE
,
13232 BGP_STATS_ASPATH_TOTSIZE
,
13233 BGP_STATS_ASN_HIGHEST
,
13237 #define TABLE_STATS_IDX_VTY 0
13238 #define TABLE_STATS_IDX_JSON 1
13240 static const char *table_stats_strs
[][2] = {
13241 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13242 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13243 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13244 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13245 "unaggregateablePrefixes"},
13246 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13247 "maximumAggregateablePrefixes"},
13248 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13249 "bgpAggregateAdvertisements"},
13250 [BGP_STATS_SPACE
] = {"Address space advertised",
13251 "addressSpaceAdvertised"},
13252 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13253 "advertisementsWithPaths"},
13254 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13256 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13258 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13259 "averageAsPathLengthHops"},
13260 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13261 "averageAsPathSizeBytes"},
13262 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13263 [BGP_STATS_MAX
] = {NULL
, NULL
}
13266 struct bgp_table_stats
{
13267 struct bgp_table
*table
;
13268 unsigned long long counts
[BGP_STATS_MAX
];
13271 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13274 double total_space
;
13277 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13278 struct bgp_table_stats
*ts
, unsigned int space
)
13280 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13281 struct bgp_path_info
*pi
;
13282 const struct prefix
*rn_p
;
13284 if (!bgp_dest_has_bgp_path_info_data(dest
))
13287 rn_p
= bgp_dest_get_prefix(dest
);
13288 ts
->counts
[BGP_STATS_PREFIXES
]++;
13289 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13291 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13292 /* check if the prefix is included by any other announcements */
13293 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13294 pdest
= bgp_dest_parent_nolock(pdest
);
13296 if (pdest
== NULL
|| pdest
== top
) {
13297 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13298 /* announced address space */
13300 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13301 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13302 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13305 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13306 ts
->counts
[BGP_STATS_RIB
]++;
13308 if (CHECK_FLAG(pi
->attr
->flag
,
13309 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13310 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13312 /* as-path stats */
13313 if (pi
->attr
->aspath
) {
13314 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13315 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13316 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13318 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13320 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13321 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13323 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13324 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13326 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13327 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13328 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13329 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13334 static void bgp_table_stats_walker(struct thread
*t
)
13336 struct bgp_dest
*dest
, *ndest
;
13337 struct bgp_dest
*top
;
13338 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13339 unsigned int space
= 0;
13341 if (!(top
= bgp_table_top(ts
->table
)))
13344 switch (ts
->table
->afi
) {
13346 space
= IPV4_MAX_BITLEN
;
13349 space
= IPV6_MAX_BITLEN
;
13352 space
= EVPN_ROUTE_PREFIXLEN
;
13358 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13360 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13361 if (ts
->table
->safi
== SAFI_MPLS_VPN
13362 || ts
->table
->safi
== SAFI_ENCAP
13363 || ts
->table
->safi
== SAFI_EVPN
) {
13364 struct bgp_table
*table
;
13366 table
= bgp_dest_get_bgp_table_info(dest
);
13370 top
= bgp_table_top(table
);
13371 for (ndest
= bgp_table_top(table
); ndest
;
13372 ndest
= bgp_route_next(ndest
))
13373 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13375 bgp_table_stats_rn(dest
, top
, ts
, space
);
13380 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13381 struct json_object
*json_array
)
13383 struct listnode
*node
, *nnode
;
13386 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13387 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13390 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13391 safi_t safi
, struct json_object
*json_array
)
13393 struct bgp_table_stats ts
;
13395 int ret
= CMD_SUCCESS
;
13397 struct json_object
*json
= NULL
;
13398 uint32_t bitlen
= 0;
13399 struct json_object
*json_bitlen
;
13402 json
= json_object_new_object();
13404 if (!bgp
->rib
[afi
][safi
]) {
13405 char warning_msg
[50];
13407 snprintf(warning_msg
, sizeof(warning_msg
),
13408 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13412 vty_out(vty
, "%s\n", warning_msg
);
13414 json_object_string_add(json
, "warning", warning_msg
);
13417 goto end_table_stats
;
13421 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13422 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13424 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13426 /* labeled-unicast routes live in the unicast table */
13427 if (safi
== SAFI_LABELED_UNICAST
)
13428 safi
= SAFI_UNICAST
;
13430 memset(&ts
, 0, sizeof(ts
));
13431 ts
.table
= bgp
->rib
[afi
][safi
];
13432 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13434 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13435 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13436 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13440 case BGP_STATS_ASPATH_TOTHOPS
:
13441 case BGP_STATS_ASPATH_TOTSIZE
:
13444 temp_buf
, sizeof(temp_buf
), "%12.2f",
13446 ? (float)ts
.counts
[i
]
13448 [BGP_STATS_ASPATH_COUNT
]
13450 vty_out(vty
, "%-30s: %s",
13451 table_stats_strs
[i
]
13452 [TABLE_STATS_IDX_VTY
],
13455 json_object_double_add(
13457 table_stats_strs
[i
]
13458 [TABLE_STATS_IDX_JSON
],
13460 ? (double)ts
.counts
[i
]
13461 / (double)ts
.counts
13462 [BGP_STATS_ASPATH_COUNT
]
13466 case BGP_STATS_TOTPLEN
:
13469 temp_buf
, sizeof(temp_buf
), "%12.2f",
13471 ? (float)ts
.counts
[i
]
13473 [BGP_STATS_PREFIXES
]
13475 vty_out(vty
, "%-30s: %s",
13476 table_stats_strs
[i
]
13477 [TABLE_STATS_IDX_VTY
],
13480 json_object_double_add(
13482 table_stats_strs
[i
]
13483 [TABLE_STATS_IDX_JSON
],
13485 ? (double)ts
.counts
[i
]
13486 / (double)ts
.counts
13487 [BGP_STATS_PREFIXES
]
13491 case BGP_STATS_SPACE
:
13493 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13495 vty_out(vty
, "%-30s: %s\n",
13496 table_stats_strs
[i
]
13497 [TABLE_STATS_IDX_VTY
],
13500 json_object_double_add(
13502 table_stats_strs
[i
]
13503 [TABLE_STATS_IDX_JSON
],
13504 (double)ts
.total_space
);
13506 if (afi
== AFI_IP6
) {
13508 snprintf(temp_buf
, sizeof(temp_buf
),
13511 * pow(2.0, -128 + 32));
13512 vty_out(vty
, "%30s: %s\n",
13513 "/32 equivalent %s\n",
13516 json_object_double_add(
13517 json
, "/32equivalent",
13518 (double)(ts
.total_space
13523 snprintf(temp_buf
, sizeof(temp_buf
),
13526 * pow(2.0, -128 + 48));
13527 vty_out(vty
, "%30s: %s\n",
13528 "/48 equivalent %s\n",
13531 json_object_double_add(
13532 json
, "/48equivalent",
13533 (double)(ts
.total_space
13539 snprintf(temp_buf
, sizeof(temp_buf
),
13541 ts
.total_space
* 100.
13543 vty_out(vty
, "%30s: %s\n",
13544 "% announced ", temp_buf
);
13546 json_object_double_add(
13547 json
, "%announced",
13548 (double)(ts
.total_space
* 100.
13552 snprintf(temp_buf
, sizeof(temp_buf
),
13555 * pow(2.0, -32 + 8));
13556 vty_out(vty
, "%30s: %s\n",
13557 "/8 equivalent ", temp_buf
);
13559 json_object_double_add(
13560 json
, "/8equivalent",
13561 (double)(ts
.total_space
13562 * pow(2.0, -32 + 8)));
13565 snprintf(temp_buf
, sizeof(temp_buf
),
13568 * pow(2.0, -32 + 24));
13569 vty_out(vty
, "%30s: %s\n",
13570 "/24 equivalent ", temp_buf
);
13572 json_object_double_add(
13573 json
, "/24equivalent",
13574 (double)(ts
.total_space
13575 * pow(2.0, -32 + 24)));
13581 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13583 vty_out(vty
, "%-30s: %s",
13584 table_stats_strs
[i
]
13585 [TABLE_STATS_IDX_VTY
],
13588 json_object_int_add(
13590 table_stats_strs
[i
]
13591 [TABLE_STATS_IDX_JSON
],
13596 vty_out(vty
, "\n");
13601 bitlen
= IPV4_MAX_BITLEN
;
13604 bitlen
= IPV6_MAX_BITLEN
;
13607 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13614 json_bitlen
= json_object_new_array();
13616 for (i
= 0; i
<= bitlen
; i
++) {
13617 struct json_object
*ind_bit
= json_object_new_object();
13619 if (!ts
.prefix_len_count
[i
])
13622 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13623 json_object_int_add(ind_bit
, temp_buf
,
13624 ts
.prefix_len_count
[i
]);
13625 json_object_array_add(json_bitlen
, ind_bit
);
13627 json_object_object_add(json
, "prefixLength", json_bitlen
);
13632 json_object_array_add(json_array
, json
);
13636 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13637 safi_t safi
, struct json_object
*json_array
)
13640 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13641 return CMD_SUCCESS
;
13644 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13656 PCOUNT_BPATH_SELECTED
,
13657 PCOUNT_PFCNT
, /* the figure we display to users */
13661 static const char *const pcount_strs
[] = {
13662 [PCOUNT_ADJ_IN
] = "Adj-in",
13663 [PCOUNT_DAMPED
] = "Damped",
13664 [PCOUNT_REMOVED
] = "Removed",
13665 [PCOUNT_HISTORY
] = "History",
13666 [PCOUNT_STALE
] = "Stale",
13667 [PCOUNT_VALID
] = "Valid",
13668 [PCOUNT_ALL
] = "All RIB",
13669 [PCOUNT_COUNTED
] = "PfxCt counted",
13670 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13671 [PCOUNT_PFCNT
] = "Useable",
13672 [PCOUNT_MAX
] = NULL
,
13675 struct peer_pcounts
{
13676 unsigned int count
[PCOUNT_MAX
];
13677 const struct peer
*peer
;
13678 const struct bgp_table
*table
;
13682 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13684 const struct bgp_adj_in
*ain
;
13685 const struct bgp_path_info
*pi
;
13686 const struct peer
*peer
= pc
->peer
;
13688 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13689 if (ain
->peer
== peer
)
13690 pc
->count
[PCOUNT_ADJ_IN
]++;
13692 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13694 if (pi
->peer
!= peer
)
13697 pc
->count
[PCOUNT_ALL
]++;
13699 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13700 pc
->count
[PCOUNT_DAMPED
]++;
13701 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13702 pc
->count
[PCOUNT_HISTORY
]++;
13703 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13704 pc
->count
[PCOUNT_REMOVED
]++;
13705 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13706 pc
->count
[PCOUNT_STALE
]++;
13707 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13708 pc
->count
[PCOUNT_VALID
]++;
13709 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13710 pc
->count
[PCOUNT_PFCNT
]++;
13711 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13712 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13714 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13715 pc
->count
[PCOUNT_COUNTED
]++;
13716 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13718 EC_LIB_DEVELOPMENT
,
13719 "Attempting to count but flags say it is unusable");
13721 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13723 EC_LIB_DEVELOPMENT
,
13724 "Not counted but flags say we should");
13729 static void bgp_peer_count_walker(struct thread
*t
)
13731 struct bgp_dest
*rn
, *rm
;
13732 const struct bgp_table
*table
;
13733 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13735 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13736 || pc
->safi
== SAFI_EVPN
) {
13737 /* Special handling for 2-level routing tables. */
13738 for (rn
= bgp_table_top(pc
->table
); rn
;
13739 rn
= bgp_route_next(rn
)) {
13740 table
= bgp_dest_get_bgp_table_info(rn
);
13742 for (rm
= bgp_table_top(table
); rm
;
13743 rm
= bgp_route_next(rm
))
13744 bgp_peer_count_proc(rm
, pc
);
13747 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13748 bgp_peer_count_proc(rn
, pc
);
13751 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13752 safi_t safi
, bool use_json
)
13754 struct peer_pcounts pcounts
= {.peer
= peer
};
13756 json_object
*json
= NULL
;
13757 json_object
*json_loop
= NULL
;
13760 json
= json_object_new_object();
13761 json_loop
= json_object_new_object();
13764 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13765 || !peer
->bgp
->rib
[afi
][safi
]) {
13767 json_object_string_add(
13769 "No such neighbor or address family");
13770 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13771 json_object_free(json
);
13772 json_object_free(json_loop
);
13774 vty_out(vty
, "%% No such neighbor or address family\n");
13776 return CMD_WARNING
;
13779 memset(&pcounts
, 0, sizeof(pcounts
));
13780 pcounts
.peer
= peer
;
13781 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13782 pcounts
.safi
= safi
;
13784 /* in-place call via thread subsystem so as to record execution time
13785 * stats for the thread-walk (i.e. ensure this can't be blamed on
13786 * on just vty_read()).
13788 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13791 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13792 json_object_string_add(json
, "multiProtocol",
13793 get_afi_safi_str(afi
, safi
, true));
13794 json_object_int_add(json
, "pfxCounter",
13795 peer
->pcount
[afi
][safi
]);
13797 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13798 json_object_int_add(json_loop
, pcount_strs
[i
],
13801 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13803 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13804 json_object_string_add(json
, "pfxctDriftFor",
13806 json_object_string_add(
13807 json
, "recommended",
13808 "Please report this bug, with the above command output");
13810 vty_json(vty
, json
);
13814 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13815 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13816 peer
->hostname
, peer
->host
,
13817 get_afi_safi_str(afi
, safi
, false));
13819 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13820 get_afi_safi_str(afi
, safi
, false));
13823 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13824 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13826 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13827 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13830 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13831 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13833 "Please report this bug, with the above command output\n");
13837 return CMD_SUCCESS
;
13840 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13841 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13842 "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]",
13846 BGP_INSTANCE_HELP_STR
13849 "Detailed information on TCP and BGP neighbor connections\n"
13850 "Neighbor to display information about\n"
13851 "Neighbor to display information about\n"
13852 "Neighbor on BGP configured interface\n"
13853 "Display detailed prefix count information\n"
13856 afi_t afi
= AFI_IP6
;
13857 safi_t safi
= SAFI_UNICAST
;
13860 struct bgp
*bgp
= NULL
;
13861 bool uj
= use_json(argc
, argv
);
13866 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13869 return CMD_WARNING
;
13871 argv_find(argv
, argc
, "neighbors", &idx
);
13872 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13874 return CMD_WARNING
;
13876 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13879 #ifdef KEEP_OLD_VPN_COMMANDS
13880 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13881 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13882 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13887 "Display information about all VPNv4 NLRIs\n"
13888 "Detailed information on TCP and BGP neighbor connections\n"
13889 "Neighbor to display information about\n"
13890 "Neighbor to display information about\n"
13891 "Neighbor on BGP configured interface\n"
13892 "Display detailed prefix count information\n"
13897 bool uj
= use_json(argc
, argv
);
13899 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13901 return CMD_WARNING
;
13903 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13906 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13907 show_ip_bgp_vpn_all_route_prefix_cmd
,
13908 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13913 "Display information about all VPNv4 NLRIs\n"
13914 "Network in the BGP routing table to display\n"
13915 "Network in the BGP routing table to display\n"
13919 char *network
= NULL
;
13920 struct bgp
*bgp
= bgp_get_default();
13922 vty_out(vty
, "Can't find default instance\n");
13923 return CMD_WARNING
;
13926 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13927 network
= argv
[idx
]->arg
;
13928 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13929 network
= argv
[idx
]->arg
;
13931 vty_out(vty
, "Unable to figure out Network\n");
13932 return CMD_WARNING
;
13935 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13936 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13937 use_json(argc
, argv
));
13939 #endif /* KEEP_OLD_VPN_COMMANDS */
13941 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13942 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13943 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13948 "Network in the BGP routing table to display\n"
13949 "Network in the BGP routing table to display\n"
13950 "Network in the BGP routing table to display\n"
13951 "Network in the BGP routing table to display\n"
13955 char *network
= NULL
;
13956 int prefix_check
= 0;
13958 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13959 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13960 network
= argv
[idx
]->arg
;
13961 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13962 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13963 network
= argv
[idx
]->arg
;
13966 vty_out(vty
, "Unable to figure out Network\n");
13967 return CMD_WARNING
;
13969 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13970 prefix_check
, BGP_PATH_SHOW_ALL
,
13971 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13974 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13975 struct bgp_table
*table
, int *header1
,
13976 int *header2
, json_object
*json
,
13977 json_object
*json_scode
,
13978 json_object
*json_ocode
, bool wide
)
13980 uint64_t version
= table
? table
->version
: 0;
13984 json_object_int_add(json
, "bgpTableVersion", version
);
13985 json_object_string_addf(json
, "bgpLocalRouterId",
13986 "%pI4", &peer
->bgp
->router_id
);
13987 json_object_int_add(json
, "defaultLocPrf",
13988 peer
->bgp
->default_local_pref
);
13989 json_object_int_add(json
, "localAS",
13990 peer
->change_local_as
13991 ? peer
->change_local_as
13993 json_object_object_add(json
, "bgpStatusCodes",
13995 json_object_object_add(json
, "bgpOriginCodes",
13999 "BGP table version is %" PRIu64
14000 ", local router ID is %pI4, vrf id ",
14001 version
, &peer
->bgp
->router_id
);
14002 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
14003 vty_out(vty
, "%s", VRFID_NONE_STR
);
14005 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
14006 vty_out(vty
, "\n");
14007 vty_out(vty
, "Default local pref %u, ",
14008 peer
->bgp
->default_local_pref
);
14009 vty_out(vty
, "local AS %u\n",
14010 peer
->change_local_as
? peer
->change_local_as
14012 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14013 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14014 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14015 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14021 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14022 : BGP_SHOW_HEADER
));
14028 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14029 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14030 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14031 json_object
*json_scode
, json_object
*json_ocode
,
14032 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14033 unsigned long *output_count
, unsigned long *filtered_count
)
14035 struct bgp_adj_in
*ain
;
14036 struct bgp_adj_out
*adj
;
14037 struct bgp_dest
*dest
;
14041 struct update_subgroup
*subgrp
;
14042 struct peer_af
*paf
;
14043 bool route_filtered
;
14044 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14045 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14046 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14047 || (safi
== SAFI_EVPN
))
14053 subgrp
= peer_subgroup(peer
, afi
, safi
);
14055 if (type
== bgp_show_adj_route_advertised
&& subgrp
14056 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14058 json_object_int_add(json
, "bgpTableVersion",
14060 json_object_string_addf(json
, "bgpLocalRouterId",
14061 "%pI4", &bgp
->router_id
);
14062 json_object_int_add(json
, "defaultLocPrf",
14063 bgp
->default_local_pref
);
14064 json_object_int_add(json
, "localAS",
14065 peer
->change_local_as
14066 ? peer
->change_local_as
14068 json_object_object_add(json
, "bgpStatusCodes",
14070 json_object_object_add(json
, "bgpOriginCodes",
14072 json_object_string_add(
14073 json
, "bgpOriginatingDefaultNetwork",
14074 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14077 "BGP table version is %" PRIu64
14078 ", local router ID is %pI4, vrf id ",
14079 table
->version
, &bgp
->router_id
);
14080 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14081 vty_out(vty
, "%s", VRFID_NONE_STR
);
14083 vty_out(vty
, "%u", bgp
->vrf_id
);
14084 vty_out(vty
, "\n");
14085 vty_out(vty
, "Default local pref %u, ",
14086 bgp
->default_local_pref
);
14087 vty_out(vty
, "local AS %u\n",
14088 peer
->change_local_as
? peer
->change_local_as
14090 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14091 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14092 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14093 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14095 vty_out(vty
, "Originating default network %s\n\n",
14096 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14102 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14103 if (type
== bgp_show_adj_route_received
14104 || type
== bgp_show_adj_route_filtered
) {
14105 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14106 if (ain
->peer
!= peer
)
14109 show_adj_route_header(vty
, peer
, table
, header1
,
14110 header2
, json
, json_scode
,
14113 if ((safi
== SAFI_MPLS_VPN
)
14114 || (safi
== SAFI_ENCAP
)
14115 || (safi
== SAFI_EVPN
)) {
14117 json_object_string_add(
14118 json_ar
, "rd", rd_str
);
14119 else if (show_rd
&& rd_str
) {
14121 "Route Distinguisher: %s\n",
14128 route_filtered
= false;
14130 /* Filter prefix using distribute list,
14131 * filter list or prefix list
14133 const struct prefix
*rn_p
=
14134 bgp_dest_get_prefix(dest
);
14135 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14138 route_filtered
= true;
14140 /* Filter prefix using route-map */
14141 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14142 safi
, rmap_name
, NULL
,
14145 if (type
== bgp_show_adj_route_filtered
&&
14146 !route_filtered
&& ret
!= RMAP_DENY
) {
14147 bgp_attr_flush(&attr
);
14151 if (type
== bgp_show_adj_route_received
14152 && (route_filtered
|| ret
== RMAP_DENY
))
14153 (*filtered_count
)++;
14155 route_vty_out_tmp(vty
, dest
, rn_p
, &attr
, safi
,
14156 use_json
, json_ar
, wide
);
14157 bgp_attr_flush(&attr
);
14160 } else if (type
== bgp_show_adj_route_advertised
) {
14161 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14162 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14163 if (paf
->peer
!= peer
|| !adj
->attr
)
14166 show_adj_route_header(vty
, peer
, table
,
14171 const struct prefix
*rn_p
=
14172 bgp_dest_get_prefix(dest
);
14175 ret
= bgp_output_modifier(
14176 peer
, rn_p
, &attr
, afi
, safi
,
14179 if (ret
!= RMAP_DENY
) {
14180 if ((safi
== SAFI_MPLS_VPN
)
14181 || (safi
== SAFI_ENCAP
)
14182 || (safi
== SAFI_EVPN
)) {
14184 json_object_string_add(
14191 "Route Distinguisher: %s\n",
14197 vty
, dest
, rn_p
, &attr
,
14198 safi
, use_json
, json_ar
,
14202 (*filtered_count
)++;
14205 bgp_attr_flush(&attr
);
14207 } else if (type
== bgp_show_adj_route_bestpath
) {
14208 struct bgp_path_info
*pi
;
14210 show_adj_route_header(vty
, peer
, table
, header1
,
14211 header2
, json
, json_scode
,
14214 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14216 if (pi
->peer
!= peer
)
14219 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14222 route_vty_out_tmp(vty
, dest
,
14223 bgp_dest_get_prefix(dest
),
14224 pi
->attr
, safi
, use_json
,
14232 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14233 safi_t safi
, enum bgp_show_adj_route_type type
,
14234 const char *rmap_name
, uint16_t show_flags
)
14237 struct bgp_table
*table
;
14238 json_object
*json
= NULL
;
14239 json_object
*json_scode
= NULL
;
14240 json_object
*json_ocode
= NULL
;
14241 json_object
*json_ar
= NULL
;
14242 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14244 /* Init BGP headers here so they're only displayed once
14245 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14251 * Initialize variables for each RD
14252 * All prefixes under an RD is aggregated within "json_routes"
14254 char rd_str
[BUFSIZ
] = {0};
14255 json_object
*json_routes
= NULL
;
14258 /* For 2-tier tables, prefix counts need to be
14259 * maintained across multiple runs of show_adj_route()
14261 unsigned long output_count_per_rd
;
14262 unsigned long filtered_count_per_rd
;
14263 unsigned long output_count
= 0;
14264 unsigned long filtered_count
= 0;
14267 json
= json_object_new_object();
14268 json_ar
= json_object_new_object();
14269 json_scode
= json_object_new_object();
14270 json_ocode
= json_object_new_object();
14271 #if CONFDATE > 20231208
14272 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14274 json_object_string_add(json_scode
, "suppressed", "s");
14275 json_object_string_add(json_scode
, "damped", "d");
14276 json_object_string_add(json_scode
, "history", "h");
14277 json_object_string_add(json_scode
, "valid", "*");
14278 json_object_string_add(json_scode
, "best", ">");
14279 json_object_string_add(json_scode
, "multipath", "=");
14280 json_object_string_add(json_scode
, "internal", "i");
14281 json_object_string_add(json_scode
, "ribFailure", "r");
14282 json_object_string_add(json_scode
, "stale", "S");
14283 json_object_string_add(json_scode
, "removed", "R");
14285 #if CONFDATE > 20231208
14286 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14288 json_object_string_add(json_ocode
, "igp", "i");
14289 json_object_string_add(json_ocode
, "egp", "e");
14290 json_object_string_add(json_ocode
, "incomplete", "?");
14293 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14295 json_object_string_add(
14297 "No such neighbor or address family");
14298 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14299 json_object_free(json
);
14300 json_object_free(json_ar
);
14301 json_object_free(json_scode
);
14302 json_object_free(json_ocode
);
14304 vty_out(vty
, "%% No such neighbor or address family\n");
14306 return CMD_WARNING
;
14309 if ((type
== bgp_show_adj_route_received
14310 || type
== bgp_show_adj_route_filtered
)
14311 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14312 PEER_FLAG_SOFT_RECONFIG
)) {
14314 json_object_string_add(
14316 "Inbound soft reconfiguration not enabled");
14317 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14318 json_object_free(json
);
14319 json_object_free(json_ar
);
14320 json_object_free(json_scode
);
14321 json_object_free(json_ocode
);
14324 "%% Inbound soft reconfiguration not enabled\n");
14326 return CMD_WARNING
;
14331 /* labeled-unicast routes live in the unicast table */
14332 if (safi
== SAFI_LABELED_UNICAST
)
14333 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14335 table
= bgp
->rib
[afi
][safi
];
14337 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14338 || (safi
== SAFI_EVPN
)) {
14340 struct bgp_dest
*dest
;
14342 for (dest
= bgp_table_top(table
); dest
;
14343 dest
= bgp_route_next(dest
)) {
14344 table
= bgp_dest_get_bgp_table_info(dest
);
14348 output_count_per_rd
= 0;
14349 filtered_count_per_rd
= 0;
14352 json_routes
= json_object_new_object();
14354 const struct prefix_rd
*prd
;
14355 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14358 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
14360 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
14361 rmap_name
, json
, json_routes
, json_scode
,
14362 json_ocode
, show_flags
, &header1
,
14363 &header2
, rd_str
, &output_count_per_rd
,
14364 &filtered_count_per_rd
);
14366 /* Don't include an empty RD in the output! */
14367 if (json_routes
&& (output_count_per_rd
> 0))
14368 json_object_object_add(json_ar
, rd_str
,
14371 output_count
+= output_count_per_rd
;
14372 filtered_count
+= filtered_count_per_rd
;
14375 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14376 json
, json_ar
, json_scode
, json_ocode
,
14377 show_flags
, &header1
, &header2
, rd_str
,
14378 &output_count
, &filtered_count
);
14381 if (type
== bgp_show_adj_route_advertised
)
14382 json_object_object_add(json
, "advertisedRoutes",
14385 json_object_object_add(json
, "receivedRoutes", json_ar
);
14386 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14387 json_object_int_add(json
, "filteredPrefixCounter",
14391 * These fields only give up ownership to `json` when `header1`
14392 * is used (set to zero). See code in `show_adj_route` and
14393 * `show_adj_route_header`.
14395 if (header1
== 1) {
14396 json_object_free(json_scode
);
14397 json_object_free(json_ocode
);
14400 vty_json(vty
, json
);
14401 } else if (output_count
> 0) {
14402 if (filtered_count
> 0)
14404 "\nTotal number of prefixes %ld (%ld filtered)\n",
14405 output_count
, filtered_count
);
14407 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14411 return CMD_SUCCESS
;
14414 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14415 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14416 "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]",
14420 BGP_INSTANCE_HELP_STR
14422 BGP_SAFI_WITH_LABEL_HELP_STR
14423 "Detailed information on TCP and BGP neighbor connections\n"
14424 "Neighbor to display information about\n"
14425 "Neighbor to display information about\n"
14426 "Neighbor on BGP configured interface\n"
14427 "Display the routes selected by best path\n"
14429 "Increase table width for longer prefixes\n")
14431 afi_t afi
= AFI_IP6
;
14432 safi_t safi
= SAFI_UNICAST
;
14433 char *rmap_name
= NULL
;
14434 char *peerstr
= NULL
;
14435 struct bgp
*bgp
= NULL
;
14437 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14439 uint16_t show_flags
= 0;
14442 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14445 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14447 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14451 return CMD_WARNING
;
14453 argv_find(argv
, argc
, "neighbors", &idx
);
14454 peerstr
= argv
[++idx
]->arg
;
14456 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14458 return CMD_WARNING
;
14460 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
14464 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
14465 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14466 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [json$uj | wide$wide]",
14470 BGP_INSTANCE_HELP_STR
14472 BGP_SAFI_WITH_LABEL_HELP_STR
14473 "Display the entries for all address families\n"
14474 "Detailed information on TCP and BGP neighbor connections\n"
14475 "Neighbor to display information about\n"
14476 "Neighbor to display information about\n"
14477 "Neighbor on BGP configured interface\n"
14478 "Display the routes advertised to a BGP neighbor\n"
14479 "Display the received routes from neighbor\n"
14480 "Display the filtered routes received from neighbor\n"
14481 "Route-map to modify the attributes\n"
14482 "Name of the route map\n"
14484 "Increase table width for longer prefixes\n")
14486 afi_t afi
= AFI_IP6
;
14487 safi_t safi
= SAFI_UNICAST
;
14488 char *peerstr
= NULL
;
14489 struct bgp
*bgp
= NULL
;
14491 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14494 uint16_t show_flags
= 0;
14495 struct listnode
*node
;
14500 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14504 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14505 if (argv_find(argv
, argc
, "ipv4", &idx
))
14506 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14508 if (argv_find(argv
, argc
, "ipv6", &idx
))
14509 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14513 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14515 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14518 return CMD_WARNING
;
14520 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14521 argv_find(argv
, argc
, "neighbors", &idx
);
14522 peerstr
= argv
[++idx
]->arg
;
14524 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14526 return CMD_WARNING
;
14528 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14529 type
= bgp_show_adj_route_advertised
;
14530 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14531 type
= bgp_show_adj_route_received
;
14532 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14533 type
= bgp_show_adj_route_filtered
;
14536 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14539 vty_out(vty
, "{\n");
14541 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14542 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14543 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14545 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14546 FOREACH_SAFI (safi
) {
14547 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14554 vty_out(vty
, ",\n");
14555 vty_out(vty
, "\"%s\":",
14556 get_afi_safi_str(afi
, safi
,
14560 "\nFor address family: %s\n",
14561 get_afi_safi_str(afi
, safi
,
14564 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14565 route_map
, show_flags
);
14569 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14570 FOREACH_AFI_SAFI (afi
, safi
) {
14571 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14578 vty_out(vty
, ",\n");
14579 vty_out(vty
, "\"%s\":",
14580 get_afi_safi_str(afi
, safi
,
14584 "\nFor address family: %s\n",
14585 get_afi_safi_str(afi
, safi
,
14588 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14589 route_map
, show_flags
);
14594 vty_out(vty
, "}\n");
14596 return CMD_SUCCESS
;
14599 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14600 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14601 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14605 BGP_INSTANCE_HELP_STR
14608 BGP_AF_MODIFIER_STR
14609 "Detailed information on TCP and BGP neighbor connections\n"
14610 "Neighbor to display information about\n"
14611 "Neighbor to display information about\n"
14612 "Neighbor on BGP configured interface\n"
14613 "Display information received from a BGP neighbor\n"
14614 "Display the prefixlist filter\n"
14617 afi_t afi
= AFI_IP6
;
14618 safi_t safi
= SAFI_UNICAST
;
14619 char *peerstr
= NULL
;
14624 struct bgp
*bgp
= NULL
;
14625 bool uj
= use_json(argc
, argv
);
14630 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14633 return CMD_WARNING
;
14635 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14636 argv_find(argv
, argc
, "neighbors", &idx
);
14637 peerstr
= argv
[++idx
]->arg
;
14639 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14641 return CMD_WARNING
;
14643 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14644 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14647 vty_out(vty
, "Address Family: %s\n",
14648 get_afi_safi_str(afi
, safi
, false));
14649 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14652 vty_out(vty
, "{}\n");
14654 vty_out(vty
, "No functional output\n");
14657 return CMD_SUCCESS
;
14660 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14661 afi_t afi
, safi_t safi
,
14662 enum bgp_show_type type
, bool use_json
)
14664 uint16_t show_flags
= 0;
14667 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14669 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14671 json_object
*json_no
= NULL
;
14672 json_no
= json_object_new_object();
14673 json_object_string_add(
14674 json_no
, "warning",
14675 "No such neighbor or address family");
14676 vty_out(vty
, "%s\n",
14677 json_object_to_json_string(json_no
));
14678 json_object_free(json_no
);
14680 vty_out(vty
, "%% No such neighbor or address family\n");
14681 return CMD_WARNING
;
14684 /* labeled-unicast routes live in the unicast table */
14685 if (safi
== SAFI_LABELED_UNICAST
)
14686 safi
= SAFI_UNICAST
;
14688 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14689 RPKI_NOT_BEING_USED
);
14692 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14693 show_ip_bgp_flowspec_routes_detailed_cmd
,
14694 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14698 BGP_INSTANCE_HELP_STR
14701 "Detailed information on flowspec entries\n"
14704 afi_t afi
= AFI_IP6
;
14705 safi_t safi
= SAFI_UNICAST
;
14706 struct bgp
*bgp
= NULL
;
14708 bool uj
= use_json(argc
, argv
);
14709 uint16_t show_flags
= BGP_SHOW_OPT_DETAIL
;
14713 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14716 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14719 return CMD_WARNING
;
14721 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14722 show_flags
, RPKI_NOT_BEING_USED
);
14725 DEFUN (show_ip_bgp_neighbor_routes
,
14726 show_ip_bgp_neighbor_routes_cmd
,
14727 "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]",
14731 BGP_INSTANCE_HELP_STR
14733 BGP_SAFI_WITH_LABEL_HELP_STR
14734 "Detailed information on TCP and BGP neighbor connections\n"
14735 "Neighbor to display information about\n"
14736 "Neighbor to display information about\n"
14737 "Neighbor on BGP configured interface\n"
14738 "Display flap statistics of the routes learned from neighbor\n"
14739 "Display the dampened routes received from neighbor\n"
14740 "Display routes learned from neighbor\n"
14743 char *peerstr
= NULL
;
14744 struct bgp
*bgp
= NULL
;
14745 afi_t afi
= AFI_IP6
;
14746 safi_t safi
= SAFI_UNICAST
;
14748 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14750 bool uj
= use_json(argc
, argv
);
14755 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14758 return CMD_WARNING
;
14760 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14761 argv_find(argv
, argc
, "neighbors", &idx
);
14762 peerstr
= argv
[++idx
]->arg
;
14764 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14766 return CMD_WARNING
;
14768 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14769 sh_type
= bgp_show_type_flap_neighbor
;
14770 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14771 sh_type
= bgp_show_type_damp_neighbor
;
14772 else if (argv_find(argv
, argc
, "routes", &idx
))
14773 sh_type
= bgp_show_type_neighbor
;
14775 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14778 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14780 struct bgp_distance
{
14781 /* Distance value for the IP source prefix. */
14784 /* Name of the access-list to be matched. */
14788 DEFUN (show_bgp_afi_vpn_rd_route
,
14789 show_bgp_afi_vpn_rd_route_cmd
,
14790 "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]",
14794 BGP_AF_MODIFIER_STR
14795 "Display information for a route distinguisher\n"
14796 "Route Distinguisher\n"
14797 "All Route Distinguishers\n"
14798 "Network in the BGP routing table to display\n"
14799 "Network in the BGP routing table to display\n"
14803 struct prefix_rd prd
;
14804 afi_t afi
= AFI_MAX
;
14807 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14808 vty_out(vty
, "%% Malformed Address Family\n");
14809 return CMD_WARNING
;
14812 if (!strcmp(argv
[5]->arg
, "all"))
14813 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14814 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14815 RPKI_NOT_BEING_USED
,
14816 use_json(argc
, argv
));
14818 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14820 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14821 return CMD_WARNING
;
14824 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14825 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14826 use_json(argc
, argv
));
14829 static struct bgp_distance
*bgp_distance_new(void)
14831 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14834 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14836 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14839 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14840 const char *ip_str
, const char *access_list_str
)
14847 struct bgp_dest
*dest
;
14848 struct bgp_distance
*bdistance
;
14850 afi
= bgp_node_afi(vty
);
14851 safi
= bgp_node_safi(vty
);
14853 ret
= str2prefix(ip_str
, &p
);
14855 vty_out(vty
, "Malformed prefix\n");
14856 return CMD_WARNING_CONFIG_FAILED
;
14859 distance
= atoi(distance_str
);
14861 /* Get BGP distance node. */
14862 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
14863 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14865 bgp_dest_unlock_node(dest
);
14867 bdistance
= bgp_distance_new();
14868 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
14871 /* Set distance value. */
14872 bdistance
->distance
= distance
;
14874 /* Reset access-list configuration. */
14875 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14876 if (access_list_str
)
14877 bdistance
->access_list
=
14878 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
14880 return CMD_SUCCESS
;
14883 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
14884 const char *ip_str
, const char *access_list_str
)
14891 struct bgp_dest
*dest
;
14892 struct bgp_distance
*bdistance
;
14894 afi
= bgp_node_afi(vty
);
14895 safi
= bgp_node_safi(vty
);
14897 ret
= str2prefix(ip_str
, &p
);
14899 vty_out(vty
, "Malformed prefix\n");
14900 return CMD_WARNING_CONFIG_FAILED
;
14903 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
14905 vty_out(vty
, "Can't find specified prefix\n");
14906 return CMD_WARNING_CONFIG_FAILED
;
14909 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14910 distance
= atoi(distance_str
);
14912 if (bdistance
->distance
!= distance
) {
14913 vty_out(vty
, "Distance does not match configured\n");
14914 bgp_dest_unlock_node(dest
);
14915 return CMD_WARNING_CONFIG_FAILED
;
14918 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
14919 bgp_distance_free(bdistance
);
14921 bgp_dest_set_bgp_path_info(dest
, NULL
);
14922 bgp_dest_unlock_node(dest
);
14923 bgp_dest_unlock_node(dest
);
14925 return CMD_SUCCESS
;
14928 /* Apply BGP information to distance method. */
14929 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
14930 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
14932 struct bgp_dest
*dest
;
14933 struct prefix q
= {0};
14935 struct bgp_distance
*bdistance
;
14936 struct access_list
*alist
;
14937 struct bgp_static
*bgp_static
;
14942 peer
= pinfo
->peer
;
14944 if (pinfo
->attr
->distance
)
14945 return pinfo
->attr
->distance
;
14947 /* Check source address.
14948 * Note: for aggregate route, peer can have unspec af type.
14950 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
14951 && !sockunion2hostprefix(&peer
->su
, &q
))
14954 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
14956 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14957 bgp_dest_unlock_node(dest
);
14959 if (bdistance
->access_list
) {
14960 alist
= access_list_lookup(afi
, bdistance
->access_list
);
14962 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
14963 return bdistance
->distance
;
14965 return bdistance
->distance
;
14968 /* Backdoor check. */
14969 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14971 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14972 bgp_dest_unlock_node(dest
);
14974 if (bgp_static
->backdoor
) {
14975 if (bgp
->distance_local
[afi
][safi
])
14976 return bgp
->distance_local
[afi
][safi
];
14978 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14982 if (peer
->sort
== BGP_PEER_EBGP
) {
14983 if (bgp
->distance_ebgp
[afi
][safi
])
14984 return bgp
->distance_ebgp
[afi
][safi
];
14985 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14986 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14987 if (bgp
->distance_ibgp
[afi
][safi
])
14988 return bgp
->distance_ibgp
[afi
][safi
];
14989 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14991 if (bgp
->distance_local
[afi
][safi
])
14992 return bgp
->distance_local
[afi
][safi
];
14993 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14997 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14998 * we should tell ZEBRA update the routes for a specific
14999 * AFI/SAFI to reflect changes in RIB.
15001 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15003 safi_t update_safi
)
15008 FOREACH_AFI_SAFI (afi
, safi
) {
15009 if (!bgp_fibupd_safi(safi
))
15012 if (afi
!= update_afi
&& safi
!= update_safi
)
15015 if (BGP_DEBUG(zebra
, ZEBRA
))
15017 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15018 __func__
, afi
, safi
);
15019 bgp_zebra_announce_table(bgp
, afi
, safi
);
15023 DEFUN (bgp_distance
,
15025 "distance bgp (1-255) (1-255) (1-255)",
15026 "Define an administrative distance\n"
15028 "Distance for routes external to the AS\n"
15029 "Distance for routes internal to the AS\n"
15030 "Distance for local routes\n")
15032 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15033 int idx_number
= 2;
15034 int idx_number_2
= 3;
15035 int idx_number_3
= 4;
15036 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15037 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15038 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15042 afi
= bgp_node_afi(vty
);
15043 safi
= bgp_node_safi(vty
);
15045 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15046 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15047 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15048 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15049 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15050 bgp
->distance_local
[afi
][safi
] = distance_local
;
15051 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15053 return CMD_SUCCESS
;
15056 DEFUN (no_bgp_distance
,
15057 no_bgp_distance_cmd
,
15058 "no distance bgp [(1-255) (1-255) (1-255)]",
15060 "Define an administrative distance\n"
15062 "Distance for routes external to the AS\n"
15063 "Distance for routes internal to the AS\n"
15064 "Distance for local routes\n")
15066 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15070 afi
= bgp_node_afi(vty
);
15071 safi
= bgp_node_safi(vty
);
15073 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15074 || bgp
->distance_ibgp
[afi
][safi
] != 0
15075 || bgp
->distance_local
[afi
][safi
] != 0) {
15076 bgp
->distance_ebgp
[afi
][safi
] = 0;
15077 bgp
->distance_ibgp
[afi
][safi
] = 0;
15078 bgp
->distance_local
[afi
][safi
] = 0;
15079 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15081 return CMD_SUCCESS
;
15085 DEFUN (bgp_distance_source
,
15086 bgp_distance_source_cmd
,
15087 "distance (1-255) A.B.C.D/M",
15088 "Define an administrative distance\n"
15089 "Administrative distance\n"
15090 "IP source prefix\n")
15092 int idx_number
= 1;
15093 int idx_ipv4_prefixlen
= 2;
15094 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15095 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15096 return CMD_SUCCESS
;
15099 DEFUN (no_bgp_distance_source
,
15100 no_bgp_distance_source_cmd
,
15101 "no distance (1-255) A.B.C.D/M",
15103 "Define an administrative distance\n"
15104 "Administrative distance\n"
15105 "IP source prefix\n")
15107 int idx_number
= 2;
15108 int idx_ipv4_prefixlen
= 3;
15109 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15110 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15111 return CMD_SUCCESS
;
15114 DEFUN (bgp_distance_source_access_list
,
15115 bgp_distance_source_access_list_cmd
,
15116 "distance (1-255) A.B.C.D/M WORD",
15117 "Define an administrative distance\n"
15118 "Administrative distance\n"
15119 "IP source prefix\n"
15120 "Access list name\n")
15122 int idx_number
= 1;
15123 int idx_ipv4_prefixlen
= 2;
15125 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15126 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15127 return CMD_SUCCESS
;
15130 DEFUN (no_bgp_distance_source_access_list
,
15131 no_bgp_distance_source_access_list_cmd
,
15132 "no distance (1-255) A.B.C.D/M WORD",
15134 "Define an administrative distance\n"
15135 "Administrative distance\n"
15136 "IP source prefix\n"
15137 "Access list name\n")
15139 int idx_number
= 2;
15140 int idx_ipv4_prefixlen
= 3;
15142 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15143 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15144 return CMD_SUCCESS
;
15147 DEFUN (ipv6_bgp_distance_source
,
15148 ipv6_bgp_distance_source_cmd
,
15149 "distance (1-255) X:X::X:X/M",
15150 "Define an administrative distance\n"
15151 "Administrative distance\n"
15152 "IP source prefix\n")
15154 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15155 return CMD_SUCCESS
;
15158 DEFUN (no_ipv6_bgp_distance_source
,
15159 no_ipv6_bgp_distance_source_cmd
,
15160 "no distance (1-255) X:X::X:X/M",
15162 "Define an administrative distance\n"
15163 "Administrative distance\n"
15164 "IP source prefix\n")
15166 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15167 return CMD_SUCCESS
;
15170 DEFUN (ipv6_bgp_distance_source_access_list
,
15171 ipv6_bgp_distance_source_access_list_cmd
,
15172 "distance (1-255) X:X::X:X/M WORD",
15173 "Define an administrative distance\n"
15174 "Administrative distance\n"
15175 "IP source prefix\n"
15176 "Access list name\n")
15178 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15179 return CMD_SUCCESS
;
15182 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15183 no_ipv6_bgp_distance_source_access_list_cmd
,
15184 "no distance (1-255) X:X::X:X/M WORD",
15186 "Define an administrative distance\n"
15187 "Administrative distance\n"
15188 "IP source prefix\n"
15189 "Access list name\n")
15191 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15192 return CMD_SUCCESS
;
15195 DEFUN (bgp_damp_set
,
15197 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15198 "BGP Specific commands\n"
15199 "Enable route-flap dampening\n"
15200 "Half-life time for the penalty\n"
15201 "Value to start reusing a route\n"
15202 "Value to start suppressing a route\n"
15203 "Maximum duration to suppress a stable route\n")
15205 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15206 int idx_half_life
= 2;
15208 int idx_suppress
= 4;
15209 int idx_max_suppress
= 5;
15210 int half
= DEFAULT_HALF_LIFE
* 60;
15211 int reuse
= DEFAULT_REUSE
;
15212 int suppress
= DEFAULT_SUPPRESS
;
15213 int max
= 4 * half
;
15216 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15217 reuse
= atoi(argv
[idx_reuse
]->arg
);
15218 suppress
= atoi(argv
[idx_suppress
]->arg
);
15219 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15220 } else if (argc
== 3) {
15221 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15226 * These can't be 0 but our SA doesn't understand the
15227 * way our cli is constructed
15231 if (suppress
< reuse
) {
15233 "Suppress value cannot be less than reuse value \n");
15237 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15238 reuse
, suppress
, max
);
15241 DEFUN (bgp_damp_unset
,
15242 bgp_damp_unset_cmd
,
15243 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15245 "BGP Specific commands\n"
15246 "Enable route-flap dampening\n"
15247 "Half-life time for the penalty\n"
15248 "Value to start reusing a route\n"
15249 "Value to start suppressing a route\n"
15250 "Maximum duration to suppress a stable route\n")
15252 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15253 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15256 /* Display specified route of BGP table. */
15257 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15258 const char *ip_str
, afi_t afi
, safi_t safi
,
15259 struct prefix_rd
*prd
, int prefix_check
)
15262 struct prefix match
;
15263 struct bgp_dest
*dest
;
15264 struct bgp_dest
*rm
;
15265 struct bgp_path_info
*pi
;
15266 struct bgp_path_info
*pi_temp
;
15268 struct bgp_table
*table
;
15270 /* BGP structure lookup. */
15272 bgp
= bgp_lookup_by_name(view_name
);
15274 vty_out(vty
, "%% Can't find BGP instance %s\n",
15276 return CMD_WARNING
;
15279 bgp
= bgp_get_default();
15281 vty_out(vty
, "%% No BGP process is configured\n");
15282 return CMD_WARNING
;
15286 /* Check IP address argument. */
15287 ret
= str2prefix(ip_str
, &match
);
15289 vty_out(vty
, "%% address is malformed\n");
15290 return CMD_WARNING
;
15293 match
.family
= afi2family(afi
);
15295 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15296 || (safi
== SAFI_EVPN
)) {
15297 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15298 dest
= bgp_route_next(dest
)) {
15299 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15301 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15303 table
= bgp_dest_get_bgp_table_info(dest
);
15306 rm
= bgp_node_match(table
, &match
);
15310 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15313 || rm_p
->prefixlen
== match
.prefixlen
) {
15314 pi
= bgp_dest_get_bgp_path_info(rm
);
15316 if (pi
->extra
&& pi
->extra
->damp_info
) {
15317 pi_temp
= pi
->next
;
15318 bgp_damp_info_free(
15319 pi
->extra
->damp_info
,
15327 bgp_dest_unlock_node(rm
);
15330 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15331 if (dest
!= NULL
) {
15332 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15335 || dest_p
->prefixlen
== match
.prefixlen
) {
15336 pi
= bgp_dest_get_bgp_path_info(dest
);
15338 if (pi
->extra
&& pi
->extra
->damp_info
) {
15339 pi_temp
= pi
->next
;
15340 bgp_damp_info_free(
15341 pi
->extra
->damp_info
,
15349 bgp_dest_unlock_node(dest
);
15353 return CMD_SUCCESS
;
15356 DEFUN (clear_ip_bgp_dampening
,
15357 clear_ip_bgp_dampening_cmd
,
15358 "clear ip bgp dampening",
15362 "Clear route flap dampening information\n")
15364 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15365 return CMD_SUCCESS
;
15368 DEFUN (clear_ip_bgp_dampening_prefix
,
15369 clear_ip_bgp_dampening_prefix_cmd
,
15370 "clear ip bgp dampening A.B.C.D/M",
15374 "Clear route flap dampening information\n"
15377 int idx_ipv4_prefixlen
= 4;
15378 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15379 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15382 DEFUN (clear_ip_bgp_dampening_address
,
15383 clear_ip_bgp_dampening_address_cmd
,
15384 "clear ip bgp dampening A.B.C.D",
15388 "Clear route flap dampening information\n"
15389 "Network to clear damping information\n")
15392 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15393 SAFI_UNICAST
, NULL
, 0);
15396 DEFUN (clear_ip_bgp_dampening_address_mask
,
15397 clear_ip_bgp_dampening_address_mask_cmd
,
15398 "clear ip bgp dampening A.B.C.D A.B.C.D",
15402 "Clear route flap dampening information\n"
15403 "Network to clear damping information\n"
15407 int idx_ipv4_2
= 5;
15409 char prefix_str
[BUFSIZ
];
15411 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15412 prefix_str
, sizeof(prefix_str
));
15414 vty_out(vty
, "%% Inconsistent address and mask\n");
15415 return CMD_WARNING
;
15418 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15422 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15424 struct vty
*vty
= arg
;
15425 struct peer
*peer
= bucket
->data
;
15427 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15430 DEFUN (show_bgp_listeners
,
15431 show_bgp_listeners_cmd
,
15432 "show bgp listeners",
15435 "Display Listen Sockets and who created them\n")
15437 bgp_dump_listener_info(vty
);
15439 return CMD_SUCCESS
;
15442 DEFUN (show_bgp_peerhash
,
15443 show_bgp_peerhash_cmd
,
15444 "show bgp peerhash",
15447 "Display information about the BGP peerhash\n")
15449 struct list
*instances
= bm
->bgp
;
15450 struct listnode
*node
;
15453 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15454 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15455 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15459 return CMD_SUCCESS
;
15462 /* also used for encap safi */
15463 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15464 afi_t afi
, safi_t safi
)
15466 struct bgp_dest
*pdest
;
15467 struct bgp_dest
*dest
;
15468 struct bgp_table
*table
;
15469 const struct prefix
*p
;
15470 const struct prefix_rd
*prd
;
15471 struct bgp_static
*bgp_static
;
15472 mpls_label_t label
;
15474 /* Network configuration. */
15475 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15476 pdest
= bgp_route_next(pdest
)) {
15477 table
= bgp_dest_get_bgp_table_info(pdest
);
15481 for (dest
= bgp_table_top(table
); dest
;
15482 dest
= bgp_route_next(dest
)) {
15483 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15484 if (bgp_static
== NULL
)
15487 p
= bgp_dest_get_prefix(dest
);
15488 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
15491 /* "network" configuration display. */
15492 label
= decode_label(&bgp_static
->label
);
15494 vty_out(vty
, " network %pFX rd %pRD", p
, prd
);
15495 if (safi
== SAFI_MPLS_VPN
)
15496 vty_out(vty
, " label %u", label
);
15498 if (bgp_static
->rmap
.name
)
15499 vty_out(vty
, " route-map %s",
15500 bgp_static
->rmap
.name
);
15502 if (bgp_static
->backdoor
)
15503 vty_out(vty
, " backdoor");
15505 vty_out(vty
, "\n");
15510 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15511 afi_t afi
, safi_t safi
)
15513 struct bgp_dest
*pdest
;
15514 struct bgp_dest
*dest
;
15515 struct bgp_table
*table
;
15516 const struct prefix
*p
;
15517 const struct prefix_rd
*prd
;
15518 struct bgp_static
*bgp_static
;
15519 char buf
[PREFIX_STRLEN
* 2];
15520 char buf2
[SU_ADDRSTRLEN
];
15521 char esi_buf
[ESI_STR_LEN
];
15523 /* Network configuration. */
15524 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15525 pdest
= bgp_route_next(pdest
)) {
15526 table
= bgp_dest_get_bgp_table_info(pdest
);
15530 for (dest
= bgp_table_top(table
); dest
;
15531 dest
= bgp_route_next(dest
)) {
15532 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15533 if (bgp_static
== NULL
)
15536 char *macrouter
= NULL
;
15538 if (bgp_static
->router_mac
)
15539 macrouter
= prefix_mac2str(
15540 bgp_static
->router_mac
, NULL
, 0);
15541 if (bgp_static
->eth_s_id
)
15542 esi_to_str(bgp_static
->eth_s_id
,
15543 esi_buf
, sizeof(esi_buf
));
15544 p
= bgp_dest_get_prefix(dest
);
15545 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
15547 /* "network" configuration display. */
15548 if (p
->u
.prefix_evpn
.route_type
== 5) {
15549 char local_buf
[PREFIX_STRLEN
];
15551 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15552 struct prefix_evpn
*)p
)
15556 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15558 local_buf
, sizeof(local_buf
));
15559 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15560 p
->u
.prefix_evpn
.prefix_addr
15561 .ip_prefix_length
);
15563 prefix2str(p
, buf
, sizeof(buf
));
15566 if (bgp_static
->gatewayIp
.family
== AF_INET
15567 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15568 inet_ntop(bgp_static
->gatewayIp
.family
,
15569 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15572 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15573 buf
, prd
, p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15574 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15577 XFREE(MTYPE_TMP
, macrouter
);
15582 /* Configuration of static route announcement and aggregate
15584 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15587 struct bgp_dest
*dest
;
15588 const struct prefix
*p
;
15589 struct bgp_static
*bgp_static
;
15590 struct bgp_aggregate
*bgp_aggregate
;
15592 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15593 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15597 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15598 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15602 /* Network configuration. */
15603 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15604 dest
= bgp_route_next(dest
)) {
15605 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15606 if (bgp_static
== NULL
)
15609 p
= bgp_dest_get_prefix(dest
);
15611 vty_out(vty
, " network %pFX", p
);
15613 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15614 vty_out(vty
, " label-index %u",
15615 bgp_static
->label_index
);
15617 if (bgp_static
->rmap
.name
)
15618 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15620 if (bgp_static
->backdoor
)
15621 vty_out(vty
, " backdoor");
15623 vty_out(vty
, "\n");
15626 /* Aggregate-address configuration. */
15627 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15628 dest
= bgp_route_next(dest
)) {
15629 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15630 if (bgp_aggregate
== NULL
)
15633 p
= bgp_dest_get_prefix(dest
);
15635 vty_out(vty
, " aggregate-address %pFX", p
);
15637 if (bgp_aggregate
->as_set
)
15638 vty_out(vty
, " as-set");
15640 if (bgp_aggregate
->summary_only
)
15641 vty_out(vty
, " summary-only");
15643 if (bgp_aggregate
->rmap
.name
)
15644 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15646 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15647 vty_out(vty
, " origin %s",
15648 bgp_origin2str(bgp_aggregate
->origin
));
15650 if (bgp_aggregate
->match_med
)
15651 vty_out(vty
, " matching-MED-only");
15653 if (bgp_aggregate
->suppress_map_name
)
15654 vty_out(vty
, " suppress-map %s",
15655 bgp_aggregate
->suppress_map_name
);
15657 vty_out(vty
, "\n");
15661 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15664 struct bgp_dest
*dest
;
15665 struct bgp_distance
*bdistance
;
15667 /* Distance configuration. */
15668 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15669 && bgp
->distance_local
[afi
][safi
]
15670 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15671 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15672 || bgp
->distance_local
[afi
][safi
]
15673 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15674 vty_out(vty
, " distance bgp %d %d %d\n",
15675 bgp
->distance_ebgp
[afi
][safi
],
15676 bgp
->distance_ibgp
[afi
][safi
],
15677 bgp
->distance_local
[afi
][safi
]);
15680 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15681 dest
= bgp_route_next(dest
)) {
15682 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15683 if (bdistance
!= NULL
)
15684 vty_out(vty
, " distance %d %pBD %s\n",
15685 bdistance
->distance
, dest
,
15686 bdistance
->access_list
? bdistance
->access_list
15691 /* Allocate routing table structure and install commands. */
15692 void bgp_route_init(void)
15697 /* Init BGP distance table. */
15698 FOREACH_AFI_SAFI (afi
, safi
)
15699 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15701 /* IPv4 BGP commands. */
15702 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15703 install_element(BGP_NODE
, &bgp_network_cmd
);
15704 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15706 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15708 /* IPv4 unicast configuration. */
15709 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15710 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15711 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15713 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15715 /* IPv4 multicast configuration. */
15716 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15717 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15718 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15719 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15721 /* IPv4 labeled-unicast configuration. */
15722 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15723 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15725 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15726 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15727 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15728 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15729 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15730 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15731 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15732 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15734 install_element(VIEW_NODE
,
15735 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15736 install_element(VIEW_NODE
,
15737 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15738 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15739 install_element(VIEW_NODE
,
15740 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15741 #ifdef KEEP_OLD_VPN_COMMANDS
15742 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15743 #endif /* KEEP_OLD_VPN_COMMANDS */
15744 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15745 install_element(VIEW_NODE
,
15746 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15748 /* BGP dampening clear commands */
15749 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15750 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15752 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15753 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15756 install_element(ENABLE_NODE
,
15757 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15758 #ifdef KEEP_OLD_VPN_COMMANDS
15759 install_element(ENABLE_NODE
,
15760 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15761 #endif /* KEEP_OLD_VPN_COMMANDS */
15763 /* New config IPv6 BGP commands. */
15764 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15765 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15766 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15768 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15770 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15772 /* IPv6 labeled unicast address family. */
15773 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15774 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15776 install_element(BGP_NODE
, &bgp_distance_cmd
);
15777 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15778 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15779 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15780 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15781 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15782 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15783 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15784 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15785 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15786 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15787 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15788 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15789 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15790 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15791 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15792 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15793 install_element(BGP_IPV4M_NODE
,
15794 &no_bgp_distance_source_access_list_cmd
);
15795 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15796 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15797 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15798 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15799 install_element(BGP_IPV6_NODE
,
15800 &ipv6_bgp_distance_source_access_list_cmd
);
15801 install_element(BGP_IPV6_NODE
,
15802 &no_ipv6_bgp_distance_source_access_list_cmd
);
15803 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15804 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15805 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15806 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15807 install_element(BGP_IPV6M_NODE
,
15808 &ipv6_bgp_distance_source_access_list_cmd
);
15809 install_element(BGP_IPV6M_NODE
,
15810 &no_ipv6_bgp_distance_source_access_list_cmd
);
15812 /* BGP dampening */
15813 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15814 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15815 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15816 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15817 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15818 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15819 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15820 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15821 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15822 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15823 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15824 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15825 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15826 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15828 /* Large Communities */
15829 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15830 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15832 /* show bgp ipv4 flowspec detailed */
15833 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15835 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15836 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
15839 void bgp_route_finish(void)
15844 FOREACH_AFI_SAFI (afi
, safi
) {
15845 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
15846 bgp_distance_table
[afi
][safi
] = NULL
;