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
35 #include "sockunion.h"
38 #include "workqueue.h"
43 #include "lib_errors.h"
45 #include "bgpd/bgpd.h"
46 #include "bgpd/bgp_table.h"
47 #include "bgpd/bgp_route.h"
48 #include "bgpd/bgp_attr.h"
49 #include "bgpd/bgp_debug.h"
50 #include "bgpd/bgp_errors.h"
51 #include "bgpd/bgp_aspath.h"
52 #include "bgpd/bgp_regex.h"
53 #include "bgpd/bgp_community.h"
54 #include "bgpd/bgp_ecommunity.h"
55 #include "bgpd/bgp_lcommunity.h"
56 #include "bgpd/bgp_clist.h"
57 #include "bgpd/bgp_packet.h"
58 #include "bgpd/bgp_filter.h"
59 #include "bgpd/bgp_fsm.h"
60 #include "bgpd/bgp_mplsvpn.h"
61 #include "bgpd/bgp_nexthop.h"
62 #include "bgpd/bgp_damp.h"
63 #include "bgpd/bgp_advertise.h"
64 #include "bgpd/bgp_zebra.h"
65 #include "bgpd/bgp_vty.h"
66 #include "bgpd/bgp_mpath.h"
67 #include "bgpd/bgp_nht.h"
68 #include "bgpd/bgp_updgrp.h"
69 #include "bgpd/bgp_label.h"
70 #include "bgpd/bgp_addpath.h"
71 #include "bgpd/bgp_mac.h"
72 #include "bgpd/bgp_network.h"
75 #include "bgpd/rfapi/rfapi_backend.h"
76 #include "bgpd/rfapi/vnc_import_bgp.h"
77 #include "bgpd/rfapi/vnc_export_bgp.h"
79 #include "bgpd/bgp_encap_types.h"
80 #include "bgpd/bgp_encap_tlv.h"
81 #include "bgpd/bgp_evpn.h"
82 #include "bgpd/bgp_evpn_mh.h"
83 #include "bgpd/bgp_evpn_vty.h"
84 #include "bgpd/bgp_flowspec.h"
85 #include "bgpd/bgp_flowspec_util.h"
86 #include "bgpd/bgp_pbr.h"
88 #ifndef VTYSH_EXTRACT_PL
89 #include "bgpd/bgp_route_clippy.c"
92 /* Extern from bgp_dump.c */
93 extern const char *bgp_origin_str
[];
94 extern const char *bgp_origin_long_str
[];
95 const char *get_afi_safi_str(afi_t afi
, safi_t safi
, bool for_json
);
97 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
98 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
99 static const struct message bgp_pmsi_tnltype_str
[] = {
100 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
101 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
102 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
103 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
104 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
105 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
106 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
107 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
111 #define VRFID_NONE_STR "-"
113 DEFINE_HOOK(bgp_process
,
114 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
115 struct peer
*peer
, bool withdraw
),
116 (bgp
, afi
, safi
, bn
, peer
, withdraw
))
119 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
120 safi_t safi
, const struct prefix
*p
,
121 struct prefix_rd
*prd
)
123 struct bgp_dest
*dest
;
124 struct bgp_dest
*pdest
= NULL
;
128 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
129 || (safi
== SAFI_EVPN
)) {
130 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
132 if (!bgp_dest_has_bgp_path_info_data(pdest
))
133 bgp_dest_set_bgp_table_info(
134 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
136 bgp_dest_unlock_node(pdest
);
137 table
= bgp_dest_get_bgp_table_info(pdest
);
140 dest
= bgp_node_get(table
, p
);
142 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
143 || (safi
== SAFI_EVPN
))
149 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
150 safi_t safi
, const struct prefix
*p
,
151 struct prefix_rd
*prd
)
153 struct bgp_dest
*dest
;
154 struct bgp_dest
*pdest
= NULL
;
159 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
160 || (safi
== SAFI_EVPN
)) {
161 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
165 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
166 bgp_dest_unlock_node(pdest
);
170 table
= bgp_dest_get_bgp_table_info(pdest
);
173 dest
= bgp_node_lookup(table
, p
);
178 /* Allocate bgp_path_info_extra */
179 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
181 struct bgp_path_info_extra
*new;
182 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
183 sizeof(struct bgp_path_info_extra
));
184 new->label
[0] = MPLS_INVALID_LABEL
;
186 new->bgp_fs_pbr
= NULL
;
187 new->bgp_fs_iprule
= NULL
;
191 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
193 struct bgp_path_info_extra
*e
;
195 if (!extra
|| !*extra
)
200 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
205 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
208 /* FIXME: since multiple e may have the same e->parent
209 * and e->parent->net is holding a refcount for each
210 * of them, we need to do some fudging here.
212 * WARNING: if bpi->net->lock drops to 0, bpi may be
213 * freed as well (because bpi->net was holding the
214 * last reference to bpi) => write after free!
218 bpi
= bgp_path_info_lock(bpi
);
219 refcount
= bpi
->net
->lock
- 1;
220 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
223 bgp_path_info_unlock(bpi
);
225 bgp_path_info_unlock(e
->parent
);
230 bgp_unlock(e
->bgp_orig
);
232 if ((*extra
)->bgp_fs_iprule
)
233 list_delete(&((*extra
)->bgp_fs_iprule
));
234 if ((*extra
)->bgp_fs_pbr
)
235 list_delete(&((*extra
)->bgp_fs_pbr
));
236 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
239 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
240 * allocated if required.
242 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
245 pi
->extra
= bgp_path_info_extra_new();
249 /* Free bgp route information. */
250 static void bgp_path_info_free(struct bgp_path_info
*path
)
252 bgp_attr_unintern(&path
->attr
);
254 bgp_unlink_nexthop(path
);
255 bgp_path_info_extra_free(&path
->extra
);
256 bgp_path_info_mpath_free(&path
->mpath
);
258 bgp_addpath_free_info_data(&path
->tx_addpath
,
259 &path
->net
->tx_addpath
);
261 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
263 XFREE(MTYPE_BGP_ROUTE
, path
);
266 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
272 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
274 assert(path
&& path
->lock
> 0);
277 if (path
->lock
== 0) {
279 zlog_debug ("%s: unlocked and freeing", __func__
);
280 zlog_backtrace (LOG_DEBUG
);
282 bgp_path_info_free(path
);
289 zlog_debug ("%s: unlocked to 1", __func__
);
290 zlog_backtrace (LOG_DEBUG
);
297 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
298 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
301 struct bgp_path_info
*old_pi
, *nextpi
;
302 bool set_flag
= false;
303 struct bgp
*bgp
= NULL
;
304 struct bgp_table
*table
= NULL
;
308 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
309 * then the route selection is deferred
311 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
314 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
315 if (BGP_DEBUG(update
, UPDATE_OUT
))
317 "Route %pRN is in workqueue and being processed, not deferred.",
318 bgp_dest_to_rnode(dest
));
323 table
= bgp_dest_table(dest
);
330 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
331 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
332 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
335 /* Route selection is deferred if there is a stale path which
336 * which indicates peer is in restart mode
338 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
339 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
342 /* If the peer is graceful restart capable and peer is
343 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
346 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
347 && BGP_PEER_RESTARTING_MODE(peer
)
349 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
357 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
360 if (set_flag
&& table
) {
361 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
362 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
363 if (dest
->rt_node
== NULL
)
364 dest
->rt_node
= listnode_add(
365 bgp
->gr_info
[afi
][safi
].route_list
,
367 if (BGP_DEBUG(update
, UPDATE_OUT
))
368 zlog_debug("DEFER route %pRN, dest %p, node %p",
369 dest
, dest
, dest
->rt_node
);
376 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
378 struct bgp_path_info
*top
;
380 top
= bgp_dest_get_bgp_path_info(dest
);
386 bgp_dest_set_bgp_path_info(dest
, pi
);
388 bgp_path_info_lock(pi
);
389 bgp_dest_lock_node(dest
);
390 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
391 bgp_dest_set_defer_flag(dest
, false);
394 /* Do the actual removal of info from RIB, for use by bgp_process
395 completion callback *only* */
396 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
399 pi
->next
->prev
= pi
->prev
;
401 pi
->prev
->next
= pi
->next
;
403 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
405 bgp_path_info_mpath_dequeue(pi
);
406 bgp_path_info_unlock(pi
);
407 bgp_dest_unlock_node(dest
);
410 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
412 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
413 /* set of previous already took care of pcount */
414 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
417 /* undo the effects of a previous call to bgp_path_info_delete; typically
418 called when a route is deleted and then quickly re-added before the
419 deletion has been processed */
420 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
422 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
423 /* unset of previous already took care of pcount */
424 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
427 /* Adjust pcount as required */
428 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
430 struct bgp_table
*table
;
432 assert(dest
&& bgp_dest_table(dest
));
433 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
435 table
= bgp_dest_table(dest
);
437 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
440 if (!BGP_PATH_COUNTABLE(pi
)
441 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
443 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
445 /* slight hack, but more robust against errors. */
446 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
447 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
449 flog_err(EC_LIB_DEVELOPMENT
,
450 "Asked to decrement 0 prefix count for peer");
451 } else if (BGP_PATH_COUNTABLE(pi
)
452 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
453 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
454 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
458 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
459 struct bgp_path_info
*pi2
)
461 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
464 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
465 * This is here primarily to keep prefix-count in check.
467 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
470 SET_FLAG(pi
->flags
, flag
);
472 /* early bath if we know it's not a flag that changes countability state
474 if (!CHECK_FLAG(flag
,
475 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
478 bgp_pcount_adjust(dest
, pi
);
481 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
484 UNSET_FLAG(pi
->flags
, flag
);
486 /* early bath if we know it's not a flag that changes countability state
488 if (!CHECK_FLAG(flag
,
489 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
492 bgp_pcount_adjust(dest
, pi
);
495 /* Get MED value. If MED value is missing and "bgp bestpath
496 missing-as-worst" is specified, treat it as the worst value. */
497 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
499 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
502 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
509 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
511 if (pi
->addpath_rx_id
)
512 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
515 sprintf(buf
, "path %s", pi
->peer
->host
);
518 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
520 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
521 struct bgp_path_info
*exist
, int *paths_eq
,
522 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
523 char *pfx_buf
, afi_t afi
, safi_t safi
,
524 enum bgp_path_selection_reason
*reason
)
526 struct attr
*newattr
, *existattr
;
527 bgp_peer_sort_t new_sort
;
528 bgp_peer_sort_t exist_sort
;
534 uint32_t exist_weight
;
535 uint32_t newm
, existm
;
536 struct in_addr new_id
;
537 struct in_addr exist_id
;
540 int internal_as_route
;
543 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
544 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
546 uint32_t exist_mm_seq
;
558 *reason
= bgp_path_selection_none
;
560 zlog_debug("%s: new is NULL", pfx_buf
);
565 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
568 *reason
= bgp_path_selection_first
;
570 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
576 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
577 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
578 pfx_buf
, new_buf
, new->flags
, exist_buf
,
583 existattr
= exist
->attr
;
585 /* For EVPN routes, we cannot just go by local vs remote, we have to
586 * look at the MAC mobility sequence number, if present.
588 if (safi
== SAFI_EVPN
) {
589 /* This is an error condition described in RFC 7432 Section
591 * states that in this scenario "the PE MUST alert the operator"
593 * does not state what other action to take. In order to provide
595 * consistency in this scenario we are going to prefer the path
599 if (newattr
->sticky
!= existattr
->sticky
) {
602 bgp_dest_get_prefix(new->net
), pfx_buf
,
603 sizeof(*pfx_buf
) * PREFIX2STR_BUFFER
);
604 bgp_path_info_path_with_addpath_rx_str(new,
606 bgp_path_info_path_with_addpath_rx_str(
610 if (newattr
->sticky
&& !existattr
->sticky
) {
611 *reason
= bgp_path_selection_evpn_sticky_mac
;
614 "%s: %s wins over %s due to sticky MAC flag",
615 pfx_buf
, new_buf
, exist_buf
);
619 if (!newattr
->sticky
&& existattr
->sticky
) {
620 *reason
= bgp_path_selection_evpn_sticky_mac
;
623 "%s: %s loses to %s due to sticky MAC flag",
624 pfx_buf
, new_buf
, exist_buf
);
629 new_esi
= bgp_evpn_attr_get_esi(newattr
);
630 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
631 if (bgp_evpn_is_esi_valid(new_esi
) &&
632 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
638 /* If both paths have the same non-zero ES and
639 * one path is local it wins.
640 * PS: Note the local path wins even if the remote
641 * has the higher MM seq. The local path's
642 * MM seq will be fixed up to match the highest
643 * rem seq, subsequently.
646 char esi_buf
[ESI_STR_LEN
];
648 if (bgp_evpn_is_path_local(bgp
, new)) {
649 *reason
= bgp_path_selection_evpn_local_path
;
652 "%s: %s wins over %s as ES %s is same and local",
653 pfx_buf
, new_buf
, exist_buf
,
654 esi_to_str(new_esi
, esi_buf
,
658 if (bgp_evpn_is_path_local(bgp
, exist
)) {
659 *reason
= bgp_path_selection_evpn_local_path
;
662 "%s: %s loses to %s as ES %s is same and local",
663 pfx_buf
, new_buf
, exist_buf
,
664 esi_to_str(new_esi
, esi_buf
,
670 new_mm_seq
= mac_mobility_seqnum(newattr
);
671 exist_mm_seq
= mac_mobility_seqnum(existattr
);
673 if (new_mm_seq
> exist_mm_seq
) {
674 *reason
= bgp_path_selection_evpn_seq
;
677 "%s: %s wins over %s due to MM seq %u > %u",
678 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
683 if (new_mm_seq
< exist_mm_seq
) {
684 *reason
= bgp_path_selection_evpn_seq
;
687 "%s: %s loses to %s due to MM seq %u < %u",
688 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
693 /* if the sequence numbers and ESI are the same and one path
694 * is non-proxy it wins (over proxy)
696 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
697 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
698 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
699 old_proxy
!= new_proxy
) {
701 *reason
= bgp_path_selection_evpn_non_proxy
;
704 "%s: %s wins over %s, same seq/es and non-proxy",
705 pfx_buf
, new_buf
, exist_buf
);
709 *reason
= bgp_path_selection_evpn_non_proxy
;
712 "%s: %s loses to %s, same seq/es and non-proxy",
713 pfx_buf
, new_buf
, exist_buf
);
718 * if sequence numbers are the same path with the lowest IP
721 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
723 *reason
= bgp_path_selection_evpn_lower_ip
;
726 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
727 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
728 inet_ntoa(new->attr
->nexthop
));
732 *reason
= bgp_path_selection_evpn_lower_ip
;
735 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
736 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
737 inet_ntoa(new->attr
->nexthop
));
742 /* 1. Weight check. */
743 new_weight
= newattr
->weight
;
744 exist_weight
= existattr
->weight
;
746 if (new_weight
> exist_weight
) {
747 *reason
= bgp_path_selection_weight
;
749 zlog_debug("%s: %s wins over %s due to weight %d > %d",
750 pfx_buf
, new_buf
, exist_buf
, new_weight
,
755 if (new_weight
< exist_weight
) {
756 *reason
= bgp_path_selection_weight
;
758 zlog_debug("%s: %s loses to %s due to weight %d < %d",
759 pfx_buf
, new_buf
, exist_buf
, new_weight
,
764 /* 2. Local preference check. */
765 new_pref
= exist_pref
= bgp
->default_local_pref
;
767 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
768 new_pref
= newattr
->local_pref
;
769 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
770 exist_pref
= existattr
->local_pref
;
772 if (new_pref
> exist_pref
) {
773 *reason
= bgp_path_selection_local_pref
;
776 "%s: %s wins over %s due to localpref %d > %d",
777 pfx_buf
, new_buf
, exist_buf
, new_pref
,
782 if (new_pref
< exist_pref
) {
783 *reason
= bgp_path_selection_local_pref
;
786 "%s: %s loses to %s due to localpref %d < %d",
787 pfx_buf
, new_buf
, exist_buf
, new_pref
,
792 /* 3. Local route check. We prefer:
794 * - BGP_ROUTE_AGGREGATE
795 * - BGP_ROUTE_REDISTRIBUTE
797 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
798 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
799 *reason
= bgp_path_selection_local_route
;
802 "%s: %s wins over %s due to preferred BGP_ROUTE type",
803 pfx_buf
, new_buf
, exist_buf
);
807 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
808 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
809 *reason
= bgp_path_selection_local_route
;
812 "%s: %s loses to %s due to preferred BGP_ROUTE type",
813 pfx_buf
, new_buf
, exist_buf
);
817 /* 4. AS path length check. */
818 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
819 int exist_hops
= aspath_count_hops(existattr
->aspath
);
820 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
822 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
825 aspath_hops
= aspath_count_hops(newattr
->aspath
);
826 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
828 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
829 *reason
= bgp_path_selection_confed_as_path
;
832 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
833 pfx_buf
, new_buf
, exist_buf
,
835 (exist_hops
+ exist_confeds
));
839 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
840 *reason
= bgp_path_selection_confed_as_path
;
843 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
844 pfx_buf
, new_buf
, exist_buf
,
846 (exist_hops
+ exist_confeds
));
850 int newhops
= aspath_count_hops(newattr
->aspath
);
852 if (newhops
< exist_hops
) {
853 *reason
= bgp_path_selection_as_path
;
856 "%s: %s wins over %s due to aspath hopcount %d < %d",
857 pfx_buf
, new_buf
, exist_buf
,
858 newhops
, exist_hops
);
862 if (newhops
> exist_hops
) {
863 *reason
= bgp_path_selection_as_path
;
866 "%s: %s loses to %s due to aspath hopcount %d > %d",
867 pfx_buf
, new_buf
, exist_buf
,
868 newhops
, exist_hops
);
874 /* 5. Origin check. */
875 if (newattr
->origin
< existattr
->origin
) {
876 *reason
= bgp_path_selection_origin
;
878 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
879 pfx_buf
, new_buf
, exist_buf
,
880 bgp_origin_long_str
[newattr
->origin
],
881 bgp_origin_long_str
[existattr
->origin
]);
885 if (newattr
->origin
> existattr
->origin
) {
886 *reason
= bgp_path_selection_origin
;
888 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
889 pfx_buf
, new_buf
, exist_buf
,
890 bgp_origin_long_str
[newattr
->origin
],
891 bgp_origin_long_str
[existattr
->origin
]);
896 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
897 && aspath_count_hops(existattr
->aspath
) == 0);
898 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
899 && aspath_count_confeds(existattr
->aspath
) > 0
900 && aspath_count_hops(newattr
->aspath
) == 0
901 && aspath_count_hops(existattr
->aspath
) == 0);
903 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
904 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
905 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
906 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
907 || internal_as_route
) {
908 new_med
= bgp_med_value(new->attr
, bgp
);
909 exist_med
= bgp_med_value(exist
->attr
, bgp
);
911 if (new_med
< exist_med
) {
912 *reason
= bgp_path_selection_med
;
915 "%s: %s wins over %s due to MED %d < %d",
916 pfx_buf
, new_buf
, exist_buf
, new_med
,
921 if (new_med
> exist_med
) {
922 *reason
= bgp_path_selection_med
;
925 "%s: %s loses to %s due to MED %d > %d",
926 pfx_buf
, new_buf
, exist_buf
, new_med
,
932 /* 7. Peer type check. */
933 new_sort
= new->peer
->sort
;
934 exist_sort
= exist
->peer
->sort
;
936 if (new_sort
== BGP_PEER_EBGP
937 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
938 *reason
= bgp_path_selection_peer
;
941 "%s: %s wins over %s due to eBGP peer > iBGP peer",
942 pfx_buf
, new_buf
, exist_buf
);
946 if (exist_sort
== BGP_PEER_EBGP
947 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
948 *reason
= bgp_path_selection_peer
;
951 "%s: %s loses to %s due to iBGP peer < eBGP peer",
952 pfx_buf
, new_buf
, exist_buf
);
956 /* 8. IGP metric check. */
960 newm
= new->extra
->igpmetric
;
962 existm
= exist
->extra
->igpmetric
;
967 "%s: %s wins over %s due to IGP metric %d < %d",
968 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
975 "%s: %s loses to %s due to IGP metric %d > %d",
976 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
980 /* 9. Same IGP metric. Compare the cluster list length as
981 representative of IGP hops metric. Rewrite the metric value
982 pair (newm, existm) with the cluster list length. Prefer the
983 path with smaller cluster list length. */
984 if (newm
== existm
) {
985 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
986 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
987 && (mpath_cfg
== NULL
989 mpath_cfg
->ibgp_flags
,
990 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
991 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
992 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
997 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
998 pfx_buf
, new_buf
, exist_buf
,
1003 if (newm
> existm
) {
1006 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1007 pfx_buf
, new_buf
, exist_buf
,
1014 /* 10. confed-external vs. confed-internal */
1015 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1016 if (new_sort
== BGP_PEER_CONFED
1017 && exist_sort
== BGP_PEER_IBGP
) {
1018 *reason
= bgp_path_selection_confed
;
1021 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1022 pfx_buf
, new_buf
, exist_buf
);
1026 if (exist_sort
== BGP_PEER_CONFED
1027 && new_sort
== BGP_PEER_IBGP
) {
1028 *reason
= bgp_path_selection_confed
;
1031 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1032 pfx_buf
, new_buf
, exist_buf
);
1037 /* 11. Maximum path check. */
1038 if (newm
== existm
) {
1039 /* If one path has a label but the other does not, do not treat
1040 * them as equals for multipath
1042 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1044 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1047 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1048 pfx_buf
, new_buf
, exist_buf
);
1049 } else if (CHECK_FLAG(bgp
->flags
,
1050 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1053 * For the two paths, all comparison steps till IGP
1055 * have succeeded - including AS_PATH hop count. Since
1057 * bestpath as-path multipath-relax' knob is on, we
1059 * an exact match of AS_PATH. Thus, mark the paths are
1061 * That will trigger both these paths to get into the
1069 "%s: %s and %s are equal via multipath-relax",
1070 pfx_buf
, new_buf
, exist_buf
);
1071 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1072 if (aspath_cmp(new->attr
->aspath
,
1073 exist
->attr
->aspath
)) {
1078 "%s: %s and %s are equal via matching aspaths",
1079 pfx_buf
, new_buf
, exist_buf
);
1081 } else if (new->peer
->as
== exist
->peer
->as
) {
1086 "%s: %s and %s are equal via same remote-as",
1087 pfx_buf
, new_buf
, exist_buf
);
1091 * TODO: If unequal cost ibgp multipath is enabled we can
1092 * mark the paths as equal here instead of returning
1097 "%s: %s wins over %s after IGP metric comparison",
1098 pfx_buf
, new_buf
, exist_buf
);
1101 "%s: %s loses to %s after IGP metric comparison",
1102 pfx_buf
, new_buf
, exist_buf
);
1104 *reason
= bgp_path_selection_igp_metric
;
1108 /* 12. If both paths are external, prefer the path that was received
1109 first (the oldest one). This step minimizes route-flap, since a
1110 newer path won't displace an older one, even if it was the
1111 preferred route based on the additional decision criteria below. */
1112 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1113 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1114 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1115 *reason
= bgp_path_selection_older
;
1118 "%s: %s wins over %s due to oldest external",
1119 pfx_buf
, new_buf
, exist_buf
);
1123 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1124 *reason
= bgp_path_selection_older
;
1127 "%s: %s loses to %s due to oldest external",
1128 pfx_buf
, new_buf
, exist_buf
);
1133 /* 13. Router-ID comparision. */
1134 /* If one of the paths is "stale", the corresponding peer router-id will
1135 * be 0 and would always win over the other path. If originator id is
1136 * used for the comparision, it will decide which path is better.
1138 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1139 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1141 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1142 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1143 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1145 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1147 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1148 *reason
= bgp_path_selection_router_id
;
1151 "%s: %s wins over %s due to Router-ID comparison",
1152 pfx_buf
, new_buf
, exist_buf
);
1156 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1157 *reason
= bgp_path_selection_router_id
;
1160 "%s: %s loses to %s due to Router-ID comparison",
1161 pfx_buf
, new_buf
, exist_buf
);
1165 /* 14. Cluster length comparision. */
1166 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1167 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1169 if (new_cluster
< exist_cluster
) {
1170 *reason
= bgp_path_selection_cluster_length
;
1173 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1174 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1179 if (new_cluster
> exist_cluster
) {
1180 *reason
= bgp_path_selection_cluster_length
;
1183 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1184 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1189 /* 15. Neighbor address comparision. */
1190 /* Do this only if neither path is "stale" as stale paths do not have
1191 * valid peer information (as the connection may or may not be up).
1193 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1194 *reason
= bgp_path_selection_stale
;
1197 "%s: %s wins over %s due to latter path being STALE",
1198 pfx_buf
, new_buf
, exist_buf
);
1202 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1203 *reason
= bgp_path_selection_stale
;
1206 "%s: %s loses to %s due to former path being STALE",
1207 pfx_buf
, new_buf
, exist_buf
);
1211 /* locally configured routes to advertise do not have su_remote */
1212 if (new->peer
->su_remote
== NULL
) {
1213 *reason
= bgp_path_selection_local_configured
;
1216 if (exist
->peer
->su_remote
== NULL
) {
1217 *reason
= bgp_path_selection_local_configured
;
1221 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1224 *reason
= bgp_path_selection_neighbor_ip
;
1227 "%s: %s loses to %s due to Neighor IP comparison",
1228 pfx_buf
, new_buf
, exist_buf
);
1233 *reason
= bgp_path_selection_neighbor_ip
;
1236 "%s: %s wins over %s due to Neighor IP comparison",
1237 pfx_buf
, new_buf
, exist_buf
);
1241 *reason
= bgp_path_selection_default
;
1243 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1244 pfx_buf
, new_buf
, exist_buf
);
1250 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1251 struct bgp_path_info
*exist
, int *paths_eq
)
1253 enum bgp_path_selection_reason reason
;
1254 char pfx_buf
[PREFIX2STR_BUFFER
];
1256 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1257 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1260 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1261 * is preferred, or 0 if they are the same (usually will only occur if
1262 * multipath is enabled
1263 * This version is compatible with */
1264 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1265 struct bgp_path_info
*exist
, char *pfx_buf
,
1266 afi_t afi
, safi_t safi
,
1267 enum bgp_path_selection_reason
*reason
)
1271 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1285 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1286 const struct prefix
*p
,
1287 struct attr
*attr
, afi_t afi
,
1290 struct bgp_filter
*filter
;
1292 filter
= &peer
->filter
[afi
][safi
];
1294 #define FILTER_EXIST_WARN(F, f, filter) \
1295 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1296 zlog_debug("%s: Could not find configured input %s-list %s!", \
1297 peer->host, #f, F##_IN_NAME(filter));
1299 if (DISTRIBUTE_IN_NAME(filter
)) {
1300 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1302 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1306 if (PREFIX_LIST_IN_NAME(filter
)) {
1307 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1309 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1313 if (FILTER_LIST_IN_NAME(filter
)) {
1314 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1316 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1321 return FILTER_PERMIT
;
1322 #undef FILTER_EXIST_WARN
1325 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1326 const struct prefix
*p
,
1327 struct attr
*attr
, afi_t afi
,
1330 struct bgp_filter
*filter
;
1332 filter
= &peer
->filter
[afi
][safi
];
1334 #define FILTER_EXIST_WARN(F, f, filter) \
1335 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1336 zlog_debug("%s: Could not find configured output %s-list %s!", \
1337 peer->host, #f, F##_OUT_NAME(filter));
1339 if (DISTRIBUTE_OUT_NAME(filter
)) {
1340 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1342 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1346 if (PREFIX_LIST_OUT_NAME(filter
)) {
1347 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1349 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1354 if (FILTER_LIST_OUT_NAME(filter
)) {
1355 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1357 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1362 return FILTER_PERMIT
;
1363 #undef FILTER_EXIST_WARN
1366 /* If community attribute includes no_export then return 1. */
1367 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1369 if (attr
->community
) {
1370 /* NO_ADVERTISE check. */
1371 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1374 /* NO_EXPORT check. */
1375 if (peer
->sort
== BGP_PEER_EBGP
1376 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1379 /* NO_EXPORT_SUBCONFED check. */
1380 if (peer
->sort
== BGP_PEER_EBGP
1381 || peer
->sort
== BGP_PEER_CONFED
)
1382 if (community_include(attr
->community
,
1383 COMMUNITY_NO_EXPORT_SUBCONFED
))
1389 /* Route reflection loop check. */
1390 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1392 struct in_addr cluster_id
;
1394 if (attr
->cluster
) {
1395 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1396 cluster_id
= peer
->bgp
->cluster_id
;
1398 cluster_id
= peer
->bgp
->router_id
;
1400 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1406 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1407 struct attr
*attr
, afi_t afi
, safi_t safi
,
1408 const char *rmap_name
, mpls_label_t
*label
,
1409 uint32_t num_labels
, struct bgp_dest
*dest
)
1411 struct bgp_filter
*filter
;
1412 struct bgp_path_info rmap_path
= { 0 };
1413 struct bgp_path_info_extra extra
= { 0 };
1414 route_map_result_t ret
;
1415 struct route_map
*rmap
= NULL
;
1417 filter
= &peer
->filter
[afi
][safi
];
1419 /* Apply default weight value. */
1420 if (peer
->weight
[afi
][safi
])
1421 attr
->weight
= peer
->weight
[afi
][safi
];
1424 rmap
= route_map_lookup_by_name(rmap_name
);
1429 if (ROUTE_MAP_IN_NAME(filter
)) {
1430 rmap
= ROUTE_MAP_IN(filter
);
1437 /* Route map apply. */
1439 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1440 /* Duplicate current value to new strucutre for modification. */
1441 rmap_path
.peer
= peer
;
1442 rmap_path
.attr
= attr
;
1443 rmap_path
.extra
= &extra
;
1444 rmap_path
.net
= dest
;
1446 extra
.num_labels
= num_labels
;
1447 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1448 memcpy(extra
.label
, label
,
1449 num_labels
* sizeof(mpls_label_t
));
1451 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1453 /* Apply BGP route map to the attribute. */
1454 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1456 peer
->rmap_type
= 0;
1458 if (ret
== RMAP_DENYMATCH
)
1464 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1465 struct attr
*attr
, afi_t afi
, safi_t safi
,
1466 const char *rmap_name
)
1468 struct bgp_path_info rmap_path
;
1469 route_map_result_t ret
;
1470 struct route_map
*rmap
= NULL
;
1474 * So if we get to this point and have no rmap_name
1475 * we want to just show the output as it currently
1481 /* Apply default weight value. */
1482 if (peer
->weight
[afi
][safi
])
1483 attr
->weight
= peer
->weight
[afi
][safi
];
1485 rmap
= route_map_lookup_by_name(rmap_name
);
1488 * If we have a route map name and we do not find
1489 * the routemap that means we have an implicit
1495 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1496 /* Route map apply. */
1497 /* Duplicate current value to new strucutre for modification. */
1498 rmap_path
.peer
= peer
;
1499 rmap_path
.attr
= attr
;
1501 rmap_type
= peer
->rmap_type
;
1502 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1504 /* Apply BGP route map to the attribute. */
1505 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1507 peer
->rmap_type
= rmap_type
;
1509 if (ret
== RMAP_DENYMATCH
)
1511 * caller has multiple error paths with bgp_attr_flush()
1518 /* If this is an EBGP peer with remove-private-AS */
1519 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1520 struct peer
*peer
, struct attr
*attr
)
1522 if (peer
->sort
== BGP_PEER_EBGP
1523 && (peer_af_flag_check(peer
, afi
, safi
,
1524 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1525 || peer_af_flag_check(peer
, afi
, safi
,
1526 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1527 || peer_af_flag_check(peer
, afi
, safi
,
1528 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1529 || peer_af_flag_check(peer
, afi
, safi
,
1530 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1531 // Take action on the entire aspath
1532 if (peer_af_flag_check(peer
, afi
, safi
,
1533 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1534 || peer_af_flag_check(peer
, afi
, safi
,
1535 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1536 if (peer_af_flag_check(
1538 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1539 attr
->aspath
= aspath_replace_private_asns(
1540 attr
->aspath
, bgp
->as
, peer
->as
);
1542 // The entire aspath consists of private ASNs so create
1544 else if (aspath_private_as_check(attr
->aspath
))
1545 attr
->aspath
= aspath_empty_get();
1547 // There are some public and some private ASNs, remove
1550 attr
->aspath
= aspath_remove_private_asns(
1551 attr
->aspath
, peer
->as
);
1554 // 'all' was not specified so the entire aspath must be private
1556 // for us to do anything
1557 else if (aspath_private_as_check(attr
->aspath
)) {
1558 if (peer_af_flag_check(
1560 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1561 attr
->aspath
= aspath_replace_private_asns(
1562 attr
->aspath
, bgp
->as
, peer
->as
);
1564 attr
->aspath
= aspath_empty_get();
1569 /* If this is an EBGP peer with as-override */
1570 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1571 struct peer
*peer
, struct attr
*attr
)
1573 if (peer
->sort
== BGP_PEER_EBGP
1574 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1575 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1576 attr
->aspath
= aspath_replace_specific_asn(
1577 attr
->aspath
, peer
->as
, bgp
->as
);
1581 void bgp_attr_add_gshut_community(struct attr
*attr
)
1583 struct community
*old
;
1584 struct community
*new;
1585 struct community
*merge
;
1586 struct community
*gshut
;
1588 old
= attr
->community
;
1589 gshut
= community_str2com("graceful-shutdown");
1594 merge
= community_merge(community_dup(old
), gshut
);
1596 if (old
->refcnt
== 0)
1597 community_free(&old
);
1599 new = community_uniq_sort(merge
);
1600 community_free(&merge
);
1602 new = community_dup(gshut
);
1605 community_free(&gshut
);
1606 attr
->community
= new;
1607 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1609 /* When we add the graceful-shutdown community we must also
1610 * lower the local-preference */
1611 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1612 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1616 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1618 if (family
== AF_INET
) {
1619 attr
->nexthop
.s_addr
= INADDR_ANY
;
1620 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1622 if (family
== AF_INET6
)
1623 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1624 if (family
== AF_EVPN
)
1625 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1628 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1629 struct update_subgroup
*subgrp
,
1630 const struct prefix
*p
, struct attr
*attr
)
1632 struct bgp_filter
*filter
;
1635 struct peer
*onlypeer
;
1637 struct attr
*piattr
;
1638 char buf
[PREFIX_STRLEN
];
1639 route_map_result_t ret
;
1644 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1645 bool nh_reset
= false;
1648 if (DISABLE_BGP_ANNOUNCE
)
1651 afi
= SUBGRP_AFI(subgrp
);
1652 safi
= SUBGRP_SAFI(subgrp
);
1653 peer
= SUBGRP_PEER(subgrp
);
1655 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1656 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1659 filter
= &peer
->filter
[afi
][safi
];
1660 bgp
= SUBGRP_INST(subgrp
);
1661 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1664 #ifdef ENABLE_BGP_VNC
1665 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1666 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1667 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1670 * direct and direct_ext type routes originate internally even
1671 * though they can have peer pointers that reference other
1674 prefix2str(p
, buf
, PREFIX_STRLEN
);
1675 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1681 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1682 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1683 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1684 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1686 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1691 /* With addpath we may be asked to TX all kinds of paths so make sure
1693 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1694 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1695 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1699 /* If this is not the bestpath then check to see if there is an enabled
1701 * feature that requires us to advertise it */
1702 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1703 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1708 /* Aggregate-address suppress check. */
1709 if (pi
->extra
&& pi
->extra
->suppress
)
1710 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1715 * If we are doing VRF 2 VRF leaking via the import
1716 * statement, we want to prevent the route going
1717 * off box as that the RT and RD created are localy
1718 * significant and globaly useless.
1720 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1721 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1724 /* If it's labeled safi, make sure the route has a valid label. */
1725 if (safi
== SAFI_LABELED_UNICAST
) {
1726 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1727 if (!bgp_is_valid_label(&label
)) {
1728 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1729 zlog_debug("u%" PRIu64
":s%" PRIu64
" %s/%d is filtered - no label (%p)",
1730 subgrp
->update_group
->id
, subgrp
->id
,
1731 inet_ntop(p
->family
, &p
->u
.prefix
,
1732 buf
, SU_ADDRSTRLEN
),
1733 p
->prefixlen
, &label
);
1738 /* Do not send back route to sender. */
1739 if (onlypeer
&& from
== onlypeer
) {
1743 /* Do not send the default route in the BGP table if the neighbor is
1744 * configured for default-originate */
1745 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1746 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1747 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1749 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1753 /* Transparency check. */
1754 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1755 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1760 /* If community is not disabled check the no-export and local. */
1761 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1762 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1764 "subgrpannouncecheck: community filter check fail");
1768 /* If the attribute has originator-id and it is same as remote
1770 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1771 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1772 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1774 "%s [Update:SEND] %s originator-id is same as remote router-id",
1776 prefix2str(p
, buf
, sizeof(buf
)));
1780 /* ORF prefix-list filter check */
1781 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1782 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1783 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1784 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1785 if (peer
->orf_plist
[afi
][safi
]) {
1786 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1788 if (bgp_debug_update(NULL
, p
,
1789 subgrp
->update_group
, 0))
1791 "%s [Update:SEND] %s is filtered via ORF",
1799 /* Output filter check. */
1800 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1801 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1802 zlog_debug("%s [Update:SEND] %s is filtered",
1803 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1807 /* AS path loop check. */
1808 if (onlypeer
&& onlypeer
->as_path_loop_detection
1809 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1810 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1812 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1813 onlypeer
->host
, onlypeer
->as
);
1817 /* If we're a CONFED we need to loop check the CONFED ID too */
1818 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1819 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1820 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1822 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1823 peer
->host
, bgp
->confed_id
);
1828 /* Route-Reflect check. */
1829 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1834 /* IBGP reflection check. */
1835 if (reflect
&& !samepeer_safe
) {
1836 /* A route from a Client peer. */
1837 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1838 PEER_FLAG_REFLECTOR_CLIENT
)) {
1839 /* Reflect to all the Non-Client peers and also to the
1840 Client peers other than the originator. Originator
1842 is already done. So there is noting to do. */
1843 /* no bgp client-to-client reflection check. */
1844 if (CHECK_FLAG(bgp
->flags
,
1845 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1846 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1847 PEER_FLAG_REFLECTOR_CLIENT
))
1850 /* A route from a Non-client peer. Reflect to all other
1852 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1853 PEER_FLAG_REFLECTOR_CLIENT
))
1858 /* For modify attribute, copy it to temporary structure. */
1861 /* If local-preference is not set. */
1862 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1863 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1864 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1865 attr
->local_pref
= bgp
->default_local_pref
;
1868 /* If originator-id is not set and the route is to be reflected,
1869 set the originator id */
1871 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1872 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1873 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1876 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1878 if (peer
->sort
== BGP_PEER_EBGP
1879 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1880 if (from
!= bgp
->peer_self
&& !transparent
1881 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1882 PEER_FLAG_MED_UNCHANGED
))
1884 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1887 /* Since the nexthop attribute can vary per peer, it is not explicitly
1889 * in announce check, only certain flags and length (or number of
1891 * -- for IPv6/MP_REACH) are set here in order to guide the update
1893 * code in setting the nexthop(s) on a per peer basis in
1895 * Typically, the source nexthop in the attribute is preserved but in
1897 * scenarios where we know it will always be overwritten, we reset the
1898 * nexthop to "0" in an attempt to achieve better Update packing. An
1899 * example of this is when a prefix from each of 2 IBGP peers needs to
1901 * announced to an EBGP peer (and they have the same attributes barring
1905 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1907 #define NEXTHOP_IS_V6 \
1908 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1909 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1910 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1911 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1913 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1915 * the peer (group) is configured to receive link-local nexthop
1917 * and it is available in the prefix OR we're not reflecting the route,
1918 * link-local nexthop address is valid and
1919 * the peer (group) to whom we're going to announce is on a shared
1921 * and this is either a self-originated route or the peer is EBGP.
1922 * By checking if nexthop LL address is valid we are sure that
1923 * we do not announce LL address as `::`.
1925 if (NEXTHOP_IS_V6
) {
1926 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1927 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1928 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1929 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1931 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
1932 && peer
->shared_network
1933 && (from
== bgp
->peer_self
1934 || peer
->sort
== BGP_PEER_EBGP
))) {
1935 attr
->mp_nexthop_len
=
1936 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1939 /* Clear off link-local nexthop in source, whenever it is not
1941 * ensure more prefixes share the same attribute for
1944 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1945 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1946 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1949 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1950 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1952 /* Route map & unsuppress-map apply. */
1953 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1954 struct bgp_path_info rmap_path
= {0};
1955 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
1956 struct attr dummy_attr
= {0};
1958 /* Fill temp path_info */
1959 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
1962 /* don't confuse inbound and outbound setting */
1963 RESET_FLAG(attr
->rmap_change_flags
);
1966 * The route reflector is not allowed to modify the attributes
1967 * of the reflected IBGP routes unless explicitly allowed.
1969 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1970 && !CHECK_FLAG(bgp
->flags
,
1971 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1973 rmap_path
.attr
= &dummy_attr
;
1976 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1978 if (pi
->extra
&& pi
->extra
->suppress
)
1979 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1980 RMAP_BGP
, &rmap_path
);
1982 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1983 RMAP_BGP
, &rmap_path
);
1985 peer
->rmap_type
= 0;
1987 if (ret
== RMAP_DENYMATCH
) {
1988 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1989 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1990 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1992 bgp_attr_flush(attr
);
1997 /* RFC 8212 to prevent route leaks.
1998 * This specification intends to improve this situation by requiring the
1999 * explicit configuration of both BGP Import and Export Policies for any
2000 * External BGP (EBGP) session such as customers, peers, or
2001 * confederation boundaries for all enabled address families. Through
2002 * codification of the aforementioned requirement, operators will
2003 * benefit from consistent behavior across different BGP
2006 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2007 if (!bgp_outbound_policy_exists(peer
, filter
))
2010 /* draft-ietf-idr-deprecate-as-set-confed-set
2011 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2012 * Eventually, This document (if approved) updates RFC 4271
2013 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2014 * and obsoletes RFC 6472.
2016 if (peer
->bgp
->reject_as_sets
)
2017 if (aspath_check_as_sets(attr
->aspath
))
2020 /* Codification of AS 0 Processing */
2021 if (aspath_check_as_zero(attr
->aspath
))
2024 if (bgp_in_graceful_shutdown(bgp
)) {
2025 if (peer
->sort
== BGP_PEER_IBGP
2026 || peer
->sort
== BGP_PEER_CONFED
) {
2027 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2028 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2030 bgp_attr_add_gshut_community(attr
);
2034 /* After route-map has been applied, we check to see if the nexthop to
2035 * be carried in the attribute (that is used for the announcement) can
2036 * be cleared off or not. We do this in all cases where we would be
2037 * setting the nexthop to "ourselves". For IPv6, we only need to
2039 * the global nexthop here; the link-local nexthop would have been
2041 * already, and if not, it is required by the update formation code.
2042 * Also see earlier comments in this function.
2045 * If route-map has performed some operation on the nexthop or the peer
2046 * configuration says to pass it unchanged, we cannot reset the nexthop
2047 * here, so only attempt to do it if these aren't true. Note that the
2048 * route-map handler itself might have cleared the nexthop, if for
2050 * it is configured as 'peer-address'.
2052 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2053 piattr
->rmap_change_flags
)
2055 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2056 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2057 /* We can reset the nexthop, if setting (or forcing) it to
2059 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2060 PEER_FLAG_NEXTHOP_SELF
)
2061 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2062 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2064 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2065 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2066 subgroup_announce_reset_nhop(
2067 (peer_cap_enhe(peer
, afi
, safi
)
2073 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2074 /* Can also reset the nexthop if announcing to EBGP, but
2076 * no peer in the subgroup is on a shared subnet.
2077 * Note: 3rd party nexthop currently implemented for
2080 if ((p
->family
== AF_INET
) &&
2081 (!bgp_subgrp_multiaccess_check_v4(
2084 subgroup_announce_reset_nhop(
2085 (peer_cap_enhe(peer
, afi
, safi
)
2092 if ((p
->family
== AF_INET6
) &&
2093 (!bgp_subgrp_multiaccess_check_v6(
2094 piattr
->mp_nexthop_global
,
2096 subgroup_announce_reset_nhop(
2097 (peer_cap_enhe(peer
, afi
, safi
)
2106 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2108 * This flag is used for leaked vpn-vrf routes
2110 int family
= p
->family
;
2112 if (peer_cap_enhe(peer
, afi
, safi
))
2115 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2117 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2118 __func__
, family2str(family
));
2119 subgroup_announce_reset_nhop(family
, attr
);
2124 /* If IPv6/MP and nexthop does not have any override and happens
2126 * be a link-local address, reset it so that we don't pass along
2128 * source's link-local IPv6 address to recipients who may not be
2130 * the same interface.
2132 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2133 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2134 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2140 * When the next hop is set to ourselves, if all multipaths have
2141 * link-bandwidth announce the cumulative bandwidth as that makes
2142 * the most sense. However, don't modify if the link-bandwidth has
2143 * been explicitly set by user policy.
2146 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2147 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2148 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2149 attr
->ecommunity
= ecommunity_replace_linkbw(
2150 bgp
->as
, attr
->ecommunity
, cum_bw
);
2155 static int bgp_route_select_timer_expire(struct thread
*thread
)
2157 struct afi_safi_info
*info
;
2162 info
= THREAD_ARG(thread
);
2167 if (BGP_DEBUG(update
, UPDATE_OUT
))
2168 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2171 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2173 XFREE(MTYPE_TMP
, info
);
2175 /* Best path selection */
2176 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2179 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2180 struct bgp_maxpaths_cfg
*mpath_cfg
,
2181 struct bgp_path_info_pair
*result
, afi_t afi
,
2184 struct bgp_path_info
*new_select
;
2185 struct bgp_path_info
*old_select
;
2186 struct bgp_path_info
*pi
;
2187 struct bgp_path_info
*pi1
;
2188 struct bgp_path_info
*pi2
;
2189 struct bgp_path_info
*nextpi
= NULL
;
2190 int paths_eq
, do_mpath
, debug
;
2191 struct list mp_list
;
2192 char pfx_buf
[PREFIX2STR_BUFFER
];
2193 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2195 bgp_mp_list_init(&mp_list
);
2197 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2199 debug
= bgp_debug_bestpath(dest
);
2202 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2204 dest
->reason
= bgp_path_selection_none
;
2205 /* bgp deterministic-med */
2207 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2209 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2210 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2212 bgp_path_info_unset_flag(dest
, pi1
,
2213 BGP_PATH_DMED_SELECTED
);
2215 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2217 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2219 if (BGP_PATH_HOLDDOWN(pi1
))
2221 if (pi1
->peer
!= bgp
->peer_self
)
2222 if (pi1
->peer
->status
!= Established
)
2227 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2228 if (CHECK_FLAG(pi2
->flags
,
2229 BGP_PATH_DMED_CHECK
))
2231 if (BGP_PATH_HOLDDOWN(pi2
))
2233 if (pi2
->peer
!= bgp
->peer_self
2236 PEER_STATUS_NSF_WAIT
))
2237 if (pi2
->peer
->status
2241 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2243 && !aspath_cmp_left_confed(
2248 if (bgp_path_info_cmp(
2249 bgp
, pi2
, new_select
,
2250 &paths_eq
, mpath_cfg
, debug
,
2253 bgp_path_info_unset_flag(
2255 BGP_PATH_DMED_SELECTED
);
2259 bgp_path_info_set_flag(
2260 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2263 bgp_path_info_set_flag(dest
, new_select
,
2264 BGP_PATH_DMED_CHECK
);
2265 bgp_path_info_set_flag(dest
, new_select
,
2266 BGP_PATH_DMED_SELECTED
);
2269 bgp_path_info_path_with_addpath_rx_str(
2270 new_select
, path_buf
);
2271 zlog_debug("%s: %s is the bestpath from AS %u",
2273 aspath_get_first_as(
2274 new_select
->attr
->aspath
));
2279 /* Check old selected route and new selected route. */
2282 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2283 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2284 enum bgp_path_selection_reason reason
;
2286 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2289 if (BGP_PATH_HOLDDOWN(pi
)) {
2290 /* reap REMOVED routes, if needs be
2291 * selected route must stay for a while longer though
2293 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2294 && (pi
!= old_select
))
2295 bgp_path_info_reap(dest
, pi
);
2298 zlog_debug("%s: pi %p in holddown", __func__
,
2304 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2305 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2306 if (pi
->peer
->status
!= Established
) {
2310 "%s: pi %p non self peer %s not estab state",
2311 __func__
, pi
, pi
->peer
->host
);
2316 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2317 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2318 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2320 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2324 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2326 reason
= dest
->reason
;
2327 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2328 debug
, pfx_buf
, afi
, safi
,
2330 if (new_select
== NULL
&&
2331 reason
!= bgp_path_selection_none
)
2332 dest
->reason
= reason
;
2337 /* Now that we know which path is the bestpath see if any of the other
2339 * qualify as multipaths
2343 bgp_path_info_path_with_addpath_rx_str(new_select
,
2346 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2348 "%s: After path selection, newbest is %s oldbest was %s",
2350 old_select
? old_select
->peer
->host
: "NONE");
2353 if (do_mpath
&& new_select
) {
2354 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2355 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2358 bgp_path_info_path_with_addpath_rx_str(
2361 if (pi
== new_select
) {
2364 "%s: %s is the bestpath, add to the multipath list",
2366 bgp_mp_list_add(&mp_list
, pi
);
2370 if (BGP_PATH_HOLDDOWN(pi
))
2373 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2374 && !CHECK_FLAG(pi
->peer
->sflags
,
2375 PEER_STATUS_NSF_WAIT
))
2376 if (pi
->peer
->status
!= Established
)
2379 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2382 "%s: %s has the same nexthop as the bestpath, skip it",
2387 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2388 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2394 "%s: %s is equivalent to the bestpath, add to the multipath list",
2396 bgp_mp_list_add(&mp_list
, pi
);
2401 bgp_path_info_mpath_update(dest
, new_select
, old_select
, &mp_list
,
2403 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2404 bgp_mp_list_clear(&mp_list
);
2406 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2408 result
->old
= old_select
;
2409 result
->new = new_select
;
2415 * A new route/change in bestpath of an existing route. Evaluate the path
2416 * for advertisement to the subgroup.
2418 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2419 struct bgp_path_info
*selected
,
2420 struct bgp_dest
*dest
,
2421 uint32_t addpath_tx_id
)
2423 const struct prefix
*p
;
2424 struct peer
*onlypeer
;
2429 p
= bgp_dest_get_prefix(dest
);
2430 afi
= SUBGRP_AFI(subgrp
);
2431 safi
= SUBGRP_SAFI(subgrp
);
2432 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2435 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2436 char buf_prefix
[PREFIX_STRLEN
];
2437 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2438 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2442 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2443 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2444 PEER_STATUS_ORF_WAIT_REFRESH
))
2447 memset(&attr
, 0, sizeof(struct attr
));
2448 /* It's initialized in bgp_announce_check() */
2450 /* Announcement to the subgroup. If the route is filtered withdraw it.
2453 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
))
2454 bgp_adj_out_set_subgroup(dest
, subgrp
, &attr
, selected
);
2456 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2460 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2462 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2467 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2468 * This is called at the end of route processing.
2470 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2472 struct bgp_path_info
*pi
;
2474 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2475 if (BGP_PATH_HOLDDOWN(pi
))
2477 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2478 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2483 * Has the route changed from the RIB's perspective? This is invoked only
2484 * if the route selection returns the same best route as earlier - to
2485 * determine if we need to update zebra or not.
2487 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2489 struct bgp_path_info
*mpinfo
;
2491 /* If this is multipath, check all selected paths for any nexthop
2492 * change or attribute change. Some attribute changes (e.g., community)
2493 * aren't of relevance to the RIB, but we'll update zebra to ensure
2494 * we handle the case of BGP nexthop change. This is the behavior
2495 * when the best path has an attribute change anyway.
2497 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2498 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2499 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2503 * If this is multipath, check all selected paths for any nexthop change
2505 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2506 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2507 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2508 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2512 /* Nothing has changed from the RIB's perspective. */
2516 struct bgp_process_queue
{
2518 STAILQ_HEAD(, bgp_dest
) pqueue
;
2519 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2521 unsigned int queued
;
2524 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2525 safi_t safi
, struct bgp_dest
*dest
,
2526 struct bgp_path_info
*new_select
,
2527 struct bgp_path_info
*old_select
)
2529 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2531 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2534 if (advertise_type5_routes(bgp
, afi
) && new_select
2535 && is_route_injectable_into_evpn(new_select
)) {
2537 /* apply the route-map */
2538 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2539 route_map_result_t ret
;
2540 struct bgp_path_info rmap_path
;
2541 struct bgp_path_info_extra rmap_path_extra
;
2542 struct attr dummy_attr
;
2544 dummy_attr
= *new_select
->attr
;
2546 /* Fill temp path_info */
2547 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2548 new_select
, new_select
->peer
,
2551 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2553 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2554 p
, RMAP_BGP
, &rmap_path
);
2556 if (ret
== RMAP_DENYMATCH
) {
2557 bgp_attr_flush(&dummy_attr
);
2558 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2561 bgp_evpn_advertise_type5_route(
2562 bgp
, p
, &dummy_attr
, afi
, safi
);
2564 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2567 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2568 && is_route_injectable_into_evpn(old_select
))
2569 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2573 * old_select = The old best path
2574 * new_select = the new best path
2576 * if (!old_select && new_select)
2577 * We are sending new information on.
2579 * if (old_select && new_select) {
2580 * if (new_select != old_select)
2581 * We have a new best path send a change
2583 * We've received a update with new attributes that needs
2587 * if (old_select && !new_select)
2588 * We have no eligible route that we can announce or the rn
2591 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2592 afi_t afi
, safi_t safi
)
2594 struct bgp_path_info
*new_select
;
2595 struct bgp_path_info
*old_select
;
2596 struct bgp_path_info_pair old_and_new
;
2599 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2601 debug
= bgp_debug_bestpath(dest
);
2604 "%s: bgp delete in progress, ignoring event, p=%pRN",
2608 /* Is it end of initial update? (after startup) */
2610 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2611 sizeof(bgp
->update_delay_zebra_resume_time
));
2613 bgp
->main_zebra_update_hold
= 0;
2614 FOREACH_AFI_SAFI (afi
, safi
) {
2615 if (bgp_fibupd_safi(safi
))
2616 bgp_zebra_announce_table(bgp
, afi
, safi
);
2618 bgp
->main_peers_update_hold
= 0;
2620 bgp_start_routeadv(bgp
);
2624 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2626 debug
= bgp_debug_bestpath(dest
);
2628 zlog_debug("%s: p=%pRN afi=%s, safi=%s start", __func__
, dest
,
2629 afi2str(afi
), safi2str(safi
));
2631 /* The best path calculation for the route is deferred if
2632 * BGP_NODE_SELECT_DEFER is set
2634 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2635 if (BGP_DEBUG(update
, UPDATE_OUT
))
2636 zlog_debug("SELECT_DEFER falg set for route %p", dest
);
2640 /* Best path selection. */
2641 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2643 old_select
= old_and_new
.old
;
2644 new_select
= old_and_new
.new;
2646 /* Do we need to allocate or free labels?
2647 * Right now, since we only deal with per-prefix labels, it is not
2648 * necessary to do this upon changes to best path. Exceptions:
2649 * - label index has changed -> recalculate resulting label
2650 * - path_info sub_type changed -> switch to/from implicit-null
2651 * - no valid label (due to removed static label binding) -> get new one
2653 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2656 || bgp_label_index_differs(new_select
, old_select
)
2657 || new_select
->sub_type
!= old_select
->sub_type
2658 || !bgp_is_valid_label(&dest
->local_label
)) {
2659 /* Enforced penultimate hop popping:
2660 * implicit-null for local routes, aggregate
2661 * and redistributed routes
2663 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2664 || new_select
->sub_type
2665 == BGP_ROUTE_AGGREGATE
2666 || new_select
->sub_type
2667 == BGP_ROUTE_REDISTRIBUTE
) {
2670 BGP_NODE_REGISTERED_FOR_LABEL
))
2671 bgp_unregister_for_label(dest
);
2672 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2673 &dest
->local_label
);
2674 bgp_set_valid_label(&dest
->local_label
);
2676 bgp_register_for_label(dest
,
2679 } else if (CHECK_FLAG(dest
->flags
,
2680 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2681 bgp_unregister_for_label(dest
);
2683 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2684 bgp_unregister_for_label(dest
);
2689 "%s: p=%pRN afi=%s, safi=%s, old_select=%p, new_select=%p",
2690 __func__
, dest
, afi2str(afi
), safi2str(safi
),
2691 old_select
, new_select
);
2693 /* If best route remains the same and this is not due to user-initiated
2694 * clear, see exactly what needs to be done.
2696 if (old_select
&& old_select
== new_select
2697 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2698 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2699 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2700 if (bgp_zebra_has_route_changed(old_select
)) {
2701 #ifdef ENABLE_BGP_VNC
2702 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2703 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2705 if (bgp_fibupd_safi(safi
)
2706 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2708 if (new_select
->type
== ZEBRA_ROUTE_BGP
2709 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2710 || new_select
->sub_type
2711 == BGP_ROUTE_IMPORTED
))
2713 bgp_zebra_announce(dest
, p
, old_select
,
2718 /* If there is a change of interest to peers, reannounce the
2720 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2721 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2722 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2723 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2725 /* unicast routes must also be annouced to
2726 * labeled-unicast update-groups */
2727 if (safi
== SAFI_UNICAST
)
2728 group_announce_route(bgp
, afi
,
2729 SAFI_LABELED_UNICAST
, dest
,
2732 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2733 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
2736 /* advertise/withdraw type-5 routes */
2737 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2738 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
2739 bgp_process_evpn_route_injection(
2740 bgp
, afi
, safi
, dest
, old_select
, old_select
);
2742 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2743 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2744 bgp_zebra_clear_route_change_flags(dest
);
2745 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2749 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2751 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
2753 /* bestpath has changed; bump version */
2754 if (old_select
|| new_select
) {
2755 bgp_bump_version(dest
);
2757 if (!bgp
->t_rmap_def_originate_eval
) {
2761 update_group_refresh_default_originate_route_map
,
2762 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2763 &bgp
->t_rmap_def_originate_eval
);
2768 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
2771 zlog_debug("%s: setting SELECTED flag", __func__
);
2772 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
2773 bgp_path_info_unset_flag(dest
, new_select
,
2774 BGP_PATH_ATTR_CHANGED
);
2775 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2776 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2779 #ifdef ENABLE_BGP_VNC
2780 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2781 if (old_select
!= new_select
) {
2783 vnc_import_bgp_exterior_del_route(bgp
, p
,
2785 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2788 vnc_import_bgp_exterior_add_route(bgp
, p
,
2790 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2796 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2798 /* unicast routes must also be annouced to labeled-unicast update-groups
2800 if (safi
== SAFI_UNICAST
)
2801 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
2805 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2806 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2807 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2808 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2809 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2810 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2812 /* if this is an evpn imported type-5 prefix,
2813 * we need to withdraw the route first to clear
2814 * the nh neigh and the RMAC entry.
2817 is_route_parent_evpn(old_select
))
2818 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2820 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
2822 /* Withdraw the route from the kernel. */
2823 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2824 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2825 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2826 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2828 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2832 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
2835 /* Clear any route change flags. */
2836 bgp_zebra_clear_route_change_flags(dest
);
2838 /* Reap old select bgp_path_info, if it has been removed */
2839 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2840 bgp_path_info_reap(dest
, old_select
);
2842 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2846 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2847 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2849 struct bgp_dest
*dest
;
2851 struct afi_safi_info
*thread_info
;
2852 struct listnode
*node
= NULL
, *nnode
= NULL
;
2854 if (bgp
->gr_info
[afi
][safi
].t_route_select
)
2855 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
2857 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2858 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
2859 get_afi_safi_str(afi
, safi
, false),
2860 listcount(bgp
->gr_info
[afi
][safi
].route_list
));
2863 /* Process the route list */
2864 node
= listhead(bgp
->gr_info
[afi
][safi
].route_list
);
2866 dest
= listgetdata(node
);
2868 list_delete_node(bgp
->gr_info
[afi
][safi
].route_list
, node
);
2869 dest
->rt_node
= NULL
;
2871 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2872 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
2873 bgp_process_main_one(bgp
, dest
, afi
, safi
);
2875 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
)
2881 /* Send EOR message when all routes are processed */
2882 if (list_isempty(bgp
->gr_info
[afi
][safi
].route_list
)) {
2883 bgp_send_delayed_eor(bgp
);
2884 /* Send route processing complete message to RIB */
2885 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
2886 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
2890 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
2892 thread_info
->afi
= afi
;
2893 thread_info
->safi
= safi
;
2894 thread_info
->bgp
= bgp
;
2896 /* If there are more routes to be processed, start the
2899 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
2900 BGP_ROUTE_SELECT_DELAY
,
2901 &bgp
->gr_info
[afi
][safi
].t_route_select
);
2905 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2907 struct bgp_process_queue
*pqnode
= data
;
2908 struct bgp
*bgp
= pqnode
->bgp
;
2909 struct bgp_table
*table
;
2910 struct bgp_dest
*dest
;
2913 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2914 bgp_process_main_one(bgp
, NULL
, 0, 0);
2915 /* should always have dedicated wq call */
2916 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2920 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2921 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
2922 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2923 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
2924 table
= bgp_dest_table(dest
);
2925 /* note, new DESTs may be added as part of processing */
2926 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
2928 bgp_dest_unlock_node(dest
);
2929 bgp_table_unlock(table
);
2935 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2937 struct bgp_process_queue
*pqnode
= data
;
2939 bgp_unlock(pqnode
->bgp
);
2941 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2944 void bgp_process_queue_init(void)
2946 if (!bm
->process_main_queue
)
2947 bm
->process_main_queue
=
2948 work_queue_new(bm
->master
, "process_main_queue");
2950 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2951 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2952 bm
->process_main_queue
->spec
.max_retries
= 0;
2953 bm
->process_main_queue
->spec
.hold
= 50;
2954 /* Use a higher yield value of 50ms for main queue processing */
2955 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2958 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2960 struct bgp_process_queue
*pqnode
;
2962 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2963 sizeof(struct bgp_process_queue
));
2965 /* unlocked in bgp_processq_del */
2966 pqnode
->bgp
= bgp_lock(bgp
);
2967 STAILQ_INIT(&pqnode
->pqueue
);
2972 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
2974 #define ARBITRARY_PROCESS_QLEN 10000
2975 struct work_queue
*wq
= bm
->process_main_queue
;
2976 struct bgp_process_queue
*pqnode
;
2977 int pqnode_reuse
= 0;
2979 /* already scheduled for processing? */
2980 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2983 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2986 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2987 if (BGP_DEBUG(update
, UPDATE_OUT
))
2988 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
2996 /* Add route nodes to an existing work queue item until reaching the
2997 limit only if is from the same BGP view and it's not an EOIU marker
2999 if (work_queue_item_count(wq
)) {
3000 struct work_queue_item
*item
= work_queue_last_item(wq
);
3001 pqnode
= item
->data
;
3003 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3004 || pqnode
->bgp
!= bgp
3005 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3006 pqnode
= bgp_processq_alloc(bgp
);
3010 pqnode
= bgp_processq_alloc(bgp
);
3011 /* all unlocked in bgp_process_wq */
3012 bgp_table_lock(bgp_dest_table(dest
));
3014 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3015 bgp_dest_lock_node(dest
);
3017 /* can't be enqueued twice */
3018 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3019 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3023 work_queue_add(wq
, pqnode
);
3028 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3030 struct bgp_process_queue
*pqnode
;
3032 if (bm
->process_main_queue
== NULL
)
3035 pqnode
= bgp_processq_alloc(bgp
);
3037 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3038 work_queue_add(bm
->process_main_queue
, pqnode
);
3041 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3045 peer
= THREAD_ARG(thread
);
3046 peer
->t_pmax_restart
= NULL
;
3048 if (bgp_debug_neighbor_events(peer
))
3050 "%s Maximum-prefix restart timer expired, restore peering",
3053 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3054 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3059 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3063 bool filtered
= false;
3064 struct bgp_dest
*dest
;
3065 struct bgp_adj_in
*ain
;
3066 struct attr attr
= {};
3067 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3069 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3070 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3071 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3075 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3079 if (bgp_input_modifier(
3080 peer
, rn_p
, &attr
, afi
, safi
,
3081 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3089 bgp_attr_undup(&attr
, ain
->attr
);
3096 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3100 iana_safi_t pkt_safi
;
3101 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3102 PEER_FLAG_MAX_PREFIX_FORCE
))
3103 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3104 + peer
->pcount
[afi
][safi
]
3105 : peer
->pcount
[afi
][safi
];
3107 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3110 if (pcount
> peer
->pmax
[afi
][safi
]) {
3111 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3112 PEER_STATUS_PREFIX_LIMIT
)
3117 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3118 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3119 peer
->pmax
[afi
][safi
]);
3120 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3122 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3123 PEER_FLAG_MAX_PREFIX_WARNING
))
3126 /* Convert AFI, SAFI to values for packet. */
3127 pkt_afi
= afi_int2iana(afi
);
3128 pkt_safi
= safi_int2iana(safi
);
3132 ndata
[0] = (pkt_afi
>> 8);
3134 ndata
[2] = pkt_safi
;
3135 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3136 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3137 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3138 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3140 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3141 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3142 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3146 /* Dynamic peers will just close their connection. */
3147 if (peer_dynamic_neighbor(peer
))
3150 /* restart timer start */
3151 if (peer
->pmax_restart
[afi
][safi
]) {
3152 peer
->v_pmax_restart
=
3153 peer
->pmax_restart
[afi
][safi
] * 60;
3155 if (bgp_debug_neighbor_events(peer
))
3157 "%s Maximum-prefix restart timer started for %d secs",
3158 peer
->host
, peer
->v_pmax_restart
);
3160 BGP_TIMER_ON(peer
->t_pmax_restart
,
3161 bgp_maximum_prefix_restart_timer
,
3162 peer
->v_pmax_restart
);
3167 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3168 PEER_STATUS_PREFIX_LIMIT
);
3170 if (pcount
> (pcount
* peer
->pmax_threshold
[afi
][safi
] / 100)) {
3171 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3172 PEER_STATUS_PREFIX_THRESHOLD
)
3177 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3178 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3179 peer
->pmax
[afi
][safi
]);
3180 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3181 PEER_STATUS_PREFIX_THRESHOLD
);
3183 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3184 PEER_STATUS_PREFIX_THRESHOLD
);
3188 /* Unconditionally remove the route from the RIB, without taking
3189 * damping into consideration (eg, because the session went down)
3191 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3192 struct peer
*peer
, afi_t afi
, safi_t safi
)
3195 struct bgp
*bgp
= NULL
;
3196 bool delete_route
= false;
3198 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3201 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3202 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3204 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3207 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3208 delete_route
= true;
3209 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3210 delete_route
= true;
3212 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3213 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3214 bgp
= pi
->peer
->bgp
;
3216 && (bgp
->gr_info
[afi
][safi
].route_list
)) {
3217 list_delete_node(bgp
->gr_info
[afi
][safi
]
3220 dest
->rt_node
= NULL
;
3226 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3227 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3230 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3231 struct peer
*peer
, afi_t afi
, safi_t safi
,
3232 struct prefix_rd
*prd
)
3234 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3236 /* apply dampening, if result is suppressed, we'll be retaining
3237 * the bgp_path_info in the RIB for historical reference.
3239 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3240 && peer
->sort
== BGP_PEER_EBGP
)
3241 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3242 == BGP_DAMP_SUPPRESSED
) {
3243 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3248 #ifdef ENABLE_BGP_VNC
3249 if (safi
== SAFI_MPLS_VPN
) {
3250 struct bgp_dest
*pdest
= NULL
;
3251 struct bgp_table
*table
= NULL
;
3253 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3254 (struct prefix
*)prd
);
3255 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3256 table
= bgp_dest_get_bgp_table_info(pdest
);
3258 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3259 peer
->bgp
, prd
, table
, p
, pi
);
3261 bgp_dest_unlock_node(pdest
);
3263 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3264 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3266 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3267 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3272 /* If this is an EVPN route, process for un-import. */
3273 if (safi
== SAFI_EVPN
)
3274 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3276 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3279 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3280 struct peer
*peer
, struct attr
*attr
,
3281 struct bgp_dest
*dest
)
3283 struct bgp_path_info
*new;
3285 /* Make new BGP info. */
3286 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3288 new->instance
= instance
;
3289 new->sub_type
= sub_type
;
3292 new->uptime
= bgp_clock();
3297 static void overlay_index_update(struct attr
*attr
,
3298 union gw_addr
*gw_ip
)
3302 if (gw_ip
== NULL
) {
3303 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
3305 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
3306 sizeof(union gw_addr
));
3310 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3311 union gw_addr
*gw_ip
)
3313 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
3319 if (afi
!= AFI_L2VPN
)
3322 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
3324 if (gw_ip
== NULL
) {
3325 memset(&temp
, 0, sizeof(temp
));
3326 path_gw_ip_remote
= &temp
.ip
;
3328 path_gw_ip_remote
= gw_ip
;
3330 return !!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
));
3333 /* Check if received nexthop is valid or not. */
3334 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3335 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3336 struct bgp_dest
*dest
)
3339 bool is_bgp_static_route
=
3340 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3344 * Only validated for unicast and multicast currently.
3345 * Also valid for EVPN where the nexthop is an IP address.
3346 * If we are a bgp static route being checked then there is
3347 * no need to check to see if the nexthop is martian as
3348 * that it should be ok.
3350 if (is_bgp_static_route
||
3351 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3354 /* If NEXT_HOP is present, validate it. */
3355 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3356 if (attr
->nexthop
.s_addr
== INADDR_ANY
3357 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3358 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3362 /* If MP_NEXTHOP is present, validate it. */
3363 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3364 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3365 * it is not an IPv6 link-local address.
3367 * If we receive an UPDATE with nexthop length set to 32 bytes
3368 * we shouldn't discard an UPDATE if it's set to (::).
3369 * The link-local (2st) is validated along the code path later.
3371 if (attr
->mp_nexthop_len
) {
3372 switch (attr
->mp_nexthop_len
) {
3373 case BGP_ATTR_NHLEN_IPV4
:
3374 case BGP_ATTR_NHLEN_VPNV4
:
3375 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3377 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3378 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3382 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3383 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3384 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3385 &attr
->mp_nexthop_global
)
3386 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3387 || IN6_IS_ADDR_MULTICAST(
3388 &attr
->mp_nexthop_global
)
3389 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3392 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3393 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3394 || IN6_IS_ADDR_MULTICAST(
3395 &attr
->mp_nexthop_global
)
3396 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3409 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3410 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3411 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3412 uint32_t num_labels
, int soft_reconfig
,
3413 struct bgp_route_evpn
*evpn
)
3416 int aspath_loop_count
= 0;
3417 struct bgp_dest
*dest
;
3419 struct attr new_attr
;
3420 struct attr
*attr_new
;
3421 struct bgp_path_info
*pi
;
3422 struct bgp_path_info
*new;
3423 struct bgp_path_info_extra
*extra
;
3425 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3427 int do_loop_check
= 1;
3428 int has_valid_label
= 0;
3430 uint8_t pi_type
= 0;
3431 uint8_t pi_sub_type
= 0;
3433 #ifdef ENABLE_BGP_VNC
3434 int vnc_implicit_withdraw
= 0;
3438 memset(&new_attr
, 0, sizeof(struct attr
));
3439 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3440 new_attr
.label
= MPLS_INVALID_LABEL
;
3443 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3444 /* TODO: Check to see if we can get rid of "is_valid_label" */
3445 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3446 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3448 has_valid_label
= bgp_is_valid_label(label
);
3450 /* When peer's soft reconfiguration enabled. Record input packet in
3453 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3454 && peer
!= bgp
->peer_self
)
3455 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3457 /* Check previously received route. */
3458 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3459 if (pi
->peer
== peer
&& pi
->type
== type
3460 && pi
->sub_type
== sub_type
3461 && pi
->addpath_rx_id
== addpath_id
)
3464 /* AS path local-as loop check. */
3465 if (peer
->change_local_as
) {
3466 if (peer
->allowas_in
[afi
][safi
])
3467 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3468 else if (!CHECK_FLAG(peer
->flags
,
3469 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3470 aspath_loop_count
= 1;
3472 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3473 > aspath_loop_count
) {
3474 peer
->stat_pfx_aspath_loop
++;
3475 reason
= "as-path contains our own AS A;";
3480 /* If the peer is configured for "allowas-in origin" and the last ASN in
3482 * as-path is our ASN then we do not need to call aspath_loop_check
3484 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3485 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3488 /* AS path loop check. */
3489 if (do_loop_check
) {
3490 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3491 > peer
->allowas_in
[afi
][safi
]
3492 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3493 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3494 > peer
->allowas_in
[afi
][safi
])) {
3495 peer
->stat_pfx_aspath_loop
++;
3496 reason
= "as-path contains our own AS;";
3501 /* Route reflector originator ID check. */
3502 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3503 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3504 peer
->stat_pfx_originator_loop
++;
3505 reason
= "originator is us;";
3509 /* Route reflector cluster ID check. */
3510 if (bgp_cluster_filter(peer
, attr
)) {
3511 peer
->stat_pfx_cluster_loop
++;
3512 reason
= "reflected from the same cluster;";
3516 /* Apply incoming filter. */
3517 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3518 peer
->stat_pfx_filter
++;
3523 /* RFC 8212 to prevent route leaks.
3524 * This specification intends to improve this situation by requiring the
3525 * explicit configuration of both BGP Import and Export Policies for any
3526 * External BGP (EBGP) session such as customers, peers, or
3527 * confederation boundaries for all enabled address families. Through
3528 * codification of the aforementioned requirement, operators will
3529 * benefit from consistent behavior across different BGP
3532 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3533 if (!bgp_inbound_policy_exists(peer
,
3534 &peer
->filter
[afi
][safi
])) {
3535 reason
= "inbound policy missing";
3539 /* draft-ietf-idr-deprecate-as-set-confed-set
3540 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3541 * Eventually, This document (if approved) updates RFC 4271
3542 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3543 * and obsoletes RFC 6472.
3545 if (peer
->bgp
->reject_as_sets
)
3546 if (aspath_check_as_sets(attr
->aspath
)) {
3548 "as-path contains AS_SET or AS_CONFED_SET type;";
3554 /* Apply incoming route-map.
3555 * NB: new_attr may now contain newly allocated values from route-map
3557 * commands, so we need bgp_attr_flush in the error paths, until we
3559 * the attr (which takes over the memory references) */
3560 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
, label
,
3563 peer
->stat_pfx_filter
++;
3564 reason
= "route-map;";
3565 bgp_attr_flush(&new_attr
);
3569 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3570 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3571 /* remove from RIB previous entry */
3572 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3575 if (peer
->sort
== BGP_PEER_EBGP
) {
3577 /* If we receive the graceful-shutdown community from an eBGP
3578 * peer we must lower local-preference */
3579 if (new_attr
.community
3580 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3581 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3582 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3584 /* If graceful-shutdown is configured then add the GSHUT
3585 * community to all paths received from eBGP peers */
3586 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3587 bgp_attr_add_gshut_community(&new_attr
);
3592 pi_sub_type
= pi
->sub_type
;
3595 /* next hop check. */
3596 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3597 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3599 peer
->stat_pfx_nh_invalid
++;
3600 reason
= "martian or self next-hop;";
3601 bgp_attr_flush(&new_attr
);
3605 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3606 peer
->stat_pfx_nh_invalid
++;
3607 reason
= "self mac;";
3611 /* Update Overlay Index */
3612 if (afi
== AFI_L2VPN
) {
3613 overlay_index_update(&new_attr
,
3614 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3617 attr_new
= bgp_attr_intern(&new_attr
);
3619 /* If maximum prefix count is configured and current prefix
3622 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3625 /* If the update is implicit withdraw. */
3627 pi
->uptime
= bgp_clock();
3628 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3630 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3632 /* Same attribute comes in. */
3633 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3634 && attrhash_cmp(pi
->attr
, attr_new
)
3635 && (!has_valid_label
3636 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3637 num_labels
* sizeof(mpls_label_t
))
3639 && (overlay_index_equal(
3641 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3642 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3643 BGP_CONFIG_DAMPENING
)
3644 && peer
->sort
== BGP_PEER_EBGP
3645 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3646 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3647 bgp_debug_rdpfxpath2str(
3648 afi
, safi
, prd
, p
, label
,
3649 num_labels
, addpath_id
? 1 : 0,
3650 addpath_id
, pfx_buf
,
3652 zlog_debug("%s rcvd %s", peer
->host
,
3656 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3657 != BGP_DAMP_SUPPRESSED
) {
3658 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3660 bgp_process(bgp
, dest
, afi
, safi
);
3662 } else /* Duplicate - odd */
3664 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3665 if (!peer
->rcvd_attr_printed
) {
3667 "%s rcvd UPDATE w/ attr: %s",
3669 peer
->rcvd_attr_str
);
3670 peer
->rcvd_attr_printed
= 1;
3673 bgp_debug_rdpfxpath2str(
3674 afi
, safi
, prd
, p
, label
,
3675 num_labels
, addpath_id
? 1 : 0,
3676 addpath_id
, pfx_buf
,
3679 "%s rcvd %s...duplicate ignored",
3680 peer
->host
, pfx_buf
);
3683 /* graceful restart STALE flag unset. */
3684 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3685 bgp_path_info_unset_flag(
3686 dest
, pi
, BGP_PATH_STALE
);
3687 bgp_dest_set_defer_flag(dest
, false);
3688 bgp_process(bgp
, dest
, afi
, safi
);
3692 bgp_dest_unlock_node(dest
);
3693 bgp_attr_unintern(&attr_new
);
3698 /* Withdraw/Announce before we fully processed the withdraw */
3699 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3700 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3701 bgp_debug_rdpfxpath2str(
3702 afi
, safi
, prd
, p
, label
, num_labels
,
3703 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3706 "%s rcvd %s, flapped quicker than processing",
3707 peer
->host
, pfx_buf
);
3710 bgp_path_info_restore(dest
, pi
);
3713 /* Received Logging. */
3714 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3715 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3716 num_labels
, addpath_id
? 1 : 0,
3717 addpath_id
, pfx_buf
,
3719 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3722 /* graceful restart STALE flag unset. */
3723 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3724 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
3725 bgp_dest_set_defer_flag(dest
, false);
3728 /* The attribute is changed. */
3729 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
3731 /* implicit withdraw, decrement aggregate and pcount here.
3732 * only if update is accepted, they'll increment below.
3734 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3736 /* Update bgp route dampening information. */
3737 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3738 && peer
->sort
== BGP_PEER_EBGP
) {
3739 /* This is implicit withdraw so we should update
3742 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3743 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
3745 #ifdef ENABLE_BGP_VNC
3746 if (safi
== SAFI_MPLS_VPN
) {
3747 struct bgp_dest
*pdest
= NULL
;
3748 struct bgp_table
*table
= NULL
;
3750 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3751 (struct prefix
*)prd
);
3752 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3753 table
= bgp_dest_get_bgp_table_info(pdest
);
3755 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3756 bgp
, prd
, table
, p
, pi
);
3758 bgp_dest_unlock_node(pdest
);
3760 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3761 && (safi
== SAFI_UNICAST
)) {
3762 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3764 * Implicit withdraw case.
3766 ++vnc_implicit_withdraw
;
3767 vnc_import_bgp_del_route(bgp
, p
, pi
);
3768 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3773 /* Special handling for EVPN update of an existing route. If the
3774 * extended community attribute has changed, we need to
3776 * the route using its existing extended community. It will be
3777 * subsequently processed for import with the new extended
3780 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
3783 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3785 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3788 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3789 attr_new
->ecommunity
);
3791 if (bgp_debug_update(peer
, p
, NULL
, 1))
3793 "Change in EXT-COMM, existing %s new %s",
3795 pi
->attr
->ecommunity
),
3797 attr_new
->ecommunity
));
3798 if (safi
== SAFI_EVPN
)
3799 bgp_evpn_unimport_route(
3800 bgp
, afi
, safi
, p
, pi
);
3801 else /* SAFI_MPLS_VPN */
3802 vpn_leak_to_vrf_withdraw(bgp
,
3808 /* Update to new attribute. */
3809 bgp_attr_unintern(&pi
->attr
);
3810 pi
->attr
= attr_new
;
3812 /* Update MPLS label */
3813 if (has_valid_label
) {
3814 extra
= bgp_path_info_extra_get(pi
);
3815 if (extra
->label
!= label
) {
3816 memcpy(&extra
->label
, label
,
3817 num_labels
* sizeof(mpls_label_t
));
3818 extra
->num_labels
= num_labels
;
3820 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3821 bgp_set_valid_label(&extra
->label
[0]);
3824 /* Update SRv6 SID */
3825 if (attr
->srv6_l3vpn
) {
3826 extra
= bgp_path_info_extra_get(pi
);
3827 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
3828 sid_copy(&extra
->sid
[0],
3829 &attr
->srv6_l3vpn
->sid
);
3830 extra
->num_sids
= 1;
3832 } else if (attr
->srv6_vpn
) {
3833 extra
= bgp_path_info_extra_get(pi
);
3834 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
3835 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
3836 extra
->num_sids
= 1;
3840 #ifdef ENABLE_BGP_VNC
3841 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3842 && (safi
== SAFI_UNICAST
)) {
3843 if (vnc_implicit_withdraw
) {
3845 * Add back the route with its new attributes
3847 * The route is still selected, until the route
3849 * queued by bgp_process actually runs. We have
3851 * update to the VNC side immediately to avoid
3853 * configuration changes (e.g., route-map
3855 * trigger re-importation of the entire RIB.
3857 vnc_import_bgp_add_route(bgp
, p
, pi
);
3858 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3863 /* Update bgp route dampening information. */
3864 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3865 && peer
->sort
== BGP_PEER_EBGP
) {
3866 /* Now we do normal update dampening. */
3867 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
3868 if (ret
== BGP_DAMP_SUPPRESSED
) {
3869 bgp_dest_unlock_node(dest
);
3874 /* Nexthop reachability check - for unicast and
3875 * labeled-unicast.. */
3876 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3877 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3878 || (safi
== SAFI_EVPN
&&
3879 bgp_evpn_is_prefix_nht_supported(p
))) {
3880 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3881 && peer
->ttl
== BGP_DEFAULT_TTL
3882 && !CHECK_FLAG(peer
->flags
,
3883 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3884 && !CHECK_FLAG(bgp
->flags
,
3885 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3890 struct bgp
*bgp_nexthop
= bgp
;
3892 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3893 bgp_nexthop
= pi
->extra
->bgp_orig
;
3895 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3897 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3898 pi
, NULL
, connected
)
3899 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3900 bgp_path_info_set_flag(dest
, pi
,
3903 if (BGP_DEBUG(nht
, NHT
)) {
3904 zlog_debug("%s(%pI4): NH unresolved",
3906 (in_addr_t
*)&attr_new
->nexthop
);
3908 bgp_path_info_unset_flag(dest
, pi
,
3912 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
3914 #ifdef ENABLE_BGP_VNC
3915 if (safi
== SAFI_MPLS_VPN
) {
3916 struct bgp_dest
*pdest
= NULL
;
3917 struct bgp_table
*table
= NULL
;
3919 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3920 (struct prefix
*)prd
);
3921 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3922 table
= bgp_dest_get_bgp_table_info(pdest
);
3924 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3925 bgp
, prd
, table
, p
, pi
);
3927 bgp_dest_unlock_node(pdest
);
3931 /* If this is an EVPN route and some attribute has changed,
3933 * route for import. If the extended community has changed, we
3935 * have done the un-import earlier and the import would result
3937 * route getting injected into appropriate L2 VNIs. If it is
3939 * some other attribute change, the import will result in
3941 * the attributes for the route in the VNI(s).
3943 if (safi
== SAFI_EVPN
&& !same_attr
&&
3944 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3945 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3947 /* Process change. */
3948 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3950 bgp_process(bgp
, dest
, afi
, safi
);
3951 bgp_dest_unlock_node(dest
);
3953 if (SAFI_UNICAST
== safi
3954 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3955 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3957 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3959 if ((SAFI_MPLS_VPN
== safi
)
3960 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3962 vpn_leak_to_vrf_update(bgp
, pi
);
3965 #ifdef ENABLE_BGP_VNC
3966 if (SAFI_MPLS_VPN
== safi
) {
3967 mpls_label_t label_decoded
= decode_label(label
);
3969 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3970 type
, sub_type
, &label_decoded
);
3972 if (SAFI_ENCAP
== safi
) {
3973 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3974 type
, sub_type
, NULL
);
3979 } // End of implicit withdraw
3981 /* Received Logging. */
3982 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3983 if (!peer
->rcvd_attr_printed
) {
3984 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3985 peer
->rcvd_attr_str
);
3986 peer
->rcvd_attr_printed
= 1;
3989 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3990 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3992 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3995 /* Make new BGP info. */
3996 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
3998 /* Update MPLS label */
3999 if (has_valid_label
) {
4000 extra
= bgp_path_info_extra_get(new);
4001 if (extra
->label
!= label
) {
4002 memcpy(&extra
->label
, label
,
4003 num_labels
* sizeof(mpls_label_t
));
4004 extra
->num_labels
= num_labels
;
4006 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4007 bgp_set_valid_label(&extra
->label
[0]);
4010 /* Update SRv6 SID */
4011 if (safi
== SAFI_MPLS_VPN
) {
4012 extra
= bgp_path_info_extra_get(new);
4013 if (attr
->srv6_l3vpn
) {
4014 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
4015 extra
->num_sids
= 1;
4016 } else if (attr
->srv6_vpn
) {
4017 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4018 extra
->num_sids
= 1;
4022 /* Update Overlay Index */
4023 if (afi
== AFI_L2VPN
) {
4024 overlay_index_update(new->attr
,
4025 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
4027 /* Nexthop reachability check. */
4028 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4029 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4030 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4031 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4032 && peer
->ttl
== BGP_DEFAULT_TTL
4033 && !CHECK_FLAG(peer
->flags
,
4034 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4035 && !CHECK_FLAG(bgp
->flags
,
4036 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4041 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4043 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
4045 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4046 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4048 if (BGP_DEBUG(nht
, NHT
)) {
4049 char buf1
[INET6_ADDRSTRLEN
];
4051 (const void *)&attr_new
->nexthop
,
4052 buf1
, INET6_ADDRSTRLEN
);
4053 zlog_debug("%s(%s): NH unresolved", __func__
,
4056 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4059 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4062 new->addpath_rx_id
= addpath_id
;
4064 /* Increment prefix */
4065 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4067 /* Register new BGP information. */
4068 bgp_path_info_add(dest
, new);
4070 /* route_node_get lock */
4071 bgp_dest_unlock_node(dest
);
4073 #ifdef ENABLE_BGP_VNC
4074 if (safi
== SAFI_MPLS_VPN
) {
4075 struct bgp_dest
*pdest
= NULL
;
4076 struct bgp_table
*table
= NULL
;
4078 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4079 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4080 table
= bgp_dest_get_bgp_table_info(pdest
);
4082 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4083 bgp
, prd
, table
, p
, new);
4085 bgp_dest_unlock_node(pdest
);
4089 /* If this is an EVPN route, process for import. */
4090 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4091 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4093 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4095 /* Process change. */
4096 bgp_process(bgp
, dest
, afi
, safi
);
4098 if (SAFI_UNICAST
== safi
4099 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4100 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4101 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4103 if ((SAFI_MPLS_VPN
== safi
)
4104 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4106 vpn_leak_to_vrf_update(bgp
, new);
4108 #ifdef ENABLE_BGP_VNC
4109 if (SAFI_MPLS_VPN
== safi
) {
4110 mpls_label_t label_decoded
= decode_label(label
);
4112 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4113 sub_type
, &label_decoded
);
4115 if (SAFI_ENCAP
== safi
) {
4116 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4123 /* This BGP update is filtered. Log the reason then update BGP
4126 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4128 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4129 if (!peer
->rcvd_attr_printed
) {
4130 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4131 peer
->rcvd_attr_str
);
4132 peer
->rcvd_attr_printed
= 1;
4135 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4136 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4138 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4139 peer
->host
, pfx_buf
, reason
);
4143 /* If this is an EVPN route, un-import it as it is now filtered.
4145 if (safi
== SAFI_EVPN
)
4146 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4148 if (SAFI_UNICAST
== safi
4149 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4150 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4152 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4154 if ((SAFI_MPLS_VPN
== safi
)
4155 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4157 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4160 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4163 bgp_dest_unlock_node(dest
);
4165 #ifdef ENABLE_BGP_VNC
4167 * Filtered update is treated as an implicit withdrawal (see
4169 * a few lines above)
4171 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4172 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4180 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4181 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4182 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4183 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4186 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4187 struct bgp_dest
*dest
;
4188 struct bgp_path_info
*pi
;
4190 #ifdef ENABLE_BGP_VNC
4191 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4192 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4200 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4202 /* If peer is soft reconfiguration enabled. Record input packet for
4203 * further calculation.
4205 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4206 * routes that are filtered. This tanks out Quagga RS pretty badly due
4208 * the iteration over all RS clients.
4209 * Since we need to remove the entry from adj_in anyway, do that first
4211 * if there was no entry, we don't need to do anything more.
4213 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4214 && peer
!= bgp
->peer_self
)
4215 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4216 peer
->stat_pfx_dup_withdraw
++;
4218 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4219 bgp_debug_rdpfxpath2str(
4220 afi
, safi
, prd
, p
, label
, num_labels
,
4221 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4224 "%s withdrawing route %s not in adj-in",
4225 peer
->host
, pfx_buf
);
4227 bgp_dest_unlock_node(dest
);
4231 /* Lookup withdrawn route. */
4232 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4233 if (pi
->peer
== peer
&& pi
->type
== type
4234 && pi
->sub_type
== sub_type
4235 && pi
->addpath_rx_id
== addpath_id
)
4239 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4240 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4241 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4243 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4247 /* Withdraw specified route from routing table. */
4248 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4249 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4250 if (SAFI_UNICAST
== safi
4251 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4252 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4253 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4255 if ((SAFI_MPLS_VPN
== safi
)
4256 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4258 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4260 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4261 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4262 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4264 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4267 /* Unlock bgp_node_get() lock. */
4268 bgp_dest_unlock_node(dest
);
4273 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4276 struct update_subgroup
*subgrp
;
4277 subgrp
= peer_subgroup(peer
, afi
, safi
);
4278 subgroup_default_originate(subgrp
, withdraw
);
4283 * bgp_stop_announce_route_timer
4285 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4287 if (!paf
->t_announce_route
)
4290 THREAD_TIMER_OFF(paf
->t_announce_route
);
4294 * bgp_announce_route_timer_expired
4296 * Callback that is invoked when the route announcement timer for a
4299 static int bgp_announce_route_timer_expired(struct thread
*t
)
4301 struct peer_af
*paf
;
4304 paf
= THREAD_ARG(t
);
4307 if (peer
->status
!= Established
)
4310 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4313 peer_af_announce_route(paf
, 1);
4318 * bgp_announce_route
4320 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4322 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4324 struct peer_af
*paf
;
4325 struct update_subgroup
*subgrp
;
4327 paf
= peer_af_find(peer
, afi
, safi
);
4330 subgrp
= PAF_SUBGRP(paf
);
4333 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4334 * or a refresh has already been triggered.
4336 if (!subgrp
|| paf
->t_announce_route
)
4340 * Start a timer to stagger/delay the announce. This serves
4341 * two purposes - announcement can potentially be combined for
4342 * multiple peers and the announcement doesn't happen in the
4345 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4346 (subgrp
->peer_count
== 1)
4347 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4348 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4349 &paf
->t_announce_route
);
4353 * Announce routes from all AF tables to a peer.
4355 * This should ONLY be called when there is a need to refresh the
4356 * routes to the peer based on a policy change for this peer alone
4357 * or a route refresh request received from the peer.
4358 * The operation will result in splitting the peer from its existing
4359 * subgroups and putting it in new subgroups.
4361 void bgp_announce_route_all(struct peer
*peer
)
4366 FOREACH_AFI_SAFI (afi
, safi
)
4367 bgp_announce_route(peer
, afi
, safi
);
4370 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4371 struct bgp_table
*table
,
4372 struct prefix_rd
*prd
)
4375 struct bgp_dest
*dest
;
4376 struct bgp_adj_in
*ain
;
4379 table
= peer
->bgp
->rib
[afi
][safi
];
4381 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4382 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4383 if (ain
->peer
!= peer
)
4386 struct bgp_path_info
*pi
;
4387 uint32_t num_labels
= 0;
4388 mpls_label_t
*label_pnt
= NULL
;
4389 struct bgp_route_evpn evpn
;
4391 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4393 if (pi
->peer
== peer
)
4396 if (pi
&& pi
->extra
)
4397 num_labels
= pi
->extra
->num_labels
;
4399 label_pnt
= &pi
->extra
->label
[0];
4401 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
4404 memset(&evpn
, 0, sizeof(evpn
));
4406 ret
= bgp_update(peer
, bgp_dest_get_prefix(dest
),
4407 ain
->addpath_rx_id
, ain
->attr
, afi
,
4408 safi
, ZEBRA_ROUTE_BGP
,
4409 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4410 num_labels
, 1, &evpn
);
4413 bgp_dest_unlock_node(dest
);
4419 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4421 struct bgp_dest
*dest
;
4422 struct bgp_table
*table
;
4424 if (peer
->status
!= Established
)
4427 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4428 && (safi
!= SAFI_EVPN
))
4429 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4431 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4432 dest
= bgp_route_next(dest
)) {
4433 table
= bgp_dest_get_bgp_table_info(dest
);
4438 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4439 struct prefix_rd prd
;
4441 prd
.family
= AF_UNSPEC
;
4443 memcpy(&prd
.val
, p
->u
.val
, 8);
4445 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4450 struct bgp_clear_node_queue
{
4451 struct bgp_dest
*dest
;
4454 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4456 struct bgp_clear_node_queue
*cnq
= data
;
4457 struct bgp_dest
*dest
= cnq
->dest
;
4458 struct peer
*peer
= wq
->spec
.data
;
4459 struct bgp_path_info
*pi
;
4461 afi_t afi
= bgp_dest_table(dest
)->afi
;
4462 safi_t safi
= bgp_dest_table(dest
)->safi
;
4464 assert(dest
&& peer
);
4467 /* It is possible that we have multiple paths for a prefix from a peer
4468 * if that peer is using AddPath.
4470 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
4471 if (pi
->peer
!= peer
)
4474 /* graceful restart STALE flag set. */
4475 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4476 && peer
->nsf
[afi
][safi
]
4477 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4478 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4479 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
4481 /* If this is an EVPN route, process for
4483 if (safi
== SAFI_EVPN
)
4484 bgp_evpn_unimport_route(
4486 bgp_dest_get_prefix(dest
), pi
);
4487 /* Handle withdraw for VRF route-leaking and L3VPN */
4488 if (SAFI_UNICAST
== safi
4489 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4490 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4491 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4494 if (SAFI_MPLS_VPN
== safi
&&
4495 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4496 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4499 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4505 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4507 struct bgp_clear_node_queue
*cnq
= data
;
4508 struct bgp_dest
*dest
= cnq
->dest
;
4509 struct bgp_table
*table
= bgp_dest_table(dest
);
4511 bgp_dest_unlock_node(dest
);
4512 bgp_table_unlock(table
);
4513 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4516 static void bgp_clear_node_complete(struct work_queue
*wq
)
4518 struct peer
*peer
= wq
->spec
.data
;
4520 /* Tickle FSM to start moving again */
4521 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4523 peer_unlock(peer
); /* bgp_clear_route */
4526 static void bgp_clear_node_queue_init(struct peer
*peer
)
4528 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4530 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4531 #undef CLEAR_QUEUE_NAME_LEN
4533 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4534 peer
->clear_node_queue
->spec
.hold
= 10;
4535 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4536 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4537 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4538 peer
->clear_node_queue
->spec
.max_retries
= 0;
4540 /* we only 'lock' this peer reference when the queue is actually active
4542 peer
->clear_node_queue
->spec
.data
= peer
;
4545 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4546 struct bgp_table
*table
)
4548 struct bgp_dest
*dest
;
4549 int force
= bm
->process_main_queue
? 0 : 1;
4552 table
= peer
->bgp
->rib
[afi
][safi
];
4554 /* If still no table => afi/safi isn't configured at all or smth. */
4558 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4559 struct bgp_path_info
*pi
, *next
;
4560 struct bgp_adj_in
*ain
;
4561 struct bgp_adj_in
*ain_next
;
4563 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4564 * queued for every clearing peer, regardless of whether it is
4565 * relevant to the peer at hand.
4567 * Overview: There are 3 different indices which need to be
4568 * scrubbed, potentially, when a peer is removed:
4570 * 1 peer's routes visible via the RIB (ie accepted routes)
4571 * 2 peer's routes visible by the (optional) peer's adj-in index
4572 * 3 other routes visible by the peer's adj-out index
4574 * 3 there is no hurry in scrubbing, once the struct peer is
4575 * removed from bgp->peer, we could just GC such deleted peer's
4576 * adj-outs at our leisure.
4578 * 1 and 2 must be 'scrubbed' in some way, at least made
4579 * invisible via RIB index before peer session is allowed to be
4580 * brought back up. So one needs to know when such a 'search' is
4585 * - there'd be a single global queue or a single RIB walker
4586 * - rather than tracking which route_nodes still need to be
4587 * examined on a peer basis, we'd track which peers still
4590 * Given that our per-peer prefix-counts now should be reliable,
4591 * this may actually be achievable. It doesn't seem to be a huge
4592 * problem at this time,
4594 * It is possible that we have multiple paths for a prefix from
4596 * if that peer is using AddPath.
4600 ain_next
= ain
->next
;
4602 if (ain
->peer
== peer
) {
4603 bgp_adj_in_remove(dest
, ain
);
4604 bgp_dest_unlock_node(dest
);
4610 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4612 if (pi
->peer
!= peer
)
4616 bgp_path_info_reap(dest
, pi
);
4618 struct bgp_clear_node_queue
*cnq
;
4620 /* both unlocked in bgp_clear_node_queue_del */
4621 bgp_table_lock(bgp_dest_table(dest
));
4622 bgp_dest_lock_node(dest
);
4624 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4625 sizeof(struct bgp_clear_node_queue
));
4627 work_queue_add(peer
->clear_node_queue
, cnq
);
4635 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4637 struct bgp_dest
*dest
;
4638 struct bgp_table
*table
;
4640 if (peer
->clear_node_queue
== NULL
)
4641 bgp_clear_node_queue_init(peer
);
4643 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4644 * Idle until it receives a Clearing_Completed event. This protects
4645 * against peers which flap faster than we can we clear, which could
4648 * a) race with routes from the new session being installed before
4649 * clear_route_node visits the node (to delete the route of that
4651 * b) resource exhaustion, clear_route_node likely leads to an entry
4652 * on the process_main queue. Fast-flapping could cause that queue
4656 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4657 * the unlock will happen upon work-queue completion; other wise, the
4658 * unlock happens at the end of this function.
4660 if (!peer
->clear_node_queue
->thread
)
4663 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4664 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4666 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4667 dest
= bgp_route_next(dest
)) {
4668 table
= bgp_dest_get_bgp_table_info(dest
);
4672 bgp_clear_route_table(peer
, afi
, safi
, table
);
4675 /* unlock if no nodes got added to the clear-node-queue. */
4676 if (!peer
->clear_node_queue
->thread
)
4680 void bgp_clear_route_all(struct peer
*peer
)
4685 FOREACH_AFI_SAFI (afi
, safi
)
4686 bgp_clear_route(peer
, afi
, safi
);
4688 #ifdef ENABLE_BGP_VNC
4689 rfapiProcessPeerDown(peer
);
4693 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4695 struct bgp_table
*table
;
4696 struct bgp_dest
*dest
;
4697 struct bgp_adj_in
*ain
;
4698 struct bgp_adj_in
*ain_next
;
4700 table
= peer
->bgp
->rib
[afi
][safi
];
4702 /* It is possible that we have multiple paths for a prefix from a peer
4703 * if that peer is using AddPath.
4705 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4709 ain_next
= ain
->next
;
4711 if (ain
->peer
== peer
) {
4712 bgp_adj_in_remove(dest
, ain
);
4713 bgp_dest_unlock_node(dest
);
4721 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4723 struct bgp_dest
*dest
;
4724 struct bgp_path_info
*pi
;
4725 struct bgp_table
*table
;
4727 if (safi
== SAFI_MPLS_VPN
) {
4728 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4729 dest
= bgp_route_next(dest
)) {
4730 struct bgp_dest
*rm
;
4732 /* look for neighbor in tables */
4733 table
= bgp_dest_get_bgp_table_info(dest
);
4737 for (rm
= bgp_table_top(table
); rm
;
4738 rm
= bgp_route_next(rm
))
4739 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
4741 if (pi
->peer
!= peer
)
4743 if (!CHECK_FLAG(pi
->flags
,
4747 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4752 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4753 dest
= bgp_route_next(dest
))
4754 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4756 if (pi
->peer
!= peer
)
4758 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4760 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4766 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4768 if (peer
->sort
== BGP_PEER_IBGP
)
4771 if (peer
->sort
== BGP_PEER_EBGP
4772 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4773 || FILTER_LIST_OUT_NAME(filter
)
4774 || DISTRIBUTE_OUT_NAME(filter
)))
4779 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4781 if (peer
->sort
== BGP_PEER_IBGP
)
4784 if (peer
->sort
== BGP_PEER_EBGP
4785 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4786 || FILTER_LIST_IN_NAME(filter
)
4787 || DISTRIBUTE_IN_NAME(filter
)))
4792 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4795 struct bgp_dest
*dest
;
4796 struct bgp_path_info
*pi
;
4797 struct bgp_path_info
*next
;
4799 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4800 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4801 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4805 /* Unimport EVPN routes from VRFs */
4806 if (safi
== SAFI_EVPN
)
4807 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4810 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4811 && pi
->type
== ZEBRA_ROUTE_BGP
4812 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4813 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4814 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4816 if (bgp_fibupd_safi(safi
))
4817 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4820 bgp_path_info_reap(dest
, pi
);
4824 /* Delete all kernel routes. */
4825 void bgp_cleanup_routes(struct bgp
*bgp
)
4828 struct bgp_dest
*dest
;
4829 struct bgp_table
*table
;
4831 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4832 if (afi
== AFI_L2VPN
)
4834 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4837 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4839 if (afi
!= AFI_L2VPN
) {
4841 safi
= SAFI_MPLS_VPN
;
4842 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
4843 dest
= bgp_route_next(dest
)) {
4844 table
= bgp_dest_get_bgp_table_info(dest
);
4845 if (table
!= NULL
) {
4846 bgp_cleanup_table(bgp
, table
, safi
);
4847 bgp_table_finish(&table
);
4848 bgp_dest_set_bgp_table_info(dest
, NULL
);
4849 bgp_dest_unlock_node(dest
);
4853 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
4854 dest
= bgp_route_next(dest
)) {
4855 table
= bgp_dest_get_bgp_table_info(dest
);
4856 if (table
!= NULL
) {
4857 bgp_cleanup_table(bgp
, table
, safi
);
4858 bgp_table_finish(&table
);
4859 bgp_dest_set_bgp_table_info(dest
, NULL
);
4860 bgp_dest_unlock_node(dest
);
4865 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
4866 dest
= bgp_route_next(dest
)) {
4867 table
= bgp_dest_get_bgp_table_info(dest
);
4868 if (table
!= NULL
) {
4869 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4870 bgp_table_finish(&table
);
4871 bgp_dest_set_bgp_table_info(dest
, NULL
);
4872 bgp_dest_unlock_node(dest
);
4877 void bgp_reset(void)
4880 bgp_zclient_reset();
4881 access_list_reset();
4882 prefix_list_reset();
4885 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4887 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4888 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4889 PEER_CAP_ADDPATH_AF_TX_RCV
));
4892 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4894 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4895 struct bgp_nlri
*packet
)
4904 int addpath_encoded
;
4905 uint32_t addpath_id
;
4908 lim
= pnt
+ packet
->length
;
4910 safi
= packet
->safi
;
4912 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4914 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4915 syntactic validity. If the field is syntactically incorrect,
4916 then the Error Subcode is set to Invalid Network Field. */
4917 for (; pnt
< lim
; pnt
+= psize
) {
4918 /* Clear prefix structure. */
4919 memset(&p
, 0, sizeof(struct prefix
));
4921 if (addpath_encoded
) {
4923 /* When packet overflow occurs return immediately. */
4924 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4925 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4927 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
4928 addpath_id
= ntohl(addpath_id
);
4929 pnt
+= BGP_ADDPATH_ID_LEN
;
4932 /* Fetch prefix length. */
4933 p
.prefixlen
= *pnt
++;
4934 /* afi/safi validity already verified by caller,
4935 * bgp_update_receive */
4936 p
.family
= afi2family(afi
);
4938 /* Prefix length check. */
4939 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4942 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4943 peer
->host
, p
.prefixlen
, packet
->afi
);
4944 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4947 /* Packet size overflow check. */
4948 psize
= PSIZE(p
.prefixlen
);
4950 /* When packet overflow occur return immediately. */
4951 if (pnt
+ psize
> lim
) {
4954 "%s [Error] Update packet error (prefix length %d overflows packet)",
4955 peer
->host
, p
.prefixlen
);
4956 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4959 /* Defensive coding, double-check the psize fits in a struct
4961 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4964 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4965 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4966 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4969 /* Fetch prefix from NLRI packet. */
4970 memcpy(p
.u
.val
, pnt
, psize
);
4972 /* Check address. */
4973 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4974 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4975 /* From RFC4271 Section 6.3:
4977 * If a prefix in the NLRI field is semantically
4979 * (e.g., an unexpected multicast IP address),
4981 * be logged locally, and the prefix SHOULD be
4986 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4987 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4992 /* Check address. */
4993 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4994 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4999 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5001 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5006 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5011 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5013 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5020 /* Normal process. */
5022 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5023 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5024 NULL
, NULL
, 0, 0, NULL
);
5026 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5027 safi
, ZEBRA_ROUTE_BGP
,
5028 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5031 /* Do not send BGP notification twice when maximum-prefix count
5033 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5034 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5036 /* Address family configuration mismatch. */
5038 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5041 /* Packet length consistency check. */
5045 "%s [Error] Update packet error (prefix length mismatch with total length)",
5047 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5050 return BGP_NLRI_PARSE_OK
;
5053 static struct bgp_static
*bgp_static_new(void)
5055 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5058 static void bgp_static_free(struct bgp_static
*bgp_static
)
5060 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5061 route_map_counter_decrement(bgp_static
->rmap
.map
);
5063 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5064 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5067 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5068 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5070 struct bgp_dest
*dest
;
5071 struct bgp_path_info
*pi
;
5072 struct bgp_path_info
*new;
5073 struct bgp_path_info rmap_path
;
5075 struct attr
*attr_new
;
5076 route_map_result_t ret
;
5077 #ifdef ENABLE_BGP_VNC
5078 int vnc_implicit_withdraw
= 0;
5083 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5085 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5087 attr
.nexthop
= bgp_static
->igpnexthop
;
5088 attr
.med
= bgp_static
->igpmetric
;
5089 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5091 if (bgp_static
->atomic
)
5092 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5094 /* Store label index, if required. */
5095 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5096 attr
.label_index
= bgp_static
->label_index
;
5097 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5100 /* Apply route-map. */
5101 if (bgp_static
->rmap
.name
) {
5102 struct attr attr_tmp
= attr
;
5104 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5105 rmap_path
.peer
= bgp
->peer_self
;
5106 rmap_path
.attr
= &attr_tmp
;
5108 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5110 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5113 bgp
->peer_self
->rmap_type
= 0;
5115 if (ret
== RMAP_DENYMATCH
) {
5116 /* Free uninterned attribute. */
5117 bgp_attr_flush(&attr_tmp
);
5119 /* Unintern original. */
5120 aspath_unintern(&attr
.aspath
);
5121 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5125 if (bgp_in_graceful_shutdown(bgp
))
5126 bgp_attr_add_gshut_community(&attr_tmp
);
5128 attr_new
= bgp_attr_intern(&attr_tmp
);
5131 if (bgp_in_graceful_shutdown(bgp
))
5132 bgp_attr_add_gshut_community(&attr
);
5134 attr_new
= bgp_attr_intern(&attr
);
5137 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5138 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5139 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5143 if (attrhash_cmp(pi
->attr
, attr_new
)
5144 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5145 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5146 bgp_dest_unlock_node(dest
);
5147 bgp_attr_unintern(&attr_new
);
5148 aspath_unintern(&attr
.aspath
);
5151 /* The attribute is changed. */
5152 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5154 /* Rewrite BGP route information. */
5155 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5156 bgp_path_info_restore(dest
, pi
);
5158 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5159 #ifdef ENABLE_BGP_VNC
5160 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5161 && (safi
== SAFI_UNICAST
)) {
5162 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5164 * Implicit withdraw case.
5165 * We have to do this before pi is
5168 ++vnc_implicit_withdraw
;
5169 vnc_import_bgp_del_route(bgp
, p
, pi
);
5170 vnc_import_bgp_exterior_del_route(
5175 bgp_attr_unintern(&pi
->attr
);
5176 pi
->attr
= attr_new
;
5177 pi
->uptime
= bgp_clock();
5178 #ifdef ENABLE_BGP_VNC
5179 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5180 && (safi
== SAFI_UNICAST
)) {
5181 if (vnc_implicit_withdraw
) {
5182 vnc_import_bgp_add_route(bgp
, p
, pi
);
5183 vnc_import_bgp_exterior_add_route(
5189 /* Nexthop reachability check. */
5190 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5191 && (safi
== SAFI_UNICAST
5192 || safi
== SAFI_LABELED_UNICAST
)) {
5194 struct bgp
*bgp_nexthop
= bgp
;
5196 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5197 bgp_nexthop
= pi
->extra
->bgp_orig
;
5199 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5201 bgp_path_info_set_flag(dest
, pi
,
5204 if (BGP_DEBUG(nht
, NHT
)) {
5205 char buf1
[INET6_ADDRSTRLEN
];
5206 inet_ntop(p
->family
,
5210 "%s(%s): Route not in table, not advertising",
5213 bgp_path_info_unset_flag(
5214 dest
, pi
, BGP_PATH_VALID
);
5217 /* Delete the NHT structure if any, if we're
5219 * enabling/disabling import check. We
5220 * deregister the route
5221 * from NHT to avoid overloading NHT and the
5222 * process interaction
5224 bgp_unlink_nexthop(pi
);
5225 bgp_path_info_set_flag(dest
, pi
,
5228 /* Process change. */
5229 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5230 bgp_process(bgp
, dest
, afi
, safi
);
5232 if (SAFI_UNICAST
== safi
5233 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5235 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5236 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5240 bgp_dest_unlock_node(dest
);
5241 aspath_unintern(&attr
.aspath
);
5246 /* Make new BGP info. */
5247 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5249 /* Nexthop reachability check. */
5250 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5251 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5252 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
5253 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5255 if (BGP_DEBUG(nht
, NHT
)) {
5256 char buf1
[INET6_ADDRSTRLEN
];
5257 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5260 "%s(%s): Route not in table, not advertising",
5263 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5266 /* Delete the NHT structure if any, if we're toggling between
5267 * enabling/disabling import check. We deregister the route
5268 * from NHT to avoid overloading NHT and the process interaction
5270 bgp_unlink_nexthop(new);
5272 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5275 /* Aggregate address increment. */
5276 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5278 /* Register new BGP information. */
5279 bgp_path_info_add(dest
, new);
5281 /* route_node_get lock */
5282 bgp_dest_unlock_node(dest
);
5284 /* Process change. */
5285 bgp_process(bgp
, dest
, afi
, safi
);
5287 if (SAFI_UNICAST
== safi
5288 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5289 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5290 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5293 /* Unintern original. */
5294 aspath_unintern(&attr
.aspath
);
5297 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
5300 struct bgp_dest
*dest
;
5301 struct bgp_path_info
*pi
;
5303 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5305 /* Check selected route and self inserted route. */
5306 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5307 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5308 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5311 /* Withdraw static BGP route from routing table. */
5313 if (SAFI_UNICAST
== safi
5314 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5315 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5316 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5318 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5319 bgp_unlink_nexthop(pi
);
5320 bgp_path_info_delete(dest
, pi
);
5321 bgp_process(bgp
, dest
, afi
, safi
);
5324 /* Unlock bgp_node_lookup. */
5325 bgp_dest_unlock_node(dest
);
5329 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5331 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
5332 afi_t afi
, safi_t safi
,
5333 struct prefix_rd
*prd
)
5335 struct bgp_dest
*dest
;
5336 struct bgp_path_info
*pi
;
5338 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5340 /* Check selected route and self inserted route. */
5341 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5342 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5343 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5346 /* Withdraw static BGP route from routing table. */
5348 #ifdef ENABLE_BGP_VNC
5349 rfapiProcessWithdraw(
5350 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5351 1); /* Kill, since it is an administrative change */
5353 if (SAFI_MPLS_VPN
== safi
5354 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5355 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5357 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5358 bgp_path_info_delete(dest
, pi
);
5359 bgp_process(bgp
, dest
, afi
, safi
);
5362 /* Unlock bgp_node_lookup. */
5363 bgp_dest_unlock_node(dest
);
5366 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
5367 struct bgp_static
*bgp_static
, afi_t afi
,
5370 struct bgp_dest
*dest
;
5371 struct bgp_path_info
*new;
5372 struct attr
*attr_new
;
5373 struct attr attr
= {0};
5374 struct bgp_path_info
*pi
;
5375 #ifdef ENABLE_BGP_VNC
5376 mpls_label_t label
= 0;
5378 uint32_t num_labels
= 0;
5383 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5385 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5388 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5390 attr
.nexthop
= bgp_static
->igpnexthop
;
5391 attr
.med
= bgp_static
->igpmetric
;
5392 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5394 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5395 || (safi
== SAFI_ENCAP
)) {
5396 if (afi
== AFI_IP
) {
5397 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5398 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5401 if (afi
== AFI_L2VPN
) {
5402 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5404 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5405 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5406 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5407 sizeof(struct in6_addr
));
5408 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
5409 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5410 struct bgp_encap_type_vxlan bet
;
5411 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5412 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5413 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5415 if (bgp_static
->router_mac
) {
5416 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5419 /* Apply route-map. */
5420 if (bgp_static
->rmap
.name
) {
5421 struct attr attr_tmp
= attr
;
5422 struct bgp_path_info rmap_path
;
5423 route_map_result_t ret
;
5425 rmap_path
.peer
= bgp
->peer_self
;
5426 rmap_path
.attr
= &attr_tmp
;
5428 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5430 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5433 bgp
->peer_self
->rmap_type
= 0;
5435 if (ret
== RMAP_DENYMATCH
) {
5436 /* Free uninterned attribute. */
5437 bgp_attr_flush(&attr_tmp
);
5439 /* Unintern original. */
5440 aspath_unintern(&attr
.aspath
);
5441 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5446 attr_new
= bgp_attr_intern(&attr_tmp
);
5448 attr_new
= bgp_attr_intern(&attr
);
5451 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5452 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5453 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5457 memset(&add
, 0, sizeof(union gw_addr
));
5458 if (attrhash_cmp(pi
->attr
, attr_new
)
5459 && overlay_index_equal(afi
, pi
, &add
)
5460 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5461 bgp_dest_unlock_node(dest
);
5462 bgp_attr_unintern(&attr_new
);
5463 aspath_unintern(&attr
.aspath
);
5466 /* The attribute is changed. */
5467 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5469 /* Rewrite BGP route information. */
5470 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5471 bgp_path_info_restore(dest
, pi
);
5473 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5474 bgp_attr_unintern(&pi
->attr
);
5475 pi
->attr
= attr_new
;
5476 pi
->uptime
= bgp_clock();
5477 #ifdef ENABLE_BGP_VNC
5479 label
= decode_label(&pi
->extra
->label
[0]);
5482 /* Process change. */
5483 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5484 bgp_process(bgp
, dest
, afi
, safi
);
5486 if (SAFI_MPLS_VPN
== safi
5487 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5488 vpn_leak_to_vrf_update(bgp
, pi
);
5490 #ifdef ENABLE_BGP_VNC
5491 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5492 pi
->attr
, afi
, safi
, pi
->type
,
5493 pi
->sub_type
, &label
);
5495 bgp_dest_unlock_node(dest
);
5496 aspath_unintern(&attr
.aspath
);
5502 /* Make new BGP info. */
5503 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5505 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5506 new->extra
= bgp_path_info_extra_new();
5508 new->extra
->label
[0] = bgp_static
->label
;
5509 new->extra
->num_labels
= num_labels
;
5511 #ifdef ENABLE_BGP_VNC
5512 label
= decode_label(&bgp_static
->label
);
5515 /* Aggregate address increment. */
5516 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5518 /* Register new BGP information. */
5519 bgp_path_info_add(dest
, new);
5520 /* route_node_get lock */
5521 bgp_dest_unlock_node(dest
);
5523 /* Process change. */
5524 bgp_process(bgp
, dest
, afi
, safi
);
5526 if (SAFI_MPLS_VPN
== safi
5527 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5528 vpn_leak_to_vrf_update(bgp
, new);
5530 #ifdef ENABLE_BGP_VNC
5531 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5532 safi
, new->type
, new->sub_type
, &label
);
5535 /* Unintern original. */
5536 aspath_unintern(&attr
.aspath
);
5539 /* Configure static BGP network. When user don't run zebra, static
5540 route should be installed as valid. */
5541 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5542 const char *ip_str
, afi_t afi
, safi_t safi
,
5543 const char *rmap
, int backdoor
, uint32_t label_index
)
5545 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5548 struct bgp_static
*bgp_static
;
5549 struct bgp_dest
*dest
;
5550 uint8_t need_update
= 0;
5552 /* Convert IP prefix string to struct prefix. */
5553 ret
= str2prefix(ip_str
, &p
);
5555 vty_out(vty
, "%% Malformed prefix\n");
5556 return CMD_WARNING_CONFIG_FAILED
;
5558 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5559 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5560 return CMD_WARNING_CONFIG_FAILED
;
5567 /* Set BGP static route configuration. */
5568 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5571 vty_out(vty
, "%% Can't find static route specified\n");
5572 return CMD_WARNING_CONFIG_FAILED
;
5575 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5577 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5578 && (label_index
!= bgp_static
->label_index
)) {
5580 "%% label-index doesn't match static route\n");
5581 return CMD_WARNING_CONFIG_FAILED
;
5584 if ((rmap
&& bgp_static
->rmap
.name
)
5585 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5587 "%% route-map name doesn't match static route\n");
5588 return CMD_WARNING_CONFIG_FAILED
;
5591 /* Update BGP RIB. */
5592 if (!bgp_static
->backdoor
)
5593 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5595 /* Clear configuration. */
5596 bgp_static_free(bgp_static
);
5597 bgp_dest_set_bgp_static_info(dest
, NULL
);
5598 bgp_dest_unlock_node(dest
);
5599 bgp_dest_unlock_node(dest
);
5602 /* Set BGP static route configuration. */
5603 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5604 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5606 /* Configuration change. */
5607 /* Label index cannot be changed. */
5608 if (bgp_static
->label_index
!= label_index
) {
5609 vty_out(vty
, "%% cannot change label-index\n");
5610 return CMD_WARNING_CONFIG_FAILED
;
5613 /* Check previous routes are installed into BGP. */
5614 if (bgp_static
->valid
5615 && bgp_static
->backdoor
!= backdoor
)
5618 bgp_static
->backdoor
= backdoor
;
5621 XFREE(MTYPE_ROUTE_MAP_NAME
,
5622 bgp_static
->rmap
.name
);
5623 route_map_counter_decrement(
5624 bgp_static
->rmap
.map
);
5625 bgp_static
->rmap
.name
=
5626 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5627 bgp_static
->rmap
.map
=
5628 route_map_lookup_by_name(rmap
);
5629 route_map_counter_increment(
5630 bgp_static
->rmap
.map
);
5632 XFREE(MTYPE_ROUTE_MAP_NAME
,
5633 bgp_static
->rmap
.name
);
5634 route_map_counter_decrement(
5635 bgp_static
->rmap
.map
);
5636 bgp_static
->rmap
.map
= NULL
;
5637 bgp_static
->valid
= 0;
5639 bgp_dest_unlock_node(dest
);
5641 /* New configuration. */
5642 bgp_static
= bgp_static_new();
5643 bgp_static
->backdoor
= backdoor
;
5644 bgp_static
->valid
= 0;
5645 bgp_static
->igpmetric
= 0;
5646 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5647 bgp_static
->label_index
= label_index
;
5650 XFREE(MTYPE_ROUTE_MAP_NAME
,
5651 bgp_static
->rmap
.name
);
5652 route_map_counter_decrement(
5653 bgp_static
->rmap
.map
);
5654 bgp_static
->rmap
.name
=
5655 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5656 bgp_static
->rmap
.map
=
5657 route_map_lookup_by_name(rmap
);
5658 route_map_counter_increment(
5659 bgp_static
->rmap
.map
);
5661 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5664 bgp_static
->valid
= 1;
5666 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5668 if (!bgp_static
->backdoor
)
5669 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5675 void bgp_static_add(struct bgp
*bgp
)
5679 struct bgp_dest
*dest
;
5680 struct bgp_dest
*rm
;
5681 struct bgp_table
*table
;
5682 struct bgp_static
*bgp_static
;
5684 FOREACH_AFI_SAFI (afi
, safi
)
5685 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5686 dest
= bgp_route_next(dest
)) {
5687 if (!bgp_dest_has_bgp_path_info_data(dest
))
5690 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5691 || (safi
== SAFI_EVPN
)) {
5692 table
= bgp_dest_get_bgp_table_info(dest
);
5694 for (rm
= bgp_table_top(table
); rm
;
5695 rm
= bgp_route_next(rm
)) {
5697 bgp_dest_get_bgp_static_info(
5699 bgp_static_update_safi(
5700 bgp
, bgp_dest_get_prefix(rm
),
5701 bgp_static
, afi
, safi
);
5705 bgp
, bgp_dest_get_prefix(dest
),
5706 bgp_dest_get_bgp_static_info(dest
), afi
,
5712 /* Called from bgp_delete(). Delete all static routes from the BGP
5714 void bgp_static_delete(struct bgp
*bgp
)
5718 struct bgp_dest
*dest
;
5719 struct bgp_dest
*rm
;
5720 struct bgp_table
*table
;
5721 struct bgp_static
*bgp_static
;
5723 FOREACH_AFI_SAFI (afi
, safi
)
5724 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5725 dest
= bgp_route_next(dest
)) {
5726 if (!bgp_dest_has_bgp_path_info_data(dest
))
5729 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5730 || (safi
== SAFI_EVPN
)) {
5731 table
= bgp_dest_get_bgp_table_info(dest
);
5733 for (rm
= bgp_table_top(table
); rm
;
5734 rm
= bgp_route_next(rm
)) {
5736 bgp_dest_get_bgp_static_info(
5741 bgp_static_withdraw_safi(
5742 bgp
, bgp_dest_get_prefix(rm
),
5744 (struct prefix_rd
*)
5745 bgp_dest_get_prefix(
5747 bgp_static_free(bgp_static
);
5748 bgp_dest_set_bgp_static_info(dest
,
5750 bgp_dest_unlock_node(dest
);
5753 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5754 bgp_static_withdraw(bgp
,
5755 bgp_dest_get_prefix(dest
),
5757 bgp_static_free(bgp_static
);
5758 bgp_dest_set_bgp_static_info(dest
, NULL
);
5759 bgp_dest_unlock_node(dest
);
5764 void bgp_static_redo_import_check(struct bgp
*bgp
)
5768 struct bgp_dest
*dest
;
5769 struct bgp_dest
*rm
;
5770 struct bgp_table
*table
;
5771 struct bgp_static
*bgp_static
;
5773 /* Use this flag to force reprocessing of the route */
5774 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5775 FOREACH_AFI_SAFI (afi
, safi
) {
5776 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5777 dest
= bgp_route_next(dest
)) {
5778 if (!bgp_dest_has_bgp_path_info_data(dest
))
5781 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5782 || (safi
== SAFI_EVPN
)) {
5783 table
= bgp_dest_get_bgp_table_info(dest
);
5785 for (rm
= bgp_table_top(table
); rm
;
5786 rm
= bgp_route_next(rm
)) {
5788 bgp_dest_get_bgp_static_info(
5790 bgp_static_update_safi(
5791 bgp
, bgp_dest_get_prefix(rm
),
5792 bgp_static
, afi
, safi
);
5795 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5796 bgp_static_update(bgp
,
5797 bgp_dest_get_prefix(dest
),
5798 bgp_static
, afi
, safi
);
5802 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5805 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5808 struct bgp_table
*table
;
5809 struct bgp_dest
*dest
;
5810 struct bgp_path_info
*pi
;
5812 /* Do not install the aggregate route if BGP is in the
5813 * process of termination.
5815 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
5816 || (bgp
->peer_self
== NULL
))
5819 table
= bgp
->rib
[afi
][safi
];
5820 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5821 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5822 if (pi
->peer
== bgp
->peer_self
5823 && ((pi
->type
== ZEBRA_ROUTE_BGP
5824 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5825 || (pi
->type
!= ZEBRA_ROUTE_BGP
5827 == BGP_ROUTE_REDISTRIBUTE
))) {
5828 bgp_aggregate_decrement(
5829 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
5831 bgp_unlink_nexthop(pi
);
5832 bgp_path_info_delete(dest
, pi
);
5833 bgp_process(bgp
, dest
, afi
, safi
);
5840 * Purge all networks and redistributed routes from routing table.
5841 * Invoked upon the instance going down.
5843 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5848 FOREACH_AFI_SAFI (afi
, safi
)
5849 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5854 * Currently this is used to set static routes for VPN and ENCAP.
5855 * I think it can probably be factored with bgp_static_set.
5857 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5858 const char *ip_str
, const char *rd_str
,
5859 const char *label_str
, const char *rmap_str
,
5860 int evpn_type
, const char *esi
, const char *gwip
,
5861 const char *ethtag
, const char *routermac
)
5863 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5866 struct prefix_rd prd
;
5867 struct bgp_dest
*pdest
;
5868 struct bgp_dest
*dest
;
5869 struct bgp_table
*table
;
5870 struct bgp_static
*bgp_static
;
5871 mpls_label_t label
= MPLS_INVALID_LABEL
;
5872 struct prefix gw_ip
;
5874 /* validate ip prefix */
5875 ret
= str2prefix(ip_str
, &p
);
5877 vty_out(vty
, "%% Malformed prefix\n");
5878 return CMD_WARNING_CONFIG_FAILED
;
5881 if ((afi
== AFI_L2VPN
)
5882 && (bgp_build_evpn_prefix(evpn_type
,
5883 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5884 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5885 return CMD_WARNING_CONFIG_FAILED
;
5888 ret
= str2prefix_rd(rd_str
, &prd
);
5890 vty_out(vty
, "%% Malformed rd\n");
5891 return CMD_WARNING_CONFIG_FAILED
;
5895 unsigned long label_val
;
5896 label_val
= strtoul(label_str
, NULL
, 10);
5897 encode_label(label_val
, &label
);
5900 if (safi
== SAFI_EVPN
) {
5901 if (esi
&& str2esi(esi
, NULL
) == 0) {
5902 vty_out(vty
, "%% Malformed ESI\n");
5903 return CMD_WARNING_CONFIG_FAILED
;
5905 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5906 vty_out(vty
, "%% Malformed Router MAC\n");
5907 return CMD_WARNING_CONFIG_FAILED
;
5910 memset(&gw_ip
, 0, sizeof(struct prefix
));
5911 ret
= str2prefix(gwip
, &gw_ip
);
5913 vty_out(vty
, "%% Malformed GatewayIp\n");
5914 return CMD_WARNING_CONFIG_FAILED
;
5916 if ((gw_ip
.family
== AF_INET
5917 && is_evpn_prefix_ipaddr_v6(
5918 (struct prefix_evpn
*)&p
))
5919 || (gw_ip
.family
== AF_INET6
5920 && is_evpn_prefix_ipaddr_v4(
5921 (struct prefix_evpn
*)&p
))) {
5923 "%% GatewayIp family differs with IP prefix\n");
5924 return CMD_WARNING_CONFIG_FAILED
;
5928 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5929 if (!bgp_dest_has_bgp_path_info_data(pdest
))
5930 bgp_dest_set_bgp_table_info(pdest
,
5931 bgp_table_init(bgp
, afi
, safi
));
5932 table
= bgp_dest_get_bgp_table_info(pdest
);
5934 dest
= bgp_node_get(table
, &p
);
5936 if (bgp_dest_has_bgp_path_info_data(dest
)) {
5937 vty_out(vty
, "%% Same network configuration exists\n");
5938 bgp_dest_unlock_node(dest
);
5940 /* New configuration. */
5941 bgp_static
= bgp_static_new();
5942 bgp_static
->backdoor
= 0;
5943 bgp_static
->valid
= 0;
5944 bgp_static
->igpmetric
= 0;
5945 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5946 bgp_static
->label
= label
;
5947 bgp_static
->prd
= prd
;
5950 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5951 route_map_counter_decrement(bgp_static
->rmap
.map
);
5952 bgp_static
->rmap
.name
=
5953 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5954 bgp_static
->rmap
.map
=
5955 route_map_lookup_by_name(rmap_str
);
5956 route_map_counter_increment(bgp_static
->rmap
.map
);
5959 if (safi
== SAFI_EVPN
) {
5961 bgp_static
->eth_s_id
=
5964 str2esi(esi
, bgp_static
->eth_s_id
);
5967 bgp_static
->router_mac
=
5968 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5969 (void)prefix_str2mac(routermac
,
5970 bgp_static
->router_mac
);
5973 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5975 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5977 bgp_static
->valid
= 1;
5978 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5984 /* Configure static BGP network. */
5985 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5986 const char *ip_str
, const char *rd_str
,
5987 const char *label_str
, int evpn_type
, const char *esi
,
5988 const char *gwip
, const char *ethtag
)
5990 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5993 struct prefix_rd prd
;
5994 struct bgp_dest
*pdest
;
5995 struct bgp_dest
*dest
;
5996 struct bgp_table
*table
;
5997 struct bgp_static
*bgp_static
;
5998 mpls_label_t label
= MPLS_INVALID_LABEL
;
6000 /* Convert IP prefix string to struct prefix. */
6001 ret
= str2prefix(ip_str
, &p
);
6003 vty_out(vty
, "%% Malformed prefix\n");
6004 return CMD_WARNING_CONFIG_FAILED
;
6007 if ((afi
== AFI_L2VPN
)
6008 && (bgp_build_evpn_prefix(evpn_type
,
6009 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6010 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6011 return CMD_WARNING_CONFIG_FAILED
;
6013 ret
= str2prefix_rd(rd_str
, &prd
);
6015 vty_out(vty
, "%% Malformed rd\n");
6016 return CMD_WARNING_CONFIG_FAILED
;
6020 unsigned long label_val
;
6021 label_val
= strtoul(label_str
, NULL
, 10);
6022 encode_label(label_val
, &label
);
6025 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6026 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6027 bgp_dest_set_bgp_table_info(pdest
,
6028 bgp_table_init(bgp
, afi
, safi
));
6030 bgp_dest_unlock_node(pdest
);
6031 table
= bgp_dest_get_bgp_table_info(pdest
);
6033 dest
= bgp_node_lookup(table
, &p
);
6036 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6038 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6039 bgp_static_free(bgp_static
);
6040 bgp_dest_set_bgp_static_info(dest
, NULL
);
6041 bgp_dest_unlock_node(dest
);
6042 bgp_dest_unlock_node(dest
);
6044 vty_out(vty
, "%% Can't find the route\n");
6049 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6050 const char *rmap_name
)
6052 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6053 struct bgp_rmap
*rmap
;
6055 rmap
= &bgp
->table_map
[afi
][safi
];
6057 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6058 route_map_counter_decrement(rmap
->map
);
6059 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6060 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6061 route_map_counter_increment(rmap
->map
);
6063 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6064 route_map_counter_decrement(rmap
->map
);
6068 if (bgp_fibupd_safi(safi
))
6069 bgp_zebra_announce_table(bgp
, afi
, safi
);
6074 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6075 const char *rmap_name
)
6077 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6078 struct bgp_rmap
*rmap
;
6080 rmap
= &bgp
->table_map
[afi
][safi
];
6081 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6082 route_map_counter_decrement(rmap
->map
);
6085 if (bgp_fibupd_safi(safi
))
6086 bgp_zebra_announce_table(bgp
, afi
, safi
);
6091 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6094 if (bgp
->table_map
[afi
][safi
].name
) {
6095 vty_out(vty
, " table-map %s\n",
6096 bgp
->table_map
[afi
][safi
].name
);
6100 DEFUN (bgp_table_map
,
6103 "BGP table to RIB route download filter\n"
6104 "Name of the route map\n")
6107 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6108 argv
[idx_word
]->arg
);
6110 DEFUN (no_bgp_table_map
,
6111 no_bgp_table_map_cmd
,
6112 "no table-map WORD",
6114 "BGP table to RIB route download filter\n"
6115 "Name of the route map\n")
6118 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6119 argv
[idx_word
]->arg
);
6125 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6126 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6127 backdoor$backdoor}]",
6129 "Specify a network to announce via BGP\n"
6134 "Route-map to modify the attributes\n"
6135 "Name of the route map\n"
6136 "Label index to associate with the prefix\n"
6137 "Label index value\n"
6138 "Specify a BGP backdoor route\n")
6140 char addr_prefix_str
[BUFSIZ
];
6145 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6148 vty_out(vty
, "%% Inconsistent address and mask\n");
6149 return CMD_WARNING_CONFIG_FAILED
;
6153 return bgp_static_set(
6154 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
6155 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
6156 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6159 DEFPY(ipv6_bgp_network
,
6160 ipv6_bgp_network_cmd
,
6161 "[no] network X:X::X:X/M$prefix \
6162 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6164 "Specify a network to announce via BGP\n"
6166 "Route-map to modify the attributes\n"
6167 "Name of the route map\n"
6168 "Label index to associate with the prefix\n"
6169 "Label index value\n")
6171 return bgp_static_set(
6172 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
6173 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6176 static struct bgp_aggregate
*bgp_aggregate_new(void)
6178 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6181 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6183 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6184 route_map_counter_decrement(aggregate
->rmap
.map
);
6185 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6188 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6189 struct aspath
*aspath
,
6190 struct community
*comm
,
6191 struct ecommunity
*ecomm
,
6192 struct lcommunity
*lcomm
)
6194 static struct aspath
*ae
= NULL
;
6197 ae
= aspath_empty();
6202 if (origin
!= pi
->attr
->origin
)
6205 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6208 if (!community_cmp(pi
->attr
->community
, comm
))
6211 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6214 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6217 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6223 static void bgp_aggregate_install(
6224 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6225 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6226 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6227 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6229 struct bgp_dest
*dest
;
6230 struct bgp_table
*table
;
6231 struct bgp_path_info
*pi
, *orig
, *new;
6234 table
= bgp
->rib
[afi
][safi
];
6236 dest
= bgp_node_get(table
, p
);
6238 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6239 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6240 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6243 if (aggregate
->count
> 0) {
6245 * If the aggregate information has not changed
6246 * no need to re-install it again.
6248 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6249 ecommunity
, lcommunity
)) {
6250 bgp_dest_unlock_node(dest
);
6253 aspath_free(aspath
);
6255 community_free(&community
);
6257 ecommunity_free(&ecommunity
);
6259 lcommunity_free(&lcommunity
);
6265 * Mark the old as unusable
6268 bgp_path_info_delete(dest
, pi
);
6270 attr
= bgp_attr_aggregate_intern(
6271 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6272 aggregate
, atomic_aggregate
, p
);
6275 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6279 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6280 bgp
->peer_self
, attr
, dest
);
6282 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6284 bgp_path_info_add(dest
, new);
6285 bgp_process(bgp
, dest
, afi
, safi
);
6287 for (pi
= orig
; pi
; pi
= pi
->next
)
6288 if (pi
->peer
== bgp
->peer_self
6289 && pi
->type
== ZEBRA_ROUTE_BGP
6290 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6293 /* Withdraw static BGP route from routing table. */
6295 bgp_path_info_delete(dest
, pi
);
6296 bgp_process(bgp
, dest
, afi
, safi
);
6300 bgp_dest_unlock_node(dest
);
6303 /* Update an aggregate as routes are added/removed from the BGP table */
6304 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6305 safi_t safi
, struct bgp_aggregate
*aggregate
)
6307 struct bgp_table
*table
;
6308 struct bgp_dest
*top
;
6309 struct bgp_dest
*dest
;
6311 struct aspath
*aspath
= NULL
;
6312 struct community
*community
= NULL
;
6313 struct ecommunity
*ecommunity
= NULL
;
6314 struct lcommunity
*lcommunity
= NULL
;
6315 struct bgp_path_info
*pi
;
6316 unsigned long match
= 0;
6317 uint8_t atomic_aggregate
= 0;
6319 /* If the bgp instance is being deleted or self peer is deleted
6320 * then do not create aggregate route
6322 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6323 || (bgp
->peer_self
== NULL
))
6326 /* ORIGIN attribute: If at least one route among routes that are
6327 aggregated has ORIGIN with the value INCOMPLETE, then the
6328 aggregated route must have the ORIGIN attribute with the value
6329 INCOMPLETE. Otherwise, if at least one route among routes that
6330 are aggregated has ORIGIN with the value EGP, then the aggregated
6331 route must have the origin attribute with the value EGP. In all
6332 other case the value of the ORIGIN attribute of the aggregated
6333 route is INTERNAL. */
6334 origin
= BGP_ORIGIN_IGP
;
6336 table
= bgp
->rib
[afi
][safi
];
6338 top
= bgp_node_get(table
, p
);
6339 for (dest
= bgp_node_get(table
, p
); dest
;
6340 dest
= bgp_route_next_until(dest
, top
)) {
6341 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6343 if (dest_p
->prefixlen
<= p
->prefixlen
)
6348 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6349 if (BGP_PATH_HOLDDOWN(pi
))
6353 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6354 atomic_aggregate
= 1;
6356 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6360 * summary-only aggregate route suppress
6361 * aggregated route announcements.
6363 if (aggregate
->summary_only
) {
6364 (bgp_path_info_extra_get(pi
))->suppress
++;
6365 bgp_path_info_set_flag(dest
, pi
,
6366 BGP_PATH_ATTR_CHANGED
);
6373 * If at least one route among routes that are
6374 * aggregated has ORIGIN with the value INCOMPLETE,
6375 * then the aggregated route MUST have the ORIGIN
6376 * attribute with the value INCOMPLETE. Otherwise, if
6377 * at least one route among routes that are aggregated
6378 * has ORIGIN with the value EGP, then the aggregated
6379 * route MUST have the ORIGIN attribute with the value
6382 switch (pi
->attr
->origin
) {
6383 case BGP_ORIGIN_INCOMPLETE
:
6384 aggregate
->incomplete_origin_count
++;
6386 case BGP_ORIGIN_EGP
:
6387 aggregate
->egp_origin_count
++;
6395 if (!aggregate
->as_set
)
6399 * as-set aggregate route generate origin, as path,
6400 * and community aggregation.
6402 /* Compute aggregate route's as-path.
6404 bgp_compute_aggregate_aspath_hash(aggregate
,
6407 /* Compute aggregate route's community.
6409 if (pi
->attr
->community
)
6410 bgp_compute_aggregate_community_hash(
6412 pi
->attr
->community
);
6414 /* Compute aggregate route's extended community.
6416 if (pi
->attr
->ecommunity
)
6417 bgp_compute_aggregate_ecommunity_hash(
6419 pi
->attr
->ecommunity
);
6421 /* Compute aggregate route's large community.
6423 if (pi
->attr
->lcommunity
)
6424 bgp_compute_aggregate_lcommunity_hash(
6426 pi
->attr
->lcommunity
);
6429 bgp_process(bgp
, dest
, afi
, safi
);
6431 if (aggregate
->as_set
) {
6432 bgp_compute_aggregate_aspath_val(aggregate
);
6433 bgp_compute_aggregate_community_val(aggregate
);
6434 bgp_compute_aggregate_ecommunity_val(aggregate
);
6435 bgp_compute_aggregate_lcommunity_val(aggregate
);
6439 bgp_dest_unlock_node(top
);
6442 if (aggregate
->incomplete_origin_count
> 0)
6443 origin
= BGP_ORIGIN_INCOMPLETE
;
6444 else if (aggregate
->egp_origin_count
> 0)
6445 origin
= BGP_ORIGIN_EGP
;
6447 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6448 origin
= aggregate
->origin
;
6450 if (aggregate
->as_set
) {
6451 if (aggregate
->aspath
)
6452 /* Retrieve aggregate route's as-path.
6454 aspath
= aspath_dup(aggregate
->aspath
);
6456 if (aggregate
->community
)
6457 /* Retrieve aggregate route's community.
6459 community
= community_dup(aggregate
->community
);
6461 if (aggregate
->ecommunity
)
6462 /* Retrieve aggregate route's ecommunity.
6464 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6466 if (aggregate
->lcommunity
)
6467 /* Retrieve aggregate route's lcommunity.
6469 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6472 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6473 ecommunity
, lcommunity
, atomic_aggregate
,
6477 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6478 safi_t safi
, struct bgp_aggregate
*aggregate
)
6480 struct bgp_table
*table
;
6481 struct bgp_dest
*top
;
6482 struct bgp_dest
*dest
;
6483 struct bgp_path_info
*pi
;
6484 unsigned long match
;
6486 table
= bgp
->rib
[afi
][safi
];
6488 /* If routes exists below this node, generate aggregate routes. */
6489 top
= bgp_node_get(table
, p
);
6490 for (dest
= bgp_node_get(table
, p
); dest
;
6491 dest
= bgp_route_next_until(dest
, top
)) {
6492 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6494 if (dest_p
->prefixlen
<= p
->prefixlen
)
6498 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6499 if (BGP_PATH_HOLDDOWN(pi
))
6502 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6505 if (aggregate
->summary_only
&& pi
->extra
) {
6506 pi
->extra
->suppress
--;
6508 if (pi
->extra
->suppress
== 0) {
6509 bgp_path_info_set_flag(
6511 BGP_PATH_ATTR_CHANGED
);
6517 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6518 aggregate
->incomplete_origin_count
--;
6519 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6520 aggregate
->egp_origin_count
--;
6522 if (aggregate
->as_set
) {
6523 /* Remove as-path from aggregate.
6525 bgp_remove_aspath_from_aggregate_hash(
6529 if (pi
->attr
->community
)
6530 /* Remove community from aggregate.
6532 bgp_remove_comm_from_aggregate_hash(
6534 pi
->attr
->community
);
6536 if (pi
->attr
->ecommunity
)
6537 /* Remove ecommunity from aggregate.
6539 bgp_remove_ecomm_from_aggregate_hash(
6541 pi
->attr
->ecommunity
);
6543 if (pi
->attr
->lcommunity
)
6544 /* Remove lcommunity from aggregate.
6546 bgp_remove_lcomm_from_aggregate_hash(
6548 pi
->attr
->lcommunity
);
6552 /* If this node was suppressed, process the change. */
6554 bgp_process(bgp
, dest
, afi
, safi
);
6556 if (aggregate
->as_set
) {
6557 aspath_free(aggregate
->aspath
);
6558 aggregate
->aspath
= NULL
;
6559 if (aggregate
->community
)
6560 community_free(&aggregate
->community
);
6561 if (aggregate
->ecommunity
)
6562 ecommunity_free(&aggregate
->ecommunity
);
6563 if (aggregate
->lcommunity
)
6564 lcommunity_free(&aggregate
->lcommunity
);
6567 bgp_dest_unlock_node(top
);
6570 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
6571 const struct prefix
*aggr_p
,
6572 struct bgp_path_info
*pinew
, afi_t afi
,
6574 struct bgp_aggregate
*aggregate
)
6577 struct aspath
*aspath
= NULL
;
6578 uint8_t atomic_aggregate
= 0;
6579 struct community
*community
= NULL
;
6580 struct ecommunity
*ecommunity
= NULL
;
6581 struct lcommunity
*lcommunity
= NULL
;
6583 /* ORIGIN attribute: If at least one route among routes that are
6584 * aggregated has ORIGIN with the value INCOMPLETE, then the
6585 * aggregated route must have the ORIGIN attribute with the value
6586 * INCOMPLETE. Otherwise, if at least one route among routes that
6587 * are aggregated has ORIGIN with the value EGP, then the aggregated
6588 * route must have the origin attribute with the value EGP. In all
6589 * other case the value of the ORIGIN attribute of the aggregated
6590 * route is INTERNAL.
6592 origin
= BGP_ORIGIN_IGP
;
6596 if (aggregate
->summary_only
)
6597 (bgp_path_info_extra_get(pinew
))->suppress
++;
6599 switch (pinew
->attr
->origin
) {
6600 case BGP_ORIGIN_INCOMPLETE
:
6601 aggregate
->incomplete_origin_count
++;
6603 case BGP_ORIGIN_EGP
:
6604 aggregate
->egp_origin_count
++;
6612 if (aggregate
->incomplete_origin_count
> 0)
6613 origin
= BGP_ORIGIN_INCOMPLETE
;
6614 else if (aggregate
->egp_origin_count
> 0)
6615 origin
= BGP_ORIGIN_EGP
;
6617 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6618 origin
= aggregate
->origin
;
6620 if (aggregate
->as_set
) {
6621 /* Compute aggregate route's as-path.
6623 bgp_compute_aggregate_aspath(aggregate
,
6624 pinew
->attr
->aspath
);
6626 /* Compute aggregate route's community.
6628 if (pinew
->attr
->community
)
6629 bgp_compute_aggregate_community(
6631 pinew
->attr
->community
);
6633 /* Compute aggregate route's extended community.
6635 if (pinew
->attr
->ecommunity
)
6636 bgp_compute_aggregate_ecommunity(
6638 pinew
->attr
->ecommunity
);
6640 /* Compute aggregate route's large community.
6642 if (pinew
->attr
->lcommunity
)
6643 bgp_compute_aggregate_lcommunity(
6645 pinew
->attr
->lcommunity
);
6647 /* Retrieve aggregate route's as-path.
6649 if (aggregate
->aspath
)
6650 aspath
= aspath_dup(aggregate
->aspath
);
6652 /* Retrieve aggregate route's community.
6654 if (aggregate
->community
)
6655 community
= community_dup(aggregate
->community
);
6657 /* Retrieve aggregate route's ecommunity.
6659 if (aggregate
->ecommunity
)
6660 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6662 /* Retrieve aggregate route's lcommunity.
6664 if (aggregate
->lcommunity
)
6665 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6668 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6669 aspath
, community
, ecommunity
,
6670 lcommunity
, atomic_aggregate
, aggregate
);
6673 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6675 struct bgp_path_info
*pi
,
6676 struct bgp_aggregate
*aggregate
,
6677 const struct prefix
*aggr_p
)
6680 struct aspath
*aspath
= NULL
;
6681 uint8_t atomic_aggregate
= 0;
6682 struct community
*community
= NULL
;
6683 struct ecommunity
*ecommunity
= NULL
;
6684 struct lcommunity
*lcommunity
= NULL
;
6685 unsigned long match
= 0;
6687 if (BGP_PATH_HOLDDOWN(pi
))
6690 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6693 if (aggregate
->summary_only
6695 && pi
->extra
->suppress
> 0) {
6696 pi
->extra
->suppress
--;
6698 if (pi
->extra
->suppress
== 0) {
6699 bgp_path_info_set_flag(pi
->net
, pi
,
6700 BGP_PATH_ATTR_CHANGED
);
6705 if (aggregate
->count
> 0)
6708 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6709 aggregate
->incomplete_origin_count
--;
6710 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6711 aggregate
->egp_origin_count
--;
6713 if (aggregate
->as_set
) {
6714 /* Remove as-path from aggregate.
6716 bgp_remove_aspath_from_aggregate(aggregate
,
6719 if (pi
->attr
->community
)
6720 /* Remove community from aggregate.
6722 bgp_remove_community_from_aggregate(
6724 pi
->attr
->community
);
6726 if (pi
->attr
->ecommunity
)
6727 /* Remove ecommunity from aggregate.
6729 bgp_remove_ecommunity_from_aggregate(
6731 pi
->attr
->ecommunity
);
6733 if (pi
->attr
->lcommunity
)
6734 /* Remove lcommunity from aggregate.
6736 bgp_remove_lcommunity_from_aggregate(
6738 pi
->attr
->lcommunity
);
6741 /* If this node was suppressed, process the change. */
6743 bgp_process(bgp
, pi
->net
, afi
, safi
);
6745 origin
= BGP_ORIGIN_IGP
;
6746 if (aggregate
->incomplete_origin_count
> 0)
6747 origin
= BGP_ORIGIN_INCOMPLETE
;
6748 else if (aggregate
->egp_origin_count
> 0)
6749 origin
= BGP_ORIGIN_EGP
;
6751 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6752 origin
= aggregate
->origin
;
6754 if (aggregate
->as_set
) {
6755 /* Retrieve aggregate route's as-path.
6757 if (aggregate
->aspath
)
6758 aspath
= aspath_dup(aggregate
->aspath
);
6760 /* Retrieve aggregate route's community.
6762 if (aggregate
->community
)
6763 community
= community_dup(aggregate
->community
);
6765 /* Retrieve aggregate route's ecommunity.
6767 if (aggregate
->ecommunity
)
6768 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6770 /* Retrieve aggregate route's lcommunity.
6772 if (aggregate
->lcommunity
)
6773 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6776 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6777 aspath
, community
, ecommunity
,
6778 lcommunity
, atomic_aggregate
, aggregate
);
6781 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
6782 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6784 struct bgp_dest
*child
;
6785 struct bgp_dest
*dest
;
6786 struct bgp_aggregate
*aggregate
;
6787 struct bgp_table
*table
;
6789 table
= bgp
->aggregate
[afi
][safi
];
6791 /* No aggregates configured. */
6792 if (bgp_table_top_nolock(table
) == NULL
)
6795 if (p
->prefixlen
== 0)
6798 if (BGP_PATH_HOLDDOWN(pi
))
6801 child
= bgp_node_get(table
, p
);
6803 /* Aggregate address configuration check. */
6804 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
6805 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6807 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
6808 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
6809 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
6813 bgp_dest_unlock_node(child
);
6816 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
6817 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6819 struct bgp_dest
*child
;
6820 struct bgp_dest
*dest
;
6821 struct bgp_aggregate
*aggregate
;
6822 struct bgp_table
*table
;
6824 table
= bgp
->aggregate
[afi
][safi
];
6826 /* No aggregates configured. */
6827 if (bgp_table_top_nolock(table
) == NULL
)
6830 if (p
->prefixlen
== 0)
6833 child
= bgp_node_get(table
, p
);
6835 /* Aggregate address configuration check. */
6836 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
6837 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6839 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
6840 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
6841 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
6845 bgp_dest_unlock_node(child
);
6848 /* Aggregate route attribute. */
6849 #define AGGREGATE_SUMMARY_ONLY 1
6850 #define AGGREGATE_AS_SET 1
6851 #define AGGREGATE_AS_UNSET 0
6853 static const char *bgp_origin2str(uint8_t origin
)
6856 case BGP_ORIGIN_IGP
:
6858 case BGP_ORIGIN_EGP
:
6860 case BGP_ORIGIN_INCOMPLETE
:
6861 return "incomplete";
6866 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6867 afi_t afi
, safi_t safi
)
6869 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6872 struct bgp_dest
*dest
;
6873 struct bgp_aggregate
*aggregate
;
6875 /* Convert string to prefix structure. */
6876 ret
= str2prefix(prefix_str
, &p
);
6878 vty_out(vty
, "Malformed prefix\n");
6879 return CMD_WARNING_CONFIG_FAILED
;
6883 /* Old configuration check. */
6884 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6887 "%% There is no aggregate-address configuration.\n");
6888 return CMD_WARNING_CONFIG_FAILED
;
6891 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
6892 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6893 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6894 NULL
, NULL
, 0, aggregate
);
6896 /* Unlock aggregate address configuration. */
6897 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
6899 if (aggregate
->community
)
6900 community_free(&aggregate
->community
);
6902 if (aggregate
->community_hash
) {
6903 /* Delete all communities in the hash.
6905 hash_clean(aggregate
->community_hash
,
6906 bgp_aggr_community_remove
);
6907 /* Free up the community_hash.
6909 hash_free(aggregate
->community_hash
);
6912 if (aggregate
->ecommunity
)
6913 ecommunity_free(&aggregate
->ecommunity
);
6915 if (aggregate
->ecommunity_hash
) {
6916 /* Delete all ecommunities in the hash.
6918 hash_clean(aggregate
->ecommunity_hash
,
6919 bgp_aggr_ecommunity_remove
);
6920 /* Free up the ecommunity_hash.
6922 hash_free(aggregate
->ecommunity_hash
);
6925 if (aggregate
->lcommunity
)
6926 lcommunity_free(&aggregate
->lcommunity
);
6928 if (aggregate
->lcommunity_hash
) {
6929 /* Delete all lcommunities in the hash.
6931 hash_clean(aggregate
->lcommunity_hash
,
6932 bgp_aggr_lcommunity_remove
);
6933 /* Free up the lcommunity_hash.
6935 hash_free(aggregate
->lcommunity_hash
);
6938 if (aggregate
->aspath
)
6939 aspath_free(aggregate
->aspath
);
6941 if (aggregate
->aspath_hash
) {
6942 /* Delete all as-paths in the hash.
6944 hash_clean(aggregate
->aspath_hash
,
6945 bgp_aggr_aspath_remove
);
6946 /* Free up the aspath_hash.
6948 hash_free(aggregate
->aspath_hash
);
6951 bgp_aggregate_free(aggregate
);
6952 bgp_dest_unlock_node(dest
);
6953 bgp_dest_unlock_node(dest
);
6958 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6959 safi_t safi
, const char *rmap
,
6960 uint8_t summary_only
, uint8_t as_set
,
6963 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6966 struct bgp_dest
*dest
;
6967 struct bgp_aggregate
*aggregate
;
6968 uint8_t as_set_new
= as_set
;
6970 /* Convert string to prefix structure. */
6971 ret
= str2prefix(prefix_str
, &p
);
6973 vty_out(vty
, "Malformed prefix\n");
6974 return CMD_WARNING_CONFIG_FAILED
;
6978 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6979 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6980 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6982 return CMD_WARNING_CONFIG_FAILED
;
6985 /* Old configuration check. */
6986 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6987 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
6990 vty_out(vty
, "There is already same aggregate network.\n");
6991 /* try to remove the old entry */
6992 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6994 vty_out(vty
, "Error deleting aggregate.\n");
6995 bgp_dest_unlock_node(dest
);
6996 return CMD_WARNING_CONFIG_FAILED
;
7000 /* Make aggregate address structure. */
7001 aggregate
= bgp_aggregate_new();
7002 aggregate
->summary_only
= summary_only
;
7004 /* Network operators MUST NOT locally generate any new
7005 * announcements containing AS_SET or AS_CONFED_SET. If they have
7006 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7007 * SHOULD withdraw those routes and re-announce routes for the
7008 * aggregate or component prefixes (i.e., the more-specific routes
7009 * subsumed by the previously aggregated route) without AS_SET
7010 * or AS_CONFED_SET in the updates.
7012 if (bgp
->reject_as_sets
) {
7013 if (as_set
== AGGREGATE_AS_SET
) {
7014 as_set_new
= AGGREGATE_AS_UNSET
;
7016 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7019 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7023 aggregate
->as_set
= as_set_new
;
7024 aggregate
->safi
= safi
;
7025 /* Override ORIGIN attribute if defined.
7026 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7027 * to IGP which is not what rfc4271 says.
7028 * This enables the same behavior, optionally.
7030 aggregate
->origin
= origin
;
7033 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7034 route_map_counter_decrement(aggregate
->rmap
.map
);
7035 aggregate
->rmap
.name
=
7036 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
7037 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
7038 route_map_counter_increment(aggregate
->rmap
.map
);
7040 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
7042 /* Aggregate address insert into BGP routing table. */
7043 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
7048 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
7049 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7051 "|summary-only$summary_only"
7052 "|route-map WORD$rmap_name"
7053 "|origin <egp|igp|incomplete>$origin_s"
7056 "Configure BGP aggregate entries\n"
7057 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
7058 "Generate AS set path information\n"
7059 "Filter more specific routes from updates\n"
7060 "Apply route map to aggregate network\n"
7065 "Unknown heritage\n")
7067 const char *prefix_s
= NULL
;
7068 safi_t safi
= bgp_node_safi(vty
);
7069 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
7070 int as_set
= AGGREGATE_AS_UNSET
;
7071 char prefix_buf
[PREFIX2STR_BUFFER
];
7074 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
)
7076 vty_out(vty
, "%% Inconsistent address and mask\n");
7077 return CMD_WARNING_CONFIG_FAILED
;
7079 prefix_s
= prefix_buf
;
7081 prefix_s
= prefix_str
;
7084 if (strcmp(origin_s
, "egp") == 0)
7085 origin
= BGP_ORIGIN_EGP
;
7086 else if (strcmp(origin_s
, "igp") == 0)
7087 origin
= BGP_ORIGIN_IGP
;
7088 else if (strcmp(origin_s
, "incomplete") == 0)
7089 origin
= BGP_ORIGIN_INCOMPLETE
;
7093 as_set
= AGGREGATE_AS_SET
;
7095 /* Handle configuration removal, otherwise installation. */
7097 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
7099 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
7100 summary_only
!= NULL
, as_set
, origin
);
7103 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
7104 "[no] aggregate-address X:X::X:X/M$prefix {"
7106 "|summary-only$summary_only"
7107 "|route-map WORD$rmap_name"
7108 "|origin <egp|igp|incomplete>$origin_s"
7111 "Configure BGP aggregate entries\n"
7112 "Aggregate prefix\n"
7113 "Generate AS set path information\n"
7114 "Filter more specific routes from updates\n"
7115 "Apply route map to aggregate network\n"
7120 "Unknown heritage\n")
7122 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
7123 int as_set
= AGGREGATE_AS_UNSET
;
7126 if (strcmp(origin_s
, "egp") == 0)
7127 origin
= BGP_ORIGIN_EGP
;
7128 else if (strcmp(origin_s
, "igp") == 0)
7129 origin
= BGP_ORIGIN_IGP
;
7130 else if (strcmp(origin_s
, "incomplete") == 0)
7131 origin
= BGP_ORIGIN_INCOMPLETE
;
7135 as_set
= AGGREGATE_AS_SET
;
7137 /* Handle configuration removal, otherwise installation. */
7139 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
7142 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
7143 rmap_name
, summary_only
!= NULL
, as_set
,
7147 /* Redistribute route treatment. */
7148 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7149 const union g_addr
*nexthop
, ifindex_t ifindex
,
7150 enum nexthop_types_t nhtype
, uint32_t metric
,
7151 uint8_t type
, unsigned short instance
,
7154 struct bgp_path_info
*new;
7155 struct bgp_path_info
*bpi
;
7156 struct bgp_path_info rmap_path
;
7157 struct bgp_dest
*bn
;
7159 struct attr
*new_attr
;
7161 route_map_result_t ret
;
7162 struct bgp_redist
*red
;
7164 /* Make default attribute. */
7165 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7167 * This must not be NULL to satisfy Coverity SA
7169 assert(attr
.aspath
);
7172 case NEXTHOP_TYPE_IFINDEX
:
7174 case NEXTHOP_TYPE_IPV4
:
7175 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7176 attr
.nexthop
= nexthop
->ipv4
;
7178 case NEXTHOP_TYPE_IPV6
:
7179 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7180 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7181 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7183 case NEXTHOP_TYPE_BLACKHOLE
:
7184 switch (p
->family
) {
7186 attr
.nexthop
.s_addr
= INADDR_ANY
;
7189 memset(&attr
.mp_nexthop_global
, 0,
7190 sizeof(attr
.mp_nexthop_global
));
7191 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7196 attr
.nh_ifindex
= ifindex
;
7199 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
7202 afi
= family2afi(p
->family
);
7204 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7206 struct attr attr_new
;
7208 /* Copy attribute for modification. */
7211 if (red
->redist_metric_flag
)
7212 attr_new
.med
= red
->redist_metric
;
7214 /* Apply route-map. */
7215 if (red
->rmap
.name
) {
7216 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
7217 rmap_path
.peer
= bgp
->peer_self
;
7218 rmap_path
.attr
= &attr_new
;
7220 SET_FLAG(bgp
->peer_self
->rmap_type
,
7221 PEER_RMAP_TYPE_REDISTRIBUTE
);
7223 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
7226 bgp
->peer_self
->rmap_type
= 0;
7228 if (ret
== RMAP_DENYMATCH
) {
7229 /* Free uninterned attribute. */
7230 bgp_attr_flush(&attr_new
);
7232 /* Unintern original. */
7233 aspath_unintern(&attr
.aspath
);
7234 bgp_redistribute_delete(bgp
, p
, type
, instance
);
7239 if (bgp_in_graceful_shutdown(bgp
))
7240 bgp_attr_add_gshut_community(&attr_new
);
7242 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7243 SAFI_UNICAST
, p
, NULL
);
7245 new_attr
= bgp_attr_intern(&attr_new
);
7247 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
7248 if (bpi
->peer
== bgp
->peer_self
7249 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
7253 /* Ensure the (source route) type is updated. */
7255 if (attrhash_cmp(bpi
->attr
, new_attr
)
7256 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
7257 bgp_attr_unintern(&new_attr
);
7258 aspath_unintern(&attr
.aspath
);
7259 bgp_dest_unlock_node(bn
);
7262 /* The attribute is changed. */
7263 bgp_path_info_set_flag(bn
, bpi
,
7264 BGP_PATH_ATTR_CHANGED
);
7266 /* Rewrite BGP route information. */
7267 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
7268 bgp_path_info_restore(bn
, bpi
);
7270 bgp_aggregate_decrement(
7271 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
7272 bgp_attr_unintern(&bpi
->attr
);
7273 bpi
->attr
= new_attr
;
7274 bpi
->uptime
= bgp_clock();
7276 /* Process change. */
7277 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
7279 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7280 bgp_dest_unlock_node(bn
);
7281 aspath_unintern(&attr
.aspath
);
7283 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7285 == BGP_INSTANCE_TYPE_DEFAULT
)) {
7287 vpn_leak_from_vrf_update(
7288 bgp_get_default(), bgp
, bpi
);
7294 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
7295 bgp
->peer_self
, new_attr
, bn
);
7296 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7298 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
7299 bgp_path_info_add(bn
, new);
7300 bgp_dest_unlock_node(bn
);
7301 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7303 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7304 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7306 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
7310 /* Unintern original. */
7311 aspath_unintern(&attr
.aspath
);
7314 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
7315 unsigned short instance
)
7318 struct bgp_dest
*dest
;
7319 struct bgp_path_info
*pi
;
7320 struct bgp_redist
*red
;
7322 afi
= family2afi(p
->family
);
7324 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7326 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7327 SAFI_UNICAST
, p
, NULL
);
7329 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7330 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
7334 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7335 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7337 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7340 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
7341 bgp_path_info_delete(dest
, pi
);
7342 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
7344 bgp_dest_unlock_node(dest
);
7348 /* Withdraw specified route type's route. */
7349 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
7350 unsigned short instance
)
7352 struct bgp_dest
*dest
;
7353 struct bgp_path_info
*pi
;
7354 struct bgp_table
*table
;
7356 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
7358 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
7359 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7360 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
7361 && pi
->instance
== instance
)
7365 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7366 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7368 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7371 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
7372 pi
, afi
, SAFI_UNICAST
);
7373 bgp_path_info_delete(dest
, pi
);
7374 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
7379 /* Static function to display route. */
7380 static void route_vty_out_route(const struct prefix
*p
, struct vty
*vty
,
7381 json_object
*json
, bool wide
)
7387 if (p
->family
== AF_INET
) {
7391 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7394 json_object_string_add(json
, "prefix",
7395 inet_ntop(p
->family
,
7398 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7399 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7400 json_object_string_add(json
, "network", buf2
);
7402 } else if (p
->family
== AF_ETHERNET
) {
7403 prefix2str(p
, buf
, PREFIX_STRLEN
);
7404 len
= vty_out(vty
, "%s", buf
);
7405 } else if (p
->family
== AF_EVPN
) {
7409 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7412 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7413 } else if (p
->family
== AF_FLOWSPEC
) {
7414 route_vty_out_flowspec(vty
, p
, NULL
,
7416 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7417 NLRI_STRING_FORMAT_MIN
, json
);
7422 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7425 json_object_string_add(json
, "prefix",
7426 inet_ntop(p
->family
,
7429 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7430 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7431 json_object_string_add(json
, "network", buf2
);
7436 len
= wide
? (45 - len
) : (17 - len
);
7438 vty_out(vty
, "\n%*s", 20, " ");
7440 vty_out(vty
, "%*s", len
, " ");
7444 enum bgp_display_type
{
7448 /* Print the short form route status for a bgp_path_info */
7449 static void route_vty_short_status_out(struct vty
*vty
,
7450 struct bgp_path_info
*path
,
7451 json_object
*json_path
)
7455 /* Route status display. */
7456 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7457 json_object_boolean_true_add(json_path
, "removed");
7459 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7460 json_object_boolean_true_add(json_path
, "stale");
7462 if (path
->extra
&& path
->extra
->suppress
)
7463 json_object_boolean_true_add(json_path
, "suppressed");
7465 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7466 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7467 json_object_boolean_true_add(json_path
, "valid");
7470 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7471 json_object_boolean_true_add(json_path
, "history");
7473 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7474 json_object_boolean_true_add(json_path
, "damped");
7476 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7477 json_object_boolean_true_add(json_path
, "bestpath");
7479 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7480 json_object_boolean_true_add(json_path
, "multipath");
7482 /* Internal route. */
7483 if ((path
->peer
->as
)
7484 && (path
->peer
->as
== path
->peer
->local_as
))
7485 json_object_string_add(json_path
, "pathFrom",
7488 json_object_string_add(json_path
, "pathFrom",
7494 /* Route status display. */
7495 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7497 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7499 else if (path
->extra
&& path
->extra
->suppress
)
7501 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7502 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7508 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7510 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7512 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7514 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7519 /* Internal route. */
7520 if (path
->peer
&& (path
->peer
->as
)
7521 && (path
->peer
->as
== path
->peer
->local_as
))
7527 static char *bgp_nexthop_hostname(struct peer
*peer
,
7528 struct bgp_nexthop_cache
*bnc
)
7531 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
7532 return peer
->hostname
;
7536 /* called from terminal list command */
7537 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
7538 struct bgp_path_info
*path
, int display
, safi_t safi
,
7539 json_object
*json_paths
, bool wide
)
7542 struct attr
*attr
= path
->attr
;
7543 json_object
*json_path
= NULL
;
7544 json_object
*json_nexthops
= NULL
;
7545 json_object
*json_nexthop_global
= NULL
;
7546 json_object
*json_nexthop_ll
= NULL
;
7547 json_object
*json_ext_community
= NULL
;
7548 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7550 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7551 bool nexthop_othervrf
= false;
7552 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7553 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7554 char *nexthop_hostname
=
7555 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
7556 char esi_buf
[ESI_STR_LEN
];
7559 json_path
= json_object_new_object();
7561 /* short status lead text */
7562 route_vty_short_status_out(vty
, path
, json_path
);
7565 /* print prefix and mask */
7567 route_vty_out_route(p
, vty
, json_path
, wide
);
7569 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
7571 route_vty_out_route(p
, vty
, json_path
, wide
);
7575 * If vrf id of nexthop is different from that of prefix,
7576 * set up printable string to append
7578 if (path
->extra
&& path
->extra
->bgp_orig
) {
7579 const char *self
= "";
7584 nexthop_othervrf
= true;
7585 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7587 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7588 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7589 "@%s%s", VRFID_NONE_STR
, self
);
7591 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7592 path
->extra
->bgp_orig
->vrf_id
, self
);
7594 if (path
->extra
->bgp_orig
->inst_type
7595 != BGP_INSTANCE_TYPE_DEFAULT
)
7597 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7599 const char *self
= "";
7604 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7608 * For ENCAP and EVPN routes, nexthop address family is not
7609 * neccessarily the same as the prefix address family.
7610 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7611 * EVPN routes are also exchanged with a MP nexthop. Currently,
7613 * is only IPv4, the value will be present in either
7615 * attr->mp_nexthop_global_in
7617 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7620 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7624 snprintf(nexthop
, sizeof(nexthop
), "%s",
7625 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7629 snprintf(nexthop
, sizeof(nexthop
), "%s",
7630 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7634 snprintf(nexthop
, sizeof(nexthop
), "?");
7639 json_nexthop_global
= json_object_new_object();
7641 json_object_string_add(json_nexthop_global
, "ip",
7644 if (path
->peer
->hostname
)
7645 json_object_string_add(json_nexthop_global
,
7647 path
->peer
->hostname
);
7649 json_object_string_add(json_nexthop_global
, "afi",
7650 (af
== AF_INET
) ? "ipv4"
7652 json_object_boolean_true_add(json_nexthop_global
,
7655 if (nexthop_hostname
)
7656 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
7657 nexthop_hostname
, vrf_id_str
);
7659 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
7661 len
= wide
? (41 - len
) : (16 - len
);
7663 vty_out(vty
, "\n%*s", 36, " ");
7665 vty_out(vty
, "%*s", len
, " ");
7667 } else if (safi
== SAFI_EVPN
) {
7669 json_nexthop_global
= json_object_new_object();
7671 json_object_string_add(json_nexthop_global
, "ip",
7672 inet_ntoa(attr
->nexthop
));
7674 if (path
->peer
->hostname
)
7675 json_object_string_add(json_nexthop_global
,
7677 path
->peer
->hostname
);
7679 json_object_string_add(json_nexthop_global
, "afi",
7681 json_object_boolean_true_add(json_nexthop_global
,
7684 if (nexthop_hostname
)
7685 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
7686 nexthop_hostname
, vrf_id_str
);
7688 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
7691 len
= wide
? (41 - len
) : (16 - len
);
7693 vty_out(vty
, "\n%*s", 36, " ");
7695 vty_out(vty
, "%*s", len
, " ");
7697 } else if (safi
== SAFI_FLOWSPEC
) {
7698 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
7700 json_nexthop_global
= json_object_new_object();
7702 json_object_string_add(json_nexthop_global
,
7704 json_object_string_add(
7705 json_nexthop_global
, "ip",
7706 inet_ntoa(attr
->nexthop
));
7708 if (path
->peer
->hostname
)
7709 json_object_string_add(
7710 json_nexthop_global
, "hostname",
7711 path
->peer
->hostname
);
7713 json_object_boolean_true_add(
7714 json_nexthop_global
,
7717 if (nexthop_hostname
)
7718 len
= vty_out(vty
, "%pI4(%s)%s",
7723 len
= vty_out(vty
, "%pI4%s",
7727 len
= wide
? (41 - len
) : (16 - len
);
7729 vty_out(vty
, "\n%*s", 36, " ");
7731 vty_out(vty
, "%*s", len
, " ");
7734 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7736 json_nexthop_global
= json_object_new_object();
7738 json_object_string_add(json_nexthop_global
, "ip",
7739 inet_ntoa(attr
->nexthop
));
7741 if (path
->peer
->hostname
)
7742 json_object_string_add(json_nexthop_global
,
7744 path
->peer
->hostname
);
7746 json_object_string_add(json_nexthop_global
, "afi",
7748 json_object_boolean_true_add(json_nexthop_global
,
7751 if (nexthop_hostname
)
7752 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
7753 nexthop_hostname
, vrf_id_str
);
7755 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
7758 len
= wide
? (41 - len
) : (16 - len
);
7760 vty_out(vty
, "\n%*s", 36, " ");
7762 vty_out(vty
, "%*s", len
, " ");
7767 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7771 json_nexthop_global
= json_object_new_object();
7772 json_object_string_add(
7773 json_nexthop_global
, "ip",
7774 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7777 if (path
->peer
->hostname
)
7778 json_object_string_add(json_nexthop_global
,
7780 path
->peer
->hostname
);
7782 json_object_string_add(json_nexthop_global
, "afi",
7784 json_object_string_add(json_nexthop_global
, "scope",
7787 /* We display both LL & GL if both have been
7789 if ((attr
->mp_nexthop_len
7790 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7791 || (path
->peer
->conf_if
)) {
7792 json_nexthop_ll
= json_object_new_object();
7793 json_object_string_add(
7794 json_nexthop_ll
, "ip",
7796 &attr
->mp_nexthop_local
, buf
,
7799 if (path
->peer
->hostname
)
7800 json_object_string_add(
7801 json_nexthop_ll
, "hostname",
7802 path
->peer
->hostname
);
7804 json_object_string_add(json_nexthop_ll
, "afi",
7806 json_object_string_add(json_nexthop_ll
, "scope",
7809 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7810 &attr
->mp_nexthop_local
)
7812 && !attr
->mp_nexthop_prefer_global
)
7813 json_object_boolean_true_add(
7814 json_nexthop_ll
, "used");
7816 json_object_boolean_true_add(
7817 json_nexthop_global
, "used");
7819 json_object_boolean_true_add(
7820 json_nexthop_global
, "used");
7822 /* Display LL if LL/Global both in table unless
7823 * prefer-global is set */
7824 if (((attr
->mp_nexthop_len
7825 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7826 && !attr
->mp_nexthop_prefer_global
)
7827 || (path
->peer
->conf_if
)) {
7828 if (path
->peer
->conf_if
) {
7829 len
= vty_out(vty
, "%s",
7830 path
->peer
->conf_if
);
7831 /* len of IPv6 addr + max len of def
7833 len
= wide
? (41 - len
) : (16 - len
);
7836 vty_out(vty
, "\n%*s", 36, " ");
7838 vty_out(vty
, "%*s", len
, " ");
7840 if (nexthop_hostname
)
7843 &attr
->mp_nexthop_local
,
7849 &attr
->mp_nexthop_local
,
7852 len
= wide
? (41 - len
) : (16 - len
);
7855 vty_out(vty
, "\n%*s", 36, " ");
7857 vty_out(vty
, "%*s", len
, " ");
7860 if (nexthop_hostname
)
7861 len
= vty_out(vty
, "%pI6(%s)%s",
7862 &attr
->mp_nexthop_global
,
7866 len
= vty_out(vty
, "%pI6%s",
7867 &attr
->mp_nexthop_global
,
7870 len
= wide
? (41 - len
) : (16 - len
);
7873 vty_out(vty
, "\n%*s", 36, " ");
7875 vty_out(vty
, "%*s", len
, " ");
7881 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7883 json_object_int_add(json_path
, "metric", attr
->med
);
7885 vty_out(vty
, "%7u", attr
->med
);
7887 vty_out(vty
, "%10u", attr
->med
);
7888 else if (!json_paths
) {
7890 vty_out(vty
, "%*s", 7, " ");
7892 vty_out(vty
, "%*s", 10, " ");
7896 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7898 json_object_int_add(json_path
, "locPrf",
7901 vty_out(vty
, "%7u", attr
->local_pref
);
7902 else if (!json_paths
)
7906 json_object_int_add(json_path
, "weight", attr
->weight
);
7908 vty_out(vty
, "%7u ", attr
->weight
);
7912 json_object_string_add(
7913 json_path
, "peerId",
7914 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7920 json_object_string_add(json_path
, "path",
7923 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7928 json_object_string_add(json_path
, "origin",
7929 bgp_origin_long_str
[attr
->origin
]);
7931 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7934 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
7935 json_object_string_add(json_path
, "esi",
7936 esi_to_str(&attr
->esi
,
7937 esi_buf
, sizeof(esi_buf
)));
7939 if (safi
== SAFI_EVPN
&&
7940 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7941 json_ext_community
= json_object_new_object();
7942 json_object_string_add(json_ext_community
,
7944 attr
->ecommunity
->str
);
7945 json_object_object_add(json_path
,
7946 "extendedCommunity",
7947 json_ext_community
);
7951 json_object_boolean_true_add(json_path
,
7952 "announceNexthopSelf");
7953 if (nexthop_othervrf
) {
7954 json_object_string_add(json_path
, "nhVrfName",
7957 json_object_int_add(json_path
, "nhVrfId",
7958 ((nexthop_vrfid
== VRF_UNKNOWN
)
7960 : (int)nexthop_vrfid
));
7965 if (json_nexthop_global
|| json_nexthop_ll
) {
7966 json_nexthops
= json_object_new_array();
7968 if (json_nexthop_global
)
7969 json_object_array_add(json_nexthops
,
7970 json_nexthop_global
);
7972 if (json_nexthop_ll
)
7973 json_object_array_add(json_nexthops
,
7976 json_object_object_add(json_path
, "nexthops",
7980 json_object_array_add(json_paths
, json_path
);
7984 if (safi
== SAFI_EVPN
) {
7985 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
7986 vty_out(vty
, "%*s", 20, " ");
7987 vty_out(vty
, "ESI:%s\n",
7988 esi_to_str(&attr
->esi
,
7989 esi_buf
, sizeof(esi_buf
)));
7992 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7993 vty_out(vty
, "%*s", 20, " ");
7994 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7998 #ifdef ENABLE_BGP_VNC
7999 /* prints an additional line, indented, with VNC info, if
8001 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
8002 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
8007 /* called from terminal list command */
8008 void route_vty_out_tmp(struct vty
*vty
, const struct prefix
*p
,
8009 struct attr
*attr
, safi_t safi
, bool use_json
,
8010 json_object
*json_ar
, bool wide
)
8012 json_object
*json_status
= NULL
;
8013 json_object
*json_net
= NULL
;
8017 /* Route status display. */
8019 json_status
= json_object_new_object();
8020 json_net
= json_object_new_object();
8027 /* print prefix and mask */
8029 if (safi
== SAFI_EVPN
)
8030 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
8031 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
8032 json_object_string_add(
8033 json_net
, "addrPrefix",
8034 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
8036 json_object_int_add(json_net
, "prefixLen",
8038 prefix2str(p
, buff
, PREFIX_STRLEN
);
8039 json_object_string_add(json_net
, "network", buff
);
8042 route_vty_out_route(p
, vty
, NULL
, wide
);
8044 /* Print attribute */
8047 if (p
->family
== AF_INET
8048 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8049 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8050 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8051 json_object_string_add(
8052 json_net
, "nextHop",
8054 attr
->mp_nexthop_global_in
));
8056 json_object_string_add(
8057 json_net
, "nextHop",
8058 inet_ntoa(attr
->nexthop
));
8059 } else if (p
->family
== AF_INET6
8060 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8063 json_object_string_add(
8064 json_net
, "nextHopGlobal",
8066 &attr
->mp_nexthop_global
, buf
,
8068 } else if (p
->family
== AF_EVPN
&&
8069 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8070 json_object_string_add(json_net
,
8071 "nextHop", inet_ntoa(
8072 attr
->mp_nexthop_global_in
));
8075 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8076 json_object_int_add(json_net
, "metric",
8079 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8080 json_object_int_add(json_net
, "locPrf",
8083 json_object_int_add(json_net
, "weight", attr
->weight
);
8087 json_object_string_add(json_net
, "path",
8091 json_object_string_add(json_net
, "bgpOriginCode",
8092 bgp_origin_str
[attr
->origin
]);
8094 if (p
->family
== AF_INET
8095 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8096 || safi
== SAFI_EVPN
8097 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8098 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8099 || safi
== SAFI_EVPN
)
8100 vty_out(vty
, "%-16s",
8102 attr
->mp_nexthop_global_in
));
8104 vty_out(vty
, "%-41s",
8105 inet_ntoa(attr
->nexthop
));
8107 vty_out(vty
, "%-16s",
8108 inet_ntoa(attr
->nexthop
));
8109 } else if (p
->family
== AF_INET6
8110 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8116 &attr
->mp_nexthop_global
, buf
,
8118 len
= wide
? (41 - len
) : (16 - len
);
8120 vty_out(vty
, "\n%*s", 36, " ");
8122 vty_out(vty
, "%*s", len
, " ");
8125 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8127 vty_out(vty
, "%7u", attr
->med
);
8129 vty_out(vty
, "%10u", attr
->med
);
8135 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8136 vty_out(vty
, "%7u", attr
->local_pref
);
8140 vty_out(vty
, "%7u ", attr
->weight
);
8144 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8147 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8151 json_object_boolean_true_add(json_status
, "*");
8152 json_object_boolean_true_add(json_status
, ">");
8153 json_object_object_add(json_net
, "appliedStatusSymbols",
8156 prefix2str(p
, buff
, PREFIX_STRLEN
);
8157 json_object_object_add(json_ar
, buff
, json_net
);
8162 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
8163 struct bgp_path_info
*path
, int display
, safi_t safi
,
8166 json_object
*json_out
= NULL
;
8168 mpls_label_t label
= MPLS_INVALID_LABEL
;
8174 json_out
= json_object_new_object();
8176 /* short status lead text */
8177 route_vty_short_status_out(vty
, path
, json_out
);
8179 /* print prefix and mask */
8182 route_vty_out_route(p
, vty
, NULL
, false);
8184 vty_out(vty
, "%*s", 17, " ");
8187 /* Print attribute */
8189 if (((p
->family
== AF_INET
)
8190 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8191 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8192 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8193 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8194 || safi
== SAFI_EVPN
) {
8196 json_object_string_add(
8197 json_out
, "mpNexthopGlobalIn",
8198 inet_ntoa(attr
->mp_nexthop_global_in
));
8200 vty_out(vty
, "%-16s",
8201 inet_ntoa(attr
->mp_nexthop_global_in
));
8204 json_object_string_add(
8205 json_out
, "nexthop",
8206 inet_ntoa(attr
->nexthop
));
8208 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
8210 } else if (((p
->family
== AF_INET6
)
8211 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8212 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8213 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8216 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
8218 json_object_string_add(
8219 json_out
, "mpNexthopGlobalIn",
8221 &attr
->mp_nexthop_global
,
8222 buf_a
, sizeof(buf_a
)));
8226 &attr
->mp_nexthop_global
,
8227 buf_a
, sizeof(buf_a
)));
8228 } else if (attr
->mp_nexthop_len
8229 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8230 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
8231 &attr
->mp_nexthop_global
,
8232 &attr
->mp_nexthop_local
);
8234 json_object_string_add(json_out
,
8235 "mpNexthopGlobalLocal",
8238 vty_out(vty
, "%s", buf_a
);
8242 label
= decode_label(&path
->extra
->label
[0]);
8244 if (bgp_is_valid_label(&label
)) {
8246 json_object_int_add(json_out
, "notag", label
);
8247 json_object_array_add(json
, json_out
);
8249 vty_out(vty
, "notag/%d", label
);
8255 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
8256 struct bgp_path_info
*path
, int display
,
8257 json_object
*json_paths
)
8260 char buf
[BUFSIZ
] = {0};
8261 json_object
*json_path
= NULL
;
8262 json_object
*json_nexthop
= NULL
;
8263 json_object
*json_overlay
= NULL
;
8269 json_path
= json_object_new_object();
8270 json_overlay
= json_object_new_object();
8271 json_nexthop
= json_object_new_object();
8274 /* short status lead text */
8275 route_vty_short_status_out(vty
, path
, json_path
);
8277 /* print prefix and mask */
8279 route_vty_out_route(p
, vty
, json_path
, false);
8281 vty_out(vty
, "%*s", 17, " ");
8283 /* Print attribute */
8286 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8290 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
8292 vty_out(vty
, "%-16s", buf
);
8294 json_object_string_add(json_nexthop
, "ip", buf
);
8296 json_object_string_add(json_nexthop
, "afi", "ipv4");
8298 json_object_object_add(json_path
, "nexthop",
8303 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
8304 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
8306 vty_out(vty
, "%s(%s)", buf
, buf1
);
8308 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
8310 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
8313 json_object_string_add(json_nexthop
, "afi", "ipv6");
8315 json_object_object_add(json_path
, "nexthop",
8323 json_object_string_add(json_nexthop
, "Error",
8324 "Unsupported address-family");
8328 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
8329 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
8331 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
8332 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
8337 vty_out(vty
, "/%s", buf
);
8339 json_object_string_add(json_overlay
, "gw", buf
);
8341 if (attr
->ecommunity
) {
8343 struct ecommunity_val
*routermac
= ecommunity_lookup(
8344 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
8345 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
8348 mac
= ecom_mac2str((char *)routermac
->val
);
8351 vty_out(vty
, "/%s", mac
);
8353 json_object_string_add(json_overlay
, "rmac",
8356 XFREE(MTYPE_TMP
, mac
);
8363 json_object_object_add(json_path
, "overlay", json_overlay
);
8365 json_object_array_add(json_paths
, json_path
);
8369 /* dampening route */
8370 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8371 struct bgp_path_info
*path
, int display
,
8372 afi_t afi
, safi_t safi
, bool use_json
,
8377 char timebuf
[BGP_UPTIME_LEN
];
8379 /* short status lead text */
8380 route_vty_short_status_out(vty
, path
, json
);
8382 /* print prefix and mask */
8385 route_vty_out_route(p
, vty
, NULL
, false);
8387 vty_out(vty
, "%*s", 17, " ");
8390 len
= vty_out(vty
, "%s", path
->peer
->host
);
8394 vty_out(vty
, "\n%*s", 34, " ");
8397 json_object_int_add(json
, "peerHost", len
);
8399 vty_out(vty
, "%*s", len
, " ");
8403 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8404 safi
, use_json
, json
);
8407 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8408 BGP_UPTIME_LEN
, afi
, safi
,
8411 /* Print attribute */
8417 json_object_string_add(json
, "asPath",
8420 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8425 json_object_string_add(json
, "origin",
8426 bgp_origin_str
[attr
->origin
]);
8428 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8435 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8436 struct bgp_path_info
*path
, int display
,
8437 afi_t afi
, safi_t safi
, bool use_json
,
8441 struct bgp_damp_info
*bdi
;
8442 char timebuf
[BGP_UPTIME_LEN
];
8448 bdi
= path
->extra
->damp_info
;
8450 /* short status lead text */
8451 route_vty_short_status_out(vty
, path
, json
);
8453 /* print prefix and mask */
8456 route_vty_out_route(p
, vty
, NULL
, false);
8458 vty_out(vty
, "%*s", 17, " ");
8461 len
= vty_out(vty
, "%s", path
->peer
->host
);
8465 vty_out(vty
, "\n%*s", 33, " ");
8468 json_object_int_add(json
, "peerHost", len
);
8470 vty_out(vty
, "%*s", len
, " ");
8473 len
= vty_out(vty
, "%d", bdi
->flap
);
8480 json_object_int_add(json
, "bdiFlap", len
);
8482 vty_out(vty
, "%*s", len
, " ");
8486 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8489 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8490 BGP_UPTIME_LEN
, 0, NULL
));
8492 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8493 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8495 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8496 BGP_UPTIME_LEN
, afi
, safi
,
8500 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8501 BGP_UPTIME_LEN
, afi
,
8502 safi
, use_json
, json
));
8505 vty_out(vty
, "%*s ", 8, " ");
8508 /* Print attribute */
8514 json_object_string_add(json
, "asPath",
8517 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8522 json_object_string_add(json
, "origin",
8523 bgp_origin_str
[attr
->origin
]);
8525 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8531 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8532 int *first
, const char *header
,
8533 json_object
*json_adv_to
)
8535 char buf1
[INET6_ADDRSTRLEN
];
8536 json_object
*json_peer
= NULL
;
8539 /* 'advertised-to' is a dictionary of peers we have advertised
8541 * prefix too. The key is the peer's IP or swpX, the value is
8543 * hostname if we know it and "" if not.
8545 json_peer
= json_object_new_object();
8548 json_object_string_add(json_peer
, "hostname",
8552 json_object_object_add(json_adv_to
, peer
->conf_if
,
8555 json_object_object_add(
8557 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8561 vty_out(vty
, "%s", header
);
8566 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
8568 vty_out(vty
, " %s(%s)", peer
->hostname
,
8571 vty_out(vty
, " %s(%s)", peer
->hostname
,
8572 sockunion2str(&peer
->su
, buf1
,
8576 vty_out(vty
, " %s", peer
->conf_if
);
8579 sockunion2str(&peer
->su
, buf1
,
8585 static void route_vty_out_tx_ids(struct vty
*vty
,
8586 struct bgp_addpath_info_data
*d
)
8590 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8591 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8592 d
->addpath_tx_id
[i
],
8593 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8597 static const char *bgp_path_selection_reason2str(
8598 enum bgp_path_selection_reason reason
)
8601 case bgp_path_selection_none
:
8602 return "Nothing to Select";
8603 case bgp_path_selection_first
:
8604 return "First path received";
8605 case bgp_path_selection_evpn_sticky_mac
:
8606 return "EVPN Sticky Mac";
8607 case bgp_path_selection_evpn_seq
:
8608 return "EVPN sequence number";
8609 case bgp_path_selection_evpn_lower_ip
:
8610 return "EVPN lower IP";
8611 case bgp_path_selection_evpn_local_path
:
8612 return "EVPN local ES path";
8613 case bgp_path_selection_evpn_non_proxy
:
8614 return "EVPN non proxy";
8615 case bgp_path_selection_weight
:
8617 case bgp_path_selection_local_pref
:
8618 return "Local Pref";
8619 case bgp_path_selection_local_route
:
8620 return "Local Route";
8621 case bgp_path_selection_confed_as_path
:
8622 return "Confederation based AS Path";
8623 case bgp_path_selection_as_path
:
8625 case bgp_path_selection_origin
:
8627 case bgp_path_selection_med
:
8629 case bgp_path_selection_peer
:
8631 case bgp_path_selection_confed
:
8632 return "Confed Peer Type";
8633 case bgp_path_selection_igp_metric
:
8634 return "IGP Metric";
8635 case bgp_path_selection_older
:
8636 return "Older Path";
8637 case bgp_path_selection_router_id
:
8639 case bgp_path_selection_cluster_length
:
8640 return "Cluser length";
8641 case bgp_path_selection_stale
:
8642 return "Path Staleness";
8643 case bgp_path_selection_local_configured
:
8644 return "Locally configured route";
8645 case bgp_path_selection_neighbor_ip
:
8646 return "Neighbor IP";
8647 case bgp_path_selection_default
:
8648 return "Nothing left to compare";
8650 return "Invalid (internal error)";
8653 static void route_vty_out_detail_es_info(struct vty
*vty
,
8654 struct attr
*attr
, json_object
*json_path
)
8656 char esi_buf
[ESI_STR_LEN
];
8657 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
8658 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
8659 ATTR_ES_PEER_ROUTER
);
8660 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
8661 ATTR_ES_PEER_ACTIVE
);
8662 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
8663 ATTR_ES_PEER_PROXY
);
8665 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
8667 json_object
*json_es_info
= NULL
;
8669 json_object_string_add(
8672 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
8673 json_es_info
= json_object_new_object();
8675 json_object_boolean_true_add(
8676 json_es_info
, "localEs");
8678 json_object_boolean_true_add(
8679 json_es_info
, "peerActive");
8681 json_object_boolean_true_add(
8682 json_es_info
, "peerProxy");
8684 json_object_boolean_true_add(
8685 json_es_info
, "peerRouter");
8686 if (attr
->mm_sync_seqnum
)
8687 json_object_int_add(
8688 json_es_info
, "peerSeq",
8689 attr
->mm_sync_seqnum
);
8690 json_object_object_add(
8691 json_path
, "es_info",
8695 if (bgp_evpn_attr_is_sync(attr
))
8697 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
8699 es_local
? "local-es":"",
8700 peer_proxy
? "proxy " : "",
8701 peer_active
? "active ":"",
8702 peer_router
? "router ":"",
8703 attr
->mm_sync_seqnum
);
8705 vty_out(vty
, " ESI %s %s\n",
8707 es_local
? "local-es":"");
8711 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8712 struct bgp_dest
*bn
, struct bgp_path_info
*path
,
8713 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8715 char buf
[INET6_ADDRSTRLEN
];
8717 char buf2
[EVPN_ROUTE_STRLEN
];
8718 struct attr
*attr
= path
->attr
;
8719 int sockunion_vty_out(struct vty
*, union sockunion
*);
8721 json_object
*json_bestpath
= NULL
;
8722 json_object
*json_cluster_list
= NULL
;
8723 json_object
*json_cluster_list_list
= NULL
;
8724 json_object
*json_ext_community
= NULL
;
8725 json_object
*json_last_update
= NULL
;
8726 json_object
*json_pmsi
= NULL
;
8727 json_object
*json_nexthop_global
= NULL
;
8728 json_object
*json_nexthop_ll
= NULL
;
8729 json_object
*json_nexthops
= NULL
;
8730 json_object
*json_path
= NULL
;
8731 json_object
*json_peer
= NULL
;
8732 json_object
*json_string
= NULL
;
8733 json_object
*json_adv_to
= NULL
;
8735 struct listnode
*node
, *nnode
;
8737 int addpath_capable
;
8739 unsigned int first_as
;
8741 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8743 char *nexthop_hostname
=
8744 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8747 json_path
= json_object_new_object();
8748 json_peer
= json_object_new_object();
8749 json_nexthop_global
= json_object_new_object();
8757 if (path
->extra
&& path
->extra
->num_labels
) {
8758 bgp_evpn_label2str(path
->extra
->label
,
8759 path
->extra
->num_labels
, tag_buf
,
8762 if (safi
== SAFI_EVPN
) {
8765 (struct prefix_evpn
*)
8766 bgp_dest_get_prefix(bn
),
8767 buf2
, sizeof(buf2
));
8768 vty_out(vty
, " Route %s", buf2
);
8769 if (tag_buf
[0] != '\0')
8770 vty_out(vty
, " VNI %s", tag_buf
);
8774 json_object_string_add(json_path
, "VNI",
8779 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8780 struct bgp_path_info
*parent_ri
;
8781 struct bgp_dest
*dest
, *pdest
;
8783 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8784 dest
= parent_ri
->net
;
8785 if (dest
&& dest
->pdest
) {
8786 pdest
= dest
->pdest
;
8788 (struct prefix_rd
*)bgp_dest_get_prefix(
8790 buf1
, sizeof(buf1
));
8791 if (is_pi_family_evpn(parent_ri
)) {
8793 (struct prefix_evpn
*)
8794 bgp_dest_get_prefix(
8796 buf2
, sizeof(buf2
));
8797 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8799 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8804 /* Line1 display AS-path, Aggregator */
8807 if (!attr
->aspath
->json
)
8808 aspath_str_update(attr
->aspath
, true);
8809 json_object_lock(attr
->aspath
->json
);
8810 json_object_object_add(json_path
, "aspath",
8811 attr
->aspath
->json
);
8813 if (attr
->aspath
->segments
)
8814 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8816 vty_out(vty
, " Local");
8820 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8822 json_object_boolean_true_add(json_path
, "removed");
8824 vty_out(vty
, ", (removed)");
8827 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8829 json_object_boolean_true_add(json_path
, "stale");
8831 vty_out(vty
, ", (stale)");
8834 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8836 json_object_int_add(json_path
, "aggregatorAs",
8837 attr
->aggregator_as
);
8838 json_object_string_add(
8839 json_path
, "aggregatorId",
8840 inet_ntoa(attr
->aggregator_addr
));
8841 if (attr
->aggregator_as
== BGP_AS_ZERO
)
8842 json_object_boolean_true_add(
8843 json_path
, "aggregatorAsMalformed");
8845 json_object_boolean_false_add(
8846 json_path
, "aggregatorAsMalformed");
8848 if (attr
->aggregator_as
== BGP_AS_ZERO
)
8850 ", (aggregated by %u(malformed) %s)",
8851 attr
->aggregator_as
,
8852 inet_ntoa(attr
->aggregator_addr
));
8854 vty_out(vty
, ", (aggregated by %u %s)",
8855 attr
->aggregator_as
,
8856 inet_ntoa(attr
->aggregator_addr
));
8860 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8861 PEER_FLAG_REFLECTOR_CLIENT
)) {
8863 json_object_boolean_true_add(json_path
,
8864 "rxedFromRrClient");
8866 vty_out(vty
, ", (Received from a RR-client)");
8869 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8870 PEER_FLAG_RSERVER_CLIENT
)) {
8872 json_object_boolean_true_add(json_path
,
8873 "rxedFromRsClient");
8875 vty_out(vty
, ", (Received from a RS-client)");
8878 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8880 json_object_boolean_true_add(json_path
,
8881 "dampeningHistoryEntry");
8883 vty_out(vty
, ", (history entry)");
8884 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8886 json_object_boolean_true_add(json_path
,
8887 "dampeningSuppressed");
8889 vty_out(vty
, ", (suppressed due to dampening)");
8895 /* Line2 display Next-hop, Neighbor, Router-id */
8896 /* Display the nexthop */
8897 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
8899 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
8900 || bn_p
->family
== AF_EVPN
)
8901 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8902 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8903 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8904 || safi
== SAFI_EVPN
) {
8906 json_object_string_add(
8907 json_nexthop_global
, "ip",
8908 inet_ntoa(attr
->mp_nexthop_global_in
));
8910 if (path
->peer
->hostname
)
8911 json_object_string_add(
8912 json_nexthop_global
, "hostname",
8913 path
->peer
->hostname
);
8915 if (nexthop_hostname
)
8916 vty_out(vty
, " %pI4(%s)",
8917 &attr
->mp_nexthop_global_in
,
8920 vty_out(vty
, " %pI4",
8921 &attr
->mp_nexthop_global_in
);
8925 json_object_string_add(
8926 json_nexthop_global
, "ip",
8927 inet_ntoa(attr
->nexthop
));
8929 if (path
->peer
->hostname
)
8930 json_object_string_add(
8931 json_nexthop_global
, "hostname",
8932 path
->peer
->hostname
);
8934 if (nexthop_hostname
)
8935 vty_out(vty
, " %pI4(%s)",
8939 vty_out(vty
, " %pI4",
8945 json_object_string_add(json_nexthop_global
, "afi",
8949 json_object_string_add(
8950 json_nexthop_global
, "ip",
8951 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8952 buf
, INET6_ADDRSTRLEN
));
8954 if (path
->peer
->hostname
)
8955 json_object_string_add(json_nexthop_global
,
8957 path
->peer
->hostname
);
8959 json_object_string_add(json_nexthop_global
, "afi",
8961 json_object_string_add(json_nexthop_global
, "scope",
8964 if (nexthop_hostname
)
8965 vty_out(vty
, " %pI6(%s)",
8966 &attr
->mp_nexthop_global
,
8969 vty_out(vty
, " %pI6",
8970 &attr
->mp_nexthop_global
);
8974 /* Display the IGP cost or 'inaccessible' */
8975 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8977 json_object_boolean_false_add(json_nexthop_global
,
8980 vty_out(vty
, " (inaccessible)");
8982 if (path
->extra
&& path
->extra
->igpmetric
) {
8984 json_object_int_add(json_nexthop_global
,
8986 path
->extra
->igpmetric
);
8988 vty_out(vty
, " (metric %u)",
8989 path
->extra
->igpmetric
);
8992 /* IGP cost is 0, display this only for json */
8995 json_object_int_add(json_nexthop_global
,
9000 json_object_boolean_true_add(json_nexthop_global
,
9004 /* Display peer "from" output */
9005 /* This path was originated locally */
9006 if (path
->peer
== bgp
->peer_self
) {
9008 if (safi
== SAFI_EVPN
9009 || (bn_p
->family
== AF_INET
9010 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9012 json_object_string_add(json_peer
, "peerId",
9015 vty_out(vty
, " from 0.0.0.0 ");
9018 json_object_string_add(json_peer
, "peerId",
9021 vty_out(vty
, " from :: ");
9025 json_object_string_add(json_peer
, "routerId",
9026 inet_ntoa(bgp
->router_id
));
9028 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
9031 /* We RXed this path from one of our peers */
9035 json_object_string_add(json_peer
, "peerId",
9036 sockunion2str(&path
->peer
->su
,
9039 json_object_string_add(json_peer
, "routerId",
9041 &path
->peer
->remote_id
,
9042 buf1
, sizeof(buf1
)));
9044 if (path
->peer
->hostname
)
9045 json_object_string_add(json_peer
, "hostname",
9046 path
->peer
->hostname
);
9048 if (path
->peer
->domainname
)
9049 json_object_string_add(json_peer
, "domainname",
9050 path
->peer
->domainname
);
9052 if (path
->peer
->conf_if
)
9053 json_object_string_add(json_peer
, "interface",
9054 path
->peer
->conf_if
);
9056 if (path
->peer
->conf_if
) {
9057 if (path
->peer
->hostname
9058 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9059 BGP_FLAG_SHOW_HOSTNAME
))
9060 vty_out(vty
, " from %s(%s)",
9061 path
->peer
->hostname
,
9062 path
->peer
->conf_if
);
9064 vty_out(vty
, " from %s",
9065 path
->peer
->conf_if
);
9067 if (path
->peer
->hostname
9068 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9069 BGP_FLAG_SHOW_HOSTNAME
))
9070 vty_out(vty
, " from %s(%s)",
9071 path
->peer
->hostname
,
9074 vty_out(vty
, " from %s",
9075 sockunion2str(&path
->peer
->su
,
9080 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9081 vty_out(vty
, " (%s)",
9082 inet_ntoa(attr
->originator_id
));
9084 vty_out(vty
, " (%s)",
9086 &path
->peer
->remote_id
, buf1
,
9092 * Note when vrfid of nexthop is different from that of prefix
9094 if (path
->extra
&& path
->extra
->bgp_orig
) {
9095 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9100 if (path
->extra
->bgp_orig
->inst_type
9101 == BGP_INSTANCE_TYPE_DEFAULT
)
9102 vn
= VRF_DEFAULT_NAME
;
9104 vn
= path
->extra
->bgp_orig
->name
;
9106 json_object_string_add(json_path
, "nhVrfName", vn
);
9108 if (nexthop_vrfid
== VRF_UNKNOWN
) {
9109 json_object_int_add(json_path
, "nhVrfId", -1);
9111 json_object_int_add(json_path
, "nhVrfId",
9112 (int)nexthop_vrfid
);
9115 if (nexthop_vrfid
== VRF_UNKNOWN
)
9116 vty_out(vty
, " vrf ?");
9120 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
9121 vty_out(vty
, " vrf %s(%u)",
9122 VRF_LOGNAME(vrf
), nexthop_vrfid
);
9129 json_object_boolean_true_add(json_path
,
9130 "announceNexthopSelf");
9132 vty_out(vty
, " announce-nh-self");
9139 /* display the link-local nexthop */
9140 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9142 json_nexthop_ll
= json_object_new_object();
9143 json_object_string_add(
9144 json_nexthop_ll
, "ip",
9145 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9146 buf
, INET6_ADDRSTRLEN
));
9148 if (path
->peer
->hostname
)
9149 json_object_string_add(json_nexthop_ll
,
9151 path
->peer
->hostname
);
9153 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
9154 json_object_string_add(json_nexthop_ll
, "scope",
9157 json_object_boolean_true_add(json_nexthop_ll
,
9160 if (!attr
->mp_nexthop_prefer_global
)
9161 json_object_boolean_true_add(json_nexthop_ll
,
9164 json_object_boolean_true_add(
9165 json_nexthop_global
, "used");
9167 vty_out(vty
, " (%s) %s\n",
9168 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9169 buf
, INET6_ADDRSTRLEN
),
9170 attr
->mp_nexthop_prefer_global
9175 /* If we do not have a link-local nexthop then we must flag the
9179 json_object_boolean_true_add(json_nexthop_global
,
9183 if (safi
== SAFI_EVPN
&&
9184 bgp_evpn_is_esi_valid(&attr
->esi
)) {
9185 route_vty_out_detail_es_info(vty
, attr
, json_path
);
9188 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9189 * Int/Ext/Local, Atomic, best */
9191 json_object_string_add(json_path
, "origin",
9192 bgp_origin_long_str
[attr
->origin
]);
9194 vty_out(vty
, " Origin %s",
9195 bgp_origin_long_str
[attr
->origin
]);
9197 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
9199 json_object_int_add(json_path
, "metric", attr
->med
);
9201 vty_out(vty
, ", metric %u", attr
->med
);
9204 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
9206 json_object_int_add(json_path
, "locPrf",
9209 vty_out(vty
, ", localpref %u", attr
->local_pref
);
9212 if (attr
->weight
!= 0) {
9214 json_object_int_add(json_path
, "weight", attr
->weight
);
9216 vty_out(vty
, ", weight %u", attr
->weight
);
9219 if (attr
->tag
!= 0) {
9221 json_object_int_add(json_path
, "tag", attr
->tag
);
9223 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
9226 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9228 json_object_boolean_false_add(json_path
, "valid");
9230 vty_out(vty
, ", invalid");
9231 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9233 json_object_boolean_true_add(json_path
, "valid");
9235 vty_out(vty
, ", valid");
9238 if (path
->peer
!= bgp
->peer_self
) {
9239 if (path
->peer
->as
== path
->peer
->local_as
) {
9240 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
9242 json_object_string_add(
9246 vty_out(vty
, ", confed-internal");
9249 json_object_string_add(
9250 json_peer
, "type", "internal");
9252 vty_out(vty
, ", internal");
9255 if (bgp_confederation_peers_check(bgp
,
9258 json_object_string_add(
9262 vty_out(vty
, ", confed-external");
9265 json_object_string_add(
9266 json_peer
, "type", "external");
9268 vty_out(vty
, ", external");
9271 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
9273 json_object_boolean_true_add(json_path
, "aggregated");
9274 json_object_boolean_true_add(json_path
, "local");
9276 vty_out(vty
, ", aggregated, local");
9278 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
9280 json_object_boolean_true_add(json_path
, "sourced");
9282 vty_out(vty
, ", sourced");
9285 json_object_boolean_true_add(json_path
, "sourced");
9286 json_object_boolean_true_add(json_path
, "local");
9288 vty_out(vty
, ", sourced, local");
9292 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
9294 json_object_boolean_true_add(json_path
,
9297 vty_out(vty
, ", atomic-aggregate");
9300 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
9301 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
9302 && bgp_path_info_mpath_count(path
))) {
9304 json_object_boolean_true_add(json_path
, "multipath");
9306 vty_out(vty
, ", multipath");
9309 // Mark the bestpath(s)
9310 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
9311 first_as
= aspath_get_first_as(attr
->aspath
);
9315 json_bestpath
= json_object_new_object();
9316 json_object_int_add(json_bestpath
, "bestpathFromAs",
9320 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
9322 vty_out(vty
, ", bestpath-from-AS Local");
9326 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9329 json_bestpath
= json_object_new_object();
9330 json_object_boolean_true_add(json_bestpath
, "overall");
9331 json_object_string_add(
9332 json_bestpath
, "selectionReason",
9333 bgp_path_selection_reason2str(bn
->reason
));
9335 vty_out(vty
, ", best");
9336 vty_out(vty
, " (%s)",
9337 bgp_path_selection_reason2str(bn
->reason
));
9342 json_object_object_add(json_path
, "bestpath", json_bestpath
);
9347 /* Line 4 display Community */
9348 if (attr
->community
) {
9350 if (!attr
->community
->json
)
9351 community_str(attr
->community
, true);
9352 json_object_lock(attr
->community
->json
);
9353 json_object_object_add(json_path
, "community",
9354 attr
->community
->json
);
9356 vty_out(vty
, " Community: %s\n",
9357 attr
->community
->str
);
9361 /* Line 5 display Extended-community */
9362 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9364 json_ext_community
= json_object_new_object();
9365 json_object_string_add(json_ext_community
, "string",
9366 attr
->ecommunity
->str
);
9367 json_object_object_add(json_path
, "extendedCommunity",
9368 json_ext_community
);
9370 vty_out(vty
, " Extended Community: %s\n",
9371 attr
->ecommunity
->str
);
9375 /* Line 6 display Large community */
9376 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
9378 if (!attr
->lcommunity
->json
)
9379 lcommunity_str(attr
->lcommunity
, true);
9380 json_object_lock(attr
->lcommunity
->json
);
9381 json_object_object_add(json_path
, "largeCommunity",
9382 attr
->lcommunity
->json
);
9384 vty_out(vty
, " Large Community: %s\n",
9385 attr
->lcommunity
->str
);
9389 /* Line 7 display Originator, Cluster-id */
9390 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9391 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
9392 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
9394 json_object_string_add(
9395 json_path
, "originatorId",
9396 inet_ntoa(attr
->originator_id
));
9398 vty_out(vty
, " Originator: %s",
9399 inet_ntoa(attr
->originator_id
));
9402 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
9406 json_cluster_list
= json_object_new_object();
9407 json_cluster_list_list
=
9408 json_object_new_array();
9410 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9412 json_string
= json_object_new_string(
9413 inet_ntoa(attr
->cluster
9415 json_object_array_add(
9416 json_cluster_list_list
,
9421 * struct cluster_list does not have
9422 * "str" variable like aspath and community
9423 * do. Add this someday if someone asks
9425 * json_object_string_add(json_cluster_list,
9426 * "string", attr->cluster->str);
9428 json_object_object_add(json_cluster_list
,
9430 json_cluster_list_list
);
9431 json_object_object_add(json_path
, "clusterList",
9434 vty_out(vty
, ", Cluster list: ");
9436 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9439 inet_ntoa(attr
->cluster
9449 if (path
->extra
&& path
->extra
->damp_info
)
9450 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
9453 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
9454 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
9455 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
9458 json_object_int_add(json_path
, "remoteLabel", label
);
9460 vty_out(vty
, " Remote label: %d\n", label
);
9464 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
9465 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
9467 json_object_string_add(json_path
, "remoteSid", buf
);
9469 vty_out(vty
, " Remote SID: %s\n", buf
);
9473 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
9475 json_object_int_add(json_path
, "labelIndex",
9478 vty_out(vty
, " Label Index: %d\n",
9482 /* Line 8 display Addpath IDs */
9483 if (path
->addpath_rx_id
9484 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9486 json_object_int_add(json_path
, "addpathRxId",
9487 path
->addpath_rx_id
);
9489 /* Keep backwards compatibility with the old API
9490 * by putting TX All's ID in the old field
9492 json_object_int_add(
9493 json_path
, "addpathTxId",
9495 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9497 /* ... but create a specific field for each
9500 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9501 json_object_int_add(
9503 bgp_addpath_names(i
)->id_json_name
,
9504 path
->tx_addpath
.addpath_tx_id
[i
]);
9507 vty_out(vty
, " AddPath ID: RX %u, ",
9508 path
->addpath_rx_id
);
9510 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9514 /* If we used addpath to TX a non-bestpath we need to display
9515 * "Advertised to" on a path-by-path basis
9517 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9520 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9522 bgp_addpath_encode_tx(peer
, afi
, safi
);
9523 has_adj
= bgp_adj_out_lookup(
9525 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9526 &path
->tx_addpath
));
9528 if ((addpath_capable
&& has_adj
)
9529 || (!addpath_capable
&& has_adj
9530 && CHECK_FLAG(path
->flags
,
9531 BGP_PATH_SELECTED
))) {
9532 if (json_path
&& !json_adv_to
)
9533 json_adv_to
= json_object_new_object();
9535 route_vty_out_advertised_to(
9537 " Advertised to:", json_adv_to
);
9543 json_object_object_add(
9544 json_path
, "advertisedTo", json_adv_to
);
9553 /* Line 9 display Uptime */
9554 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9556 json_last_update
= json_object_new_object();
9557 json_object_int_add(json_last_update
, "epoch", tbuf
);
9558 json_object_string_add(json_last_update
, "string",
9560 json_object_object_add(json_path
, "lastUpdate",
9563 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9565 /* Line 10 display PMSI tunnel attribute, if present */
9566 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9568 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9569 PMSI_TNLTYPE_STR_DEFAULT
);
9572 json_pmsi
= json_object_new_object();
9573 json_object_string_add(json_pmsi
, "tunnelType", str
);
9574 json_object_int_add(json_pmsi
, "label",
9575 label2vni(&attr
->label
));
9576 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9578 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9579 str
, label2vni(&attr
->label
));
9582 /* We've constructed the json object for this path, add it to the json
9586 if (json_nexthop_global
|| json_nexthop_ll
) {
9587 json_nexthops
= json_object_new_array();
9589 if (json_nexthop_global
)
9590 json_object_array_add(json_nexthops
,
9591 json_nexthop_global
);
9593 if (json_nexthop_ll
)
9594 json_object_array_add(json_nexthops
,
9597 json_object_object_add(json_path
, "nexthops",
9601 json_object_object_add(json_path
, "peer", json_peer
);
9602 json_object_array_add(json_paths
, json_path
);
9606 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9607 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9608 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9610 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9611 const char *prefix_list_str
, afi_t afi
,
9612 safi_t safi
, enum bgp_show_type type
);
9613 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9614 const char *filter
, afi_t afi
, safi_t safi
,
9615 enum bgp_show_type type
);
9616 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9617 const char *rmap_str
, afi_t afi
, safi_t safi
,
9618 enum bgp_show_type type
);
9619 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9620 const char *com
, int exact
, afi_t afi
,
9622 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9623 const char *prefix
, afi_t afi
, safi_t safi
,
9624 enum bgp_show_type type
);
9625 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9626 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
9628 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9629 const char *comstr
, int exact
, afi_t afi
,
9630 safi_t safi
, uint8_t show_flags
);
9633 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9634 struct bgp_table
*table
, enum bgp_show_type type
,
9635 void *output_arg
, char *rd
, int is_last
,
9636 unsigned long *output_cum
, unsigned long *total_cum
,
9637 unsigned long *json_header_depth
, uint8_t show_flags
)
9639 struct bgp_path_info
*pi
;
9640 struct bgp_dest
*dest
;
9643 unsigned long output_count
= 0;
9644 unsigned long total_count
= 0;
9646 json_object
*json_paths
= NULL
;
9648 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
9649 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
9650 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
9652 if (output_cum
&& *output_cum
!= 0)
9655 if (use_json
&& !*json_header_depth
) {
9657 *json_header_depth
= 1;
9659 vty_out(vty
, "{\n");
9660 *json_header_depth
= 2;
9664 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9665 " \"localAS\": %u,\n \"routes\": { ",
9666 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9667 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9670 table
->version
, inet_ntoa(bgp
->router_id
),
9671 bgp
->default_local_pref
, bgp
->as
);
9673 vty_out(vty
, " \"routeDistinguishers\" : {");
9674 ++*json_header_depth
;
9678 if (use_json
&& rd
) {
9679 vty_out(vty
, " \"%s\" : { ", rd
);
9682 /* Start processing of routes. */
9683 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
9684 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
9686 pi
= bgp_dest_get_bgp_path_info(dest
);
9692 json_paths
= json_object_new_array();
9696 for (; pi
; pi
= pi
->next
) {
9698 if (type
== bgp_show_type_flap_statistics
9699 || type
== bgp_show_type_flap_neighbor
9700 || type
== bgp_show_type_dampend_paths
9701 || type
== bgp_show_type_damp_neighbor
) {
9702 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9705 if (type
== bgp_show_type_regexp
) {
9706 regex_t
*regex
= output_arg
;
9708 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9712 if (type
== bgp_show_type_prefix_list
) {
9713 struct prefix_list
*plist
= output_arg
;
9715 if (prefix_list_apply(plist
, dest_p
)
9719 if (type
== bgp_show_type_filter_list
) {
9720 struct as_list
*as_list
= output_arg
;
9722 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9723 != AS_FILTER_PERMIT
)
9726 if (type
== bgp_show_type_route_map
) {
9727 struct route_map
*rmap
= output_arg
;
9728 struct bgp_path_info path
;
9729 struct attr dummy_attr
;
9730 route_map_result_t ret
;
9732 dummy_attr
= *pi
->attr
;
9734 path
.peer
= pi
->peer
;
9735 path
.attr
= &dummy_attr
;
9737 ret
= route_map_apply(rmap
, dest_p
, RMAP_BGP
,
9739 if (ret
== RMAP_DENYMATCH
)
9742 if (type
== bgp_show_type_neighbor
9743 || type
== bgp_show_type_flap_neighbor
9744 || type
== bgp_show_type_damp_neighbor
) {
9745 union sockunion
*su
= output_arg
;
9747 if (pi
->peer
== NULL
9748 || pi
->peer
->su_remote
== NULL
9749 || !sockunion_same(pi
->peer
->su_remote
, su
))
9752 if (type
== bgp_show_type_cidr_only
) {
9753 uint32_t destination
;
9755 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
9756 if (IN_CLASSC(destination
)
9757 && dest_p
->prefixlen
== 24)
9759 if (IN_CLASSB(destination
)
9760 && dest_p
->prefixlen
== 16)
9762 if (IN_CLASSA(destination
)
9763 && dest_p
->prefixlen
== 8)
9766 if (type
== bgp_show_type_prefix_longer
) {
9768 if (!prefix_match(p
, dest_p
))
9771 if (type
== bgp_show_type_community_all
) {
9772 if (!pi
->attr
->community
)
9775 if (type
== bgp_show_type_community
) {
9776 struct community
*com
= output_arg
;
9778 if (!pi
->attr
->community
9779 || !community_match(pi
->attr
->community
,
9783 if (type
== bgp_show_type_community_exact
) {
9784 struct community
*com
= output_arg
;
9786 if (!pi
->attr
->community
9787 || !community_cmp(pi
->attr
->community
, com
))
9790 if (type
== bgp_show_type_community_list
) {
9791 struct community_list
*list
= output_arg
;
9793 if (!community_list_match(pi
->attr
->community
,
9797 if (type
== bgp_show_type_community_list_exact
) {
9798 struct community_list
*list
= output_arg
;
9800 if (!community_list_exact_match(
9801 pi
->attr
->community
, list
))
9804 if (type
== bgp_show_type_lcommunity
) {
9805 struct lcommunity
*lcom
= output_arg
;
9807 if (!pi
->attr
->lcommunity
9808 || !lcommunity_match(pi
->attr
->lcommunity
,
9813 if (type
== bgp_show_type_lcommunity_exact
) {
9814 struct lcommunity
*lcom
= output_arg
;
9816 if (!pi
->attr
->lcommunity
9817 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9821 if (type
== bgp_show_type_lcommunity_list
) {
9822 struct community_list
*list
= output_arg
;
9824 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9829 == bgp_show_type_lcommunity_list_exact
) {
9830 struct community_list
*list
= output_arg
;
9832 if (!lcommunity_list_exact_match(
9833 pi
->attr
->lcommunity
, list
))
9836 if (type
== bgp_show_type_lcommunity_all
) {
9837 if (!pi
->attr
->lcommunity
)
9840 if (type
== bgp_show_type_dampend_paths
9841 || type
== bgp_show_type_damp_neighbor
) {
9842 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9843 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9847 if (!use_json
&& header
) {
9848 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
9850 inet_ntoa(bgp
->router_id
));
9851 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9852 vty_out(vty
, "%s", VRFID_NONE_STR
);
9854 vty_out(vty
, "%u", bgp
->vrf_id
);
9856 vty_out(vty
, "Default local pref %u, ",
9857 bgp
->default_local_pref
);
9858 vty_out(vty
, "local AS %u\n", bgp
->as
);
9859 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9860 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9861 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9862 if (type
== bgp_show_type_dampend_paths
9863 || type
== bgp_show_type_damp_neighbor
)
9864 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9865 else if (type
== bgp_show_type_flap_statistics
9866 || type
== bgp_show_type_flap_neighbor
)
9867 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9869 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
9870 : BGP_SHOW_HEADER
));
9873 if (rd
!= NULL
&& !display
&& !output_count
) {
9876 "Route Distinguisher: %s\n",
9879 if (type
== bgp_show_type_dampend_paths
9880 || type
== bgp_show_type_damp_neighbor
)
9881 damp_route_vty_out(vty
, dest_p
, pi
, display
,
9882 AFI_IP
, safi
, use_json
,
9884 else if (type
== bgp_show_type_flap_statistics
9885 || type
== bgp_show_type_flap_neighbor
)
9886 flap_route_vty_out(vty
, dest_p
, pi
, display
,
9887 AFI_IP
, safi
, use_json
,
9890 route_vty_out(vty
, dest_p
, pi
, display
, safi
,
9901 if (dest_p
->family
== AF_FLOWSPEC
) {
9902 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9905 bgp_fs_nlri_get_string(
9907 dest_p
->u
.prefix_flowspec
.ptr
,
9908 dest_p
->u
.prefix_flowspec
.prefixlen
,
9909 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
9910 family2afi(dest_p
->u
9911 .prefix_flowspec
.family
));
9913 vty_out(vty
, "\"%s/%d\": ", retstr
,
9914 dest_p
->u
.prefix_flowspec
9917 vty_out(vty
, ",\"%s/%d\": ", retstr
,
9918 dest_p
->u
.prefix_flowspec
9922 vty_out(vty
, "\"%pFX\": ", dest_p
);
9924 vty_out(vty
, ",\"%pFX\": ", dest_p
);
9927 json_object_to_json_string_ext(
9928 json_paths
, JSON_C_TO_STRING_PRETTY
));
9929 json_object_free(json_paths
);
9933 json_object_free(json_paths
);
9937 output_count
+= *output_cum
;
9938 *output_cum
= output_count
;
9941 total_count
+= *total_cum
;
9942 *total_cum
= total_count
;
9946 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9950 for (i
= 0; i
< *json_header_depth
; ++i
)
9951 vty_out(vty
, " } ");
9957 /* No route is displayed */
9958 if (output_count
== 0) {
9959 if (type
== bgp_show_type_normal
)
9961 "No BGP prefixes displayed, %ld exist\n",
9965 "\nDisplayed %ld routes and %ld total paths\n",
9966 output_count
, total_count
);
9973 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9974 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9975 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9977 struct bgp_dest
*dest
, *next
;
9978 unsigned long output_cum
= 0;
9979 unsigned long total_cum
= 0;
9980 unsigned long json_header_depth
= 0;
9981 struct bgp_table
*itable
;
9983 uint8_t show_flags
= 0;
9985 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9988 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
9990 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
9991 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
9993 next
= bgp_route_next(dest
);
9994 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
9997 itable
= bgp_dest_get_bgp_table_info(dest
);
9998 if (itable
!= NULL
) {
9999 struct prefix_rd prd
;
10000 char rd
[RD_ADDRSTRLEN
];
10002 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
10003 prefix_rd2str(&prd
, rd
, sizeof(rd
));
10004 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
10005 rd
, next
== NULL
, &output_cum
,
10006 &total_cum
, &json_header_depth
,
10013 if (output_cum
== 0)
10014 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
10018 "\nDisplayed %ld routes and %ld total paths\n",
10019 output_cum
, total_cum
);
10021 return CMD_SUCCESS
;
10023 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10024 enum bgp_show_type type
, void *output_arg
,
10025 uint8_t show_flags
)
10027 struct bgp_table
*table
;
10028 unsigned long json_header_depth
= 0;
10029 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10032 bgp
= bgp_get_default();
10037 vty_out(vty
, "No BGP process is configured\n");
10039 vty_out(vty
, "{}\n");
10040 return CMD_WARNING
;
10043 table
= bgp
->rib
[afi
][safi
];
10044 /* use MPLS and ENCAP specific shows until they are merged */
10045 if (safi
== SAFI_MPLS_VPN
) {
10046 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
10047 output_arg
, use_json
);
10050 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
10051 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
10052 output_arg
, use_json
,
10055 /* labeled-unicast routes live in the unicast table */
10056 else if (safi
== SAFI_LABELED_UNICAST
)
10057 safi
= SAFI_UNICAST
;
10059 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
10060 NULL
, NULL
, &json_header_depth
, show_flags
);
10063 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
10064 safi_t safi
, uint8_t show_flags
)
10066 struct listnode
*node
, *nnode
;
10069 bool route_output
= false;
10070 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10073 vty_out(vty
, "{\n");
10075 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
10076 route_output
= true;
10079 vty_out(vty
, ",\n");
10083 vty_out(vty
, "\"%s\":",
10084 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10088 vty_out(vty
, "\nInstance %s:\n",
10089 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10093 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
10098 vty_out(vty
, "}\n");
10099 else if (!route_output
)
10100 vty_out(vty
, "%% BGP instance not found\n");
10103 /* Header of detailed BGP route information */
10104 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
10105 struct bgp_dest
*dest
, struct prefix_rd
*prd
,
10106 afi_t afi
, safi_t safi
, json_object
*json
)
10108 struct bgp_path_info
*pi
;
10109 const struct prefix
*p
;
10111 struct listnode
*node
, *nnode
;
10112 char buf1
[RD_ADDRSTRLEN
];
10113 char buf2
[INET6_ADDRSTRLEN
];
10114 char buf3
[EVPN_ROUTE_STRLEN
];
10115 char prefix_str
[BUFSIZ
];
10119 int accept_own
= 0;
10120 int route_filter_translated_v4
= 0;
10121 int route_filter_v4
= 0;
10122 int route_filter_translated_v6
= 0;
10123 int route_filter_v6
= 0;
10124 int llgr_stale
= 0;
10126 int accept_own_nexthop
= 0;
10129 int no_advertise
= 0;
10133 int has_valid_label
= 0;
10134 mpls_label_t label
= 0;
10135 json_object
*json_adv_to
= NULL
;
10137 p
= bgp_dest_get_prefix(dest
);
10138 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
10140 if (has_valid_label
)
10141 label
= label_pton(&dest
->local_label
);
10143 if (safi
== SAFI_EVPN
) {
10146 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
10147 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
10148 : "", prd
? ":" : "",
10149 bgp_evpn_route2str((struct prefix_evpn
*)p
,
10150 buf3
, sizeof(buf3
)));
10152 json_object_string_add(json
, "rd",
10153 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
10155 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
10159 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
10160 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
10161 ? prefix_rd2str(prd
, buf1
,
10164 safi
== SAFI_MPLS_VPN
? ":" : "",
10165 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
10170 json_object_string_add(json
, "prefix",
10171 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
10174 if (has_valid_label
) {
10176 json_object_int_add(json
, "localLabel", label
);
10178 vty_out(vty
, "Local label: %d\n", label
);
10182 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
10183 vty_out(vty
, "not allocated\n");
10185 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
10187 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
10189 if (pi
->extra
&& pi
->extra
->suppress
)
10192 if (pi
->attr
->community
== NULL
)
10195 no_advertise
+= community_include(
10196 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
10197 no_export
+= community_include(pi
->attr
->community
,
10198 COMMUNITY_NO_EXPORT
);
10199 local_as
+= community_include(pi
->attr
->community
,
10200 COMMUNITY_LOCAL_AS
);
10201 accept_own
+= community_include(pi
->attr
->community
,
10202 COMMUNITY_ACCEPT_OWN
);
10203 route_filter_translated_v4
+= community_include(
10204 pi
->attr
->community
,
10205 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
10206 route_filter_translated_v6
+= community_include(
10207 pi
->attr
->community
,
10208 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
10209 route_filter_v4
+= community_include(
10210 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
10211 route_filter_v6
+= community_include(
10212 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
10213 llgr_stale
+= community_include(pi
->attr
->community
,
10214 COMMUNITY_LLGR_STALE
);
10215 no_llgr
+= community_include(pi
->attr
->community
,
10216 COMMUNITY_NO_LLGR
);
10217 accept_own_nexthop
+=
10218 community_include(pi
->attr
->community
,
10219 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
10220 blackhole
+= community_include(pi
->attr
->community
,
10221 COMMUNITY_BLACKHOLE
);
10222 no_peer
+= community_include(pi
->attr
->community
,
10223 COMMUNITY_NO_PEER
);
10228 vty_out(vty
, "Paths: (%d available", count
);
10230 vty_out(vty
, ", best #%d", best
);
10231 if (safi
== SAFI_UNICAST
) {
10232 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10233 vty_out(vty
, ", table %s",
10236 vty_out(vty
, ", vrf %s",
10240 vty_out(vty
, ", no best path");
10244 ", accept own local route exported and imported in different VRF");
10245 else if (route_filter_translated_v4
)
10247 ", mark translated RTs for VPNv4 route filtering");
10248 else if (route_filter_v4
)
10250 ", attach RT as-is for VPNv4 route filtering");
10251 else if (route_filter_translated_v6
)
10253 ", mark translated RTs for VPNv6 route filtering");
10254 else if (route_filter_v6
)
10256 ", attach RT as-is for VPNv6 route filtering");
10257 else if (llgr_stale
)
10259 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10262 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10263 else if (accept_own_nexthop
)
10265 ", accept local nexthop");
10266 else if (blackhole
)
10267 vty_out(vty
, ", inform peer to blackhole prefix");
10268 else if (no_export
)
10269 vty_out(vty
, ", not advertised to EBGP peer");
10270 else if (no_advertise
)
10271 vty_out(vty
, ", not advertised to any peer");
10273 vty_out(vty
, ", not advertised outside local AS");
10276 ", inform EBGP peer not to advertise to their EBGP peers");
10280 ", Advertisements suppressed by an aggregate.");
10281 vty_out(vty
, ")\n");
10284 /* If we are not using addpath then we can display Advertised to and
10286 * show what peers we advertised the bestpath to. If we are using
10288 * though then we must display Advertised to on a path-by-path basis. */
10289 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10290 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10291 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
10292 if (json
&& !json_adv_to
)
10293 json_adv_to
= json_object_new_object();
10295 route_vty_out_advertised_to(
10297 " Advertised to non peer-group peers:\n ",
10304 json_object_object_add(json
, "advertisedTo",
10309 vty_out(vty
, " Not advertised to any peer");
10310 vty_out(vty
, "\n");
10315 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
10316 struct bgp_dest
*bgp_node
, struct vty
*vty
,
10317 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10318 json_object
*json
, enum bgp_path_type pathtype
,
10321 struct bgp_path_info
*pi
;
10323 char rdbuf
[RD_ADDRSTRLEN
];
10324 json_object
*json_header
= NULL
;
10325 json_object
*json_paths
= NULL
;
10327 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
10329 if (json
&& !json_paths
) {
10330 /* Instantiate json_paths only if path is valid */
10331 json_paths
= json_object_new_array();
10333 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
10334 json_header
= json_object_new_object();
10336 json_header
= json
;
10340 route_vty_out_detail_header(
10341 vty
, bgp
, bgp_node
, pfx_rd
,
10342 AFI_IP
, safi
, json_header
);
10347 if (pathtype
== BGP_PATH_SHOW_ALL
10348 || (pathtype
== BGP_PATH_SHOW_BESTPATH
10349 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
10350 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
10351 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
10352 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
10353 route_vty_out_detail(vty
, bgp
, bgp_node
,
10358 if (json
&& json_paths
) {
10359 json_object_object_add(json_header
, "paths", json_paths
);
10362 json_object_object_add(json
, rdbuf
, json_header
);
10366 /* Display specified route of BGP table. */
10367 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
10368 struct bgp_table
*rib
, const char *ip_str
,
10369 afi_t afi
, safi_t safi
,
10370 struct prefix_rd
*prd
, int prefix_check
,
10371 enum bgp_path_type pathtype
, bool use_json
)
10375 struct prefix match
;
10376 struct bgp_dest
*dest
;
10377 struct bgp_dest
*rm
;
10378 struct bgp_table
*table
;
10379 json_object
*json
= NULL
;
10380 json_object
*json_paths
= NULL
;
10382 /* Check IP address argument. */
10383 ret
= str2prefix(ip_str
, &match
);
10385 vty_out(vty
, "address is malformed\n");
10386 return CMD_WARNING
;
10389 match
.family
= afi2family(afi
);
10392 json
= json_object_new_object();
10394 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
10395 for (dest
= bgp_table_top(rib
); dest
;
10396 dest
= bgp_route_next(dest
)) {
10397 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10399 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
10401 table
= bgp_dest_get_bgp_table_info(dest
);
10405 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10408 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
10410 && rm_p
->prefixlen
!= match
.prefixlen
) {
10411 bgp_dest_unlock_node(rm
);
10415 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
10416 bgp
, afi
, safi
, json
, pathtype
,
10419 bgp_dest_unlock_node(rm
);
10421 } else if (safi
== SAFI_EVPN
) {
10422 struct bgp_dest
*longest_pfx
;
10423 bool is_exact_pfxlen_match
= false;
10425 for (dest
= bgp_table_top(rib
); dest
;
10426 dest
= bgp_route_next(dest
)) {
10427 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10429 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
10431 table
= bgp_dest_get_bgp_table_info(dest
);
10435 longest_pfx
= NULL
;
10436 is_exact_pfxlen_match
= false;
10438 * Search through all the prefixes for a match. The
10439 * pfx's are enumerated in ascending order of pfxlens.
10440 * So, the last pfx match is the longest match. Set
10441 * is_exact_pfxlen_match when we get exact pfxlen match
10443 for (rm
= bgp_table_top(table
); rm
;
10444 rm
= bgp_route_next(rm
)) {
10445 const struct prefix
*rm_p
=
10446 bgp_dest_get_prefix(rm
);
10448 * Get prefixlen of the ip-prefix within type5
10451 if (evpn_type5_prefix_match(rm_p
, &match
)
10455 bgp_evpn_get_type5_prefixlen(
10457 if (type5_pfxlen
== match
.prefixlen
) {
10458 is_exact_pfxlen_match
= true;
10459 bgp_dest_unlock_node(rm
);
10468 if (prefix_check
&& !is_exact_pfxlen_match
)
10472 bgp_dest_lock_node(rm
);
10474 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
10475 bgp
, afi
, safi
, json
, pathtype
,
10478 bgp_dest_unlock_node(rm
);
10480 } else if (safi
== SAFI_FLOWSPEC
) {
10482 json_paths
= json_object_new_array();
10484 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
10485 &match
, prefix_check
,
10489 if (use_json
&& display
)
10490 json_object_object_add(json
, "paths", json_paths
);
10492 if ((dest
= bgp_node_match(rib
, &match
)) != NULL
) {
10493 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10495 || dest_p
->prefixlen
== match
.prefixlen
) {
10496 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
10497 safi
, json
, pathtype
,
10501 bgp_dest_unlock_node(dest
);
10506 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10507 json
, JSON_C_TO_STRING_PRETTY
|
10508 JSON_C_TO_STRING_NOSLASHESCAPE
));
10509 json_object_free(json
);
10512 vty_out(vty
, "%% Network not in table\n");
10513 return CMD_WARNING
;
10517 return CMD_SUCCESS
;
10520 /* Display specified route of Main RIB */
10521 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10522 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10523 int prefix_check
, enum bgp_path_type pathtype
,
10527 bgp
= bgp_get_default();
10530 vty_out(vty
, "No BGP process is configured\n");
10532 vty_out(vty
, "{}\n");
10533 return CMD_WARNING
;
10537 /* labeled-unicast routes live in the unicast table */
10538 if (safi
== SAFI_LABELED_UNICAST
)
10539 safi
= SAFI_UNICAST
;
10541 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10542 afi
, safi
, prd
, prefix_check
, pathtype
,
10546 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10547 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10548 safi_t safi
, bool uj
)
10550 struct lcommunity
*lcom
;
10555 uint8_t show_flags
= 0;
10558 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10560 b
= buffer_new(1024);
10561 for (i
= 0; i
< argc
; i
++) {
10563 buffer_putc(b
, ' ');
10565 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10567 buffer_putstr(b
, argv
[i
]->arg
);
10571 buffer_putc(b
, '\0');
10573 str
= buffer_getstr(b
);
10576 lcom
= lcommunity_str2com(str
);
10577 XFREE(MTYPE_TMP
, str
);
10579 vty_out(vty
, "%% Large-community malformed\n");
10580 return CMD_WARNING
;
10583 return bgp_show(vty
, bgp
, afi
, safi
,
10584 (exact
? bgp_show_type_lcommunity_exact
10585 : bgp_show_type_lcommunity
),
10589 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10590 const char *lcom
, bool exact
, afi_t afi
,
10591 safi_t safi
, bool uj
)
10593 struct community_list
*list
;
10594 uint8_t show_flags
= 0;
10597 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10600 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10601 LARGE_COMMUNITY_LIST_MASTER
);
10602 if (list
== NULL
) {
10603 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10605 return CMD_WARNING
;
10608 return bgp_show(vty
, bgp
, afi
, safi
,
10609 (exact
? bgp_show_type_lcommunity_list_exact
10610 : bgp_show_type_lcommunity_list
),
10614 DEFUN (show_ip_bgp_large_community_list
,
10615 show_ip_bgp_large_community_list_cmd
,
10616 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
10620 BGP_INSTANCE_HELP_STR
10622 BGP_SAFI_WITH_LABEL_HELP_STR
10623 "Display routes matching the large-community-list\n"
10624 "large-community-list number\n"
10625 "large-community-list name\n"
10626 "Exact match of the large-communities\n"
10629 afi_t afi
= AFI_IP6
;
10630 safi_t safi
= SAFI_UNICAST
;
10632 bool exact_match
= 0;
10633 struct bgp
*bgp
= NULL
;
10634 bool uj
= use_json(argc
, argv
);
10639 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10642 return CMD_WARNING
;
10644 argv_find(argv
, argc
, "large-community-list", &idx
);
10646 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10648 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10651 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10652 exact_match
, afi
, safi
, uj
);
10654 DEFUN (show_ip_bgp_large_community
,
10655 show_ip_bgp_large_community_cmd
,
10656 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10660 BGP_INSTANCE_HELP_STR
10662 BGP_SAFI_WITH_LABEL_HELP_STR
10663 "Display routes matching the large-communities\n"
10664 "List of large-community numbers\n"
10665 "Exact match of the large-communities\n"
10668 afi_t afi
= AFI_IP6
;
10669 safi_t safi
= SAFI_UNICAST
;
10671 bool exact_match
= 0;
10672 struct bgp
*bgp
= NULL
;
10673 bool uj
= use_json(argc
, argv
);
10674 uint8_t show_flags
= 0;
10678 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10681 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10684 return CMD_WARNING
;
10686 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10687 if (argv_find(argv
, argc
, "exact-match", &idx
))
10689 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10690 exact_match
, afi
, safi
, uj
);
10692 return bgp_show(vty
, bgp
, afi
, safi
,
10693 bgp_show_type_lcommunity_all
, NULL
, show_flags
);
10696 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10697 safi_t safi
, struct json_object
*json_array
);
10698 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10699 safi_t safi
, struct json_object
*json
);
10702 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
10703 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
10704 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
10705 "Display number of prefixes for all afi/safi\n" JSON_STR
)
10707 bool uj
= use_json(argc
, argv
);
10708 struct bgp
*bgp
= NULL
;
10709 safi_t safi
= SAFI_UNICAST
;
10710 afi_t afi
= AFI_IP6
;
10712 struct json_object
*json_all
= NULL
;
10713 struct json_object
*json_afi_safi
= NULL
;
10715 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10718 return CMD_WARNING
;
10721 json_all
= json_object_new_object();
10723 FOREACH_AFI_SAFI (afi
, safi
) {
10725 * So limit output to those afi/safi pairs that
10726 * actually have something interesting in them
10728 if (strmatch(get_afi_safi_str(afi
, safi
, true),
10733 json_afi_safi
= json_object_new_array();
10734 json_object_object_add(
10736 get_afi_safi_str(afi
, safi
, true),
10739 json_afi_safi
= NULL
;
10742 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10747 json_object_to_json_string_ext(
10748 json_all
, JSON_C_TO_STRING_PRETTY
));
10749 json_object_free(json_all
);
10752 return CMD_SUCCESS
;
10755 /* BGP route print out function without JSON */
10756 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
10757 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
10758 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
10762 BGP_INSTANCE_HELP_STR
10765 "BGP RIB advertisement statistics\n"
10768 afi_t afi
= AFI_IP6
;
10769 safi_t safi
= SAFI_UNICAST
;
10770 struct bgp
*bgp
= NULL
;
10772 bool uj
= use_json(argc
, argv
);
10773 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
10775 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10778 return CMD_WARNING
;
10781 json_afi_safi
= json_object_new_array();
10783 json_afi_safi
= NULL
;
10785 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10788 json
= json_object_new_object();
10789 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
10791 vty_out(vty
, "%s", json_object_to_json_string_ext(
10792 json
, JSON_C_TO_STRING_PRETTY
));
10793 json_object_free(json
);
10798 /* BGP route print out function without JSON */
10799 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
10800 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10801 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10803 statistics [json]",
10804 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10805 BGP_SAFI_WITH_LABEL_HELP_STR
10806 "BGP RIB advertisement statistics\n" JSON_STR
)
10808 afi_t afi
= AFI_IP6
;
10809 safi_t safi
= SAFI_UNICAST
;
10810 struct bgp
*bgp
= NULL
;
10812 bool uj
= use_json(argc
, argv
);
10813 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
10815 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10818 return CMD_WARNING
;
10821 json_afi_safi
= json_object_new_array();
10823 json_afi_safi
= NULL
;
10825 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10828 json
= json_object_new_object();
10829 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
10832 json_object_to_json_string_ext(
10833 json
, JSON_C_TO_STRING_PRETTY
));
10834 json_object_free(json
);
10839 /* BGP route print out function without JSON */
10840 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
10841 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10842 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10844 <[all$all] dampening <parameters>\
10848 |community-list <(1-500)|WORD> [exact-match]\
10849 |A.B.C.D/M longer-prefixes\
10850 |X:X::X:X/M longer-prefixes\
10852 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10853 BGP_SAFI_WITH_LABEL_HELP_STR
10854 "Display the entries for all address families\n"
10855 "Display detailed information about dampening\n"
10856 "Display detail of configured dampening parameters\n"
10857 "Display routes matching the route-map\n"
10858 "A route-map to match on\n"
10859 "Display routes conforming to the prefix-list\n"
10860 "Prefix-list name\n"
10861 "Display routes conforming to the filter-list\n"
10862 "Regular expression access list name\n"
10863 "Display routes matching the community-list\n"
10864 "community-list number\n"
10865 "community-list name\n"
10866 "Exact match of the communities\n"
10868 "Display route and more specific routes\n"
10870 "Display route and more specific routes\n")
10872 afi_t afi
= AFI_IP6
;
10873 safi_t safi
= SAFI_UNICAST
;
10874 int exact_match
= 0;
10875 struct bgp
*bgp
= NULL
;
10877 uint8_t show_flags
= 0;
10879 /* [<ipv4|ipv6> [all]] */
10881 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10882 if (argv_find(argv
, argc
, "ipv4", &idx
))
10883 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
10885 if (argv_find(argv
, argc
, "ipv6", &idx
))
10886 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
10889 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10892 return CMD_WARNING
;
10894 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10895 if (argv_find(argv
, argc
, "parameters", &idx
))
10896 return bgp_show_dampening_parameters(vty
, afi
, safi
,
10900 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10901 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10902 safi
, bgp_show_type_prefix_list
);
10904 if (argv_find(argv
, argc
, "filter-list", &idx
))
10905 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10906 safi
, bgp_show_type_filter_list
);
10908 if (argv_find(argv
, argc
, "route-map", &idx
))
10909 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10910 safi
, bgp_show_type_route_map
);
10912 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10913 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10914 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10916 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10917 exact_match
, afi
, safi
);
10919 /* prefix-longer */
10920 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10921 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10922 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10924 bgp_show_type_prefix_longer
);
10926 return CMD_WARNING
;
10929 /* BGP route print out function with JSON */
10930 DEFPY (show_ip_bgp_json
,
10931 show_ip_bgp_json_cmd
,
10932 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10935 |dampening <flap-statistics|dampened-paths>\
10936 |community [AA:NN|local-AS|no-advertise|no-export\
10937 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10938 |accept-own|accept-own-nexthop|route-filter-v6\
10939 |route-filter-v4|route-filter-translated-v6\
10940 |route-filter-translated-v4] [exact-match]\
10941 ] [json$uj | wide$wide]",
10945 BGP_INSTANCE_HELP_STR
10947 BGP_SAFI_WITH_LABEL_HELP_STR
10948 "Display the entries for all address families\n"
10949 "Display only routes with non-natural netmasks\n"
10950 "Display detailed information about dampening\n"
10951 "Display flap statistics of routes\n"
10952 "Display paths suppressed due to dampening\n"
10953 "Display routes matching the communities\n"
10955 "Do not send outside local AS (well-known community)\n"
10956 "Do not advertise to any peer (well-known community)\n"
10957 "Do not export to next AS (well-known community)\n"
10958 "Graceful shutdown (well-known community)\n"
10959 "Do not export to any peer (well-known community)\n"
10960 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10961 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10962 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10963 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10964 "Should accept VPN route with local nexthop (well-known community)\n"
10965 "RT VPNv6 route filtering (well-known community)\n"
10966 "RT VPNv4 route filtering (well-known community)\n"
10967 "RT translated VPNv6 route filtering (well-known community)\n"
10968 "RT translated VPNv4 route filtering (well-known community)\n"
10969 "Exact match of the communities\n"
10971 "Increase table width for longer prefixes\n")
10973 afi_t afi
= AFI_IP6
;
10974 safi_t safi
= SAFI_UNICAST
;
10975 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10976 struct bgp
*bgp
= NULL
;
10978 int exact_match
= 0;
10979 char *community
= NULL
;
10981 uint8_t show_flags
= 0;
10986 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10989 /* [<ipv4|ipv6> [all]] */
10991 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10993 if (argv_find(argv
, argc
, "ipv4", &idx
))
10994 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
10996 if (argv_find(argv
, argc
, "ipv6", &idx
))
10997 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11001 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11003 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11006 return CMD_WARNING
;
11008 if (argv_find(argv
, argc
, "cidr-only", &idx
))
11009 sh_type
= bgp_show_type_cidr_only
;
11011 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11012 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
11013 sh_type
= bgp_show_type_dampend_paths
;
11014 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11015 sh_type
= bgp_show_type_flap_statistics
;
11018 if (argv_find(argv
, argc
, "community", &idx
)) {
11019 char *maybecomm
= NULL
;
11021 if (idx
+ 1 < argc
) {
11022 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
11023 maybecomm
= argv
[idx
+ 1]->arg
;
11025 maybecomm
= argv
[idx
+ 1]->text
;
11028 if (maybecomm
&& !strmatch(maybecomm
, "json")
11029 && !strmatch(maybecomm
, "exact-match"))
11030 community
= maybecomm
;
11032 if (argv_find(argv
, argc
, "exact-match", &idx
))
11036 sh_type
= bgp_show_type_community_all
;
11040 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
11042 return bgp_show_community(vty
, bgp
, community
,
11043 exact_match
, afi
, safi
,
11046 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
,
11049 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11053 vty_out(vty
, "{\n");
11055 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11056 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
11057 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11060 FOREACH_SAFI (safi
) {
11061 if (strmatch(get_afi_safi_str(afi
, safi
, true),
11065 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11072 vty_out(vty
, ",\n");
11073 vty_out(vty
, "\"%s\":{\n",
11074 get_afi_safi_str(afi
, safi
,
11078 "\nFor address family: %s\n",
11079 get_afi_safi_str(afi
, safi
,
11083 bgp_show_community(vty
, bgp
, community
,
11087 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11090 vty_out(vty
, "}\n");
11093 /* show <ip> bgp all: for each AFI and SAFI*/
11094 FOREACH_AFI_SAFI (afi
, safi
) {
11095 if (strmatch(get_afi_safi_str(afi
, safi
, true),
11099 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11106 vty_out(vty
, ",\n");
11108 vty_out(vty
, "\"%s\":{\n",
11109 get_afi_safi_str(afi
, safi
,
11113 "\nFor address family: %s\n",
11114 get_afi_safi_str(afi
, safi
,
11118 bgp_show_community(vty
, bgp
, community
,
11122 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11125 vty_out(vty
, "}\n");
11129 vty_out(vty
, "}\n");
11131 return CMD_SUCCESS
;
11134 DEFUN (show_ip_bgp_route
,
11135 show_ip_bgp_route_cmd
,
11136 "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>] [json]",
11140 BGP_INSTANCE_HELP_STR
11142 BGP_SAFI_WITH_LABEL_HELP_STR
11143 "Network in the BGP routing table to display\n"
11145 "Network in the BGP routing table to display\n"
11147 "Display only the bestpath\n"
11148 "Display only multipaths\n"
11151 int prefix_check
= 0;
11153 afi_t afi
= AFI_IP6
;
11154 safi_t safi
= SAFI_UNICAST
;
11155 char *prefix
= NULL
;
11156 struct bgp
*bgp
= NULL
;
11157 enum bgp_path_type path_type
;
11158 bool uj
= use_json(argc
, argv
);
11162 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11165 return CMD_WARNING
;
11169 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11170 return CMD_WARNING
;
11173 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11174 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
11175 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
11177 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11178 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11181 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
11182 && afi
!= AFI_IP6
) {
11184 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11185 return CMD_WARNING
;
11187 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
11188 && afi
!= AFI_IP
) {
11190 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11191 return CMD_WARNING
;
11194 prefix
= argv
[idx
]->arg
;
11196 /* [<bestpath|multipath>] */
11197 if (argv_find(argv
, argc
, "bestpath", &idx
))
11198 path_type
= BGP_PATH_SHOW_BESTPATH
;
11199 else if (argv_find(argv
, argc
, "multipath", &idx
))
11200 path_type
= BGP_PATH_SHOW_MULTIPATH
;
11202 path_type
= BGP_PATH_SHOW_ALL
;
11204 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
11208 DEFUN (show_ip_bgp_regexp
,
11209 show_ip_bgp_regexp_cmd
,
11210 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
11214 BGP_INSTANCE_HELP_STR
11216 BGP_SAFI_WITH_LABEL_HELP_STR
11217 "Display routes matching the AS path regular expression\n"
11218 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11221 afi_t afi
= AFI_IP6
;
11222 safi_t safi
= SAFI_UNICAST
;
11223 struct bgp
*bgp
= NULL
;
11224 bool uj
= use_json(argc
, argv
);
11225 char *regstr
= NULL
;
11228 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11231 return CMD_WARNING
;
11233 // get index of regex
11234 if (argv_find(argv
, argc
, "REGEX", &idx
))
11235 regstr
= argv
[idx
]->arg
;
11238 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
11239 bgp_show_type_regexp
, uj
);
11242 DEFPY (show_ip_bgp_instance_all
,
11243 show_ip_bgp_instance_all_cmd
,
11244 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
11248 BGP_INSTANCE_ALL_HELP_STR
11250 BGP_SAFI_WITH_LABEL_HELP_STR
11252 "Increase table width for longer prefixes\n")
11254 afi_t afi
= AFI_IP
;
11255 safi_t safi
= SAFI_UNICAST
;
11256 struct bgp
*bgp
= NULL
;
11258 uint8_t show_flags
= 0;
11262 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11266 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11268 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11271 return CMD_WARNING
;
11273 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
11274 return CMD_SUCCESS
;
11277 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11278 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11283 uint8_t show_flags
= 0;
11286 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11288 if (!config_bgp_aspath_validate(regstr
)) {
11289 vty_out(vty
, "Invalid character in REGEX %s\n",
11291 return CMD_WARNING_CONFIG_FAILED
;
11294 regex
= bgp_regcomp(regstr
);
11296 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
11297 return CMD_WARNING
;
11300 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
);
11301 bgp_regex_free(regex
);
11305 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
11306 const char *prefix_list_str
, afi_t afi
,
11307 safi_t safi
, enum bgp_show_type type
)
11309 struct prefix_list
*plist
;
11310 uint8_t show_flags
= 0;
11312 plist
= prefix_list_lookup(afi
, prefix_list_str
);
11313 if (plist
== NULL
) {
11314 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
11316 return CMD_WARNING
;
11319 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, show_flags
);
11322 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
11323 const char *filter
, afi_t afi
, safi_t safi
,
11324 enum bgp_show_type type
)
11326 struct as_list
*as_list
;
11327 uint8_t show_flags
= 0;
11329 as_list
= as_list_lookup(filter
);
11330 if (as_list
== NULL
) {
11331 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
11333 return CMD_WARNING
;
11336 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, show_flags
);
11339 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
11340 const char *rmap_str
, afi_t afi
, safi_t safi
,
11341 enum bgp_show_type type
)
11343 struct route_map
*rmap
;
11344 uint8_t show_flags
= 0;
11346 rmap
= route_map_lookup_by_name(rmap_str
);
11348 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
11349 return CMD_WARNING
;
11352 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, show_flags
);
11355 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11356 const char *comstr
, int exact
, afi_t afi
,
11357 safi_t safi
, uint8_t show_flags
)
11359 struct community
*com
;
11362 com
= community_str2com(comstr
);
11364 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
11365 return CMD_WARNING
;
11368 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11369 (exact
? bgp_show_type_community_exact
11370 : bgp_show_type_community
),
11372 community_free(&com
);
11377 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
11378 const char *com
, int exact
, afi_t afi
,
11381 struct community_list
*list
;
11382 uint8_t show_flags
= 0;
11384 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
11385 if (list
== NULL
) {
11386 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
11387 return CMD_WARNING
;
11390 return bgp_show(vty
, bgp
, afi
, safi
,
11391 (exact
? bgp_show_type_community_list_exact
11392 : bgp_show_type_community_list
),
11396 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
11397 const char *prefix
, afi_t afi
, safi_t safi
,
11398 enum bgp_show_type type
)
11402 uint8_t show_flags
= 0;
11406 ret
= str2prefix(prefix
, p
);
11408 vty_out(vty
, "%% Malformed Prefix\n");
11409 return CMD_WARNING
;
11412 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, show_flags
);
11418 BGP_STATS_MAXBITLEN
= 0,
11420 BGP_STATS_PREFIXES
,
11422 BGP_STATS_UNAGGREGATEABLE
,
11423 BGP_STATS_MAX_AGGREGATEABLE
,
11424 BGP_STATS_AGGREGATES
,
11426 BGP_STATS_ASPATH_COUNT
,
11427 BGP_STATS_ASPATH_MAXHOPS
,
11428 BGP_STATS_ASPATH_TOTHOPS
,
11429 BGP_STATS_ASPATH_MAXSIZE
,
11430 BGP_STATS_ASPATH_TOTSIZE
,
11431 BGP_STATS_ASN_HIGHEST
,
11435 #define TABLE_STATS_IDX_VTY 0
11436 #define TABLE_STATS_IDX_JSON 1
11438 static const char *table_stats_strs
[][2] = {
11439 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
11440 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
11441 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
11442 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
11443 "unaggregateablePrefixes"},
11444 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
11445 "maximumAggregateablePrefixes"},
11446 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
11447 "bgpAggregateAdvertisements"},
11448 [BGP_STATS_SPACE
] = {"Address space advertised",
11449 "addressSpaceAdvertised"},
11450 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
11451 "advertisementsWithPaths"},
11452 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
11454 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
11456 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
11457 "averageAsPathLengthHops"},
11458 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
11459 "averageAsPathSizeBytes"},
11460 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
11461 [BGP_STATS_MAX
] = {NULL
, NULL
}
11464 struct bgp_table_stats
{
11465 struct bgp_table
*table
;
11466 unsigned long long counts
[BGP_STATS_MAX
];
11467 double total_space
;
11471 #define TALLY_SIGFIG 100000
11472 static unsigned long
11473 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
11475 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
11476 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
11477 unsigned long ret
= newtot
/ count
;
11479 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
11486 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
11487 struct bgp_table_stats
*ts
, unsigned int space
)
11489 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
11490 struct bgp_path_info
*pi
;
11491 const struct prefix
*rn_p
;
11496 if (!bgp_dest_has_bgp_path_info_data(dest
))
11499 rn_p
= bgp_dest_get_prefix(dest
);
11500 ts
->counts
[BGP_STATS_PREFIXES
]++;
11501 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
11504 ts
->counts
[BGP_STATS_AVGPLEN
]
11505 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
11506 ts
->counts
[BGP_STATS_AVGPLEN
],
11510 /* check if the prefix is included by any other announcements */
11511 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
11512 pdest
= bgp_dest_parent_nolock(pdest
);
11514 if (pdest
== NULL
|| pdest
== top
) {
11515 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
11516 /* announced address space */
11518 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
11519 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
11520 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
11523 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11524 ts
->counts
[BGP_STATS_RIB
]++;
11526 if (CHECK_FLAG(pi
->attr
->flag
,
11527 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
11528 ts
->counts
[BGP_STATS_AGGREGATES
]++;
11530 /* as-path stats */
11531 if (pi
->attr
->aspath
) {
11532 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
11533 unsigned int size
= aspath_size(pi
->attr
->aspath
);
11534 as_t highest
= aspath_highest(pi
->attr
->aspath
);
11536 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
11538 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
11539 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
11541 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
11542 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
11544 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
11545 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
11547 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
11548 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11549 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
11551 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
11552 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11553 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
11556 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
11557 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
11562 static int bgp_table_stats_walker(struct thread
*t
)
11564 struct bgp_dest
*dest
, *ndest
;
11565 struct bgp_dest
*top
;
11566 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
11567 unsigned int space
= 0;
11569 if (!(top
= bgp_table_top(ts
->table
)))
11572 switch (ts
->table
->afi
) {
11574 space
= IPV4_MAX_BITLEN
;
11577 space
= IPV6_MAX_BITLEN
;
11583 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
11585 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
11586 if (ts
->table
->safi
== SAFI_MPLS_VPN
11587 || ts
->table
->safi
== SAFI_ENCAP
11588 || ts
->table
->safi
== SAFI_EVPN
) {
11589 struct bgp_table
*table
;
11591 table
= bgp_dest_get_bgp_table_info(dest
);
11595 top
= bgp_table_top(table
);
11596 for (ndest
= bgp_table_top(table
); ndest
;
11597 ndest
= bgp_route_next(ndest
))
11598 bgp_table_stats_rn(ndest
, top
, ts
, space
);
11600 bgp_table_stats_rn(dest
, top
, ts
, space
);
11607 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
11608 struct json_object
*json_array
)
11610 struct listnode
*node
, *nnode
;
11613 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
11614 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
11617 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11618 safi_t safi
, struct json_object
*json_array
)
11620 struct bgp_table_stats ts
;
11622 int ret
= CMD_SUCCESS
;
11624 struct json_object
*json
= NULL
;
11627 json
= json_object_new_object();
11629 if (!bgp
->rib
[afi
][safi
]) {
11630 char warning_msg
[50];
11632 snprintf(warning_msg
, sizeof(warning_msg
),
11633 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
11637 vty_out(vty
, "%s\n", warning_msg
);
11639 json_object_string_add(json
, "warning", warning_msg
);
11642 goto end_table_stats
;
11646 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
11647 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
11649 json_object_string_add(json
, "instance", bgp
->name_pretty
);
11651 /* labeled-unicast routes live in the unicast table */
11652 if (safi
== SAFI_LABELED_UNICAST
)
11653 safi
= SAFI_UNICAST
;
11655 memset(&ts
, 0, sizeof(ts
));
11656 ts
.table
= bgp
->rib
[afi
][safi
];
11657 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
11659 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
11660 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
11661 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
11666 case BGP_STATS_ASPATH_AVGHOPS
:
11667 case BGP_STATS_ASPATH_AVGSIZE
:
11668 case BGP_STATS_AVGPLEN
:
11669 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
11670 vty_out (vty
, "%12.2f",
11671 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
11674 case BGP_STATS_ASPATH_TOTHOPS
:
11675 case BGP_STATS_ASPATH_TOTSIZE
:
11678 temp_buf
, sizeof(temp_buf
), "%12.2f",
11680 ? (float)ts
.counts
[i
]
11682 [BGP_STATS_ASPATH_COUNT
]
11684 vty_out(vty
, "%-30s: %s",
11685 table_stats_strs
[i
]
11686 [TABLE_STATS_IDX_VTY
],
11689 json_object_double_add(
11691 table_stats_strs
[i
]
11692 [TABLE_STATS_IDX_JSON
],
11694 ? (double)ts
.counts
[i
]
11695 / (double)ts
.counts
11696 [BGP_STATS_ASPATH_COUNT
]
11700 case BGP_STATS_TOTPLEN
:
11703 temp_buf
, sizeof(temp_buf
), "%12.2f",
11705 ? (float)ts
.counts
[i
]
11707 [BGP_STATS_PREFIXES
]
11709 vty_out(vty
, "%-30s: %s",
11710 table_stats_strs
[i
]
11711 [TABLE_STATS_IDX_VTY
],
11714 json_object_double_add(
11716 table_stats_strs
[i
]
11717 [TABLE_STATS_IDX_JSON
],
11719 ? (double)ts
.counts
[i
]
11720 / (double)ts
.counts
11721 [BGP_STATS_PREFIXES
]
11725 case BGP_STATS_SPACE
:
11727 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
11729 vty_out(vty
, "%-30s: %s\n",
11730 table_stats_strs
[i
]
11731 [TABLE_STATS_IDX_VTY
],
11734 json_object_double_add(
11736 table_stats_strs
[i
]
11737 [TABLE_STATS_IDX_JSON
],
11738 (double)ts
.total_space
);
11740 if (afi
== AFI_IP6
) {
11742 snprintf(temp_buf
, sizeof(temp_buf
),
11745 * pow(2.0, -128 + 32));
11746 vty_out(vty
, "%30s: %s\n",
11747 "/32 equivalent %s\n",
11750 json_object_double_add(
11751 json
, "/32equivalent",
11752 (double)(ts
.total_space
11757 snprintf(temp_buf
, sizeof(temp_buf
),
11760 * pow(2.0, -128 + 48));
11761 vty_out(vty
, "%30s: %s\n",
11762 "/48 equivalent %s\n",
11765 json_object_double_add(
11766 json
, "/48equivalent",
11767 (double)(ts
.total_space
11773 snprintf(temp_buf
, sizeof(temp_buf
),
11775 ts
.total_space
* 100.
11777 vty_out(vty
, "%30s: %s\n",
11778 "% announced ", temp_buf
);
11780 json_object_double_add(
11781 json
, "%announced",
11782 (double)(ts
.total_space
* 100.
11786 snprintf(temp_buf
, sizeof(temp_buf
),
11789 * pow(2.0, -32 + 8));
11790 vty_out(vty
, "%30s: %s\n",
11791 "/8 equivalent ", temp_buf
);
11793 json_object_double_add(
11794 json
, "/8equivalent",
11795 (double)(ts
.total_space
11796 * pow(2.0, -32 + 8)));
11799 snprintf(temp_buf
, sizeof(temp_buf
),
11802 * pow(2.0, -32 + 24));
11803 vty_out(vty
, "%30s: %s\n",
11804 "/24 equivalent ", temp_buf
);
11806 json_object_double_add(
11807 json
, "/24equivalent",
11808 (double)(ts
.total_space
11809 * pow(2.0, -32 + 24)));
11815 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
11817 vty_out(vty
, "%-30s: %s",
11818 table_stats_strs
[i
]
11819 [TABLE_STATS_IDX_VTY
],
11822 json_object_int_add(
11824 table_stats_strs
[i
]
11825 [TABLE_STATS_IDX_JSON
],
11830 vty_out(vty
, "\n");
11834 json_object_array_add(json_array
, json
);
11838 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11839 safi_t safi
, struct json_object
*json_array
)
11842 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
11843 return CMD_SUCCESS
;
11846 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
11858 PCOUNT_BPATH_SELECTED
,
11859 PCOUNT_PFCNT
, /* the figure we display to users */
11863 static const char *const pcount_strs
[] = {
11864 [PCOUNT_ADJ_IN
] = "Adj-in",
11865 [PCOUNT_DAMPED
] = "Damped",
11866 [PCOUNT_REMOVED
] = "Removed",
11867 [PCOUNT_HISTORY
] = "History",
11868 [PCOUNT_STALE
] = "Stale",
11869 [PCOUNT_VALID
] = "Valid",
11870 [PCOUNT_ALL
] = "All RIB",
11871 [PCOUNT_COUNTED
] = "PfxCt counted",
11872 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
11873 [PCOUNT_PFCNT
] = "Useable",
11874 [PCOUNT_MAX
] = NULL
,
11877 struct peer_pcounts
{
11878 unsigned int count
[PCOUNT_MAX
];
11879 const struct peer
*peer
;
11880 const struct bgp_table
*table
;
11884 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
11886 const struct bgp_adj_in
*ain
;
11887 const struct bgp_path_info
*pi
;
11888 const struct peer
*peer
= pc
->peer
;
11890 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
11891 if (ain
->peer
== peer
)
11892 pc
->count
[PCOUNT_ADJ_IN
]++;
11894 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
11896 if (pi
->peer
!= peer
)
11899 pc
->count
[PCOUNT_ALL
]++;
11901 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
11902 pc
->count
[PCOUNT_DAMPED
]++;
11903 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11904 pc
->count
[PCOUNT_HISTORY
]++;
11905 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
11906 pc
->count
[PCOUNT_REMOVED
]++;
11907 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
11908 pc
->count
[PCOUNT_STALE
]++;
11909 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
11910 pc
->count
[PCOUNT_VALID
]++;
11911 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11912 pc
->count
[PCOUNT_PFCNT
]++;
11913 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11914 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
11916 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
11917 pc
->count
[PCOUNT_COUNTED
]++;
11918 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11920 EC_LIB_DEVELOPMENT
,
11921 "Attempting to count but flags say it is unusable");
11923 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11925 EC_LIB_DEVELOPMENT
,
11926 "Not counted but flags say we should");
11931 static int bgp_peer_count_walker(struct thread
*t
)
11933 struct bgp_dest
*rn
, *rm
;
11934 const struct bgp_table
*table
;
11935 struct peer_pcounts
*pc
= THREAD_ARG(t
);
11937 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
11938 || pc
->safi
== SAFI_EVPN
) {
11939 /* Special handling for 2-level routing tables. */
11940 for (rn
= bgp_table_top(pc
->table
); rn
;
11941 rn
= bgp_route_next(rn
)) {
11942 table
= bgp_dest_get_bgp_table_info(rn
);
11944 for (rm
= bgp_table_top(table
); rm
;
11945 rm
= bgp_route_next(rm
))
11946 bgp_peer_count_proc(rm
, pc
);
11949 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
11950 bgp_peer_count_proc(rn
, pc
);
11955 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11956 safi_t safi
, bool use_json
)
11958 struct peer_pcounts pcounts
= {.peer
= peer
};
11960 json_object
*json
= NULL
;
11961 json_object
*json_loop
= NULL
;
11964 json
= json_object_new_object();
11965 json_loop
= json_object_new_object();
11968 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
11969 || !peer
->bgp
->rib
[afi
][safi
]) {
11971 json_object_string_add(
11973 "No such neighbor or address family");
11974 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11975 json_object_free(json
);
11977 vty_out(vty
, "%% No such neighbor or address family\n");
11979 return CMD_WARNING
;
11982 memset(&pcounts
, 0, sizeof(pcounts
));
11983 pcounts
.peer
= peer
;
11984 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11985 pcounts
.safi
= safi
;
11987 /* in-place call via thread subsystem so as to record execution time
11988 * stats for the thread-walk (i.e. ensure this can't be blamed on
11989 * on just vty_read()).
11991 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11994 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11995 json_object_string_add(json
, "multiProtocol",
11996 get_afi_safi_str(afi
, safi
, true));
11997 json_object_int_add(json
, "pfxCounter",
11998 peer
->pcount
[afi
][safi
]);
12000 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12001 json_object_int_add(json_loop
, pcount_strs
[i
],
12004 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
12006 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12007 json_object_string_add(json
, "pfxctDriftFor",
12009 json_object_string_add(
12010 json
, "recommended",
12011 "Please report this bug, with the above command output");
12013 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
12014 json
, JSON_C_TO_STRING_PRETTY
));
12015 json_object_free(json
);
12019 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
12020 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
12021 peer
->hostname
, peer
->host
,
12022 get_afi_safi_str(afi
, safi
, false));
12024 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
12025 get_afi_safi_str(afi
, safi
, false));
12028 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
12029 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
12031 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12032 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
12035 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12036 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
12038 "Please report this bug, with the above command output\n");
12042 return CMD_SUCCESS
;
12045 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
12046 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
12047 "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]",
12051 BGP_INSTANCE_HELP_STR
12054 "Detailed information on TCP and BGP neighbor connections\n"
12055 "Neighbor to display information about\n"
12056 "Neighbor to display information about\n"
12057 "Neighbor on BGP configured interface\n"
12058 "Display detailed prefix count information\n"
12061 afi_t afi
= AFI_IP6
;
12062 safi_t safi
= SAFI_UNICAST
;
12065 struct bgp
*bgp
= NULL
;
12066 bool uj
= use_json(argc
, argv
);
12071 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12074 return CMD_WARNING
;
12076 argv_find(argv
, argc
, "neighbors", &idx
);
12077 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
12079 return CMD_WARNING
;
12081 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
12084 #ifdef KEEP_OLD_VPN_COMMANDS
12085 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
12086 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
12087 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12092 "Display information about all VPNv4 NLRIs\n"
12093 "Detailed information on TCP and BGP neighbor connections\n"
12094 "Neighbor to display information about\n"
12095 "Neighbor to display information about\n"
12096 "Neighbor on BGP configured interface\n"
12097 "Display detailed prefix count information\n"
12102 bool uj
= use_json(argc
, argv
);
12104 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
12106 return CMD_WARNING
;
12108 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
12111 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
12112 show_ip_bgp_vpn_all_route_prefix_cmd
,
12113 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
12118 "Display information about all VPNv4 NLRIs\n"
12119 "Network in the BGP routing table to display\n"
12120 "Network in the BGP routing table to display\n"
12124 char *network
= NULL
;
12125 struct bgp
*bgp
= bgp_get_default();
12127 vty_out(vty
, "Can't find default instance\n");
12128 return CMD_WARNING
;
12131 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
12132 network
= argv
[idx
]->arg
;
12133 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
12134 network
= argv
[idx
]->arg
;
12136 vty_out(vty
, "Unable to figure out Network\n");
12137 return CMD_WARNING
;
12140 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
12141 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12143 #endif /* KEEP_OLD_VPN_COMMANDS */
12145 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
12146 show_bgp_l2vpn_evpn_route_prefix_cmd
,
12147 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
12152 "Network in the BGP routing table to display\n"
12153 "Network in the BGP routing table to display\n"
12154 "Network in the BGP routing table to display\n"
12155 "Network in the BGP routing table to display\n"
12159 char *network
= NULL
;
12160 int prefix_check
= 0;
12162 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
12163 argv_find(argv
, argc
, "X:X::X:X", &idx
))
12164 network
= argv
[idx
]->arg
;
12165 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
12166 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12167 network
= argv
[idx
]->arg
;
12170 vty_out(vty
, "Unable to figure out Network\n");
12171 return CMD_WARNING
;
12173 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
12174 prefix_check
, BGP_PATH_SHOW_ALL
,
12175 use_json(argc
, argv
));
12178 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
12179 struct bgp_table
*table
, int *header1
,
12180 int *header2
, json_object
*json
,
12181 json_object
*json_scode
,
12182 json_object
*json_ocode
, bool wide
)
12184 uint64_t version
= table
? table
->version
: 0;
12188 json_object_int_add(json
, "bgpTableVersion", version
);
12189 json_object_string_add(json
, "bgpLocalRouterId",
12190 inet_ntoa(bgp
->router_id
));
12191 json_object_int_add(json
, "defaultLocPrf",
12192 bgp
->default_local_pref
);
12193 json_object_int_add(json
, "localAS", bgp
->as
);
12194 json_object_object_add(json
, "bgpStatusCodes",
12196 json_object_object_add(json
, "bgpOriginCodes",
12200 "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
12201 version
, inet_ntoa(bgp
->router_id
));
12202 if (bgp
->vrf_id
== VRF_UNKNOWN
)
12203 vty_out(vty
, "%s", VRFID_NONE_STR
);
12205 vty_out(vty
, "%u", bgp
->vrf_id
);
12206 vty_out(vty
, "\n");
12207 vty_out(vty
, "Default local pref %u, ",
12208 bgp
->default_local_pref
);
12209 vty_out(vty
, "local AS %u\n", bgp
->as
);
12210 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
12211 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
12212 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
12218 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
12219 : BGP_SHOW_HEADER
));
12224 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12225 safi_t safi
, enum bgp_show_adj_route_type type
,
12226 const char *rmap_name
, json_object
*json
,
12227 uint8_t show_flags
)
12229 struct bgp_table
*table
;
12230 struct bgp_adj_in
*ain
;
12231 struct bgp_adj_out
*adj
;
12232 unsigned long output_count
= 0;
12233 unsigned long filtered_count
= 0;
12234 struct bgp_dest
*dest
;
12240 struct update_subgroup
*subgrp
;
12241 json_object
*json_scode
= NULL
;
12242 json_object
*json_ocode
= NULL
;
12243 json_object
*json_ar
= NULL
;
12244 struct peer_af
*paf
;
12245 bool route_filtered
;
12246 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12247 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12250 json_scode
= json_object_new_object();
12251 json_ocode
= json_object_new_object();
12252 json_ar
= json_object_new_object();
12254 json_object_string_add(json_scode
, "suppressed", "s");
12255 json_object_string_add(json_scode
, "damped", "d");
12256 json_object_string_add(json_scode
, "history", "h");
12257 json_object_string_add(json_scode
, "valid", "*");
12258 json_object_string_add(json_scode
, "best", ">");
12259 json_object_string_add(json_scode
, "multipath", "=");
12260 json_object_string_add(json_scode
, "internal", "i");
12261 json_object_string_add(json_scode
, "ribFailure", "r");
12262 json_object_string_add(json_scode
, "stale", "S");
12263 json_object_string_add(json_scode
, "removed", "R");
12265 json_object_string_add(json_ocode
, "igp", "i");
12266 json_object_string_add(json_ocode
, "egp", "e");
12267 json_object_string_add(json_ocode
, "incomplete", "?");
12274 json_object_string_add(json
, "alert", "no BGP");
12275 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12276 json_object_free(json
);
12278 vty_out(vty
, "%% No bgp\n");
12282 /* labeled-unicast routes live in the unicast table */
12283 if (safi
== SAFI_LABELED_UNICAST
)
12284 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
12286 table
= bgp
->rib
[afi
][safi
];
12288 output_count
= filtered_count
= 0;
12289 subgrp
= peer_subgroup(peer
, afi
, safi
);
12291 if (type
== bgp_show_adj_route_advertised
&& subgrp
12292 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
12294 json_object_int_add(json
, "bgpTableVersion",
12296 json_object_string_add(json
, "bgpLocalRouterId",
12297 inet_ntoa(bgp
->router_id
));
12298 json_object_int_add(json
, "defaultLocPrf",
12299 bgp
->default_local_pref
);
12300 json_object_int_add(json
, "localAS", bgp
->as
);
12301 json_object_object_add(json
, "bgpStatusCodes",
12303 json_object_object_add(json
, "bgpOriginCodes",
12305 json_object_string_add(
12306 json
, "bgpOriginatingDefaultNetwork",
12307 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
12309 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
12310 table
->version
, inet_ntoa(bgp
->router_id
));
12311 if (bgp
->vrf_id
== VRF_UNKNOWN
)
12312 vty_out(vty
, "%s", VRFID_NONE_STR
);
12314 vty_out(vty
, "%u", bgp
->vrf_id
);
12315 vty_out(vty
, "\n");
12316 vty_out(vty
, "Default local pref %u, ",
12317 bgp
->default_local_pref
);
12318 vty_out(vty
, "local AS %u\n", bgp
->as
);
12319 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
12320 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
12321 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
12323 vty_out(vty
, "Originating default network %s\n\n",
12324 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
12329 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
12330 if (type
== bgp_show_adj_route_received
12331 || type
== bgp_show_adj_route_filtered
) {
12332 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
12333 if (ain
->peer
!= peer
)
12336 show_adj_route_header(
12337 vty
, bgp
, table
, &header1
, &header2
,
12338 json
, json_scode
, json_ocode
, wide
);
12341 route_filtered
= false;
12343 /* Filter prefix using distribute list,
12344 * filter list or prefix list
12346 const struct prefix
*rn_p
=
12347 bgp_dest_get_prefix(dest
);
12348 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
12351 route_filtered
= true;
12353 /* Filter prefix using route-map */
12354 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
12355 safi
, rmap_name
, NULL
,
12358 if (type
== bgp_show_adj_route_filtered
&&
12359 !route_filtered
&& ret
!= RMAP_DENY
) {
12360 bgp_attr_undup(&attr
, ain
->attr
);
12364 if (type
== bgp_show_adj_route_received
&&
12365 (route_filtered
|| ret
== RMAP_DENY
))
12368 route_vty_out_tmp(vty
, rn_p
, &attr
, safi
,
12369 use_json
, json_ar
, wide
);
12370 bgp_attr_undup(&attr
, ain
->attr
);
12373 } else if (type
== bgp_show_adj_route_advertised
) {
12374 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
12375 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
12376 if (paf
->peer
!= peer
|| !adj
->attr
)
12379 show_adj_route_header(
12380 vty
, bgp
, table
, &header1
,
12381 &header2
, json
, json_scode
,
12384 const struct prefix
*rn_p
=
12385 bgp_dest_get_prefix(dest
);
12388 ret
= bgp_output_modifier(
12389 peer
, rn_p
, &attr
, afi
, safi
,
12392 if (ret
!= RMAP_DENY
) {
12394 vty
, rn_p
, &attr
, safi
,
12402 bgp_attr_undup(&attr
, adj
->attr
);
12404 } else if (type
== bgp_show_adj_route_bestpath
) {
12405 struct bgp_path_info
*pi
;
12407 show_adj_route_header(vty
, bgp
, table
, &header1
,
12408 &header2
, json
, json_scode
,
12411 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
12413 if (pi
->peer
!= peer
)
12416 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12419 route_vty_out_tmp(vty
,
12420 bgp_dest_get_prefix(dest
),
12421 pi
->attr
, safi
, use_json
,
12429 json_object_object_add(json
, "advertisedRoutes", json_ar
);
12430 json_object_int_add(json
, "totalPrefixCounter", output_count
);
12431 json_object_int_add(json
, "filteredPrefixCounter",
12434 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
12435 json
, JSON_C_TO_STRING_PRETTY
));
12437 if (!output_count
&& !filtered_count
) {
12438 json_object_free(json_scode
);
12439 json_object_free(json_ocode
);
12442 json_object_free(json
);
12443 } else if (output_count
> 0) {
12444 if (filtered_count
> 0)
12446 "\nTotal number of prefixes %ld (%ld filtered)\n",
12447 output_count
, filtered_count
);
12449 vty_out(vty
, "\nTotal number of prefixes %ld\n",
12454 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12455 safi_t safi
, enum bgp_show_adj_route_type type
,
12456 const char *rmap_name
, uint8_t show_flags
)
12458 json_object
*json
= NULL
;
12459 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12462 json
= json_object_new_object();
12464 if (!peer
|| !peer
->afc
[afi
][safi
]) {
12466 json_object_string_add(
12468 "No such neighbor or address family");
12469 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12470 json_object_free(json
);
12472 vty_out(vty
, "%% No such neighbor or address family\n");
12474 return CMD_WARNING
;
12477 if ((type
== bgp_show_adj_route_received
12478 || type
== bgp_show_adj_route_filtered
)
12479 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
12480 PEER_FLAG_SOFT_RECONFIG
)) {
12482 json_object_string_add(
12484 "Inbound soft reconfiguration not enabled");
12485 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12486 json_object_free(json
);
12489 "%% Inbound soft reconfiguration not enabled\n");
12491 return CMD_WARNING
;
12494 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, json
, show_flags
);
12496 return CMD_SUCCESS
;
12499 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
12500 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
12501 "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]",
12505 BGP_INSTANCE_HELP_STR
12507 BGP_SAFI_WITH_LABEL_HELP_STR
12508 "Detailed information on TCP and BGP neighbor connections\n"
12509 "Neighbor to display information about\n"
12510 "Neighbor to display information about\n"
12511 "Neighbor on BGP configured interface\n"
12512 "Display the routes selected by best path\n"
12514 "Increase table width for longer prefixes\n")
12516 afi_t afi
= AFI_IP6
;
12517 safi_t safi
= SAFI_UNICAST
;
12518 char *rmap_name
= NULL
;
12519 char *peerstr
= NULL
;
12520 struct bgp
*bgp
= NULL
;
12522 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
12524 uint8_t show_flags
= 0;
12527 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12530 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12532 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12536 return CMD_WARNING
;
12538 argv_find(argv
, argc
, "neighbors", &idx
);
12539 peerstr
= argv
[++idx
]->arg
;
12541 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12543 return CMD_WARNING
;
12545 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
12549 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
12550 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
12551 "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 WORD] [json$uj | wide$wide]",
12555 BGP_INSTANCE_HELP_STR
12557 BGP_SAFI_WITH_LABEL_HELP_STR
12558 "Display the entries for all address families\n"
12559 "Detailed information on TCP and BGP neighbor connections\n"
12560 "Neighbor to display information about\n"
12561 "Neighbor to display information about\n"
12562 "Neighbor on BGP configured interface\n"
12563 "Display the routes advertised to a BGP neighbor\n"
12564 "Display the received routes from neighbor\n"
12565 "Display the filtered routes received from neighbor\n"
12566 "Route-map to modify the attributes\n"
12567 "Name of the route map\n"
12569 "Increase table width for longer prefixes\n")
12571 afi_t afi
= AFI_IP6
;
12572 safi_t safi
= SAFI_UNICAST
;
12573 char *rmap_name
= NULL
;
12574 char *peerstr
= NULL
;
12575 struct bgp
*bgp
= NULL
;
12577 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
12580 uint8_t show_flags
= 0;
12584 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12588 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12589 if (argv_find(argv
, argc
, "ipv4", &idx
))
12590 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12592 if (argv_find(argv
, argc
, "ipv6", &idx
))
12593 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12597 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12599 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12602 return CMD_WARNING
;
12604 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12605 argv_find(argv
, argc
, "neighbors", &idx
);
12606 peerstr
= argv
[++idx
]->arg
;
12608 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12610 return CMD_WARNING
;
12612 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
12613 type
= bgp_show_adj_route_advertised
;
12614 else if (argv_find(argv
, argc
, "received-routes", &idx
))
12615 type
= bgp_show_adj_route_received
;
12616 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
12617 type
= bgp_show_adj_route_filtered
;
12619 if (argv_find(argv
, argc
, "route-map", &idx
))
12620 rmap_name
= argv
[++idx
]->arg
;
12623 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
12626 vty_out(vty
, "{\n");
12628 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12629 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12630 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
12632 FOREACH_SAFI (safi
) {
12633 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12637 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12644 vty_out(vty
, ",\n");
12645 vty_out(vty
, "\"%s\":",
12646 get_afi_safi_str(afi
, safi
, true));
12648 vty_out(vty
, "\nFor address family: %s\n",
12649 get_afi_safi_str(afi
, safi
, false));
12651 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
12655 FOREACH_AFI_SAFI (afi
, safi
) {
12656 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12660 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12667 vty_out(vty
, ",\n");
12668 vty_out(vty
, "\"%s\":",
12669 get_afi_safi_str(afi
, safi
, true));
12671 vty_out(vty
, "\nFor address family: %s\n",
12672 get_afi_safi_str(afi
, safi
, false));
12674 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
12679 vty_out(vty
, "}\n");
12681 return CMD_SUCCESS
;
12684 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
12685 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
12686 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
12692 "Address Family modifier\n"
12693 "Detailed information on TCP and BGP neighbor connections\n"
12694 "Neighbor to display information about\n"
12695 "Neighbor to display information about\n"
12696 "Neighbor on BGP configured interface\n"
12697 "Display information received from a BGP neighbor\n"
12698 "Display the prefixlist filter\n"
12701 afi_t afi
= AFI_IP6
;
12702 safi_t safi
= SAFI_UNICAST
;
12703 char *peerstr
= NULL
;
12706 union sockunion su
;
12712 /* show [ip] bgp */
12713 if (argv_find(argv
, argc
, "ip", &idx
))
12715 /* [<ipv4|ipv6> [unicast]] */
12716 if (argv_find(argv
, argc
, "ipv4", &idx
))
12718 if (argv_find(argv
, argc
, "ipv6", &idx
))
12720 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12721 argv_find(argv
, argc
, "neighbors", &idx
);
12722 peerstr
= argv
[++idx
]->arg
;
12724 bool uj
= use_json(argc
, argv
);
12726 ret
= str2sockunion(peerstr
, &su
);
12728 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
12731 vty_out(vty
, "{}\n");
12734 "%% Malformed address or name: %s\n",
12736 return CMD_WARNING
;
12739 peer
= peer_lookup(NULL
, &su
);
12742 vty_out(vty
, "{}\n");
12744 vty_out(vty
, "No peer\n");
12745 return CMD_WARNING
;
12749 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
12750 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
12753 vty_out(vty
, "Address Family: %s\n",
12754 get_afi_safi_str(afi
, safi
, false));
12755 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
12758 vty_out(vty
, "{}\n");
12760 vty_out(vty
, "No functional output\n");
12763 return CMD_SUCCESS
;
12766 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
12767 afi_t afi
, safi_t safi
,
12768 enum bgp_show_type type
, bool use_json
)
12770 uint8_t show_flags
= 0;
12773 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12775 /* labeled-unicast routes live in the unicast table */
12776 if (safi
== SAFI_LABELED_UNICAST
)
12777 safi
= SAFI_UNICAST
;
12779 if (!peer
|| !peer
->afc
[afi
][safi
]) {
12781 json_object
*json_no
= NULL
;
12782 json_no
= json_object_new_object();
12783 json_object_string_add(
12784 json_no
, "warning",
12785 "No such neighbor or address family");
12786 vty_out(vty
, "%s\n",
12787 json_object_to_json_string(json_no
));
12788 json_object_free(json_no
);
12790 vty_out(vty
, "%% No such neighbor or address family\n");
12791 return CMD_WARNING
;
12794 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
);
12797 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
12798 show_ip_bgp_flowspec_routes_detailed_cmd
,
12799 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
12803 BGP_INSTANCE_HELP_STR
12806 "Detailed information on flowspec entries\n"
12809 afi_t afi
= AFI_IP
;
12810 safi_t safi
= SAFI_UNICAST
;
12811 struct bgp
*bgp
= NULL
;
12813 bool uj
= use_json(argc
, argv
);
12814 uint8_t show_flags
= 0;
12818 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12821 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12824 return CMD_WARNING
;
12826 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
12830 DEFUN (show_ip_bgp_neighbor_routes
,
12831 show_ip_bgp_neighbor_routes_cmd
,
12832 "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]",
12836 BGP_INSTANCE_HELP_STR
12838 BGP_SAFI_WITH_LABEL_HELP_STR
12839 "Detailed information on TCP and BGP neighbor connections\n"
12840 "Neighbor to display information about\n"
12841 "Neighbor to display information about\n"
12842 "Neighbor on BGP configured interface\n"
12843 "Display flap statistics of the routes learned from neighbor\n"
12844 "Display the dampened routes received from neighbor\n"
12845 "Display routes learned from neighbor\n"
12848 char *peerstr
= NULL
;
12849 struct bgp
*bgp
= NULL
;
12850 afi_t afi
= AFI_IP6
;
12851 safi_t safi
= SAFI_UNICAST
;
12853 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
12855 bool uj
= use_json(argc
, argv
);
12860 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12863 return CMD_WARNING
;
12865 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12866 argv_find(argv
, argc
, "neighbors", &idx
);
12867 peerstr
= argv
[++idx
]->arg
;
12869 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12871 return CMD_WARNING
;
12873 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12874 sh_type
= bgp_show_type_flap_neighbor
;
12875 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
12876 sh_type
= bgp_show_type_damp_neighbor
;
12877 else if (argv_find(argv
, argc
, "routes", &idx
))
12878 sh_type
= bgp_show_type_neighbor
;
12880 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
12883 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
12885 struct bgp_distance
{
12886 /* Distance value for the IP source prefix. */
12889 /* Name of the access-list to be matched. */
12893 DEFUN (show_bgp_afi_vpn_rd_route
,
12894 show_bgp_afi_vpn_rd_route_cmd
,
12895 "show bgp "BGP_AFI_CMD_STR
" vpn rd ASN:NN_OR_IP-ADDRESS:NN <A.B.C.D/M|X:X::X:X/M> [json]",
12899 "Address Family modifier\n"
12900 "Display information for a route distinguisher\n"
12901 "Route Distinguisher\n"
12902 "Network in the BGP routing table to display\n"
12903 "Network in the BGP routing table to display\n"
12907 struct prefix_rd prd
;
12908 afi_t afi
= AFI_MAX
;
12911 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
12912 vty_out(vty
, "%% Malformed Address Family\n");
12913 return CMD_WARNING
;
12916 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
12918 vty_out(vty
, "%% Malformed Route Distinguisher\n");
12919 return CMD_WARNING
;
12922 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
12923 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12926 static struct bgp_distance
*bgp_distance_new(void)
12928 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
12931 static void bgp_distance_free(struct bgp_distance
*bdistance
)
12933 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
12936 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
12937 const char *ip_str
, const char *access_list_str
)
12944 struct bgp_dest
*dest
;
12945 struct bgp_distance
*bdistance
;
12947 afi
= bgp_node_afi(vty
);
12948 safi
= bgp_node_safi(vty
);
12950 ret
= str2prefix(ip_str
, &p
);
12952 vty_out(vty
, "Malformed prefix\n");
12953 return CMD_WARNING_CONFIG_FAILED
;
12956 distance
= atoi(distance_str
);
12958 /* Get BGP distance node. */
12959 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
12960 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
12962 bgp_dest_unlock_node(dest
);
12964 bdistance
= bgp_distance_new();
12965 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
12968 /* Set distance value. */
12969 bdistance
->distance
= distance
;
12971 /* Reset access-list configuration. */
12972 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12973 if (access_list_str
)
12974 bdistance
->access_list
=
12975 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
12977 return CMD_SUCCESS
;
12980 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
12981 const char *ip_str
, const char *access_list_str
)
12988 struct bgp_dest
*dest
;
12989 struct bgp_distance
*bdistance
;
12991 afi
= bgp_node_afi(vty
);
12992 safi
= bgp_node_safi(vty
);
12994 ret
= str2prefix(ip_str
, &p
);
12996 vty_out(vty
, "Malformed prefix\n");
12997 return CMD_WARNING_CONFIG_FAILED
;
13000 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
13002 vty_out(vty
, "Can't find specified prefix\n");
13003 return CMD_WARNING_CONFIG_FAILED
;
13006 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13007 distance
= atoi(distance_str
);
13009 if (bdistance
->distance
!= distance
) {
13010 vty_out(vty
, "Distance does not match configured\n");
13011 return CMD_WARNING_CONFIG_FAILED
;
13014 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13015 bgp_distance_free(bdistance
);
13017 bgp_dest_set_bgp_path_info(dest
, NULL
);
13018 bgp_dest_unlock_node(dest
);
13019 bgp_dest_unlock_node(dest
);
13021 return CMD_SUCCESS
;
13024 /* Apply BGP information to distance method. */
13025 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
13026 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
13028 struct bgp_dest
*dest
;
13031 struct bgp_distance
*bdistance
;
13032 struct access_list
*alist
;
13033 struct bgp_static
*bgp_static
;
13038 peer
= pinfo
->peer
;
13040 if (pinfo
->attr
->distance
)
13041 return pinfo
->attr
->distance
;
13043 /* Check source address. */
13044 sockunion2hostprefix(&peer
->su
, &q
);
13045 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
13047 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13048 bgp_dest_unlock_node(dest
);
13050 if (bdistance
->access_list
) {
13051 alist
= access_list_lookup(afi
, bdistance
->access_list
);
13053 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
13054 return bdistance
->distance
;
13056 return bdistance
->distance
;
13059 /* Backdoor check. */
13060 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
13062 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13063 bgp_dest_unlock_node(dest
);
13065 if (bgp_static
->backdoor
) {
13066 if (bgp
->distance_local
[afi
][safi
])
13067 return bgp
->distance_local
[afi
][safi
];
13069 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13073 if (peer
->sort
== BGP_PEER_EBGP
) {
13074 if (bgp
->distance_ebgp
[afi
][safi
])
13075 return bgp
->distance_ebgp
[afi
][safi
];
13076 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
13078 if (bgp
->distance_ibgp
[afi
][safi
])
13079 return bgp
->distance_ibgp
[afi
][safi
];
13080 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13084 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13085 * we should tell ZEBRA update the routes for a specific
13086 * AFI/SAFI to reflect changes in RIB.
13088 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
13090 safi_t update_safi
)
13095 FOREACH_AFI_SAFI (afi
, safi
) {
13096 if (!bgp_fibupd_safi(safi
))
13099 if (afi
!= update_afi
&& safi
!= update_safi
)
13102 if (BGP_DEBUG(zebra
, ZEBRA
))
13104 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13105 __func__
, afi
, safi
);
13106 bgp_zebra_announce_table(bgp
, afi
, safi
);
13110 DEFUN (bgp_distance
,
13112 "distance bgp (1-255) (1-255) (1-255)",
13113 "Define an administrative distance\n"
13115 "Distance for routes external to the AS\n"
13116 "Distance for routes internal to the AS\n"
13117 "Distance for local routes\n")
13119 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13120 int idx_number
= 2;
13121 int idx_number_2
= 3;
13122 int idx_number_3
= 4;
13123 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
13124 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
13125 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
13129 afi
= bgp_node_afi(vty
);
13130 safi
= bgp_node_safi(vty
);
13132 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
13133 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
13134 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
13135 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
13136 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
13137 bgp
->distance_local
[afi
][safi
] = distance_local
;
13138 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
13140 return CMD_SUCCESS
;
13143 DEFUN (no_bgp_distance
,
13144 no_bgp_distance_cmd
,
13145 "no distance bgp [(1-255) (1-255) (1-255)]",
13147 "Define an administrative distance\n"
13149 "Distance for routes external to the AS\n"
13150 "Distance for routes internal to the AS\n"
13151 "Distance for local routes\n")
13153 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13157 afi
= bgp_node_afi(vty
);
13158 safi
= bgp_node_safi(vty
);
13160 if (bgp
->distance_ebgp
[afi
][safi
] != 0
13161 || bgp
->distance_ibgp
[afi
][safi
] != 0
13162 || bgp
->distance_local
[afi
][safi
] != 0) {
13163 bgp
->distance_ebgp
[afi
][safi
] = 0;
13164 bgp
->distance_ibgp
[afi
][safi
] = 0;
13165 bgp
->distance_local
[afi
][safi
] = 0;
13166 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
13168 return CMD_SUCCESS
;
13172 DEFUN (bgp_distance_source
,
13173 bgp_distance_source_cmd
,
13174 "distance (1-255) A.B.C.D/M",
13175 "Define an administrative distance\n"
13176 "Administrative distance\n"
13177 "IP source prefix\n")
13179 int idx_number
= 1;
13180 int idx_ipv4_prefixlen
= 2;
13181 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
13182 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
13183 return CMD_SUCCESS
;
13186 DEFUN (no_bgp_distance_source
,
13187 no_bgp_distance_source_cmd
,
13188 "no distance (1-255) A.B.C.D/M",
13190 "Define an administrative distance\n"
13191 "Administrative distance\n"
13192 "IP source prefix\n")
13194 int idx_number
= 2;
13195 int idx_ipv4_prefixlen
= 3;
13196 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
13197 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
13198 return CMD_SUCCESS
;
13201 DEFUN (bgp_distance_source_access_list
,
13202 bgp_distance_source_access_list_cmd
,
13203 "distance (1-255) A.B.C.D/M WORD",
13204 "Define an administrative distance\n"
13205 "Administrative distance\n"
13206 "IP source prefix\n"
13207 "Access list name\n")
13209 int idx_number
= 1;
13210 int idx_ipv4_prefixlen
= 2;
13212 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
13213 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
13214 return CMD_SUCCESS
;
13217 DEFUN (no_bgp_distance_source_access_list
,
13218 no_bgp_distance_source_access_list_cmd
,
13219 "no distance (1-255) A.B.C.D/M WORD",
13221 "Define an administrative distance\n"
13222 "Administrative distance\n"
13223 "IP source prefix\n"
13224 "Access list name\n")
13226 int idx_number
= 2;
13227 int idx_ipv4_prefixlen
= 3;
13229 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
13230 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
13231 return CMD_SUCCESS
;
13234 DEFUN (ipv6_bgp_distance_source
,
13235 ipv6_bgp_distance_source_cmd
,
13236 "distance (1-255) X:X::X:X/M",
13237 "Define an administrative distance\n"
13238 "Administrative distance\n"
13239 "IP source prefix\n")
13241 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
13242 return CMD_SUCCESS
;
13245 DEFUN (no_ipv6_bgp_distance_source
,
13246 no_ipv6_bgp_distance_source_cmd
,
13247 "no distance (1-255) X:X::X:X/M",
13249 "Define an administrative distance\n"
13250 "Administrative distance\n"
13251 "IP source prefix\n")
13253 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
13254 return CMD_SUCCESS
;
13257 DEFUN (ipv6_bgp_distance_source_access_list
,
13258 ipv6_bgp_distance_source_access_list_cmd
,
13259 "distance (1-255) X:X::X:X/M WORD",
13260 "Define an administrative distance\n"
13261 "Administrative distance\n"
13262 "IP source prefix\n"
13263 "Access list name\n")
13265 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
13266 return CMD_SUCCESS
;
13269 DEFUN (no_ipv6_bgp_distance_source_access_list
,
13270 no_ipv6_bgp_distance_source_access_list_cmd
,
13271 "no distance (1-255) X:X::X:X/M WORD",
13273 "Define an administrative distance\n"
13274 "Administrative distance\n"
13275 "IP source prefix\n"
13276 "Access list name\n")
13278 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
13279 return CMD_SUCCESS
;
13282 DEFUN (bgp_damp_set
,
13284 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
13285 "BGP Specific commands\n"
13286 "Enable route-flap dampening\n"
13287 "Half-life time for the penalty\n"
13288 "Value to start reusing a route\n"
13289 "Value to start suppressing a route\n"
13290 "Maximum duration to suppress a stable route\n")
13292 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13293 int idx_half_life
= 2;
13295 int idx_suppress
= 4;
13296 int idx_max_suppress
= 5;
13297 int half
= DEFAULT_HALF_LIFE
* 60;
13298 int reuse
= DEFAULT_REUSE
;
13299 int suppress
= DEFAULT_SUPPRESS
;
13300 int max
= 4 * half
;
13303 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
13304 reuse
= atoi(argv
[idx_reuse
]->arg
);
13305 suppress
= atoi(argv
[idx_suppress
]->arg
);
13306 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
13307 } else if (argc
== 3) {
13308 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
13313 * These can't be 0 but our SA doesn't understand the
13314 * way our cli is constructed
13318 if (suppress
< reuse
) {
13320 "Suppress value cannot be less than reuse value \n");
13324 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
13325 reuse
, suppress
, max
);
13328 DEFUN (bgp_damp_unset
,
13329 bgp_damp_unset_cmd
,
13330 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
13332 "BGP Specific commands\n"
13333 "Enable route-flap dampening\n"
13334 "Half-life time for the penalty\n"
13335 "Value to start reusing a route\n"
13336 "Value to start suppressing a route\n"
13337 "Maximum duration to suppress a stable route\n")
13339 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13340 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
13343 /* Display specified route of BGP table. */
13344 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
13345 const char *ip_str
, afi_t afi
, safi_t safi
,
13346 struct prefix_rd
*prd
, int prefix_check
)
13349 struct prefix match
;
13350 struct bgp_dest
*dest
;
13351 struct bgp_dest
*rm
;
13352 struct bgp_path_info
*pi
;
13353 struct bgp_path_info
*pi_temp
;
13355 struct bgp_table
*table
;
13357 /* BGP structure lookup. */
13359 bgp
= bgp_lookup_by_name(view_name
);
13361 vty_out(vty
, "%% Can't find BGP instance %s\n",
13363 return CMD_WARNING
;
13366 bgp
= bgp_get_default();
13368 vty_out(vty
, "%% No BGP process is configured\n");
13369 return CMD_WARNING
;
13373 /* Check IP address argument. */
13374 ret
= str2prefix(ip_str
, &match
);
13376 vty_out(vty
, "%% address is malformed\n");
13377 return CMD_WARNING
;
13380 match
.family
= afi2family(afi
);
13382 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13383 || (safi
== SAFI_EVPN
)) {
13384 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
13385 dest
= bgp_route_next(dest
)) {
13386 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
13388 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
13390 table
= bgp_dest_get_bgp_table_info(dest
);
13393 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
13396 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
13399 || rm_p
->prefixlen
== match
.prefixlen
) {
13400 pi
= bgp_dest_get_bgp_path_info(rm
);
13402 if (pi
->extra
&& pi
->extra
->damp_info
) {
13403 pi_temp
= pi
->next
;
13404 bgp_damp_info_free(
13405 pi
->extra
->damp_info
,
13413 bgp_dest_unlock_node(rm
);
13416 if ((dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
13418 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
13421 || dest_p
->prefixlen
== match
.prefixlen
) {
13422 pi
= bgp_dest_get_bgp_path_info(dest
);
13424 if (pi
->extra
&& pi
->extra
->damp_info
) {
13425 pi_temp
= pi
->next
;
13426 bgp_damp_info_free(
13427 pi
->extra
->damp_info
,
13435 bgp_dest_unlock_node(dest
);
13439 return CMD_SUCCESS
;
13442 DEFUN (clear_ip_bgp_dampening
,
13443 clear_ip_bgp_dampening_cmd
,
13444 "clear ip bgp dampening",
13448 "Clear route flap dampening information\n")
13450 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
13451 return CMD_SUCCESS
;
13454 DEFUN (clear_ip_bgp_dampening_prefix
,
13455 clear_ip_bgp_dampening_prefix_cmd
,
13456 "clear ip bgp dampening A.B.C.D/M",
13460 "Clear route flap dampening information\n"
13463 int idx_ipv4_prefixlen
= 4;
13464 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
13465 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
13468 DEFUN (clear_ip_bgp_dampening_address
,
13469 clear_ip_bgp_dampening_address_cmd
,
13470 "clear ip bgp dampening A.B.C.D",
13474 "Clear route flap dampening information\n"
13475 "Network to clear damping information\n")
13478 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
13479 SAFI_UNICAST
, NULL
, 0);
13482 DEFUN (clear_ip_bgp_dampening_address_mask
,
13483 clear_ip_bgp_dampening_address_mask_cmd
,
13484 "clear ip bgp dampening A.B.C.D A.B.C.D",
13488 "Clear route flap dampening information\n"
13489 "Network to clear damping information\n"
13493 int idx_ipv4_2
= 5;
13495 char prefix_str
[BUFSIZ
];
13497 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
13500 vty_out(vty
, "%% Inconsistent address and mask\n");
13501 return CMD_WARNING
;
13504 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
13508 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
13510 struct vty
*vty
= arg
;
13511 struct peer
*peer
= bucket
->data
;
13512 char buf
[SU_ADDRSTRLEN
];
13514 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
13515 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
13518 DEFUN (show_bgp_listeners
,
13519 show_bgp_listeners_cmd
,
13520 "show bgp listeners",
13523 "Display Listen Sockets and who created them\n")
13525 bgp_dump_listener_info(vty
);
13527 return CMD_SUCCESS
;
13530 DEFUN (show_bgp_peerhash
,
13531 show_bgp_peerhash_cmd
,
13532 "show bgp peerhash",
13535 "Display information about the BGP peerhash\n")
13537 struct list
*instances
= bm
->bgp
;
13538 struct listnode
*node
;
13541 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
13542 vty_out(vty
, "BGP: %s\n", bgp
->name
);
13543 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
13547 return CMD_SUCCESS
;
13550 /* also used for encap safi */
13551 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
13552 afi_t afi
, safi_t safi
)
13554 struct bgp_dest
*pdest
;
13555 struct bgp_dest
*dest
;
13556 struct bgp_table
*table
;
13557 const struct prefix
*p
;
13558 const struct prefix_rd
*prd
;
13559 struct bgp_static
*bgp_static
;
13560 mpls_label_t label
;
13561 char buf
[SU_ADDRSTRLEN
];
13562 char rdbuf
[RD_ADDRSTRLEN
];
13564 /* Network configuration. */
13565 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
13566 pdest
= bgp_route_next(pdest
)) {
13567 table
= bgp_dest_get_bgp_table_info(pdest
);
13571 for (dest
= bgp_table_top(table
); dest
;
13572 dest
= bgp_route_next(dest
)) {
13573 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13574 if (bgp_static
== NULL
)
13577 p
= bgp_dest_get_prefix(dest
);
13578 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13581 /* "network" configuration display. */
13582 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
13583 label
= decode_label(&bgp_static
->label
);
13585 vty_out(vty
, " network %s/%d rd %s",
13586 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
13588 p
->prefixlen
, rdbuf
);
13589 if (safi
== SAFI_MPLS_VPN
)
13590 vty_out(vty
, " label %u", label
);
13592 if (bgp_static
->rmap
.name
)
13593 vty_out(vty
, " route-map %s",
13594 bgp_static
->rmap
.name
);
13596 if (bgp_static
->backdoor
)
13597 vty_out(vty
, " backdoor");
13599 vty_out(vty
, "\n");
13604 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
13605 afi_t afi
, safi_t safi
)
13607 struct bgp_dest
*pdest
;
13608 struct bgp_dest
*dest
;
13609 struct bgp_table
*table
;
13610 const struct prefix
*p
;
13611 const struct prefix_rd
*prd
;
13612 struct bgp_static
*bgp_static
;
13613 char buf
[PREFIX_STRLEN
* 2];
13614 char buf2
[SU_ADDRSTRLEN
];
13615 char rdbuf
[RD_ADDRSTRLEN
];
13616 char esi_buf
[ESI_BYTES
];
13618 /* Network configuration. */
13619 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
13620 pdest
= bgp_route_next(pdest
)) {
13621 table
= bgp_dest_get_bgp_table_info(pdest
);
13625 for (dest
= bgp_table_top(table
); dest
;
13626 dest
= bgp_route_next(dest
)) {
13627 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13628 if (bgp_static
== NULL
)
13631 char *macrouter
= NULL
;
13633 if (bgp_static
->router_mac
)
13634 macrouter
= prefix_mac2str(
13635 bgp_static
->router_mac
, NULL
, 0);
13636 if (bgp_static
->eth_s_id
)
13637 esi_to_str(bgp_static
->eth_s_id
,
13638 esi_buf
, sizeof(esi_buf
));
13639 p
= bgp_dest_get_prefix(dest
);
13640 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
13642 /* "network" configuration display. */
13643 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
13644 if (p
->u
.prefix_evpn
.route_type
== 5) {
13645 char local_buf
[PREFIX_STRLEN
];
13646 uint8_t family
= is_evpn_prefix_ipaddr_v4((
13647 struct prefix_evpn
*)p
)
13651 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
13652 local_buf
, PREFIX_STRLEN
);
13653 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
13654 p
->u
.prefix_evpn
.prefix_addr
13655 .ip_prefix_length
);
13657 prefix2str(p
, buf
, sizeof(buf
));
13660 if (bgp_static
->gatewayIp
.family
== AF_INET
13661 || bgp_static
->gatewayIp
.family
== AF_INET6
)
13662 inet_ntop(bgp_static
->gatewayIp
.family
,
13663 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
13666 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
13668 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
13669 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
13672 XFREE(MTYPE_TMP
, macrouter
);
13677 /* Configuration of static route announcement and aggregate
13679 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13682 struct bgp_dest
*dest
;
13683 const struct prefix
*p
;
13684 struct bgp_static
*bgp_static
;
13685 struct bgp_aggregate
*bgp_aggregate
;
13686 char buf
[SU_ADDRSTRLEN
];
13688 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
13689 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
13693 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
13694 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
13698 /* Network configuration. */
13699 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
13700 dest
= bgp_route_next(dest
)) {
13701 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13702 if (bgp_static
== NULL
)
13705 p
= bgp_dest_get_prefix(dest
);
13707 vty_out(vty
, " network %s/%d",
13708 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
13711 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
13712 vty_out(vty
, " label-index %u",
13713 bgp_static
->label_index
);
13715 if (bgp_static
->rmap
.name
)
13716 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
13718 if (bgp_static
->backdoor
)
13719 vty_out(vty
, " backdoor");
13721 vty_out(vty
, "\n");
13724 /* Aggregate-address configuration. */
13725 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
13726 dest
= bgp_route_next(dest
)) {
13727 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
13728 if (bgp_aggregate
== NULL
)
13731 p
= bgp_dest_get_prefix(dest
);
13733 vty_out(vty
, " aggregate-address %s/%d",
13734 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
13737 if (bgp_aggregate
->as_set
)
13738 vty_out(vty
, " as-set");
13740 if (bgp_aggregate
->summary_only
)
13741 vty_out(vty
, " summary-only");
13743 if (bgp_aggregate
->rmap
.name
)
13744 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
13746 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
13747 vty_out(vty
, " origin %s",
13748 bgp_origin2str(bgp_aggregate
->origin
));
13750 vty_out(vty
, "\n");
13754 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13757 struct bgp_dest
*dest
;
13758 struct bgp_distance
*bdistance
;
13760 /* Distance configuration. */
13761 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
13762 && bgp
->distance_local
[afi
][safi
]
13763 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
13764 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
13765 || bgp
->distance_local
[afi
][safi
]
13766 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
13767 vty_out(vty
, " distance bgp %d %d %d\n",
13768 bgp
->distance_ebgp
[afi
][safi
],
13769 bgp
->distance_ibgp
[afi
][safi
],
13770 bgp
->distance_local
[afi
][safi
]);
13773 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
13774 dest
= bgp_route_next(dest
)) {
13775 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13776 if (bdistance
!= NULL
)
13777 vty_out(vty
, " distance %d %pRN %s\n",
13778 bdistance
->distance
, dest
,
13779 bdistance
->access_list
? bdistance
->access_list
13784 /* Allocate routing table structure and install commands. */
13785 void bgp_route_init(void)
13790 /* Init BGP distance table. */
13791 FOREACH_AFI_SAFI (afi
, safi
)
13792 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
13794 /* IPv4 BGP commands. */
13795 install_element(BGP_NODE
, &bgp_table_map_cmd
);
13796 install_element(BGP_NODE
, &bgp_network_cmd
);
13797 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
13799 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
13801 /* IPv4 unicast configuration. */
13802 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
13803 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
13804 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
13806 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
13808 /* IPv4 multicast configuration. */
13809 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
13810 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
13811 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
13812 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
13814 /* IPv4 labeled-unicast configuration. */
13815 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
13816 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
13818 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
13819 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
13820 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
13821 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
13822 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
13823 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
13824 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
13825 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
13827 install_element(VIEW_NODE
,
13828 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
13829 install_element(VIEW_NODE
,
13830 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
13831 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
13832 install_element(VIEW_NODE
,
13833 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
13834 #ifdef KEEP_OLD_VPN_COMMANDS
13835 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
13836 #endif /* KEEP_OLD_VPN_COMMANDS */
13837 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
13838 install_element(VIEW_NODE
,
13839 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
13841 /* BGP dampening clear commands */
13842 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
13843 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
13845 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
13846 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
13849 install_element(ENABLE_NODE
,
13850 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
13851 #ifdef KEEP_OLD_VPN_COMMANDS
13852 install_element(ENABLE_NODE
,
13853 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
13854 #endif /* KEEP_OLD_VPN_COMMANDS */
13856 /* New config IPv6 BGP commands. */
13857 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
13858 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
13859 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
13861 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
13863 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
13865 /* IPv6 labeled unicast address family. */
13866 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
13867 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
13869 install_element(BGP_NODE
, &bgp_distance_cmd
);
13870 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
13871 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
13872 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
13873 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
13874 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
13875 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
13876 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
13877 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
13878 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
13879 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
13880 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
13881 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
13882 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
13883 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
13884 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
13885 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
13886 install_element(BGP_IPV4M_NODE
,
13887 &no_bgp_distance_source_access_list_cmd
);
13888 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
13889 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
13890 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
13891 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13892 install_element(BGP_IPV6_NODE
,
13893 &ipv6_bgp_distance_source_access_list_cmd
);
13894 install_element(BGP_IPV6_NODE
,
13895 &no_ipv6_bgp_distance_source_access_list_cmd
);
13896 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
13897 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
13898 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
13899 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13900 install_element(BGP_IPV6M_NODE
,
13901 &ipv6_bgp_distance_source_access_list_cmd
);
13902 install_element(BGP_IPV6M_NODE
,
13903 &no_ipv6_bgp_distance_source_access_list_cmd
);
13905 /* BGP dampening */
13906 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
13907 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
13908 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
13909 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
13910 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
13911 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
13912 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
13913 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
13914 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
13915 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
13916 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
13917 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
13918 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
13919 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
13921 /* Large Communities */
13922 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
13923 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
13925 /* show bgp ipv4 flowspec detailed */
13926 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
13928 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
13929 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
13932 void bgp_route_finish(void)
13937 FOREACH_AFI_SAFI (afi
, safi
) {
13938 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
13939 bgp_distance_table
[afi
][safi
] = NULL
;