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 (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
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 bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3068 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3069 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3070 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3071 struct attr attr
= {};
3073 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3077 if (bgp_input_modifier(
3078 peer
, rn_p
, &attr
, afi
, safi
,
3079 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3087 bgp_attr_undup(&attr
, ain
->attr
);
3094 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3098 iana_safi_t pkt_safi
;
3099 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3100 PEER_FLAG_MAX_PREFIX_FORCE
))
3101 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3102 + peer
->pcount
[afi
][safi
]
3103 : peer
->pcount
[afi
][safi
];
3105 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3108 if (pcount
> peer
->pmax
[afi
][safi
]) {
3109 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3110 PEER_STATUS_PREFIX_LIMIT
)
3115 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3116 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3117 peer
->pmax
[afi
][safi
]);
3118 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3120 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3121 PEER_FLAG_MAX_PREFIX_WARNING
))
3124 /* Convert AFI, SAFI to values for packet. */
3125 pkt_afi
= afi_int2iana(afi
);
3126 pkt_safi
= safi_int2iana(safi
);
3130 ndata
[0] = (pkt_afi
>> 8);
3132 ndata
[2] = pkt_safi
;
3133 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3134 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3135 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3136 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3138 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3139 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3140 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3144 /* Dynamic peers will just close their connection. */
3145 if (peer_dynamic_neighbor(peer
))
3148 /* restart timer start */
3149 if (peer
->pmax_restart
[afi
][safi
]) {
3150 peer
->v_pmax_restart
=
3151 peer
->pmax_restart
[afi
][safi
] * 60;
3153 if (bgp_debug_neighbor_events(peer
))
3155 "%s Maximum-prefix restart timer started for %d secs",
3156 peer
->host
, peer
->v_pmax_restart
);
3158 BGP_TIMER_ON(peer
->t_pmax_restart
,
3159 bgp_maximum_prefix_restart_timer
,
3160 peer
->v_pmax_restart
);
3165 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3166 PEER_STATUS_PREFIX_LIMIT
);
3168 if (pcount
> (pcount
* peer
->pmax_threshold
[afi
][safi
] / 100)) {
3169 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3170 PEER_STATUS_PREFIX_THRESHOLD
)
3175 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3176 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3177 peer
->pmax
[afi
][safi
]);
3178 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3179 PEER_STATUS_PREFIX_THRESHOLD
);
3181 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3182 PEER_STATUS_PREFIX_THRESHOLD
);
3186 /* Unconditionally remove the route from the RIB, without taking
3187 * damping into consideration (eg, because the session went down)
3189 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3190 struct peer
*peer
, afi_t afi
, safi_t safi
)
3193 struct bgp
*bgp
= NULL
;
3194 bool delete_route
= false;
3196 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3199 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3200 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3202 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3205 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3206 delete_route
= true;
3207 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3208 delete_route
= true;
3210 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3211 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3212 bgp
= pi
->peer
->bgp
;
3214 && (bgp
->gr_info
[afi
][safi
].route_list
)) {
3215 list_delete_node(bgp
->gr_info
[afi
][safi
]
3218 dest
->rt_node
= NULL
;
3224 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3225 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3228 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3229 struct peer
*peer
, afi_t afi
, safi_t safi
,
3230 struct prefix_rd
*prd
)
3232 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3234 /* apply dampening, if result is suppressed, we'll be retaining
3235 * the bgp_path_info in the RIB for historical reference.
3237 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3238 && peer
->sort
== BGP_PEER_EBGP
)
3239 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3240 == BGP_DAMP_SUPPRESSED
) {
3241 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3246 #ifdef ENABLE_BGP_VNC
3247 if (safi
== SAFI_MPLS_VPN
) {
3248 struct bgp_dest
*pdest
= NULL
;
3249 struct bgp_table
*table
= NULL
;
3251 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3252 (struct prefix
*)prd
);
3253 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3254 table
= bgp_dest_get_bgp_table_info(pdest
);
3256 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3257 peer
->bgp
, prd
, table
, p
, pi
);
3259 bgp_dest_unlock_node(pdest
);
3261 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3262 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3264 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3265 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3270 /* If this is an EVPN route, process for un-import. */
3271 if (safi
== SAFI_EVPN
)
3272 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3274 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3277 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3278 struct peer
*peer
, struct attr
*attr
,
3279 struct bgp_dest
*dest
)
3281 struct bgp_path_info
*new;
3283 /* Make new BGP info. */
3284 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3286 new->instance
= instance
;
3287 new->sub_type
= sub_type
;
3290 new->uptime
= bgp_clock();
3295 static void overlay_index_update(struct attr
*attr
,
3296 union gw_addr
*gw_ip
)
3300 if (gw_ip
== NULL
) {
3301 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
3303 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
3304 sizeof(union gw_addr
));
3308 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3309 union gw_addr
*gw_ip
)
3311 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
3317 if (afi
!= AFI_L2VPN
)
3320 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
3322 if (gw_ip
== NULL
) {
3323 memset(&temp
, 0, sizeof(temp
));
3324 path_gw_ip_remote
= &temp
.ip
;
3326 path_gw_ip_remote
= gw_ip
;
3328 return !!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
));
3331 /* Check if received nexthop is valid or not. */
3332 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3333 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3334 struct bgp_dest
*dest
)
3337 bool is_bgp_static_route
=
3338 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3341 /* Only validated for unicast and multicast currently. */
3342 /* Also valid for EVPN where the nexthop is an IP address. */
3343 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
3346 /* If NEXT_HOP is present, validate it. */
3347 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3348 if ((attr
->nexthop
.s_addr
== INADDR_ANY
&& !is_bgp_static_route
)
3349 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3350 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3354 /* If MP_NEXTHOP is present, validate it. */
3355 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3356 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3357 * it is not an IPv6 link-local address.
3359 * If we receive an UPDATE with nexthop length set to 32 bytes
3360 * we shouldn't discard an UPDATE if it's set to (::).
3361 * The link-local (2st) is validated along the code path later.
3363 if (attr
->mp_nexthop_len
) {
3364 switch (attr
->mp_nexthop_len
) {
3365 case BGP_ATTR_NHLEN_IPV4
:
3366 case BGP_ATTR_NHLEN_VPNV4
:
3367 ret
= ((attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3368 && !is_bgp_static_route
)
3370 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3371 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3375 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3376 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3377 ret
= ((IN6_IS_ADDR_UNSPECIFIED(
3378 &attr
->mp_nexthop_global
)
3379 && !is_bgp_static_route
)
3380 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3381 || IN6_IS_ADDR_MULTICAST(
3382 &attr
->mp_nexthop_global
)
3383 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3386 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3387 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3388 || IN6_IS_ADDR_MULTICAST(
3389 &attr
->mp_nexthop_global
)
3390 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3403 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3404 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3405 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3406 uint32_t num_labels
, int soft_reconfig
,
3407 struct bgp_route_evpn
*evpn
)
3410 int aspath_loop_count
= 0;
3411 struct bgp_dest
*dest
;
3413 struct attr new_attr
;
3414 struct attr
*attr_new
;
3415 struct bgp_path_info
*pi
;
3416 struct bgp_path_info
*new;
3417 struct bgp_path_info_extra
*extra
;
3419 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3421 int do_loop_check
= 1;
3422 int has_valid_label
= 0;
3424 uint8_t pi_type
= 0;
3425 uint8_t pi_sub_type
= 0;
3427 #ifdef ENABLE_BGP_VNC
3428 int vnc_implicit_withdraw
= 0;
3432 memset(&new_attr
, 0, sizeof(struct attr
));
3433 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3434 new_attr
.label
= MPLS_INVALID_LABEL
;
3437 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3438 /* TODO: Check to see if we can get rid of "is_valid_label" */
3439 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3440 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3442 has_valid_label
= bgp_is_valid_label(label
);
3444 /* When peer's soft reconfiguration enabled. Record input packet in
3447 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3448 && peer
!= bgp
->peer_self
)
3449 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3451 /* Check previously received route. */
3452 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3453 if (pi
->peer
== peer
&& pi
->type
== type
3454 && pi
->sub_type
== sub_type
3455 && pi
->addpath_rx_id
== addpath_id
)
3458 /* AS path local-as loop check. */
3459 if (peer
->change_local_as
) {
3460 if (peer
->allowas_in
[afi
][safi
])
3461 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3462 else if (!CHECK_FLAG(peer
->flags
,
3463 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3464 aspath_loop_count
= 1;
3466 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3467 > aspath_loop_count
) {
3468 peer
->stat_pfx_aspath_loop
++;
3469 reason
= "as-path contains our own AS A;";
3474 /* If the peer is configured for "allowas-in origin" and the last ASN in
3476 * as-path is our ASN then we do not need to call aspath_loop_check
3478 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3479 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3482 /* AS path loop check. */
3483 if (do_loop_check
) {
3484 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3485 > peer
->allowas_in
[afi
][safi
]
3486 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3487 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3488 > peer
->allowas_in
[afi
][safi
])) {
3489 peer
->stat_pfx_aspath_loop
++;
3490 reason
= "as-path contains our own AS;";
3495 /* Route reflector originator ID check. */
3496 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3497 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3498 peer
->stat_pfx_originator_loop
++;
3499 reason
= "originator is us;";
3503 /* Route reflector cluster ID check. */
3504 if (bgp_cluster_filter(peer
, attr
)) {
3505 peer
->stat_pfx_cluster_loop
++;
3506 reason
= "reflected from the same cluster;";
3510 /* Apply incoming filter. */
3511 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3512 peer
->stat_pfx_filter
++;
3517 /* RFC 8212 to prevent route leaks.
3518 * This specification intends to improve this situation by requiring the
3519 * explicit configuration of both BGP Import and Export Policies for any
3520 * External BGP (EBGP) session such as customers, peers, or
3521 * confederation boundaries for all enabled address families. Through
3522 * codification of the aforementioned requirement, operators will
3523 * benefit from consistent behavior across different BGP
3526 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3527 if (!bgp_inbound_policy_exists(peer
,
3528 &peer
->filter
[afi
][safi
])) {
3529 reason
= "inbound policy missing";
3533 /* draft-ietf-idr-deprecate-as-set-confed-set
3534 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3535 * Eventually, This document (if approved) updates RFC 4271
3536 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3537 * and obsoletes RFC 6472.
3539 if (peer
->bgp
->reject_as_sets
)
3540 if (aspath_check_as_sets(attr
->aspath
)) {
3542 "as-path contains AS_SET or AS_CONFED_SET type;";
3548 /* Apply incoming route-map.
3549 * NB: new_attr may now contain newly allocated values from route-map
3551 * commands, so we need bgp_attr_flush in the error paths, until we
3553 * the attr (which takes over the memory references) */
3554 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
, label
,
3557 peer
->stat_pfx_filter
++;
3558 reason
= "route-map;";
3559 bgp_attr_flush(&new_attr
);
3563 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3564 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3565 /* remove from RIB previous entry */
3566 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3569 if (peer
->sort
== BGP_PEER_EBGP
) {
3571 /* If we receive the graceful-shutdown community from an eBGP
3572 * peer we must lower local-preference */
3573 if (new_attr
.community
3574 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3575 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3576 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3578 /* If graceful-shutdown is configured then add the GSHUT
3579 * community to all paths received from eBGP peers */
3580 } else if (CHECK_FLAG(peer
->bgp
->flags
,
3581 BGP_FLAG_GRACEFUL_SHUTDOWN
))
3582 bgp_attr_add_gshut_community(&new_attr
);
3587 pi_sub_type
= pi
->sub_type
;
3590 /* next hop check. */
3591 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3592 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3594 peer
->stat_pfx_nh_invalid
++;
3595 reason
= "martian or self next-hop;";
3596 bgp_attr_flush(&new_attr
);
3600 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3601 peer
->stat_pfx_nh_invalid
++;
3602 reason
= "self mac;";
3606 attr_new
= bgp_attr_intern(&new_attr
);
3608 /* If maximum prefix count is configured and current prefix
3611 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3614 /* If the update is implicit withdraw. */
3616 pi
->uptime
= bgp_clock();
3617 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3619 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3621 /* Same attribute comes in. */
3622 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3623 && attrhash_cmp(pi
->attr
, attr_new
)
3624 && (!has_valid_label
3625 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3626 num_labels
* sizeof(mpls_label_t
))
3628 && (overlay_index_equal(
3630 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3631 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3632 BGP_CONFIG_DAMPENING
)
3633 && peer
->sort
== BGP_PEER_EBGP
3634 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3635 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3636 bgp_debug_rdpfxpath2str(
3637 afi
, safi
, prd
, p
, label
,
3638 num_labels
, addpath_id
? 1 : 0,
3639 addpath_id
, pfx_buf
,
3641 zlog_debug("%s rcvd %s", peer
->host
,
3645 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3646 != BGP_DAMP_SUPPRESSED
) {
3647 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3649 bgp_process(bgp
, dest
, afi
, safi
);
3651 } else /* Duplicate - odd */
3653 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3654 if (!peer
->rcvd_attr_printed
) {
3656 "%s rcvd UPDATE w/ attr: %s",
3658 peer
->rcvd_attr_str
);
3659 peer
->rcvd_attr_printed
= 1;
3662 bgp_debug_rdpfxpath2str(
3663 afi
, safi
, prd
, p
, label
,
3664 num_labels
, addpath_id
? 1 : 0,
3665 addpath_id
, pfx_buf
,
3668 "%s rcvd %s...duplicate ignored",
3669 peer
->host
, pfx_buf
);
3672 /* graceful restart STALE flag unset. */
3673 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3674 bgp_path_info_unset_flag(
3675 dest
, pi
, BGP_PATH_STALE
);
3676 bgp_dest_set_defer_flag(dest
, false);
3677 bgp_process(bgp
, dest
, afi
, safi
);
3681 bgp_dest_unlock_node(dest
);
3682 bgp_attr_unintern(&attr_new
);
3687 /* Withdraw/Announce before we fully processed the withdraw */
3688 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3689 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3690 bgp_debug_rdpfxpath2str(
3691 afi
, safi
, prd
, p
, label
, num_labels
,
3692 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3695 "%s rcvd %s, flapped quicker than processing",
3696 peer
->host
, pfx_buf
);
3699 bgp_path_info_restore(dest
, pi
);
3702 /* Received Logging. */
3703 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3704 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3705 num_labels
, addpath_id
? 1 : 0,
3706 addpath_id
, pfx_buf
,
3708 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3711 /* graceful restart STALE flag unset. */
3712 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3713 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
3714 bgp_dest_set_defer_flag(dest
, false);
3717 /* The attribute is changed. */
3718 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
3720 /* implicit withdraw, decrement aggregate and pcount here.
3721 * only if update is accepted, they'll increment below.
3723 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3725 /* Update bgp route dampening information. */
3726 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3727 && peer
->sort
== BGP_PEER_EBGP
) {
3728 /* This is implicit withdraw so we should update
3731 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3732 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
3734 #ifdef ENABLE_BGP_VNC
3735 if (safi
== SAFI_MPLS_VPN
) {
3736 struct bgp_dest
*pdest
= NULL
;
3737 struct bgp_table
*table
= NULL
;
3739 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3740 (struct prefix
*)prd
);
3741 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3742 table
= bgp_dest_get_bgp_table_info(pdest
);
3744 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3745 bgp
, prd
, table
, p
, pi
);
3747 bgp_dest_unlock_node(pdest
);
3749 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3750 && (safi
== SAFI_UNICAST
)) {
3751 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3753 * Implicit withdraw case.
3755 ++vnc_implicit_withdraw
;
3756 vnc_import_bgp_del_route(bgp
, p
, pi
);
3757 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3762 /* Special handling for EVPN update of an existing route. If the
3763 * extended community attribute has changed, we need to
3765 * the route using its existing extended community. It will be
3766 * subsequently processed for import with the new extended
3769 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
3772 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3774 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3777 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3778 attr_new
->ecommunity
);
3780 if (bgp_debug_update(peer
, p
, NULL
, 1))
3782 "Change in EXT-COMM, existing %s new %s",
3784 pi
->attr
->ecommunity
),
3786 attr_new
->ecommunity
));
3787 if (safi
== SAFI_EVPN
)
3788 bgp_evpn_unimport_route(
3789 bgp
, afi
, safi
, p
, pi
);
3790 else /* SAFI_MPLS_VPN */
3791 vpn_leak_to_vrf_withdraw(bgp
,
3797 /* Update to new attribute. */
3798 bgp_attr_unintern(&pi
->attr
);
3799 pi
->attr
= attr_new
;
3801 /* Update MPLS label */
3802 if (has_valid_label
) {
3803 extra
= bgp_path_info_extra_get(pi
);
3804 if (extra
->label
!= label
) {
3805 memcpy(&extra
->label
, label
,
3806 num_labels
* sizeof(mpls_label_t
));
3807 extra
->num_labels
= num_labels
;
3809 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3810 bgp_set_valid_label(&extra
->label
[0]);
3813 /* Update SRv6 SID */
3814 if (attr
->srv6_l3vpn
) {
3815 extra
= bgp_path_info_extra_get(pi
);
3816 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
3817 sid_copy(&extra
->sid
[0],
3818 &attr
->srv6_l3vpn
->sid
);
3819 extra
->num_sids
= 1;
3821 } else if (attr
->srv6_vpn
) {
3822 extra
= bgp_path_info_extra_get(pi
);
3823 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
3824 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
3825 extra
->num_sids
= 1;
3829 #ifdef ENABLE_BGP_VNC
3830 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3831 && (safi
== SAFI_UNICAST
)) {
3832 if (vnc_implicit_withdraw
) {
3834 * Add back the route with its new attributes
3836 * The route is still selected, until the route
3838 * queued by bgp_process actually runs. We have
3840 * update to the VNC side immediately to avoid
3842 * configuration changes (e.g., route-map
3844 * trigger re-importation of the entire RIB.
3846 vnc_import_bgp_add_route(bgp
, p
, pi
);
3847 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3851 /* Update Overlay Index */
3852 if (afi
== AFI_L2VPN
) {
3853 overlay_index_update(
3855 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3858 /* Update bgp route dampening information. */
3859 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3860 && peer
->sort
== BGP_PEER_EBGP
) {
3861 /* Now we do normal update dampening. */
3862 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
3863 if (ret
== BGP_DAMP_SUPPRESSED
) {
3864 bgp_dest_unlock_node(dest
);
3869 /* Nexthop reachability check - for unicast and
3870 * labeled-unicast.. */
3871 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3872 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3873 || (safi
== SAFI_EVPN
&&
3874 bgp_evpn_is_prefix_nht_supported(p
))) {
3875 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3876 && peer
->ttl
== BGP_DEFAULT_TTL
3877 && !CHECK_FLAG(peer
->flags
,
3878 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3879 && !CHECK_FLAG(bgp
->flags
,
3880 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3885 struct bgp
*bgp_nexthop
= bgp
;
3887 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3888 bgp_nexthop
= pi
->extra
->bgp_orig
;
3890 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3892 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3893 pi
, NULL
, connected
)
3894 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3895 bgp_path_info_set_flag(dest
, pi
,
3898 if (BGP_DEBUG(nht
, NHT
)) {
3899 zlog_debug("%s(%pI4): NH unresolved",
3901 (in_addr_t
*)&attr_new
->nexthop
);
3903 bgp_path_info_unset_flag(dest
, pi
,
3907 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
3909 #ifdef ENABLE_BGP_VNC
3910 if (safi
== SAFI_MPLS_VPN
) {
3911 struct bgp_dest
*pdest
= NULL
;
3912 struct bgp_table
*table
= NULL
;
3914 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3915 (struct prefix
*)prd
);
3916 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3917 table
= bgp_dest_get_bgp_table_info(pdest
);
3919 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3920 bgp
, prd
, table
, p
, pi
);
3922 bgp_dest_unlock_node(pdest
);
3926 /* If this is an EVPN route and some attribute has changed,
3928 * route for import. If the extended community has changed, we
3930 * have done the un-import earlier and the import would result
3932 * route getting injected into appropriate L2 VNIs. If it is
3934 * some other attribute change, the import will result in
3936 * the attributes for the route in the VNI(s).
3938 if (safi
== SAFI_EVPN
&& !same_attr
&&
3939 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3940 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3942 /* Process change. */
3943 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3945 bgp_process(bgp
, dest
, afi
, safi
);
3946 bgp_dest_unlock_node(dest
);
3948 if (SAFI_UNICAST
== safi
3949 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3950 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3952 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3954 if ((SAFI_MPLS_VPN
== safi
)
3955 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3957 vpn_leak_to_vrf_update(bgp
, pi
);
3960 #ifdef ENABLE_BGP_VNC
3961 if (SAFI_MPLS_VPN
== safi
) {
3962 mpls_label_t label_decoded
= decode_label(label
);
3964 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3965 type
, sub_type
, &label_decoded
);
3967 if (SAFI_ENCAP
== safi
) {
3968 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3969 type
, sub_type
, NULL
);
3974 } // End of implicit withdraw
3976 /* Received Logging. */
3977 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3978 if (!peer
->rcvd_attr_printed
) {
3979 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3980 peer
->rcvd_attr_str
);
3981 peer
->rcvd_attr_printed
= 1;
3984 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3985 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3987 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3990 /* Make new BGP info. */
3991 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
3993 /* Update MPLS label */
3994 if (has_valid_label
) {
3995 extra
= bgp_path_info_extra_get(new);
3996 if (extra
->label
!= label
) {
3997 memcpy(&extra
->label
, label
,
3998 num_labels
* sizeof(mpls_label_t
));
3999 extra
->num_labels
= num_labels
;
4001 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4002 bgp_set_valid_label(&extra
->label
[0]);
4005 /* Update SRv6 SID */
4006 if (safi
== SAFI_MPLS_VPN
) {
4007 extra
= bgp_path_info_extra_get(new);
4008 if (attr
->srv6_l3vpn
) {
4009 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
4010 extra
->num_sids
= 1;
4011 } else if (attr
->srv6_vpn
) {
4012 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4013 extra
->num_sids
= 1;
4017 /* Update Overlay Index */
4018 if (afi
== AFI_L2VPN
) {
4019 overlay_index_update(new->attr
,
4020 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
4022 /* Nexthop reachability check. */
4023 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4024 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4025 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4026 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4027 && peer
->ttl
== BGP_DEFAULT_TTL
4028 && !CHECK_FLAG(peer
->flags
,
4029 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4030 && !CHECK_FLAG(bgp
->flags
,
4031 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4036 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4038 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
4040 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4041 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4043 if (BGP_DEBUG(nht
, NHT
)) {
4044 char buf1
[INET6_ADDRSTRLEN
];
4046 (const void *)&attr_new
->nexthop
,
4047 buf1
, INET6_ADDRSTRLEN
);
4048 zlog_debug("%s(%s): NH unresolved", __func__
,
4051 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4054 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4057 new->addpath_rx_id
= addpath_id
;
4059 /* Increment prefix */
4060 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4062 /* Register new BGP information. */
4063 bgp_path_info_add(dest
, new);
4065 /* route_node_get lock */
4066 bgp_dest_unlock_node(dest
);
4068 #ifdef ENABLE_BGP_VNC
4069 if (safi
== SAFI_MPLS_VPN
) {
4070 struct bgp_dest
*pdest
= NULL
;
4071 struct bgp_table
*table
= NULL
;
4073 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4074 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4075 table
= bgp_dest_get_bgp_table_info(pdest
);
4077 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4078 bgp
, prd
, table
, p
, new);
4080 bgp_dest_unlock_node(pdest
);
4084 /* If this is an EVPN route, process for import. */
4085 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4086 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4088 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4090 /* Process change. */
4091 bgp_process(bgp
, dest
, afi
, safi
);
4093 if (SAFI_UNICAST
== safi
4094 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4095 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4096 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4098 if ((SAFI_MPLS_VPN
== safi
)
4099 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4101 vpn_leak_to_vrf_update(bgp
, new);
4103 #ifdef ENABLE_BGP_VNC
4104 if (SAFI_MPLS_VPN
== safi
) {
4105 mpls_label_t label_decoded
= decode_label(label
);
4107 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4108 sub_type
, &label_decoded
);
4110 if (SAFI_ENCAP
== safi
) {
4111 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4118 /* This BGP update is filtered. Log the reason then update BGP
4121 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4123 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4124 if (!peer
->rcvd_attr_printed
) {
4125 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4126 peer
->rcvd_attr_str
);
4127 peer
->rcvd_attr_printed
= 1;
4130 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4131 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4133 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4134 peer
->host
, pfx_buf
, reason
);
4138 /* If this is an EVPN route, un-import it as it is now filtered.
4140 if (safi
== SAFI_EVPN
)
4141 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4143 if (SAFI_UNICAST
== safi
4144 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4145 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4147 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4149 if ((SAFI_MPLS_VPN
== safi
)
4150 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4152 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4155 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4158 bgp_dest_unlock_node(dest
);
4160 #ifdef ENABLE_BGP_VNC
4162 * Filtered update is treated as an implicit withdrawal (see
4164 * a few lines above)
4166 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4167 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4175 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4176 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4177 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4178 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4181 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4182 struct bgp_dest
*dest
;
4183 struct bgp_path_info
*pi
;
4185 #ifdef ENABLE_BGP_VNC
4186 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4187 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4195 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4197 /* If peer is soft reconfiguration enabled. Record input packet for
4198 * further calculation.
4200 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4201 * routes that are filtered. This tanks out Quagga RS pretty badly due
4203 * the iteration over all RS clients.
4204 * Since we need to remove the entry from adj_in anyway, do that first
4206 * if there was no entry, we don't need to do anything more.
4208 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4209 && peer
!= bgp
->peer_self
)
4210 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4211 peer
->stat_pfx_dup_withdraw
++;
4213 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4214 bgp_debug_rdpfxpath2str(
4215 afi
, safi
, prd
, p
, label
, num_labels
,
4216 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4219 "%s withdrawing route %s not in adj-in",
4220 peer
->host
, pfx_buf
);
4222 bgp_dest_unlock_node(dest
);
4226 /* Lookup withdrawn route. */
4227 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4228 if (pi
->peer
== peer
&& pi
->type
== type
4229 && pi
->sub_type
== sub_type
4230 && pi
->addpath_rx_id
== addpath_id
)
4234 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4235 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4236 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4238 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4242 /* Withdraw specified route from routing table. */
4243 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4244 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4245 if (SAFI_UNICAST
== safi
4246 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4247 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4248 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4250 if ((SAFI_MPLS_VPN
== safi
)
4251 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4253 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4255 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4256 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4257 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4259 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4262 /* Unlock bgp_node_get() lock. */
4263 bgp_dest_unlock_node(dest
);
4268 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4271 struct update_subgroup
*subgrp
;
4272 subgrp
= peer_subgroup(peer
, afi
, safi
);
4273 subgroup_default_originate(subgrp
, withdraw
);
4278 * bgp_stop_announce_route_timer
4280 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4282 if (!paf
->t_announce_route
)
4285 THREAD_TIMER_OFF(paf
->t_announce_route
);
4289 * bgp_announce_route_timer_expired
4291 * Callback that is invoked when the route announcement timer for a
4294 static int bgp_announce_route_timer_expired(struct thread
*t
)
4296 struct peer_af
*paf
;
4299 paf
= THREAD_ARG(t
);
4302 if (peer
->status
!= Established
)
4305 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4308 peer_af_announce_route(paf
, 1);
4313 * bgp_announce_route
4315 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4317 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4319 struct peer_af
*paf
;
4320 struct update_subgroup
*subgrp
;
4322 paf
= peer_af_find(peer
, afi
, safi
);
4325 subgrp
= PAF_SUBGRP(paf
);
4328 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4329 * or a refresh has already been triggered.
4331 if (!subgrp
|| paf
->t_announce_route
)
4335 * Start a timer to stagger/delay the announce. This serves
4336 * two purposes - announcement can potentially be combined for
4337 * multiple peers and the announcement doesn't happen in the
4340 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4341 (subgrp
->peer_count
== 1)
4342 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4343 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4344 &paf
->t_announce_route
);
4348 * Announce routes from all AF tables to a peer.
4350 * This should ONLY be called when there is a need to refresh the
4351 * routes to the peer based on a policy change for this peer alone
4352 * or a route refresh request received from the peer.
4353 * The operation will result in splitting the peer from its existing
4354 * subgroups and putting it in new subgroups.
4356 void bgp_announce_route_all(struct peer
*peer
)
4361 FOREACH_AFI_SAFI (afi
, safi
)
4362 bgp_announce_route(peer
, afi
, safi
);
4365 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4366 struct bgp_table
*table
,
4367 struct prefix_rd
*prd
)
4370 struct bgp_dest
*dest
;
4371 struct bgp_adj_in
*ain
;
4374 table
= peer
->bgp
->rib
[afi
][safi
];
4376 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4377 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4378 if (ain
->peer
!= peer
)
4381 struct bgp_path_info
*pi
;
4382 uint32_t num_labels
= 0;
4383 mpls_label_t
*label_pnt
= NULL
;
4384 struct bgp_route_evpn evpn
;
4386 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4388 if (pi
->peer
== peer
)
4391 if (pi
&& pi
->extra
)
4392 num_labels
= pi
->extra
->num_labels
;
4394 label_pnt
= &pi
->extra
->label
[0];
4396 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
4399 memset(&evpn
, 0, sizeof(evpn
));
4401 ret
= bgp_update(peer
, bgp_dest_get_prefix(dest
),
4402 ain
->addpath_rx_id
, ain
->attr
, afi
,
4403 safi
, ZEBRA_ROUTE_BGP
,
4404 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4405 num_labels
, 1, &evpn
);
4408 bgp_dest_unlock_node(dest
);
4414 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4416 struct bgp_dest
*dest
;
4417 struct bgp_table
*table
;
4419 if (peer
->status
!= Established
)
4422 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4423 && (safi
!= SAFI_EVPN
))
4424 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4426 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4427 dest
= bgp_route_next(dest
)) {
4428 table
= bgp_dest_get_bgp_table_info(dest
);
4433 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4434 struct prefix_rd prd
;
4436 prd
.family
= AF_UNSPEC
;
4438 memcpy(&prd
.val
, p
->u
.val
, 8);
4440 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4445 struct bgp_clear_node_queue
{
4446 struct bgp_dest
*dest
;
4449 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4451 struct bgp_clear_node_queue
*cnq
= data
;
4452 struct bgp_dest
*dest
= cnq
->dest
;
4453 struct peer
*peer
= wq
->spec
.data
;
4454 struct bgp_path_info
*pi
;
4456 afi_t afi
= bgp_dest_table(dest
)->afi
;
4457 safi_t safi
= bgp_dest_table(dest
)->safi
;
4459 assert(dest
&& peer
);
4462 /* It is possible that we have multiple paths for a prefix from a peer
4463 * if that peer is using AddPath.
4465 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
4466 if (pi
->peer
!= peer
)
4469 /* graceful restart STALE flag set. */
4470 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4471 && peer
->nsf
[afi
][safi
]
4472 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4473 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4474 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
4476 /* If this is an EVPN route, process for
4478 if (safi
== SAFI_EVPN
)
4479 bgp_evpn_unimport_route(
4481 bgp_dest_get_prefix(dest
), pi
);
4482 /* Handle withdraw for VRF route-leaking and L3VPN */
4483 if (SAFI_UNICAST
== safi
4484 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4485 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4486 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4489 if (SAFI_MPLS_VPN
== safi
&&
4490 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4491 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4494 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4500 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4502 struct bgp_clear_node_queue
*cnq
= data
;
4503 struct bgp_dest
*dest
= cnq
->dest
;
4504 struct bgp_table
*table
= bgp_dest_table(dest
);
4506 bgp_dest_unlock_node(dest
);
4507 bgp_table_unlock(table
);
4508 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4511 static void bgp_clear_node_complete(struct work_queue
*wq
)
4513 struct peer
*peer
= wq
->spec
.data
;
4515 /* Tickle FSM to start moving again */
4516 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4518 peer_unlock(peer
); /* bgp_clear_route */
4521 static void bgp_clear_node_queue_init(struct peer
*peer
)
4523 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4525 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4526 #undef CLEAR_QUEUE_NAME_LEN
4528 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4529 peer
->clear_node_queue
->spec
.hold
= 10;
4530 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4531 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4532 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4533 peer
->clear_node_queue
->spec
.max_retries
= 0;
4535 /* we only 'lock' this peer reference when the queue is actually active
4537 peer
->clear_node_queue
->spec
.data
= peer
;
4540 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4541 struct bgp_table
*table
)
4543 struct bgp_dest
*dest
;
4544 int force
= bm
->process_main_queue
? 0 : 1;
4547 table
= peer
->bgp
->rib
[afi
][safi
];
4549 /* If still no table => afi/safi isn't configured at all or smth. */
4553 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4554 struct bgp_path_info
*pi
, *next
;
4555 struct bgp_adj_in
*ain
;
4556 struct bgp_adj_in
*ain_next
;
4558 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4559 * queued for every clearing peer, regardless of whether it is
4560 * relevant to the peer at hand.
4562 * Overview: There are 3 different indices which need to be
4563 * scrubbed, potentially, when a peer is removed:
4565 * 1 peer's routes visible via the RIB (ie accepted routes)
4566 * 2 peer's routes visible by the (optional) peer's adj-in index
4567 * 3 other routes visible by the peer's adj-out index
4569 * 3 there is no hurry in scrubbing, once the struct peer is
4570 * removed from bgp->peer, we could just GC such deleted peer's
4571 * adj-outs at our leisure.
4573 * 1 and 2 must be 'scrubbed' in some way, at least made
4574 * invisible via RIB index before peer session is allowed to be
4575 * brought back up. So one needs to know when such a 'search' is
4580 * - there'd be a single global queue or a single RIB walker
4581 * - rather than tracking which route_nodes still need to be
4582 * examined on a peer basis, we'd track which peers still
4585 * Given that our per-peer prefix-counts now should be reliable,
4586 * this may actually be achievable. It doesn't seem to be a huge
4587 * problem at this time,
4589 * It is possible that we have multiple paths for a prefix from
4591 * if that peer is using AddPath.
4595 ain_next
= ain
->next
;
4597 if (ain
->peer
== peer
) {
4598 bgp_adj_in_remove(dest
, ain
);
4599 bgp_dest_unlock_node(dest
);
4605 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4607 if (pi
->peer
!= peer
)
4611 bgp_path_info_reap(dest
, pi
);
4613 struct bgp_clear_node_queue
*cnq
;
4615 /* both unlocked in bgp_clear_node_queue_del */
4616 bgp_table_lock(bgp_dest_table(dest
));
4617 bgp_dest_lock_node(dest
);
4619 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4620 sizeof(struct bgp_clear_node_queue
));
4622 work_queue_add(peer
->clear_node_queue
, cnq
);
4630 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4632 struct bgp_dest
*dest
;
4633 struct bgp_table
*table
;
4635 if (peer
->clear_node_queue
== NULL
)
4636 bgp_clear_node_queue_init(peer
);
4638 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4639 * Idle until it receives a Clearing_Completed event. This protects
4640 * against peers which flap faster than we can we clear, which could
4643 * a) race with routes from the new session being installed before
4644 * clear_route_node visits the node (to delete the route of that
4646 * b) resource exhaustion, clear_route_node likely leads to an entry
4647 * on the process_main queue. Fast-flapping could cause that queue
4651 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4652 * the unlock will happen upon work-queue completion; other wise, the
4653 * unlock happens at the end of this function.
4655 if (!peer
->clear_node_queue
->thread
)
4658 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4659 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4661 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4662 dest
= bgp_route_next(dest
)) {
4663 table
= bgp_dest_get_bgp_table_info(dest
);
4667 bgp_clear_route_table(peer
, afi
, safi
, table
);
4670 /* unlock if no nodes got added to the clear-node-queue. */
4671 if (!peer
->clear_node_queue
->thread
)
4675 void bgp_clear_route_all(struct peer
*peer
)
4680 FOREACH_AFI_SAFI (afi
, safi
)
4681 bgp_clear_route(peer
, afi
, safi
);
4683 #ifdef ENABLE_BGP_VNC
4684 rfapiProcessPeerDown(peer
);
4688 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4690 struct bgp_table
*table
;
4691 struct bgp_dest
*dest
;
4692 struct bgp_adj_in
*ain
;
4693 struct bgp_adj_in
*ain_next
;
4695 table
= peer
->bgp
->rib
[afi
][safi
];
4697 /* It is possible that we have multiple paths for a prefix from a peer
4698 * if that peer is using AddPath.
4700 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4704 ain_next
= ain
->next
;
4706 if (ain
->peer
== peer
) {
4707 bgp_adj_in_remove(dest
, ain
);
4708 bgp_dest_unlock_node(dest
);
4716 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4718 struct bgp_dest
*dest
;
4719 struct bgp_path_info
*pi
;
4720 struct bgp_table
*table
;
4722 if (safi
== SAFI_MPLS_VPN
) {
4723 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4724 dest
= bgp_route_next(dest
)) {
4725 struct bgp_dest
*rm
;
4727 /* look for neighbor in tables */
4728 table
= bgp_dest_get_bgp_table_info(dest
);
4732 for (rm
= bgp_table_top(table
); rm
;
4733 rm
= bgp_route_next(rm
))
4734 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
4736 if (pi
->peer
!= peer
)
4738 if (!CHECK_FLAG(pi
->flags
,
4742 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4747 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4748 dest
= bgp_route_next(dest
))
4749 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4751 if (pi
->peer
!= peer
)
4753 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4755 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4761 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4763 if (peer
->sort
== BGP_PEER_IBGP
)
4766 if (peer
->sort
== BGP_PEER_EBGP
4767 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4768 || FILTER_LIST_OUT_NAME(filter
)
4769 || DISTRIBUTE_OUT_NAME(filter
)))
4774 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4776 if (peer
->sort
== BGP_PEER_IBGP
)
4779 if (peer
->sort
== BGP_PEER_EBGP
4780 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4781 || FILTER_LIST_IN_NAME(filter
)
4782 || DISTRIBUTE_IN_NAME(filter
)))
4787 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4790 struct bgp_dest
*dest
;
4791 struct bgp_path_info
*pi
;
4792 struct bgp_path_info
*next
;
4794 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4795 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4796 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4800 /* Unimport EVPN routes from VRFs */
4801 if (safi
== SAFI_EVPN
)
4802 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4805 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4806 && pi
->type
== ZEBRA_ROUTE_BGP
4807 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4808 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4809 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4811 if (bgp_fibupd_safi(safi
))
4812 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4815 bgp_path_info_reap(dest
, pi
);
4819 /* Delete all kernel routes. */
4820 void bgp_cleanup_routes(struct bgp
*bgp
)
4823 struct bgp_dest
*dest
;
4824 struct bgp_table
*table
;
4826 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4827 if (afi
== AFI_L2VPN
)
4829 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4832 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4834 if (afi
!= AFI_L2VPN
) {
4836 safi
= SAFI_MPLS_VPN
;
4837 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
4838 dest
= bgp_route_next(dest
)) {
4839 table
= bgp_dest_get_bgp_table_info(dest
);
4840 if (table
!= NULL
) {
4841 bgp_cleanup_table(bgp
, table
, safi
);
4842 bgp_table_finish(&table
);
4843 bgp_dest_set_bgp_table_info(dest
, NULL
);
4844 bgp_dest_unlock_node(dest
);
4848 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
4849 dest
= bgp_route_next(dest
)) {
4850 table
= bgp_dest_get_bgp_table_info(dest
);
4851 if (table
!= NULL
) {
4852 bgp_cleanup_table(bgp
, table
, safi
);
4853 bgp_table_finish(&table
);
4854 bgp_dest_set_bgp_table_info(dest
, NULL
);
4855 bgp_dest_unlock_node(dest
);
4860 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
4861 dest
= bgp_route_next(dest
)) {
4862 table
= bgp_dest_get_bgp_table_info(dest
);
4863 if (table
!= NULL
) {
4864 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4865 bgp_table_finish(&table
);
4866 bgp_dest_set_bgp_table_info(dest
, NULL
);
4867 bgp_dest_unlock_node(dest
);
4872 void bgp_reset(void)
4875 bgp_zclient_reset();
4876 access_list_reset();
4877 prefix_list_reset();
4880 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4882 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4883 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4884 PEER_CAP_ADDPATH_AF_TX_RCV
));
4887 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4889 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4890 struct bgp_nlri
*packet
)
4899 int addpath_encoded
;
4900 uint32_t addpath_id
;
4903 lim
= pnt
+ packet
->length
;
4905 safi
= packet
->safi
;
4907 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4909 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4910 syntactic validity. If the field is syntactically incorrect,
4911 then the Error Subcode is set to Invalid Network Field. */
4912 for (; pnt
< lim
; pnt
+= psize
) {
4913 /* Clear prefix structure. */
4914 memset(&p
, 0, sizeof(struct prefix
));
4916 if (addpath_encoded
) {
4918 /* When packet overflow occurs return immediately. */
4919 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4920 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4922 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
4923 addpath_id
= ntohl(addpath_id
);
4924 pnt
+= BGP_ADDPATH_ID_LEN
;
4927 /* Fetch prefix length. */
4928 p
.prefixlen
= *pnt
++;
4929 /* afi/safi validity already verified by caller,
4930 * bgp_update_receive */
4931 p
.family
= afi2family(afi
);
4933 /* Prefix length check. */
4934 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4937 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4938 peer
->host
, p
.prefixlen
, packet
->afi
);
4939 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4942 /* Packet size overflow check. */
4943 psize
= PSIZE(p
.prefixlen
);
4945 /* When packet overflow occur return immediately. */
4946 if (pnt
+ psize
> lim
) {
4949 "%s [Error] Update packet error (prefix length %d overflows packet)",
4950 peer
->host
, p
.prefixlen
);
4951 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4954 /* Defensive coding, double-check the psize fits in a struct
4956 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4959 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4960 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4961 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4964 /* Fetch prefix from NLRI packet. */
4965 memcpy(p
.u
.val
, pnt
, psize
);
4967 /* Check address. */
4968 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4969 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4970 /* From RFC4271 Section 6.3:
4972 * If a prefix in the NLRI field is semantically
4974 * (e.g., an unexpected multicast IP address),
4976 * be logged locally, and the prefix SHOULD be
4981 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4982 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4987 /* Check address. */
4988 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4989 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4994 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4996 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5001 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5006 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5008 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5015 /* Normal process. */
5017 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5018 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5019 NULL
, NULL
, 0, 0, NULL
);
5021 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5022 safi
, ZEBRA_ROUTE_BGP
,
5023 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5026 /* Do not send BGP notification twice when maximum-prefix count
5028 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5029 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5031 /* Address family configuration mismatch. */
5033 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5036 /* Packet length consistency check. */
5040 "%s [Error] Update packet error (prefix length mismatch with total length)",
5042 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5045 return BGP_NLRI_PARSE_OK
;
5048 static struct bgp_static
*bgp_static_new(void)
5050 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5053 static void bgp_static_free(struct bgp_static
*bgp_static
)
5055 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5056 route_map_counter_decrement(bgp_static
->rmap
.map
);
5058 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5059 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5062 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5063 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5065 struct bgp_dest
*dest
;
5066 struct bgp_path_info
*pi
;
5067 struct bgp_path_info
*new;
5068 struct bgp_path_info rmap_path
;
5070 struct attr
*attr_new
;
5071 route_map_result_t ret
;
5072 #ifdef ENABLE_BGP_VNC
5073 int vnc_implicit_withdraw
= 0;
5078 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5080 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5082 attr
.nexthop
= bgp_static
->igpnexthop
;
5083 attr
.med
= bgp_static
->igpmetric
;
5084 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5086 if (bgp_static
->atomic
)
5087 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5089 /* Store label index, if required. */
5090 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5091 attr
.label_index
= bgp_static
->label_index
;
5092 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5095 /* Apply route-map. */
5096 if (bgp_static
->rmap
.name
) {
5097 struct attr attr_tmp
= attr
;
5099 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5100 rmap_path
.peer
= bgp
->peer_self
;
5101 rmap_path
.attr
= &attr_tmp
;
5103 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5105 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5108 bgp
->peer_self
->rmap_type
= 0;
5110 if (ret
== RMAP_DENYMATCH
) {
5111 /* Free uninterned attribute. */
5112 bgp_attr_flush(&attr_tmp
);
5114 /* Unintern original. */
5115 aspath_unintern(&attr
.aspath
);
5116 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5120 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
5121 bgp_attr_add_gshut_community(&attr_tmp
);
5123 attr_new
= bgp_attr_intern(&attr_tmp
);
5126 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
5127 bgp_attr_add_gshut_community(&attr
);
5129 attr_new
= bgp_attr_intern(&attr
);
5132 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5133 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5134 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5138 if (attrhash_cmp(pi
->attr
, attr_new
)
5139 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5140 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5141 bgp_dest_unlock_node(dest
);
5142 bgp_attr_unintern(&attr_new
);
5143 aspath_unintern(&attr
.aspath
);
5146 /* The attribute is changed. */
5147 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5149 /* Rewrite BGP route information. */
5150 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5151 bgp_path_info_restore(dest
, pi
);
5153 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5154 #ifdef ENABLE_BGP_VNC
5155 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5156 && (safi
== SAFI_UNICAST
)) {
5157 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5159 * Implicit withdraw case.
5160 * We have to do this before pi is
5163 ++vnc_implicit_withdraw
;
5164 vnc_import_bgp_del_route(bgp
, p
, pi
);
5165 vnc_import_bgp_exterior_del_route(
5170 bgp_attr_unintern(&pi
->attr
);
5171 pi
->attr
= attr_new
;
5172 pi
->uptime
= bgp_clock();
5173 #ifdef ENABLE_BGP_VNC
5174 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5175 && (safi
== SAFI_UNICAST
)) {
5176 if (vnc_implicit_withdraw
) {
5177 vnc_import_bgp_add_route(bgp
, p
, pi
);
5178 vnc_import_bgp_exterior_add_route(
5184 /* Nexthop reachability check. */
5185 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5186 && (safi
== SAFI_UNICAST
5187 || safi
== SAFI_LABELED_UNICAST
)) {
5189 struct bgp
*bgp_nexthop
= bgp
;
5191 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5192 bgp_nexthop
= pi
->extra
->bgp_orig
;
5194 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5196 bgp_path_info_set_flag(dest
, pi
,
5199 if (BGP_DEBUG(nht
, NHT
)) {
5200 char buf1
[INET6_ADDRSTRLEN
];
5201 inet_ntop(p
->family
,
5205 "%s(%s): Route not in table, not advertising",
5208 bgp_path_info_unset_flag(
5209 dest
, pi
, BGP_PATH_VALID
);
5212 /* Delete the NHT structure if any, if we're
5214 * enabling/disabling import check. We
5215 * deregister the route
5216 * from NHT to avoid overloading NHT and the
5217 * process interaction
5219 bgp_unlink_nexthop(pi
);
5220 bgp_path_info_set_flag(dest
, pi
,
5223 /* Process change. */
5224 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5225 bgp_process(bgp
, dest
, afi
, safi
);
5227 if (SAFI_UNICAST
== safi
5228 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5230 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5231 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5235 bgp_dest_unlock_node(dest
);
5236 aspath_unintern(&attr
.aspath
);
5241 /* Make new BGP info. */
5242 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5244 /* Nexthop reachability check. */
5245 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5246 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5247 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
5248 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5250 if (BGP_DEBUG(nht
, NHT
)) {
5251 char buf1
[INET6_ADDRSTRLEN
];
5252 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5255 "%s(%s): Route not in table, not advertising",
5258 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5261 /* Delete the NHT structure if any, if we're toggling between
5262 * enabling/disabling import check. We deregister the route
5263 * from NHT to avoid overloading NHT and the process interaction
5265 bgp_unlink_nexthop(new);
5267 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5270 /* Aggregate address increment. */
5271 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5273 /* Register new BGP information. */
5274 bgp_path_info_add(dest
, new);
5276 /* route_node_get lock */
5277 bgp_dest_unlock_node(dest
);
5279 /* Process change. */
5280 bgp_process(bgp
, dest
, afi
, safi
);
5282 if (SAFI_UNICAST
== safi
5283 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5284 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5285 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5288 /* Unintern original. */
5289 aspath_unintern(&attr
.aspath
);
5292 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
5295 struct bgp_dest
*dest
;
5296 struct bgp_path_info
*pi
;
5298 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5300 /* Check selected route and self inserted route. */
5301 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5302 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5303 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5306 /* Withdraw static BGP route from routing table. */
5308 if (SAFI_UNICAST
== safi
5309 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5310 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5311 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5313 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5314 bgp_unlink_nexthop(pi
);
5315 bgp_path_info_delete(dest
, pi
);
5316 bgp_process(bgp
, dest
, afi
, safi
);
5319 /* Unlock bgp_node_lookup. */
5320 bgp_dest_unlock_node(dest
);
5324 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5326 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
5327 afi_t afi
, safi_t safi
,
5328 struct prefix_rd
*prd
)
5330 struct bgp_dest
*dest
;
5331 struct bgp_path_info
*pi
;
5333 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5335 /* Check selected route and self inserted route. */
5336 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5337 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5338 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5341 /* Withdraw static BGP route from routing table. */
5343 #ifdef ENABLE_BGP_VNC
5344 rfapiProcessWithdraw(
5345 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5346 1); /* Kill, since it is an administrative change */
5348 if (SAFI_MPLS_VPN
== safi
5349 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5350 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5352 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5353 bgp_path_info_delete(dest
, pi
);
5354 bgp_process(bgp
, dest
, afi
, safi
);
5357 /* Unlock bgp_node_lookup. */
5358 bgp_dest_unlock_node(dest
);
5361 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
5362 struct bgp_static
*bgp_static
, afi_t afi
,
5365 struct bgp_dest
*dest
;
5366 struct bgp_path_info
*new;
5367 struct attr
*attr_new
;
5368 struct attr attr
= {0};
5369 struct bgp_path_info
*pi
;
5370 #ifdef ENABLE_BGP_VNC
5371 mpls_label_t label
= 0;
5373 uint32_t num_labels
= 0;
5378 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5380 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5383 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5385 attr
.nexthop
= bgp_static
->igpnexthop
;
5386 attr
.med
= bgp_static
->igpmetric
;
5387 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5389 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5390 || (safi
== SAFI_ENCAP
)) {
5391 if (afi
== AFI_IP
) {
5392 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5393 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5396 if (afi
== AFI_L2VPN
) {
5397 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5399 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5400 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5401 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5402 sizeof(struct in6_addr
));
5403 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
5404 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5405 struct bgp_encap_type_vxlan bet
;
5406 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5407 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5408 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5410 if (bgp_static
->router_mac
) {
5411 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5414 /* Apply route-map. */
5415 if (bgp_static
->rmap
.name
) {
5416 struct attr attr_tmp
= attr
;
5417 struct bgp_path_info rmap_path
;
5418 route_map_result_t ret
;
5420 rmap_path
.peer
= bgp
->peer_self
;
5421 rmap_path
.attr
= &attr_tmp
;
5423 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5425 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5428 bgp
->peer_self
->rmap_type
= 0;
5430 if (ret
== RMAP_DENYMATCH
) {
5431 /* Free uninterned attribute. */
5432 bgp_attr_flush(&attr_tmp
);
5434 /* Unintern original. */
5435 aspath_unintern(&attr
.aspath
);
5436 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5441 attr_new
= bgp_attr_intern(&attr_tmp
);
5443 attr_new
= bgp_attr_intern(&attr
);
5446 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5447 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5448 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5452 memset(&add
, 0, sizeof(union gw_addr
));
5453 if (attrhash_cmp(pi
->attr
, attr_new
)
5454 && overlay_index_equal(afi
, pi
, &add
)
5455 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5456 bgp_dest_unlock_node(dest
);
5457 bgp_attr_unintern(&attr_new
);
5458 aspath_unintern(&attr
.aspath
);
5461 /* The attribute is changed. */
5462 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5464 /* Rewrite BGP route information. */
5465 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5466 bgp_path_info_restore(dest
, pi
);
5468 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5469 bgp_attr_unintern(&pi
->attr
);
5470 pi
->attr
= attr_new
;
5471 pi
->uptime
= bgp_clock();
5472 #ifdef ENABLE_BGP_VNC
5474 label
= decode_label(&pi
->extra
->label
[0]);
5477 /* Process change. */
5478 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5479 bgp_process(bgp
, dest
, afi
, safi
);
5481 if (SAFI_MPLS_VPN
== safi
5482 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5483 vpn_leak_to_vrf_update(bgp
, pi
);
5485 #ifdef ENABLE_BGP_VNC
5486 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5487 pi
->attr
, afi
, safi
, pi
->type
,
5488 pi
->sub_type
, &label
);
5490 bgp_dest_unlock_node(dest
);
5491 aspath_unintern(&attr
.aspath
);
5497 /* Make new BGP info. */
5498 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5500 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5501 new->extra
= bgp_path_info_extra_new();
5503 new->extra
->label
[0] = bgp_static
->label
;
5504 new->extra
->num_labels
= num_labels
;
5506 #ifdef ENABLE_BGP_VNC
5507 label
= decode_label(&bgp_static
->label
);
5510 /* Aggregate address increment. */
5511 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5513 /* Register new BGP information. */
5514 bgp_path_info_add(dest
, new);
5515 /* route_node_get lock */
5516 bgp_dest_unlock_node(dest
);
5518 /* Process change. */
5519 bgp_process(bgp
, dest
, afi
, safi
);
5521 if (SAFI_MPLS_VPN
== safi
5522 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5523 vpn_leak_to_vrf_update(bgp
, new);
5525 #ifdef ENABLE_BGP_VNC
5526 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5527 safi
, new->type
, new->sub_type
, &label
);
5530 /* Unintern original. */
5531 aspath_unintern(&attr
.aspath
);
5534 /* Configure static BGP network. When user don't run zebra, static
5535 route should be installed as valid. */
5536 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5537 const char *ip_str
, afi_t afi
, safi_t safi
,
5538 const char *rmap
, int backdoor
, uint32_t label_index
)
5540 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5543 struct bgp_static
*bgp_static
;
5544 struct bgp_dest
*dest
;
5545 uint8_t need_update
= 0;
5547 /* Convert IP prefix string to struct prefix. */
5548 ret
= str2prefix(ip_str
, &p
);
5550 vty_out(vty
, "%% Malformed prefix\n");
5551 return CMD_WARNING_CONFIG_FAILED
;
5553 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5554 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5555 return CMD_WARNING_CONFIG_FAILED
;
5562 /* Set BGP static route configuration. */
5563 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5566 vty_out(vty
, "%% Can't find static route specified\n");
5567 return CMD_WARNING_CONFIG_FAILED
;
5570 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5572 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5573 && (label_index
!= bgp_static
->label_index
)) {
5575 "%% label-index doesn't match static route\n");
5576 return CMD_WARNING_CONFIG_FAILED
;
5579 if ((rmap
&& bgp_static
->rmap
.name
)
5580 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5582 "%% route-map name doesn't match static route\n");
5583 return CMD_WARNING_CONFIG_FAILED
;
5586 /* Update BGP RIB. */
5587 if (!bgp_static
->backdoor
)
5588 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5590 /* Clear configuration. */
5591 bgp_static_free(bgp_static
);
5592 bgp_dest_set_bgp_static_info(dest
, NULL
);
5593 bgp_dest_unlock_node(dest
);
5594 bgp_dest_unlock_node(dest
);
5597 /* Set BGP static route configuration. */
5598 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5599 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5601 /* Configuration change. */
5602 /* Label index cannot be changed. */
5603 if (bgp_static
->label_index
!= label_index
) {
5604 vty_out(vty
, "%% cannot change label-index\n");
5605 return CMD_WARNING_CONFIG_FAILED
;
5608 /* Check previous routes are installed into BGP. */
5609 if (bgp_static
->valid
5610 && bgp_static
->backdoor
!= backdoor
)
5613 bgp_static
->backdoor
= backdoor
;
5616 XFREE(MTYPE_ROUTE_MAP_NAME
,
5617 bgp_static
->rmap
.name
);
5618 route_map_counter_decrement(
5619 bgp_static
->rmap
.map
);
5620 bgp_static
->rmap
.name
=
5621 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5622 bgp_static
->rmap
.map
=
5623 route_map_lookup_by_name(rmap
);
5624 route_map_counter_increment(
5625 bgp_static
->rmap
.map
);
5627 XFREE(MTYPE_ROUTE_MAP_NAME
,
5628 bgp_static
->rmap
.name
);
5629 route_map_counter_decrement(
5630 bgp_static
->rmap
.map
);
5631 bgp_static
->rmap
.map
= NULL
;
5632 bgp_static
->valid
= 0;
5634 bgp_dest_unlock_node(dest
);
5636 /* New configuration. */
5637 bgp_static
= bgp_static_new();
5638 bgp_static
->backdoor
= backdoor
;
5639 bgp_static
->valid
= 0;
5640 bgp_static
->igpmetric
= 0;
5641 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5642 bgp_static
->label_index
= label_index
;
5645 XFREE(MTYPE_ROUTE_MAP_NAME
,
5646 bgp_static
->rmap
.name
);
5647 route_map_counter_decrement(
5648 bgp_static
->rmap
.map
);
5649 bgp_static
->rmap
.name
=
5650 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5651 bgp_static
->rmap
.map
=
5652 route_map_lookup_by_name(rmap
);
5653 route_map_counter_increment(
5654 bgp_static
->rmap
.map
);
5656 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5659 bgp_static
->valid
= 1;
5661 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5663 if (!bgp_static
->backdoor
)
5664 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5670 void bgp_static_add(struct bgp
*bgp
)
5674 struct bgp_dest
*dest
;
5675 struct bgp_dest
*rm
;
5676 struct bgp_table
*table
;
5677 struct bgp_static
*bgp_static
;
5679 FOREACH_AFI_SAFI (afi
, safi
)
5680 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5681 dest
= bgp_route_next(dest
)) {
5682 if (!bgp_dest_has_bgp_path_info_data(dest
))
5685 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5686 || (safi
== SAFI_EVPN
)) {
5687 table
= bgp_dest_get_bgp_table_info(dest
);
5689 for (rm
= bgp_table_top(table
); rm
;
5690 rm
= bgp_route_next(rm
)) {
5692 bgp_dest_get_bgp_static_info(
5694 bgp_static_update_safi(
5695 bgp
, bgp_dest_get_prefix(rm
),
5696 bgp_static
, afi
, safi
);
5700 bgp
, bgp_dest_get_prefix(dest
),
5701 bgp_dest_get_bgp_static_info(dest
), afi
,
5707 /* Called from bgp_delete(). Delete all static routes from the BGP
5709 void bgp_static_delete(struct bgp
*bgp
)
5713 struct bgp_dest
*dest
;
5714 struct bgp_dest
*rm
;
5715 struct bgp_table
*table
;
5716 struct bgp_static
*bgp_static
;
5718 FOREACH_AFI_SAFI (afi
, safi
)
5719 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5720 dest
= bgp_route_next(dest
)) {
5721 if (!bgp_dest_has_bgp_path_info_data(dest
))
5724 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5725 || (safi
== SAFI_EVPN
)) {
5726 table
= bgp_dest_get_bgp_table_info(dest
);
5728 for (rm
= bgp_table_top(table
); rm
;
5729 rm
= bgp_route_next(rm
)) {
5731 bgp_dest_get_bgp_static_info(
5736 bgp_static_withdraw_safi(
5737 bgp
, bgp_dest_get_prefix(rm
),
5739 (struct prefix_rd
*)
5740 bgp_dest_get_prefix(
5742 bgp_static_free(bgp_static
);
5743 bgp_dest_set_bgp_static_info(dest
,
5745 bgp_dest_unlock_node(dest
);
5748 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5749 bgp_static_withdraw(bgp
,
5750 bgp_dest_get_prefix(dest
),
5752 bgp_static_free(bgp_static
);
5753 bgp_dest_set_bgp_static_info(dest
, NULL
);
5754 bgp_dest_unlock_node(dest
);
5759 void bgp_static_redo_import_check(struct bgp
*bgp
)
5763 struct bgp_dest
*dest
;
5764 struct bgp_dest
*rm
;
5765 struct bgp_table
*table
;
5766 struct bgp_static
*bgp_static
;
5768 /* Use this flag to force reprocessing of the route */
5769 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5770 FOREACH_AFI_SAFI (afi
, safi
) {
5771 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5772 dest
= bgp_route_next(dest
)) {
5773 if (!bgp_dest_has_bgp_path_info_data(dest
))
5776 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5777 || (safi
== SAFI_EVPN
)) {
5778 table
= bgp_dest_get_bgp_table_info(dest
);
5780 for (rm
= bgp_table_top(table
); rm
;
5781 rm
= bgp_route_next(rm
)) {
5783 bgp_dest_get_bgp_static_info(
5785 bgp_static_update_safi(
5786 bgp
, bgp_dest_get_prefix(rm
),
5787 bgp_static
, afi
, safi
);
5790 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5791 bgp_static_update(bgp
,
5792 bgp_dest_get_prefix(dest
),
5793 bgp_static
, afi
, safi
);
5797 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5800 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5803 struct bgp_table
*table
;
5804 struct bgp_dest
*dest
;
5805 struct bgp_path_info
*pi
;
5807 /* Do not install the aggregate route if BGP is in the
5808 * process of termination.
5810 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
5811 || (bgp
->peer_self
== NULL
))
5814 table
= bgp
->rib
[afi
][safi
];
5815 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5816 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5817 if (pi
->peer
== bgp
->peer_self
5818 && ((pi
->type
== ZEBRA_ROUTE_BGP
5819 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5820 || (pi
->type
!= ZEBRA_ROUTE_BGP
5822 == BGP_ROUTE_REDISTRIBUTE
))) {
5823 bgp_aggregate_decrement(
5824 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
5826 bgp_unlink_nexthop(pi
);
5827 bgp_path_info_delete(dest
, pi
);
5828 bgp_process(bgp
, dest
, afi
, safi
);
5835 * Purge all networks and redistributed routes from routing table.
5836 * Invoked upon the instance going down.
5838 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5843 FOREACH_AFI_SAFI (afi
, safi
)
5844 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5849 * Currently this is used to set static routes for VPN and ENCAP.
5850 * I think it can probably be factored with bgp_static_set.
5852 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5853 const char *ip_str
, const char *rd_str
,
5854 const char *label_str
, const char *rmap_str
,
5855 int evpn_type
, const char *esi
, const char *gwip
,
5856 const char *ethtag
, const char *routermac
)
5858 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5861 struct prefix_rd prd
;
5862 struct bgp_dest
*pdest
;
5863 struct bgp_dest
*dest
;
5864 struct bgp_table
*table
;
5865 struct bgp_static
*bgp_static
;
5866 mpls_label_t label
= MPLS_INVALID_LABEL
;
5867 struct prefix gw_ip
;
5869 /* validate ip prefix */
5870 ret
= str2prefix(ip_str
, &p
);
5872 vty_out(vty
, "%% Malformed prefix\n");
5873 return CMD_WARNING_CONFIG_FAILED
;
5876 if ((afi
== AFI_L2VPN
)
5877 && (bgp_build_evpn_prefix(evpn_type
,
5878 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5879 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5880 return CMD_WARNING_CONFIG_FAILED
;
5883 ret
= str2prefix_rd(rd_str
, &prd
);
5885 vty_out(vty
, "%% Malformed rd\n");
5886 return CMD_WARNING_CONFIG_FAILED
;
5890 unsigned long label_val
;
5891 label_val
= strtoul(label_str
, NULL
, 10);
5892 encode_label(label_val
, &label
);
5895 if (safi
== SAFI_EVPN
) {
5896 if (esi
&& str2esi(esi
, NULL
) == 0) {
5897 vty_out(vty
, "%% Malformed ESI\n");
5898 return CMD_WARNING_CONFIG_FAILED
;
5900 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5901 vty_out(vty
, "%% Malformed Router MAC\n");
5902 return CMD_WARNING_CONFIG_FAILED
;
5905 memset(&gw_ip
, 0, sizeof(struct prefix
));
5906 ret
= str2prefix(gwip
, &gw_ip
);
5908 vty_out(vty
, "%% Malformed GatewayIp\n");
5909 return CMD_WARNING_CONFIG_FAILED
;
5911 if ((gw_ip
.family
== AF_INET
5912 && is_evpn_prefix_ipaddr_v6(
5913 (struct prefix_evpn
*)&p
))
5914 || (gw_ip
.family
== AF_INET6
5915 && is_evpn_prefix_ipaddr_v4(
5916 (struct prefix_evpn
*)&p
))) {
5918 "%% GatewayIp family differs with IP prefix\n");
5919 return CMD_WARNING_CONFIG_FAILED
;
5923 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5924 if (!bgp_dest_has_bgp_path_info_data(pdest
))
5925 bgp_dest_set_bgp_table_info(pdest
,
5926 bgp_table_init(bgp
, afi
, safi
));
5927 table
= bgp_dest_get_bgp_table_info(pdest
);
5929 dest
= bgp_node_get(table
, &p
);
5931 if (bgp_dest_has_bgp_path_info_data(dest
)) {
5932 vty_out(vty
, "%% Same network configuration exists\n");
5933 bgp_dest_unlock_node(dest
);
5935 /* New configuration. */
5936 bgp_static
= bgp_static_new();
5937 bgp_static
->backdoor
= 0;
5938 bgp_static
->valid
= 0;
5939 bgp_static
->igpmetric
= 0;
5940 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5941 bgp_static
->label
= label
;
5942 bgp_static
->prd
= prd
;
5945 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5946 route_map_counter_decrement(bgp_static
->rmap
.map
);
5947 bgp_static
->rmap
.name
=
5948 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5949 bgp_static
->rmap
.map
=
5950 route_map_lookup_by_name(rmap_str
);
5951 route_map_counter_increment(bgp_static
->rmap
.map
);
5954 if (safi
== SAFI_EVPN
) {
5956 bgp_static
->eth_s_id
=
5959 str2esi(esi
, bgp_static
->eth_s_id
);
5962 bgp_static
->router_mac
=
5963 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5964 (void)prefix_str2mac(routermac
,
5965 bgp_static
->router_mac
);
5968 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5970 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5972 bgp_static
->valid
= 1;
5973 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5979 /* Configure static BGP network. */
5980 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5981 const char *ip_str
, const char *rd_str
,
5982 const char *label_str
, int evpn_type
, const char *esi
,
5983 const char *gwip
, const char *ethtag
)
5985 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5988 struct prefix_rd prd
;
5989 struct bgp_dest
*pdest
;
5990 struct bgp_dest
*dest
;
5991 struct bgp_table
*table
;
5992 struct bgp_static
*bgp_static
;
5993 mpls_label_t label
= MPLS_INVALID_LABEL
;
5995 /* Convert IP prefix string to struct prefix. */
5996 ret
= str2prefix(ip_str
, &p
);
5998 vty_out(vty
, "%% Malformed prefix\n");
5999 return CMD_WARNING_CONFIG_FAILED
;
6002 if ((afi
== AFI_L2VPN
)
6003 && (bgp_build_evpn_prefix(evpn_type
,
6004 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6005 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6006 return CMD_WARNING_CONFIG_FAILED
;
6008 ret
= str2prefix_rd(rd_str
, &prd
);
6010 vty_out(vty
, "%% Malformed rd\n");
6011 return CMD_WARNING_CONFIG_FAILED
;
6015 unsigned long label_val
;
6016 label_val
= strtoul(label_str
, NULL
, 10);
6017 encode_label(label_val
, &label
);
6020 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6021 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6022 bgp_dest_set_bgp_table_info(pdest
,
6023 bgp_table_init(bgp
, afi
, safi
));
6025 bgp_dest_unlock_node(pdest
);
6026 table
= bgp_dest_get_bgp_table_info(pdest
);
6028 dest
= bgp_node_lookup(table
, &p
);
6031 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6033 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6034 bgp_static_free(bgp_static
);
6035 bgp_dest_set_bgp_static_info(dest
, NULL
);
6036 bgp_dest_unlock_node(dest
);
6037 bgp_dest_unlock_node(dest
);
6039 vty_out(vty
, "%% Can't find the route\n");
6044 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6045 const char *rmap_name
)
6047 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6048 struct bgp_rmap
*rmap
;
6050 rmap
= &bgp
->table_map
[afi
][safi
];
6052 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6053 route_map_counter_decrement(rmap
->map
);
6054 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6055 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6056 route_map_counter_increment(rmap
->map
);
6058 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6059 route_map_counter_decrement(rmap
->map
);
6063 if (bgp_fibupd_safi(safi
))
6064 bgp_zebra_announce_table(bgp
, afi
, safi
);
6069 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6070 const char *rmap_name
)
6072 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6073 struct bgp_rmap
*rmap
;
6075 rmap
= &bgp
->table_map
[afi
][safi
];
6076 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6077 route_map_counter_decrement(rmap
->map
);
6080 if (bgp_fibupd_safi(safi
))
6081 bgp_zebra_announce_table(bgp
, afi
, safi
);
6086 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6089 if (bgp
->table_map
[afi
][safi
].name
) {
6090 vty_out(vty
, " table-map %s\n",
6091 bgp
->table_map
[afi
][safi
].name
);
6095 DEFUN (bgp_table_map
,
6098 "BGP table to RIB route download filter\n"
6099 "Name of the route map\n")
6102 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6103 argv
[idx_word
]->arg
);
6105 DEFUN (no_bgp_table_map
,
6106 no_bgp_table_map_cmd
,
6107 "no table-map WORD",
6109 "BGP table to RIB route download filter\n"
6110 "Name of the route map\n")
6113 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6114 argv
[idx_word
]->arg
);
6120 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6121 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6122 backdoor$backdoor}]",
6124 "Specify a network to announce via BGP\n"
6129 "Route-map to modify the attributes\n"
6130 "Name of the route map\n"
6131 "Label index to associate with the prefix\n"
6132 "Label index value\n"
6133 "Specify a BGP backdoor route\n")
6135 char addr_prefix_str
[BUFSIZ
];
6140 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6143 vty_out(vty
, "%% Inconsistent address and mask\n");
6144 return CMD_WARNING_CONFIG_FAILED
;
6148 return bgp_static_set(
6149 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
6150 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
6151 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6154 DEFPY(ipv6_bgp_network
,
6155 ipv6_bgp_network_cmd
,
6156 "[no] network X:X::X:X/M$prefix \
6157 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6159 "Specify a network to announce via BGP\n"
6161 "Route-map to modify the attributes\n"
6162 "Name of the route map\n"
6163 "Label index to associate with the prefix\n"
6164 "Label index value\n")
6166 return bgp_static_set(
6167 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
6168 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6171 static struct bgp_aggregate
*bgp_aggregate_new(void)
6173 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6176 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6178 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6179 route_map_counter_decrement(aggregate
->rmap
.map
);
6180 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6183 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6184 struct aspath
*aspath
,
6185 struct community
*comm
,
6186 struct ecommunity
*ecomm
,
6187 struct lcommunity
*lcomm
)
6189 static struct aspath
*ae
= NULL
;
6192 ae
= aspath_empty();
6197 if (origin
!= pi
->attr
->origin
)
6200 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6203 if (!community_cmp(pi
->attr
->community
, comm
))
6206 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6209 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6212 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6218 static void bgp_aggregate_install(
6219 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6220 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6221 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6222 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6224 struct bgp_dest
*dest
;
6225 struct bgp_table
*table
;
6226 struct bgp_path_info
*pi
, *orig
, *new;
6229 table
= bgp
->rib
[afi
][safi
];
6231 dest
= bgp_node_get(table
, p
);
6233 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6234 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6235 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6238 if (aggregate
->count
> 0) {
6240 * If the aggregate information has not changed
6241 * no need to re-install it again.
6243 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6244 ecommunity
, lcommunity
)) {
6245 bgp_dest_unlock_node(dest
);
6248 aspath_free(aspath
);
6250 community_free(&community
);
6252 ecommunity_free(&ecommunity
);
6254 lcommunity_free(&lcommunity
);
6260 * Mark the old as unusable
6263 bgp_path_info_delete(dest
, pi
);
6265 attr
= bgp_attr_aggregate_intern(
6266 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6267 aggregate
, atomic_aggregate
, p
);
6270 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6274 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6275 bgp
->peer_self
, attr
, dest
);
6277 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6279 bgp_path_info_add(dest
, new);
6280 bgp_process(bgp
, dest
, afi
, safi
);
6282 for (pi
= orig
; pi
; pi
= pi
->next
)
6283 if (pi
->peer
== bgp
->peer_self
6284 && pi
->type
== ZEBRA_ROUTE_BGP
6285 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6288 /* Withdraw static BGP route from routing table. */
6290 bgp_path_info_delete(dest
, pi
);
6291 bgp_process(bgp
, dest
, afi
, safi
);
6295 bgp_dest_unlock_node(dest
);
6298 /* Update an aggregate as routes are added/removed from the BGP table */
6299 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6300 safi_t safi
, struct bgp_aggregate
*aggregate
)
6302 struct bgp_table
*table
;
6303 struct bgp_dest
*top
;
6304 struct bgp_dest
*dest
;
6306 struct aspath
*aspath
= NULL
;
6307 struct community
*community
= NULL
;
6308 struct ecommunity
*ecommunity
= NULL
;
6309 struct lcommunity
*lcommunity
= NULL
;
6310 struct bgp_path_info
*pi
;
6311 unsigned long match
= 0;
6312 uint8_t atomic_aggregate
= 0;
6314 /* If the bgp instance is being deleted or self peer is deleted
6315 * then do not create aggregate route
6317 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6318 || (bgp
->peer_self
== NULL
))
6321 /* ORIGIN attribute: If at least one route among routes that are
6322 aggregated has ORIGIN with the value INCOMPLETE, then the
6323 aggregated route must have the ORIGIN attribute with the value
6324 INCOMPLETE. Otherwise, if at least one route among routes that
6325 are aggregated has ORIGIN with the value EGP, then the aggregated
6326 route must have the origin attribute with the value EGP. In all
6327 other case the value of the ORIGIN attribute of the aggregated
6328 route is INTERNAL. */
6329 origin
= BGP_ORIGIN_IGP
;
6331 table
= bgp
->rib
[afi
][safi
];
6333 top
= bgp_node_get(table
, p
);
6334 for (dest
= bgp_node_get(table
, p
); dest
;
6335 dest
= bgp_route_next_until(dest
, top
)) {
6336 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6338 if (dest_p
->prefixlen
<= p
->prefixlen
)
6343 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6344 if (BGP_PATH_HOLDDOWN(pi
))
6348 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6349 atomic_aggregate
= 1;
6351 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6355 * summary-only aggregate route suppress
6356 * aggregated route announcements.
6358 if (aggregate
->summary_only
) {
6359 (bgp_path_info_extra_get(pi
))->suppress
++;
6360 bgp_path_info_set_flag(dest
, pi
,
6361 BGP_PATH_ATTR_CHANGED
);
6368 * If at least one route among routes that are
6369 * aggregated has ORIGIN with the value INCOMPLETE,
6370 * then the aggregated route MUST have the ORIGIN
6371 * attribute with the value INCOMPLETE. Otherwise, if
6372 * at least one route among routes that are aggregated
6373 * has ORIGIN with the value EGP, then the aggregated
6374 * route MUST have the ORIGIN attribute with the value
6377 switch (pi
->attr
->origin
) {
6378 case BGP_ORIGIN_INCOMPLETE
:
6379 aggregate
->incomplete_origin_count
++;
6381 case BGP_ORIGIN_EGP
:
6382 aggregate
->egp_origin_count
++;
6390 if (!aggregate
->as_set
)
6394 * as-set aggregate route generate origin, as path,
6395 * and community aggregation.
6397 /* Compute aggregate route's as-path.
6399 bgp_compute_aggregate_aspath_hash(aggregate
,
6402 /* Compute aggregate route's community.
6404 if (pi
->attr
->community
)
6405 bgp_compute_aggregate_community_hash(
6407 pi
->attr
->community
);
6409 /* Compute aggregate route's extended community.
6411 if (pi
->attr
->ecommunity
)
6412 bgp_compute_aggregate_ecommunity_hash(
6414 pi
->attr
->ecommunity
);
6416 /* Compute aggregate route's large community.
6418 if (pi
->attr
->lcommunity
)
6419 bgp_compute_aggregate_lcommunity_hash(
6421 pi
->attr
->lcommunity
);
6424 bgp_process(bgp
, dest
, afi
, safi
);
6426 if (aggregate
->as_set
) {
6427 bgp_compute_aggregate_aspath_val(aggregate
);
6428 bgp_compute_aggregate_community_val(aggregate
);
6429 bgp_compute_aggregate_ecommunity_val(aggregate
);
6430 bgp_compute_aggregate_lcommunity_val(aggregate
);
6434 bgp_dest_unlock_node(top
);
6437 if (aggregate
->incomplete_origin_count
> 0)
6438 origin
= BGP_ORIGIN_INCOMPLETE
;
6439 else if (aggregate
->egp_origin_count
> 0)
6440 origin
= BGP_ORIGIN_EGP
;
6442 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6443 origin
= aggregate
->origin
;
6445 if (aggregate
->as_set
) {
6446 if (aggregate
->aspath
)
6447 /* Retrieve aggregate route's as-path.
6449 aspath
= aspath_dup(aggregate
->aspath
);
6451 if (aggregate
->community
)
6452 /* Retrieve aggregate route's community.
6454 community
= community_dup(aggregate
->community
);
6456 if (aggregate
->ecommunity
)
6457 /* Retrieve aggregate route's ecommunity.
6459 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6461 if (aggregate
->lcommunity
)
6462 /* Retrieve aggregate route's lcommunity.
6464 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6467 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6468 ecommunity
, lcommunity
, atomic_aggregate
,
6472 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6473 safi_t safi
, struct bgp_aggregate
*aggregate
)
6475 struct bgp_table
*table
;
6476 struct bgp_dest
*top
;
6477 struct bgp_dest
*dest
;
6478 struct bgp_path_info
*pi
;
6479 unsigned long match
;
6481 table
= bgp
->rib
[afi
][safi
];
6483 /* If routes exists below this node, generate aggregate routes. */
6484 top
= bgp_node_get(table
, p
);
6485 for (dest
= bgp_node_get(table
, p
); dest
;
6486 dest
= bgp_route_next_until(dest
, top
)) {
6487 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6489 if (dest_p
->prefixlen
<= p
->prefixlen
)
6493 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6494 if (BGP_PATH_HOLDDOWN(pi
))
6497 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6500 if (aggregate
->summary_only
&& pi
->extra
) {
6501 pi
->extra
->suppress
--;
6503 if (pi
->extra
->suppress
== 0) {
6504 bgp_path_info_set_flag(
6506 BGP_PATH_ATTR_CHANGED
);
6512 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6513 aggregate
->incomplete_origin_count
--;
6514 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6515 aggregate
->egp_origin_count
--;
6517 if (aggregate
->as_set
) {
6518 /* Remove as-path from aggregate.
6520 bgp_remove_aspath_from_aggregate_hash(
6524 if (pi
->attr
->community
)
6525 /* Remove community from aggregate.
6527 bgp_remove_comm_from_aggregate_hash(
6529 pi
->attr
->community
);
6531 if (pi
->attr
->ecommunity
)
6532 /* Remove ecommunity from aggregate.
6534 bgp_remove_ecomm_from_aggregate_hash(
6536 pi
->attr
->ecommunity
);
6538 if (pi
->attr
->lcommunity
)
6539 /* Remove lcommunity from aggregate.
6541 bgp_remove_lcomm_from_aggregate_hash(
6543 pi
->attr
->lcommunity
);
6547 /* If this node was suppressed, process the change. */
6549 bgp_process(bgp
, dest
, afi
, safi
);
6551 if (aggregate
->as_set
) {
6552 aspath_free(aggregate
->aspath
);
6553 aggregate
->aspath
= NULL
;
6554 if (aggregate
->community
)
6555 community_free(&aggregate
->community
);
6556 if (aggregate
->ecommunity
)
6557 ecommunity_free(&aggregate
->ecommunity
);
6558 if (aggregate
->lcommunity
)
6559 lcommunity_free(&aggregate
->lcommunity
);
6562 bgp_dest_unlock_node(top
);
6565 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
6566 const struct prefix
*aggr_p
,
6567 struct bgp_path_info
*pinew
, afi_t afi
,
6569 struct bgp_aggregate
*aggregate
)
6572 struct aspath
*aspath
= NULL
;
6573 uint8_t atomic_aggregate
= 0;
6574 struct community
*community
= NULL
;
6575 struct ecommunity
*ecommunity
= NULL
;
6576 struct lcommunity
*lcommunity
= NULL
;
6578 /* ORIGIN attribute: If at least one route among routes that are
6579 * aggregated has ORIGIN with the value INCOMPLETE, then the
6580 * aggregated route must have the ORIGIN attribute with the value
6581 * INCOMPLETE. Otherwise, if at least one route among routes that
6582 * are aggregated has ORIGIN with the value EGP, then the aggregated
6583 * route must have the origin attribute with the value EGP. In all
6584 * other case the value of the ORIGIN attribute of the aggregated
6585 * route is INTERNAL.
6587 origin
= BGP_ORIGIN_IGP
;
6591 if (aggregate
->summary_only
)
6592 (bgp_path_info_extra_get(pinew
))->suppress
++;
6594 switch (pinew
->attr
->origin
) {
6595 case BGP_ORIGIN_INCOMPLETE
:
6596 aggregate
->incomplete_origin_count
++;
6598 case BGP_ORIGIN_EGP
:
6599 aggregate
->egp_origin_count
++;
6607 if (aggregate
->incomplete_origin_count
> 0)
6608 origin
= BGP_ORIGIN_INCOMPLETE
;
6609 else if (aggregate
->egp_origin_count
> 0)
6610 origin
= BGP_ORIGIN_EGP
;
6612 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6613 origin
= aggregate
->origin
;
6615 if (aggregate
->as_set
) {
6616 /* Compute aggregate route's as-path.
6618 bgp_compute_aggregate_aspath(aggregate
,
6619 pinew
->attr
->aspath
);
6621 /* Compute aggregate route's community.
6623 if (pinew
->attr
->community
)
6624 bgp_compute_aggregate_community(
6626 pinew
->attr
->community
);
6628 /* Compute aggregate route's extended community.
6630 if (pinew
->attr
->ecommunity
)
6631 bgp_compute_aggregate_ecommunity(
6633 pinew
->attr
->ecommunity
);
6635 /* Compute aggregate route's large community.
6637 if (pinew
->attr
->lcommunity
)
6638 bgp_compute_aggregate_lcommunity(
6640 pinew
->attr
->lcommunity
);
6642 /* Retrieve aggregate route's as-path.
6644 if (aggregate
->aspath
)
6645 aspath
= aspath_dup(aggregate
->aspath
);
6647 /* Retrieve aggregate route's community.
6649 if (aggregate
->community
)
6650 community
= community_dup(aggregate
->community
);
6652 /* Retrieve aggregate route's ecommunity.
6654 if (aggregate
->ecommunity
)
6655 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6657 /* Retrieve aggregate route's lcommunity.
6659 if (aggregate
->lcommunity
)
6660 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6663 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6664 aspath
, community
, ecommunity
,
6665 lcommunity
, atomic_aggregate
, aggregate
);
6668 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6670 struct bgp_path_info
*pi
,
6671 struct bgp_aggregate
*aggregate
,
6672 const struct prefix
*aggr_p
)
6675 struct aspath
*aspath
= NULL
;
6676 uint8_t atomic_aggregate
= 0;
6677 struct community
*community
= NULL
;
6678 struct ecommunity
*ecommunity
= NULL
;
6679 struct lcommunity
*lcommunity
= NULL
;
6680 unsigned long match
= 0;
6682 if (BGP_PATH_HOLDDOWN(pi
))
6685 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6688 if (aggregate
->summary_only
6690 && pi
->extra
->suppress
> 0) {
6691 pi
->extra
->suppress
--;
6693 if (pi
->extra
->suppress
== 0) {
6694 bgp_path_info_set_flag(pi
->net
, pi
,
6695 BGP_PATH_ATTR_CHANGED
);
6700 if (aggregate
->count
> 0)
6703 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6704 aggregate
->incomplete_origin_count
--;
6705 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6706 aggregate
->egp_origin_count
--;
6708 if (aggregate
->as_set
) {
6709 /* Remove as-path from aggregate.
6711 bgp_remove_aspath_from_aggregate(aggregate
,
6714 if (pi
->attr
->community
)
6715 /* Remove community from aggregate.
6717 bgp_remove_community_from_aggregate(
6719 pi
->attr
->community
);
6721 if (pi
->attr
->ecommunity
)
6722 /* Remove ecommunity from aggregate.
6724 bgp_remove_ecommunity_from_aggregate(
6726 pi
->attr
->ecommunity
);
6728 if (pi
->attr
->lcommunity
)
6729 /* Remove lcommunity from aggregate.
6731 bgp_remove_lcommunity_from_aggregate(
6733 pi
->attr
->lcommunity
);
6736 /* If this node was suppressed, process the change. */
6738 bgp_process(bgp
, pi
->net
, afi
, safi
);
6740 origin
= BGP_ORIGIN_IGP
;
6741 if (aggregate
->incomplete_origin_count
> 0)
6742 origin
= BGP_ORIGIN_INCOMPLETE
;
6743 else if (aggregate
->egp_origin_count
> 0)
6744 origin
= BGP_ORIGIN_EGP
;
6746 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6747 origin
= aggregate
->origin
;
6749 if (aggregate
->as_set
) {
6750 /* Retrieve aggregate route's as-path.
6752 if (aggregate
->aspath
)
6753 aspath
= aspath_dup(aggregate
->aspath
);
6755 /* Retrieve aggregate route's community.
6757 if (aggregate
->community
)
6758 community
= community_dup(aggregate
->community
);
6760 /* Retrieve aggregate route's ecommunity.
6762 if (aggregate
->ecommunity
)
6763 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6765 /* Retrieve aggregate route's lcommunity.
6767 if (aggregate
->lcommunity
)
6768 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6771 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6772 aspath
, community
, ecommunity
,
6773 lcommunity
, atomic_aggregate
, aggregate
);
6776 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
6777 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6779 struct bgp_dest
*child
;
6780 struct bgp_dest
*dest
;
6781 struct bgp_aggregate
*aggregate
;
6782 struct bgp_table
*table
;
6784 table
= bgp
->aggregate
[afi
][safi
];
6786 /* No aggregates configured. */
6787 if (bgp_table_top_nolock(table
) == NULL
)
6790 if (p
->prefixlen
== 0)
6793 if (BGP_PATH_HOLDDOWN(pi
))
6796 child
= bgp_node_get(table
, p
);
6798 /* Aggregate address configuration check. */
6799 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
6800 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6802 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
6803 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
6804 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
6808 bgp_dest_unlock_node(child
);
6811 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
6812 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6814 struct bgp_dest
*child
;
6815 struct bgp_dest
*dest
;
6816 struct bgp_aggregate
*aggregate
;
6817 struct bgp_table
*table
;
6819 table
= bgp
->aggregate
[afi
][safi
];
6821 /* No aggregates configured. */
6822 if (bgp_table_top_nolock(table
) == NULL
)
6825 if (p
->prefixlen
== 0)
6828 child
= bgp_node_get(table
, p
);
6830 /* Aggregate address configuration check. */
6831 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
6832 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6834 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
6835 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
6836 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
6840 bgp_dest_unlock_node(child
);
6843 /* Aggregate route attribute. */
6844 #define AGGREGATE_SUMMARY_ONLY 1
6845 #define AGGREGATE_AS_SET 1
6846 #define AGGREGATE_AS_UNSET 0
6848 static const char *bgp_origin2str(uint8_t origin
)
6851 case BGP_ORIGIN_IGP
:
6853 case BGP_ORIGIN_EGP
:
6855 case BGP_ORIGIN_INCOMPLETE
:
6856 return "incomplete";
6861 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6862 afi_t afi
, safi_t safi
)
6864 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6867 struct bgp_dest
*dest
;
6868 struct bgp_aggregate
*aggregate
;
6870 /* Convert string to prefix structure. */
6871 ret
= str2prefix(prefix_str
, &p
);
6873 vty_out(vty
, "Malformed prefix\n");
6874 return CMD_WARNING_CONFIG_FAILED
;
6878 /* Old configuration check. */
6879 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6882 "%% There is no aggregate-address configuration.\n");
6883 return CMD_WARNING_CONFIG_FAILED
;
6886 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
6887 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6888 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6889 NULL
, NULL
, 0, aggregate
);
6891 /* Unlock aggregate address configuration. */
6892 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
6894 if (aggregate
->community
)
6895 community_free(&aggregate
->community
);
6897 if (aggregate
->community_hash
) {
6898 /* Delete all communities in the hash.
6900 hash_clean(aggregate
->community_hash
,
6901 bgp_aggr_community_remove
);
6902 /* Free up the community_hash.
6904 hash_free(aggregate
->community_hash
);
6907 if (aggregate
->ecommunity
)
6908 ecommunity_free(&aggregate
->ecommunity
);
6910 if (aggregate
->ecommunity_hash
) {
6911 /* Delete all ecommunities in the hash.
6913 hash_clean(aggregate
->ecommunity_hash
,
6914 bgp_aggr_ecommunity_remove
);
6915 /* Free up the ecommunity_hash.
6917 hash_free(aggregate
->ecommunity_hash
);
6920 if (aggregate
->lcommunity
)
6921 lcommunity_free(&aggregate
->lcommunity
);
6923 if (aggregate
->lcommunity_hash
) {
6924 /* Delete all lcommunities in the hash.
6926 hash_clean(aggregate
->lcommunity_hash
,
6927 bgp_aggr_lcommunity_remove
);
6928 /* Free up the lcommunity_hash.
6930 hash_free(aggregate
->lcommunity_hash
);
6933 if (aggregate
->aspath
)
6934 aspath_free(aggregate
->aspath
);
6936 if (aggregate
->aspath_hash
) {
6937 /* Delete all as-paths in the hash.
6939 hash_clean(aggregate
->aspath_hash
,
6940 bgp_aggr_aspath_remove
);
6941 /* Free up the aspath_hash.
6943 hash_free(aggregate
->aspath_hash
);
6946 bgp_aggregate_free(aggregate
);
6947 bgp_dest_unlock_node(dest
);
6948 bgp_dest_unlock_node(dest
);
6953 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6954 safi_t safi
, const char *rmap
,
6955 uint8_t summary_only
, uint8_t as_set
,
6958 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6961 struct bgp_dest
*dest
;
6962 struct bgp_aggregate
*aggregate
;
6963 uint8_t as_set_new
= as_set
;
6965 /* Convert string to prefix structure. */
6966 ret
= str2prefix(prefix_str
, &p
);
6968 vty_out(vty
, "Malformed prefix\n");
6969 return CMD_WARNING_CONFIG_FAILED
;
6973 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6974 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6975 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6977 return CMD_WARNING_CONFIG_FAILED
;
6980 /* Old configuration check. */
6981 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6982 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
6985 vty_out(vty
, "There is already same aggregate network.\n");
6986 /* try to remove the old entry */
6987 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6989 vty_out(vty
, "Error deleting aggregate.\n");
6990 bgp_dest_unlock_node(dest
);
6991 return CMD_WARNING_CONFIG_FAILED
;
6995 /* Make aggregate address structure. */
6996 aggregate
= bgp_aggregate_new();
6997 aggregate
->summary_only
= summary_only
;
6999 /* Network operators MUST NOT locally generate any new
7000 * announcements containing AS_SET or AS_CONFED_SET. If they have
7001 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7002 * SHOULD withdraw those routes and re-announce routes for the
7003 * aggregate or component prefixes (i.e., the more-specific routes
7004 * subsumed by the previously aggregated route) without AS_SET
7005 * or AS_CONFED_SET in the updates.
7007 if (bgp
->reject_as_sets
) {
7008 if (as_set
== AGGREGATE_AS_SET
) {
7009 as_set_new
= AGGREGATE_AS_UNSET
;
7011 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7014 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7018 aggregate
->as_set
= as_set_new
;
7019 aggregate
->safi
= safi
;
7020 /* Override ORIGIN attribute if defined.
7021 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7022 * to IGP which is not what rfc4271 says.
7023 * This enables the same behavior, optionally.
7025 aggregate
->origin
= origin
;
7028 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7029 route_map_counter_decrement(aggregate
->rmap
.map
);
7030 aggregate
->rmap
.name
=
7031 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
7032 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
7033 route_map_counter_increment(aggregate
->rmap
.map
);
7035 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
7037 /* Aggregate address insert into BGP routing table. */
7038 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
7043 DEFUN (aggregate_address
,
7044 aggregate_address_cmd
,
7045 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7046 "Configure BGP aggregate entries\n"
7047 "Aggregate prefix\n"
7048 "Generate AS set path information\n"
7049 "Filter more specific routes from updates\n"
7050 "Filter more specific routes from updates\n"
7051 "Generate AS set path information\n"
7052 "Apply route map to aggregate network\n"
7053 "Name of route map\n"
7057 "Unknown heritage\n")
7060 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
7061 char *prefix
= argv
[idx
]->arg
;
7063 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
7064 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
7065 : AGGREGATE_AS_UNSET
;
7067 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
7068 ? AGGREGATE_SUMMARY_ONLY
7072 argv_find(argv
, argc
, "WORD", &idx
);
7074 rmap
= argv
[idx
]->arg
;
7077 if (argv_find(argv
, argc
, "origin", &idx
)) {
7078 if (strncmp(argv
[idx
+ 1]->arg
, "igp", 2) == 0)
7079 origin
= BGP_ORIGIN_IGP
;
7080 if (strncmp(argv
[idx
+ 1]->arg
, "egp", 1) == 0)
7081 origin
= BGP_ORIGIN_EGP
;
7082 if (strncmp(argv
[idx
+ 1]->arg
, "incomplete", 2) == 0)
7083 origin
= BGP_ORIGIN_INCOMPLETE
;
7086 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
), rmap
,
7087 summary_only
, as_set
, origin
);
7090 DEFUN (aggregate_address_mask
,
7091 aggregate_address_mask_cmd
,
7092 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7093 "Configure BGP aggregate entries\n"
7094 "Aggregate address\n"
7096 "Generate AS set path information\n"
7097 "Filter more specific routes from updates\n"
7098 "Filter more specific routes from updates\n"
7099 "Generate AS set path information\n"
7100 "Apply route map to aggregate network\n"
7101 "Name of route map\n"
7105 "Unknown heritage\n")
7108 argv_find(argv
, argc
, "A.B.C.D", &idx
);
7109 char *prefix
= argv
[idx
]->arg
;
7110 char *mask
= argv
[idx
+ 1]->arg
;
7113 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
7114 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
7115 : AGGREGATE_AS_UNSET
;
7117 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
7118 ? AGGREGATE_SUMMARY_ONLY
7121 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
7123 rmap
= argv
[idx
]->arg
;
7125 char prefix_str
[BUFSIZ
];
7126 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
7129 vty_out(vty
, "%% Inconsistent address and mask\n");
7130 return CMD_WARNING_CONFIG_FAILED
;
7134 if (argv_find(argv
, argc
, "origin", &idx
)) {
7135 if (strncmp(argv
[idx
+ 1]->arg
, "igp", 2) == 0)
7136 origin
= BGP_ORIGIN_IGP
;
7137 if (strncmp(argv
[idx
+ 1]->arg
, "egp", 1) == 0)
7138 origin
= BGP_ORIGIN_EGP
;
7139 if (strncmp(argv
[idx
+ 1]->arg
, "incomplete", 2) == 0)
7140 origin
= BGP_ORIGIN_INCOMPLETE
;
7143 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
7144 rmap
, summary_only
, as_set
, origin
);
7147 DEFUN (no_aggregate_address
,
7148 no_aggregate_address_cmd
,
7149 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7151 "Configure BGP aggregate entries\n"
7152 "Aggregate prefix\n"
7153 "Generate AS set path information\n"
7154 "Filter more specific routes from updates\n"
7155 "Filter more specific routes from updates\n"
7156 "Generate AS set path information\n"
7157 "Apply route map to aggregate network\n"
7158 "Name of route map\n"
7162 "Unknown heritage\n")
7165 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
7166 char *prefix
= argv
[idx
]->arg
;
7167 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
7170 DEFUN (no_aggregate_address_mask
,
7171 no_aggregate_address_mask_cmd
,
7172 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7174 "Configure BGP aggregate entries\n"
7175 "Aggregate address\n"
7177 "Generate AS set path information\n"
7178 "Filter more specific routes from updates\n"
7179 "Filter more specific routes from updates\n"
7180 "Generate AS set path information\n"
7181 "Apply route map to aggregate network\n"
7182 "Name of route map\n"
7186 "Unknown heritage\n")
7189 argv_find(argv
, argc
, "A.B.C.D", &idx
);
7190 char *prefix
= argv
[idx
]->arg
;
7191 char *mask
= argv
[idx
+ 1]->arg
;
7193 char prefix_str
[BUFSIZ
];
7194 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
7197 vty_out(vty
, "%% Inconsistent address and mask\n");
7198 return CMD_WARNING_CONFIG_FAILED
;
7201 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
7204 DEFUN (ipv6_aggregate_address
,
7205 ipv6_aggregate_address_cmd
,
7206 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7207 "Configure BGP aggregate entries\n"
7208 "Aggregate prefix\n"
7209 "Generate AS set path information\n"
7210 "Filter more specific routes from updates\n"
7211 "Filter more specific routes from updates\n"
7212 "Generate AS set path information\n"
7213 "Apply route map to aggregate network\n"
7214 "Name of route map\n"
7218 "Unknown heritage\n")
7221 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
7222 char *prefix
= argv
[idx
]->arg
;
7225 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
7226 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
7227 : AGGREGATE_AS_UNSET
;
7230 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
7231 ? AGGREGATE_SUMMARY_ONLY
7234 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
7236 rmap
= argv
[idx
]->arg
;
7239 if (argv_find(argv
, argc
, "origin", &idx
)) {
7240 if (strncmp(argv
[idx
+ 1]->arg
, "igp", 2) == 0)
7241 origin
= BGP_ORIGIN_IGP
;
7242 if (strncmp(argv
[idx
+ 1]->arg
, "egp", 1) == 0)
7243 origin
= BGP_ORIGIN_EGP
;
7244 if (strncmp(argv
[idx
+ 1]->arg
, "incomplete", 2) == 0)
7245 origin
= BGP_ORIGIN_INCOMPLETE
;
7248 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
7249 sum_only
, as_set
, origin
);
7252 DEFUN (no_ipv6_aggregate_address
,
7253 no_ipv6_aggregate_address_cmd
,
7254 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7256 "Configure BGP aggregate entries\n"
7257 "Aggregate prefix\n"
7258 "Generate AS set path information\n"
7259 "Filter more specific routes from updates\n"
7260 "Filter more specific routes from updates\n"
7261 "Generate AS set path information\n"
7262 "Apply route map to aggregate network\n"
7263 "Name of route map\n"
7267 "Unknown heritage\n")
7270 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
7271 char *prefix
= argv
[idx
]->arg
;
7272 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
7275 /* Redistribute route treatment. */
7276 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7277 const union g_addr
*nexthop
, ifindex_t ifindex
,
7278 enum nexthop_types_t nhtype
, uint32_t metric
,
7279 uint8_t type
, unsigned short instance
,
7282 struct bgp_path_info
*new;
7283 struct bgp_path_info
*bpi
;
7284 struct bgp_path_info rmap_path
;
7285 struct bgp_dest
*bn
;
7287 struct attr
*new_attr
;
7289 route_map_result_t ret
;
7290 struct bgp_redist
*red
;
7292 /* Make default attribute. */
7293 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7295 * This must not be NULL to satisfy Coverity SA
7297 assert(attr
.aspath
);
7300 case NEXTHOP_TYPE_IFINDEX
:
7302 case NEXTHOP_TYPE_IPV4
:
7303 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7304 attr
.nexthop
= nexthop
->ipv4
;
7306 case NEXTHOP_TYPE_IPV6
:
7307 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7308 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7309 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7311 case NEXTHOP_TYPE_BLACKHOLE
:
7312 switch (p
->family
) {
7314 attr
.nexthop
.s_addr
= INADDR_ANY
;
7317 memset(&attr
.mp_nexthop_global
, 0,
7318 sizeof(attr
.mp_nexthop_global
));
7319 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7324 attr
.nh_ifindex
= ifindex
;
7327 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
7330 afi
= family2afi(p
->family
);
7332 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7334 struct attr attr_new
;
7336 /* Copy attribute for modification. */
7339 if (red
->redist_metric_flag
)
7340 attr_new
.med
= red
->redist_metric
;
7342 /* Apply route-map. */
7343 if (red
->rmap
.name
) {
7344 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
7345 rmap_path
.peer
= bgp
->peer_self
;
7346 rmap_path
.attr
= &attr_new
;
7348 SET_FLAG(bgp
->peer_self
->rmap_type
,
7349 PEER_RMAP_TYPE_REDISTRIBUTE
);
7351 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
7354 bgp
->peer_self
->rmap_type
= 0;
7356 if (ret
== RMAP_DENYMATCH
) {
7357 /* Free uninterned attribute. */
7358 bgp_attr_flush(&attr_new
);
7360 /* Unintern original. */
7361 aspath_unintern(&attr
.aspath
);
7362 bgp_redistribute_delete(bgp
, p
, type
, instance
);
7367 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
7368 bgp_attr_add_gshut_community(&attr_new
);
7370 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7371 SAFI_UNICAST
, p
, NULL
);
7373 new_attr
= bgp_attr_intern(&attr_new
);
7375 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
7376 if (bpi
->peer
== bgp
->peer_self
7377 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
7381 /* Ensure the (source route) type is updated. */
7383 if (attrhash_cmp(bpi
->attr
, new_attr
)
7384 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
7385 bgp_attr_unintern(&new_attr
);
7386 aspath_unintern(&attr
.aspath
);
7387 bgp_dest_unlock_node(bn
);
7390 /* The attribute is changed. */
7391 bgp_path_info_set_flag(bn
, bpi
,
7392 BGP_PATH_ATTR_CHANGED
);
7394 /* Rewrite BGP route information. */
7395 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
7396 bgp_path_info_restore(bn
, bpi
);
7398 bgp_aggregate_decrement(
7399 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
7400 bgp_attr_unintern(&bpi
->attr
);
7401 bpi
->attr
= new_attr
;
7402 bpi
->uptime
= bgp_clock();
7404 /* Process change. */
7405 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
7407 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7408 bgp_dest_unlock_node(bn
);
7409 aspath_unintern(&attr
.aspath
);
7411 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7413 == BGP_INSTANCE_TYPE_DEFAULT
)) {
7415 vpn_leak_from_vrf_update(
7416 bgp_get_default(), bgp
, bpi
);
7422 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
7423 bgp
->peer_self
, new_attr
, bn
);
7424 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7426 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
7427 bgp_path_info_add(bn
, new);
7428 bgp_dest_unlock_node(bn
);
7429 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7431 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7432 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7434 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
7438 /* Unintern original. */
7439 aspath_unintern(&attr
.aspath
);
7442 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
7443 unsigned short instance
)
7446 struct bgp_dest
*dest
;
7447 struct bgp_path_info
*pi
;
7448 struct bgp_redist
*red
;
7450 afi
= family2afi(p
->family
);
7452 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7454 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7455 SAFI_UNICAST
, p
, NULL
);
7457 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7458 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
7462 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7463 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7465 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7468 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
7469 bgp_path_info_delete(dest
, pi
);
7470 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
7472 bgp_dest_unlock_node(dest
);
7476 /* Withdraw specified route type's route. */
7477 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
7478 unsigned short instance
)
7480 struct bgp_dest
*dest
;
7481 struct bgp_path_info
*pi
;
7482 struct bgp_table
*table
;
7484 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
7486 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
7487 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7488 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
7489 && pi
->instance
== instance
)
7493 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7494 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7496 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7499 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
7500 pi
, afi
, SAFI_UNICAST
);
7501 bgp_path_info_delete(dest
, pi
);
7502 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
7507 /* Static function to display route. */
7508 static void route_vty_out_route(const struct prefix
*p
, struct vty
*vty
,
7509 json_object
*json
, bool wide
)
7515 if (p
->family
== AF_INET
) {
7519 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7522 json_object_string_add(json
, "prefix",
7523 inet_ntop(p
->family
,
7526 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7527 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7528 json_object_string_add(json
, "network", buf2
);
7530 } else if (p
->family
== AF_ETHERNET
) {
7531 prefix2str(p
, buf
, PREFIX_STRLEN
);
7532 len
= vty_out(vty
, "%s", buf
);
7533 } else if (p
->family
== AF_EVPN
) {
7537 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7540 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7541 } else if (p
->family
== AF_FLOWSPEC
) {
7542 route_vty_out_flowspec(vty
, p
, NULL
,
7544 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7545 NLRI_STRING_FORMAT_MIN
, json
);
7550 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7553 json_object_string_add(json
, "prefix",
7554 inet_ntop(p
->family
,
7557 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7558 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7559 json_object_string_add(json
, "network", buf2
);
7564 len
= wide
? (45 - len
) : (17 - len
);
7566 vty_out(vty
, "\n%*s", 20, " ");
7568 vty_out(vty
, "%*s", len
, " ");
7572 enum bgp_display_type
{
7576 /* Print the short form route status for a bgp_path_info */
7577 static void route_vty_short_status_out(struct vty
*vty
,
7578 struct bgp_path_info
*path
,
7579 json_object
*json_path
)
7583 /* Route status display. */
7584 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7585 json_object_boolean_true_add(json_path
, "removed");
7587 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7588 json_object_boolean_true_add(json_path
, "stale");
7590 if (path
->extra
&& path
->extra
->suppress
)
7591 json_object_boolean_true_add(json_path
, "suppressed");
7593 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7594 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7595 json_object_boolean_true_add(json_path
, "valid");
7598 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7599 json_object_boolean_true_add(json_path
, "history");
7601 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7602 json_object_boolean_true_add(json_path
, "damped");
7604 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7605 json_object_boolean_true_add(json_path
, "bestpath");
7607 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7608 json_object_boolean_true_add(json_path
, "multipath");
7610 /* Internal route. */
7611 if ((path
->peer
->as
)
7612 && (path
->peer
->as
== path
->peer
->local_as
))
7613 json_object_string_add(json_path
, "pathFrom",
7616 json_object_string_add(json_path
, "pathFrom",
7622 /* Route status display. */
7623 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7625 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7627 else if (path
->extra
&& path
->extra
->suppress
)
7629 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7630 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7636 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7638 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7640 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7642 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7647 /* Internal route. */
7648 if (path
->peer
&& (path
->peer
->as
)
7649 && (path
->peer
->as
== path
->peer
->local_as
))
7655 static char *bgp_nexthop_hostname(struct peer
*peer
,
7656 struct bgp_nexthop_cache
*bnc
)
7659 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
7660 return peer
->hostname
;
7664 /* called from terminal list command */
7665 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
7666 struct bgp_path_info
*path
, int display
, safi_t safi
,
7667 json_object
*json_paths
, bool wide
)
7670 struct attr
*attr
= path
->attr
;
7671 json_object
*json_path
= NULL
;
7672 json_object
*json_nexthops
= NULL
;
7673 json_object
*json_nexthop_global
= NULL
;
7674 json_object
*json_nexthop_ll
= NULL
;
7675 json_object
*json_ext_community
= NULL
;
7676 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7678 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7679 bool nexthop_othervrf
= false;
7680 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7681 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7682 char *nexthop_hostname
=
7683 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
7684 char esi_buf
[ESI_STR_LEN
];
7687 json_path
= json_object_new_object();
7689 /* short status lead text */
7690 route_vty_short_status_out(vty
, path
, json_path
);
7693 /* print prefix and mask */
7695 route_vty_out_route(p
, vty
, json_path
, wide
);
7697 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
7699 route_vty_out_route(p
, vty
, json_path
, wide
);
7703 * If vrf id of nexthop is different from that of prefix,
7704 * set up printable string to append
7706 if (path
->extra
&& path
->extra
->bgp_orig
) {
7707 const char *self
= "";
7712 nexthop_othervrf
= true;
7713 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7715 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7716 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7717 "@%s%s", VRFID_NONE_STR
, self
);
7719 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7720 path
->extra
->bgp_orig
->vrf_id
, self
);
7722 if (path
->extra
->bgp_orig
->inst_type
7723 != BGP_INSTANCE_TYPE_DEFAULT
)
7725 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7727 const char *self
= "";
7732 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7736 * For ENCAP and EVPN routes, nexthop address family is not
7737 * neccessarily the same as the prefix address family.
7738 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7739 * EVPN routes are also exchanged with a MP nexthop. Currently,
7741 * is only IPv4, the value will be present in either
7743 * attr->mp_nexthop_global_in
7745 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7748 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7752 snprintf(nexthop
, sizeof(nexthop
), "%s",
7753 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7757 snprintf(nexthop
, sizeof(nexthop
), "%s",
7758 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7762 snprintf(nexthop
, sizeof(nexthop
), "?");
7767 json_nexthop_global
= json_object_new_object();
7769 json_object_string_add(json_nexthop_global
, "ip",
7772 if (path
->peer
->hostname
)
7773 json_object_string_add(json_nexthop_global
,
7775 path
->peer
->hostname
);
7777 json_object_string_add(json_nexthop_global
, "afi",
7778 (af
== AF_INET
) ? "ipv4"
7780 json_object_boolean_true_add(json_nexthop_global
,
7783 if (nexthop_hostname
)
7784 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
7785 nexthop_hostname
, vrf_id_str
);
7787 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
7789 len
= wide
? (41 - len
) : (16 - len
);
7791 vty_out(vty
, "\n%*s", 36, " ");
7793 vty_out(vty
, "%*s", len
, " ");
7795 } else if (safi
== SAFI_EVPN
) {
7797 json_nexthop_global
= json_object_new_object();
7799 json_object_string_add(json_nexthop_global
, "ip",
7800 inet_ntoa(attr
->nexthop
));
7802 if (path
->peer
->hostname
)
7803 json_object_string_add(json_nexthop_global
,
7805 path
->peer
->hostname
);
7807 json_object_string_add(json_nexthop_global
, "afi",
7809 json_object_boolean_true_add(json_nexthop_global
,
7812 if (nexthop_hostname
)
7813 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
7814 nexthop_hostname
, vrf_id_str
);
7816 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
7819 len
= wide
? (41 - len
) : (16 - len
);
7821 vty_out(vty
, "\n%*s", 36, " ");
7823 vty_out(vty
, "%*s", len
, " ");
7825 } else if (safi
== SAFI_FLOWSPEC
) {
7826 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
7828 json_nexthop_global
= json_object_new_object();
7830 json_object_string_add(json_nexthop_global
,
7832 json_object_string_add(
7833 json_nexthop_global
, "ip",
7834 inet_ntoa(attr
->nexthop
));
7836 if (path
->peer
->hostname
)
7837 json_object_string_add(
7838 json_nexthop_global
, "hostname",
7839 path
->peer
->hostname
);
7841 json_object_boolean_true_add(
7842 json_nexthop_global
,
7845 if (nexthop_hostname
)
7846 len
= vty_out(vty
, "%pI4(%s)%s",
7851 len
= vty_out(vty
, "%pI4%s",
7855 len
= wide
? (41 - len
) : (16 - len
);
7857 vty_out(vty
, "\n%*s", 36, " ");
7859 vty_out(vty
, "%*s", len
, " ");
7862 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7864 json_nexthop_global
= json_object_new_object();
7866 json_object_string_add(json_nexthop_global
, "ip",
7867 inet_ntoa(attr
->nexthop
));
7869 if (path
->peer
->hostname
)
7870 json_object_string_add(json_nexthop_global
,
7872 path
->peer
->hostname
);
7874 json_object_string_add(json_nexthop_global
, "afi",
7876 json_object_boolean_true_add(json_nexthop_global
,
7879 if (nexthop_hostname
)
7880 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
7881 nexthop_hostname
, vrf_id_str
);
7883 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
7886 len
= wide
? (41 - len
) : (16 - len
);
7888 vty_out(vty
, "\n%*s", 36, " ");
7890 vty_out(vty
, "%*s", len
, " ");
7895 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7899 json_nexthop_global
= json_object_new_object();
7900 json_object_string_add(
7901 json_nexthop_global
, "ip",
7902 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7905 if (path
->peer
->hostname
)
7906 json_object_string_add(json_nexthop_global
,
7908 path
->peer
->hostname
);
7910 json_object_string_add(json_nexthop_global
, "afi",
7912 json_object_string_add(json_nexthop_global
, "scope",
7915 /* We display both LL & GL if both have been
7917 if ((attr
->mp_nexthop_len
7918 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7919 || (path
->peer
->conf_if
)) {
7920 json_nexthop_ll
= json_object_new_object();
7921 json_object_string_add(
7922 json_nexthop_ll
, "ip",
7924 &attr
->mp_nexthop_local
, buf
,
7927 if (path
->peer
->hostname
)
7928 json_object_string_add(
7929 json_nexthop_ll
, "hostname",
7930 path
->peer
->hostname
);
7932 json_object_string_add(json_nexthop_ll
, "afi",
7934 json_object_string_add(json_nexthop_ll
, "scope",
7937 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7938 &attr
->mp_nexthop_local
)
7940 && !attr
->mp_nexthop_prefer_global
)
7941 json_object_boolean_true_add(
7942 json_nexthop_ll
, "used");
7944 json_object_boolean_true_add(
7945 json_nexthop_global
, "used");
7947 json_object_boolean_true_add(
7948 json_nexthop_global
, "used");
7950 /* Display LL if LL/Global both in table unless
7951 * prefer-global is set */
7952 if (((attr
->mp_nexthop_len
7953 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7954 && !attr
->mp_nexthop_prefer_global
)
7955 || (path
->peer
->conf_if
)) {
7956 if (path
->peer
->conf_if
) {
7957 len
= vty_out(vty
, "%s",
7958 path
->peer
->conf_if
);
7959 /* len of IPv6 addr + max len of def
7961 len
= wide
? (41 - len
) : (16 - len
);
7964 vty_out(vty
, "\n%*s", 36, " ");
7966 vty_out(vty
, "%*s", len
, " ");
7968 if (nexthop_hostname
)
7971 &attr
->mp_nexthop_local
,
7977 &attr
->mp_nexthop_local
,
7980 len
= wide
? (41 - len
) : (16 - len
);
7983 vty_out(vty
, "\n%*s", 36, " ");
7985 vty_out(vty
, "%*s", len
, " ");
7988 if (nexthop_hostname
)
7989 len
= vty_out(vty
, "%pI6(%s)%s",
7990 &attr
->mp_nexthop_global
,
7994 len
= vty_out(vty
, "%pI6%s",
7995 &attr
->mp_nexthop_global
,
7998 len
= wide
? (41 - len
) : (16 - len
);
8001 vty_out(vty
, "\n%*s", 36, " ");
8003 vty_out(vty
, "%*s", len
, " ");
8009 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8011 json_object_int_add(json_path
, "metric", attr
->med
);
8013 vty_out(vty
, "%7u", attr
->med
);
8015 vty_out(vty
, "%10u", attr
->med
);
8016 else if (!json_paths
) {
8018 vty_out(vty
, "%*s", 7, " ");
8020 vty_out(vty
, "%*s", 10, " ");
8024 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8026 json_object_int_add(json_path
, "locPrf",
8029 vty_out(vty
, "%7u", attr
->local_pref
);
8030 else if (!json_paths
)
8034 json_object_int_add(json_path
, "weight", attr
->weight
);
8036 vty_out(vty
, "%7u ", attr
->weight
);
8040 json_object_string_add(
8041 json_path
, "peerId",
8042 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
8048 json_object_string_add(json_path
, "path",
8051 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8056 json_object_string_add(json_path
, "origin",
8057 bgp_origin_long_str
[attr
->origin
]);
8059 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8062 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8063 json_object_string_add(json_path
, "esi",
8064 esi_to_str(&attr
->esi
,
8065 esi_buf
, sizeof(esi_buf
)));
8067 if (safi
== SAFI_EVPN
&&
8068 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8069 json_ext_community
= json_object_new_object();
8070 json_object_string_add(json_ext_community
,
8072 attr
->ecommunity
->str
);
8073 json_object_object_add(json_path
,
8074 "extendedCommunity",
8075 json_ext_community
);
8079 json_object_boolean_true_add(json_path
,
8080 "announceNexthopSelf");
8081 if (nexthop_othervrf
) {
8082 json_object_string_add(json_path
, "nhVrfName",
8085 json_object_int_add(json_path
, "nhVrfId",
8086 ((nexthop_vrfid
== VRF_UNKNOWN
)
8088 : (int)nexthop_vrfid
));
8093 if (json_nexthop_global
|| json_nexthop_ll
) {
8094 json_nexthops
= json_object_new_array();
8096 if (json_nexthop_global
)
8097 json_object_array_add(json_nexthops
,
8098 json_nexthop_global
);
8100 if (json_nexthop_ll
)
8101 json_object_array_add(json_nexthops
,
8104 json_object_object_add(json_path
, "nexthops",
8108 json_object_array_add(json_paths
, json_path
);
8112 if (safi
== SAFI_EVPN
) {
8113 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8114 vty_out(vty
, "%*s", 20, " ");
8115 vty_out(vty
, "ESI:%s\n",
8116 esi_to_str(&attr
->esi
,
8117 esi_buf
, sizeof(esi_buf
)));
8120 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8121 vty_out(vty
, "%*s", 20, " ");
8122 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
8126 #ifdef ENABLE_BGP_VNC
8127 /* prints an additional line, indented, with VNC info, if
8129 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
8130 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
8135 /* called from terminal list command */
8136 void route_vty_out_tmp(struct vty
*vty
, const struct prefix
*p
,
8137 struct attr
*attr
, safi_t safi
, bool use_json
,
8138 json_object
*json_ar
, bool wide
)
8140 json_object
*json_status
= NULL
;
8141 json_object
*json_net
= NULL
;
8145 /* Route status display. */
8147 json_status
= json_object_new_object();
8148 json_net
= json_object_new_object();
8155 /* print prefix and mask */
8157 if (safi
== SAFI_EVPN
)
8158 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
8159 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
8160 json_object_string_add(
8161 json_net
, "addrPrefix",
8162 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
8164 json_object_int_add(json_net
, "prefixLen",
8166 prefix2str(p
, buff
, PREFIX_STRLEN
);
8167 json_object_string_add(json_net
, "network", buff
);
8170 route_vty_out_route(p
, vty
, NULL
, wide
);
8172 /* Print attribute */
8175 if (p
->family
== AF_INET
8176 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8177 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8178 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8179 json_object_string_add(
8180 json_net
, "nextHop",
8182 attr
->mp_nexthop_global_in
));
8184 json_object_string_add(
8185 json_net
, "nextHop",
8186 inet_ntoa(attr
->nexthop
));
8187 } else if (p
->family
== AF_INET6
8188 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8191 json_object_string_add(
8192 json_net
, "nextHopGlobal",
8194 &attr
->mp_nexthop_global
, buf
,
8196 } else if (p
->family
== AF_EVPN
&&
8197 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8198 json_object_string_add(json_net
,
8199 "nextHop", inet_ntoa(
8200 attr
->mp_nexthop_global_in
));
8203 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8204 json_object_int_add(json_net
, "metric",
8207 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8208 json_object_int_add(json_net
, "locPrf",
8211 json_object_int_add(json_net
, "weight", attr
->weight
);
8215 json_object_string_add(json_net
, "path",
8219 json_object_string_add(json_net
, "bgpOriginCode",
8220 bgp_origin_str
[attr
->origin
]);
8222 if (p
->family
== AF_INET
8223 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8224 || safi
== SAFI_EVPN
8225 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8226 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8227 || safi
== SAFI_EVPN
)
8228 vty_out(vty
, "%-16s",
8230 attr
->mp_nexthop_global_in
));
8232 vty_out(vty
, "%-41s",
8233 inet_ntoa(attr
->nexthop
));
8235 vty_out(vty
, "%-16s",
8236 inet_ntoa(attr
->nexthop
));
8237 } else if (p
->family
== AF_INET6
8238 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8244 &attr
->mp_nexthop_global
, buf
,
8246 len
= wide
? (41 - len
) : (16 - len
);
8248 vty_out(vty
, "\n%*s", 36, " ");
8250 vty_out(vty
, "%*s", len
, " ");
8253 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8255 vty_out(vty
, "%7u", attr
->med
);
8257 vty_out(vty
, "%10u", attr
->med
);
8263 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8264 vty_out(vty
, "%7u", attr
->local_pref
);
8268 vty_out(vty
, "%7u ", attr
->weight
);
8272 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8275 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8279 json_object_boolean_true_add(json_status
, "*");
8280 json_object_boolean_true_add(json_status
, ">");
8281 json_object_object_add(json_net
, "appliedStatusSymbols",
8284 prefix2str(p
, buff
, PREFIX_STRLEN
);
8285 json_object_object_add(json_ar
, buff
, json_net
);
8290 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
8291 struct bgp_path_info
*path
, int display
, safi_t safi
,
8294 json_object
*json_out
= NULL
;
8296 mpls_label_t label
= MPLS_INVALID_LABEL
;
8302 json_out
= json_object_new_object();
8304 /* short status lead text */
8305 route_vty_short_status_out(vty
, path
, json_out
);
8307 /* print prefix and mask */
8310 route_vty_out_route(p
, vty
, NULL
, false);
8312 vty_out(vty
, "%*s", 17, " ");
8315 /* Print attribute */
8317 if (((p
->family
== AF_INET
)
8318 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8319 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8320 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8321 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8322 || safi
== SAFI_EVPN
) {
8324 json_object_string_add(
8325 json_out
, "mpNexthopGlobalIn",
8326 inet_ntoa(attr
->mp_nexthop_global_in
));
8328 vty_out(vty
, "%-16s",
8329 inet_ntoa(attr
->mp_nexthop_global_in
));
8332 json_object_string_add(
8333 json_out
, "nexthop",
8334 inet_ntoa(attr
->nexthop
));
8336 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
8338 } else if (((p
->family
== AF_INET6
)
8339 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8340 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8341 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8344 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
8346 json_object_string_add(
8347 json_out
, "mpNexthopGlobalIn",
8349 &attr
->mp_nexthop_global
,
8350 buf_a
, sizeof(buf_a
)));
8354 &attr
->mp_nexthop_global
,
8355 buf_a
, sizeof(buf_a
)));
8356 } else if (attr
->mp_nexthop_len
8357 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8358 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
8359 &attr
->mp_nexthop_global
,
8360 &attr
->mp_nexthop_local
);
8362 json_object_string_add(json_out
,
8363 "mpNexthopGlobalLocal",
8366 vty_out(vty
, "%s", buf_a
);
8370 label
= decode_label(&path
->extra
->label
[0]);
8372 if (bgp_is_valid_label(&label
)) {
8374 json_object_int_add(json_out
, "notag", label
);
8375 json_object_array_add(json
, json_out
);
8377 vty_out(vty
, "notag/%d", label
);
8383 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
8384 struct bgp_path_info
*path
, int display
,
8385 json_object
*json_paths
)
8388 char buf
[BUFSIZ
] = {0};
8389 json_object
*json_path
= NULL
;
8390 json_object
*json_nexthop
= NULL
;
8391 json_object
*json_overlay
= NULL
;
8397 json_path
= json_object_new_object();
8398 json_overlay
= json_object_new_object();
8399 json_nexthop
= json_object_new_object();
8402 /* short status lead text */
8403 route_vty_short_status_out(vty
, path
, json_path
);
8405 /* print prefix and mask */
8407 route_vty_out_route(p
, vty
, json_path
, false);
8409 vty_out(vty
, "%*s", 17, " ");
8411 /* Print attribute */
8414 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8418 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
8420 vty_out(vty
, "%-16s", buf
);
8422 json_object_string_add(json_nexthop
, "ip", buf
);
8424 json_object_string_add(json_nexthop
, "afi", "ipv4");
8426 json_object_object_add(json_path
, "nexthop",
8431 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
8432 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
8434 vty_out(vty
, "%s(%s)", buf
, buf1
);
8436 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
8438 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
8441 json_object_string_add(json_nexthop
, "afi", "ipv6");
8443 json_object_object_add(json_path
, "nexthop",
8451 json_object_string_add(json_nexthop
, "Error",
8452 "Unsupported address-family");
8456 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
8457 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
8459 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
8460 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
8465 vty_out(vty
, "/%s", buf
);
8467 json_object_string_add(json_overlay
, "gw", buf
);
8469 if (attr
->ecommunity
) {
8471 struct ecommunity_val
*routermac
= ecommunity_lookup(
8472 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
8473 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
8476 mac
= ecom_mac2str((char *)routermac
->val
);
8479 vty_out(vty
, "/%s", mac
);
8481 json_object_string_add(json_overlay
, "rmac",
8484 XFREE(MTYPE_TMP
, mac
);
8491 json_object_object_add(json_path
, "overlay", json_overlay
);
8493 json_object_array_add(json_paths
, json_path
);
8497 /* dampening route */
8498 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8499 struct bgp_path_info
*path
, int display
,
8500 afi_t afi
, safi_t safi
, bool use_json
,
8505 char timebuf
[BGP_UPTIME_LEN
];
8507 /* short status lead text */
8508 route_vty_short_status_out(vty
, path
, json
);
8510 /* print prefix and mask */
8513 route_vty_out_route(p
, vty
, NULL
, false);
8515 vty_out(vty
, "%*s", 17, " ");
8518 len
= vty_out(vty
, "%s", path
->peer
->host
);
8522 vty_out(vty
, "\n%*s", 34, " ");
8525 json_object_int_add(json
, "peerHost", len
);
8527 vty_out(vty
, "%*s", len
, " ");
8531 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8532 safi
, use_json
, json
);
8535 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8536 BGP_UPTIME_LEN
, afi
, safi
,
8539 /* Print attribute */
8545 json_object_string_add(json
, "asPath",
8548 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8553 json_object_string_add(json
, "origin",
8554 bgp_origin_str
[attr
->origin
]);
8556 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8563 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8564 struct bgp_path_info
*path
, int display
,
8565 afi_t afi
, safi_t safi
, bool use_json
,
8569 struct bgp_damp_info
*bdi
;
8570 char timebuf
[BGP_UPTIME_LEN
];
8576 bdi
= path
->extra
->damp_info
;
8578 /* short status lead text */
8579 route_vty_short_status_out(vty
, path
, json
);
8581 /* print prefix and mask */
8584 route_vty_out_route(p
, vty
, NULL
, false);
8586 vty_out(vty
, "%*s", 17, " ");
8589 len
= vty_out(vty
, "%s", path
->peer
->host
);
8593 vty_out(vty
, "\n%*s", 33, " ");
8596 json_object_int_add(json
, "peerHost", len
);
8598 vty_out(vty
, "%*s", len
, " ");
8601 len
= vty_out(vty
, "%d", bdi
->flap
);
8608 json_object_int_add(json
, "bdiFlap", len
);
8610 vty_out(vty
, "%*s", len
, " ");
8614 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8617 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8618 BGP_UPTIME_LEN
, 0, NULL
));
8620 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8621 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8623 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8624 BGP_UPTIME_LEN
, afi
, safi
,
8628 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8629 BGP_UPTIME_LEN
, afi
,
8630 safi
, use_json
, json
));
8633 vty_out(vty
, "%*s ", 8, " ");
8636 /* Print attribute */
8642 json_object_string_add(json
, "asPath",
8645 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8650 json_object_string_add(json
, "origin",
8651 bgp_origin_str
[attr
->origin
]);
8653 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8659 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8660 int *first
, const char *header
,
8661 json_object
*json_adv_to
)
8663 char buf1
[INET6_ADDRSTRLEN
];
8664 json_object
*json_peer
= NULL
;
8667 /* 'advertised-to' is a dictionary of peers we have advertised
8669 * prefix too. The key is the peer's IP or swpX, the value is
8671 * hostname if we know it and "" if not.
8673 json_peer
= json_object_new_object();
8676 json_object_string_add(json_peer
, "hostname",
8680 json_object_object_add(json_adv_to
, peer
->conf_if
,
8683 json_object_object_add(
8685 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8689 vty_out(vty
, "%s", header
);
8694 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
8696 vty_out(vty
, " %s(%s)", peer
->hostname
,
8699 vty_out(vty
, " %s(%s)", peer
->hostname
,
8700 sockunion2str(&peer
->su
, buf1
,
8704 vty_out(vty
, " %s", peer
->conf_if
);
8707 sockunion2str(&peer
->su
, buf1
,
8713 static void route_vty_out_tx_ids(struct vty
*vty
,
8714 struct bgp_addpath_info_data
*d
)
8718 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8719 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8720 d
->addpath_tx_id
[i
],
8721 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8725 static const char *bgp_path_selection_reason2str(
8726 enum bgp_path_selection_reason reason
)
8729 case bgp_path_selection_none
:
8730 return "Nothing to Select";
8731 case bgp_path_selection_first
:
8732 return "First path received";
8733 case bgp_path_selection_evpn_sticky_mac
:
8734 return "EVPN Sticky Mac";
8735 case bgp_path_selection_evpn_seq
:
8736 return "EVPN sequence number";
8737 case bgp_path_selection_evpn_lower_ip
:
8738 return "EVPN lower IP";
8739 case bgp_path_selection_evpn_local_path
:
8740 return "EVPN local ES path";
8741 case bgp_path_selection_evpn_non_proxy
:
8742 return "EVPN non proxy";
8743 case bgp_path_selection_weight
:
8745 case bgp_path_selection_local_pref
:
8746 return "Local Pref";
8747 case bgp_path_selection_local_route
:
8748 return "Local Route";
8749 case bgp_path_selection_confed_as_path
:
8750 return "Confederation based AS Path";
8751 case bgp_path_selection_as_path
:
8753 case bgp_path_selection_origin
:
8755 case bgp_path_selection_med
:
8757 case bgp_path_selection_peer
:
8759 case bgp_path_selection_confed
:
8760 return "Confed Peer Type";
8761 case bgp_path_selection_igp_metric
:
8762 return "IGP Metric";
8763 case bgp_path_selection_older
:
8764 return "Older Path";
8765 case bgp_path_selection_router_id
:
8767 case bgp_path_selection_cluster_length
:
8768 return "Cluser length";
8769 case bgp_path_selection_stale
:
8770 return "Path Staleness";
8771 case bgp_path_selection_local_configured
:
8772 return "Locally configured route";
8773 case bgp_path_selection_neighbor_ip
:
8774 return "Neighbor IP";
8775 case bgp_path_selection_default
:
8776 return "Nothing left to compare";
8778 return "Invalid (internal error)";
8781 static void route_vty_out_detail_es_info(struct vty
*vty
,
8782 struct attr
*attr
, json_object
*json_path
)
8784 char esi_buf
[ESI_STR_LEN
];
8785 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
8786 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
8787 ATTR_ES_PEER_ROUTER
);
8788 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
8789 ATTR_ES_PEER_ACTIVE
);
8790 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
8791 ATTR_ES_PEER_PROXY
);
8793 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
8795 json_object
*json_es_info
= NULL
;
8797 json_object_string_add(
8800 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
8801 json_es_info
= json_object_new_object();
8803 json_object_boolean_true_add(
8804 json_es_info
, "localEs");
8806 json_object_boolean_true_add(
8807 json_es_info
, "peerActive");
8809 json_object_boolean_true_add(
8810 json_es_info
, "peerProxy");
8812 json_object_boolean_true_add(
8813 json_es_info
, "peerRouter");
8814 if (attr
->mm_sync_seqnum
)
8815 json_object_int_add(
8816 json_es_info
, "peerSeq",
8817 attr
->mm_sync_seqnum
);
8818 json_object_object_add(
8819 json_path
, "es_info",
8823 if (bgp_evpn_attr_is_sync(attr
))
8825 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
8827 es_local
? "local-es":"",
8828 peer_proxy
? "proxy " : "",
8829 peer_active
? "active ":"",
8830 peer_router
? "router ":"",
8831 attr
->mm_sync_seqnum
);
8833 vty_out(vty
, " ESI %s %s\n",
8835 es_local
? "local-es":"");
8839 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8840 struct bgp_dest
*bn
, struct bgp_path_info
*path
,
8841 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8843 char buf
[INET6_ADDRSTRLEN
];
8845 char buf2
[EVPN_ROUTE_STRLEN
];
8846 struct attr
*attr
= path
->attr
;
8847 int sockunion_vty_out(struct vty
*, union sockunion
*);
8849 json_object
*json_bestpath
= NULL
;
8850 json_object
*json_cluster_list
= NULL
;
8851 json_object
*json_cluster_list_list
= NULL
;
8852 json_object
*json_ext_community
= NULL
;
8853 json_object
*json_last_update
= NULL
;
8854 json_object
*json_pmsi
= NULL
;
8855 json_object
*json_nexthop_global
= NULL
;
8856 json_object
*json_nexthop_ll
= NULL
;
8857 json_object
*json_nexthops
= NULL
;
8858 json_object
*json_path
= NULL
;
8859 json_object
*json_peer
= NULL
;
8860 json_object
*json_string
= NULL
;
8861 json_object
*json_adv_to
= NULL
;
8863 struct listnode
*node
, *nnode
;
8865 int addpath_capable
;
8867 unsigned int first_as
;
8869 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8871 char *nexthop_hostname
=
8872 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8875 json_path
= json_object_new_object();
8876 json_peer
= json_object_new_object();
8877 json_nexthop_global
= json_object_new_object();
8885 if (path
->extra
&& path
->extra
->num_labels
) {
8886 bgp_evpn_label2str(path
->extra
->label
,
8887 path
->extra
->num_labels
, tag_buf
,
8890 if (safi
== SAFI_EVPN
) {
8893 (struct prefix_evpn
*)
8894 bgp_dest_get_prefix(bn
),
8895 buf2
, sizeof(buf2
));
8896 vty_out(vty
, " Route %s", buf2
);
8897 if (tag_buf
[0] != '\0')
8898 vty_out(vty
, " VNI %s", tag_buf
);
8902 json_object_string_add(json_path
, "VNI",
8907 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8908 struct bgp_path_info
*parent_ri
;
8909 struct bgp_dest
*dest
, *pdest
;
8911 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8912 dest
= parent_ri
->net
;
8913 if (dest
&& dest
->pdest
) {
8914 pdest
= dest
->pdest
;
8916 (struct prefix_rd
*)bgp_dest_get_prefix(
8918 buf1
, sizeof(buf1
));
8919 if (is_pi_family_evpn(parent_ri
)) {
8921 (struct prefix_evpn
*)
8922 bgp_dest_get_prefix(
8924 buf2
, sizeof(buf2
));
8925 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8927 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8932 /* Line1 display AS-path, Aggregator */
8935 if (!attr
->aspath
->json
)
8936 aspath_str_update(attr
->aspath
, true);
8937 json_object_lock(attr
->aspath
->json
);
8938 json_object_object_add(json_path
, "aspath",
8939 attr
->aspath
->json
);
8941 if (attr
->aspath
->segments
)
8942 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8944 vty_out(vty
, " Local");
8948 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8950 json_object_boolean_true_add(json_path
, "removed");
8952 vty_out(vty
, ", (removed)");
8955 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8957 json_object_boolean_true_add(json_path
, "stale");
8959 vty_out(vty
, ", (stale)");
8962 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8964 json_object_int_add(json_path
, "aggregatorAs",
8965 attr
->aggregator_as
);
8966 json_object_string_add(
8967 json_path
, "aggregatorId",
8968 inet_ntoa(attr
->aggregator_addr
));
8969 if (attr
->aggregator_as
== BGP_AS_ZERO
)
8970 json_object_boolean_true_add(
8971 json_path
, "aggregatorAsMalformed");
8973 json_object_boolean_false_add(
8974 json_path
, "aggregatorAsMalformed");
8976 if (attr
->aggregator_as
== BGP_AS_ZERO
)
8978 ", (aggregated by %u(malformed) %s)",
8979 attr
->aggregator_as
,
8980 inet_ntoa(attr
->aggregator_addr
));
8982 vty_out(vty
, ", (aggregated by %u %s)",
8983 attr
->aggregator_as
,
8984 inet_ntoa(attr
->aggregator_addr
));
8988 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8989 PEER_FLAG_REFLECTOR_CLIENT
)) {
8991 json_object_boolean_true_add(json_path
,
8992 "rxedFromRrClient");
8994 vty_out(vty
, ", (Received from a RR-client)");
8997 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8998 PEER_FLAG_RSERVER_CLIENT
)) {
9000 json_object_boolean_true_add(json_path
,
9001 "rxedFromRsClient");
9003 vty_out(vty
, ", (Received from a RS-client)");
9006 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9008 json_object_boolean_true_add(json_path
,
9009 "dampeningHistoryEntry");
9011 vty_out(vty
, ", (history entry)");
9012 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
9014 json_object_boolean_true_add(json_path
,
9015 "dampeningSuppressed");
9017 vty_out(vty
, ", (suppressed due to dampening)");
9023 /* Line2 display Next-hop, Neighbor, Router-id */
9024 /* Display the nexthop */
9025 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
9027 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
9028 || bn_p
->family
== AF_EVPN
)
9029 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
9030 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9031 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9032 || safi
== SAFI_EVPN
) {
9034 json_object_string_add(
9035 json_nexthop_global
, "ip",
9036 inet_ntoa(attr
->mp_nexthop_global_in
));
9038 if (path
->peer
->hostname
)
9039 json_object_string_add(
9040 json_nexthop_global
, "hostname",
9041 path
->peer
->hostname
);
9043 if (nexthop_hostname
)
9044 vty_out(vty
, " %pI4(%s)",
9045 &attr
->mp_nexthop_global_in
,
9048 vty_out(vty
, " %pI4",
9049 &attr
->mp_nexthop_global_in
);
9053 json_object_string_add(
9054 json_nexthop_global
, "ip",
9055 inet_ntoa(attr
->nexthop
));
9057 if (path
->peer
->hostname
)
9058 json_object_string_add(
9059 json_nexthop_global
, "hostname",
9060 path
->peer
->hostname
);
9062 if (nexthop_hostname
)
9063 vty_out(vty
, " %pI4(%s)",
9067 vty_out(vty
, " %pI4",
9073 json_object_string_add(json_nexthop_global
, "afi",
9077 json_object_string_add(
9078 json_nexthop_global
, "ip",
9079 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
9080 buf
, INET6_ADDRSTRLEN
));
9082 if (path
->peer
->hostname
)
9083 json_object_string_add(json_nexthop_global
,
9085 path
->peer
->hostname
);
9087 json_object_string_add(json_nexthop_global
, "afi",
9089 json_object_string_add(json_nexthop_global
, "scope",
9092 if (nexthop_hostname
)
9093 vty_out(vty
, " %pI6(%s)",
9094 &attr
->mp_nexthop_global
,
9097 vty_out(vty
, " %pI6",
9098 &attr
->mp_nexthop_global
);
9102 /* Display the IGP cost or 'inaccessible' */
9103 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9105 json_object_boolean_false_add(json_nexthop_global
,
9108 vty_out(vty
, " (inaccessible)");
9110 if (path
->extra
&& path
->extra
->igpmetric
) {
9112 json_object_int_add(json_nexthop_global
,
9114 path
->extra
->igpmetric
);
9116 vty_out(vty
, " (metric %u)",
9117 path
->extra
->igpmetric
);
9120 /* IGP cost is 0, display this only for json */
9123 json_object_int_add(json_nexthop_global
,
9128 json_object_boolean_true_add(json_nexthop_global
,
9132 /* Display peer "from" output */
9133 /* This path was originated locally */
9134 if (path
->peer
== bgp
->peer_self
) {
9136 if (safi
== SAFI_EVPN
9137 || (bn_p
->family
== AF_INET
9138 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9140 json_object_string_add(json_peer
, "peerId",
9143 vty_out(vty
, " from 0.0.0.0 ");
9146 json_object_string_add(json_peer
, "peerId",
9149 vty_out(vty
, " from :: ");
9153 json_object_string_add(json_peer
, "routerId",
9154 inet_ntoa(bgp
->router_id
));
9156 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
9159 /* We RXed this path from one of our peers */
9163 json_object_string_add(json_peer
, "peerId",
9164 sockunion2str(&path
->peer
->su
,
9167 json_object_string_add(json_peer
, "routerId",
9169 &path
->peer
->remote_id
,
9170 buf1
, sizeof(buf1
)));
9172 if (path
->peer
->hostname
)
9173 json_object_string_add(json_peer
, "hostname",
9174 path
->peer
->hostname
);
9176 if (path
->peer
->domainname
)
9177 json_object_string_add(json_peer
, "domainname",
9178 path
->peer
->domainname
);
9180 if (path
->peer
->conf_if
)
9181 json_object_string_add(json_peer
, "interface",
9182 path
->peer
->conf_if
);
9184 if (path
->peer
->conf_if
) {
9185 if (path
->peer
->hostname
9186 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9187 BGP_FLAG_SHOW_HOSTNAME
))
9188 vty_out(vty
, " from %s(%s)",
9189 path
->peer
->hostname
,
9190 path
->peer
->conf_if
);
9192 vty_out(vty
, " from %s",
9193 path
->peer
->conf_if
);
9195 if (path
->peer
->hostname
9196 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9197 BGP_FLAG_SHOW_HOSTNAME
))
9198 vty_out(vty
, " from %s(%s)",
9199 path
->peer
->hostname
,
9202 vty_out(vty
, " from %s",
9203 sockunion2str(&path
->peer
->su
,
9208 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9209 vty_out(vty
, " (%s)",
9210 inet_ntoa(attr
->originator_id
));
9212 vty_out(vty
, " (%s)",
9214 &path
->peer
->remote_id
, buf1
,
9220 * Note when vrfid of nexthop is different from that of prefix
9222 if (path
->extra
&& path
->extra
->bgp_orig
) {
9223 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9228 if (path
->extra
->bgp_orig
->inst_type
9229 == BGP_INSTANCE_TYPE_DEFAULT
)
9230 vn
= VRF_DEFAULT_NAME
;
9232 vn
= path
->extra
->bgp_orig
->name
;
9234 json_object_string_add(json_path
, "nhVrfName", vn
);
9236 if (nexthop_vrfid
== VRF_UNKNOWN
) {
9237 json_object_int_add(json_path
, "nhVrfId", -1);
9239 json_object_int_add(json_path
, "nhVrfId",
9240 (int)nexthop_vrfid
);
9243 if (nexthop_vrfid
== VRF_UNKNOWN
)
9244 vty_out(vty
, " vrf ?");
9248 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
9249 vty_out(vty
, " vrf %s(%u)",
9250 VRF_LOGNAME(vrf
), nexthop_vrfid
);
9257 json_object_boolean_true_add(json_path
,
9258 "announceNexthopSelf");
9260 vty_out(vty
, " announce-nh-self");
9267 /* display the link-local nexthop */
9268 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9270 json_nexthop_ll
= json_object_new_object();
9271 json_object_string_add(
9272 json_nexthop_ll
, "ip",
9273 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9274 buf
, INET6_ADDRSTRLEN
));
9276 if (path
->peer
->hostname
)
9277 json_object_string_add(json_nexthop_ll
,
9279 path
->peer
->hostname
);
9281 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
9282 json_object_string_add(json_nexthop_ll
, "scope",
9285 json_object_boolean_true_add(json_nexthop_ll
,
9288 if (!attr
->mp_nexthop_prefer_global
)
9289 json_object_boolean_true_add(json_nexthop_ll
,
9292 json_object_boolean_true_add(
9293 json_nexthop_global
, "used");
9295 vty_out(vty
, " (%s) %s\n",
9296 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9297 buf
, INET6_ADDRSTRLEN
),
9298 attr
->mp_nexthop_prefer_global
9303 /* If we do not have a link-local nexthop then we must flag the
9307 json_object_boolean_true_add(json_nexthop_global
,
9311 if (safi
== SAFI_EVPN
&&
9312 bgp_evpn_is_esi_valid(&attr
->esi
)) {
9313 route_vty_out_detail_es_info(vty
, attr
, json_path
);
9316 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9317 * Int/Ext/Local, Atomic, best */
9319 json_object_string_add(json_path
, "origin",
9320 bgp_origin_long_str
[attr
->origin
]);
9322 vty_out(vty
, " Origin %s",
9323 bgp_origin_long_str
[attr
->origin
]);
9325 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
9327 json_object_int_add(json_path
, "metric", attr
->med
);
9329 vty_out(vty
, ", metric %u", attr
->med
);
9332 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
9334 json_object_int_add(json_path
, "locPrf",
9337 vty_out(vty
, ", localpref %u", attr
->local_pref
);
9340 if (attr
->weight
!= 0) {
9342 json_object_int_add(json_path
, "weight", attr
->weight
);
9344 vty_out(vty
, ", weight %u", attr
->weight
);
9347 if (attr
->tag
!= 0) {
9349 json_object_int_add(json_path
, "tag", attr
->tag
);
9351 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
9354 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9356 json_object_boolean_false_add(json_path
, "valid");
9358 vty_out(vty
, ", invalid");
9359 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9361 json_object_boolean_true_add(json_path
, "valid");
9363 vty_out(vty
, ", valid");
9366 if (path
->peer
!= bgp
->peer_self
) {
9367 if (path
->peer
->as
== path
->peer
->local_as
) {
9368 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
9370 json_object_string_add(
9374 vty_out(vty
, ", confed-internal");
9377 json_object_string_add(
9378 json_peer
, "type", "internal");
9380 vty_out(vty
, ", internal");
9383 if (bgp_confederation_peers_check(bgp
,
9386 json_object_string_add(
9390 vty_out(vty
, ", confed-external");
9393 json_object_string_add(
9394 json_peer
, "type", "external");
9396 vty_out(vty
, ", external");
9399 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
9401 json_object_boolean_true_add(json_path
, "aggregated");
9402 json_object_boolean_true_add(json_path
, "local");
9404 vty_out(vty
, ", aggregated, local");
9406 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
9408 json_object_boolean_true_add(json_path
, "sourced");
9410 vty_out(vty
, ", sourced");
9413 json_object_boolean_true_add(json_path
, "sourced");
9414 json_object_boolean_true_add(json_path
, "local");
9416 vty_out(vty
, ", sourced, local");
9420 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
9422 json_object_boolean_true_add(json_path
,
9425 vty_out(vty
, ", atomic-aggregate");
9428 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
9429 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
9430 && bgp_path_info_mpath_count(path
))) {
9432 json_object_boolean_true_add(json_path
, "multipath");
9434 vty_out(vty
, ", multipath");
9437 // Mark the bestpath(s)
9438 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
9439 first_as
= aspath_get_first_as(attr
->aspath
);
9443 json_bestpath
= json_object_new_object();
9444 json_object_int_add(json_bestpath
, "bestpathFromAs",
9448 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
9450 vty_out(vty
, ", bestpath-from-AS Local");
9454 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9457 json_bestpath
= json_object_new_object();
9458 json_object_boolean_true_add(json_bestpath
, "overall");
9459 json_object_string_add(
9460 json_bestpath
, "selectionReason",
9461 bgp_path_selection_reason2str(bn
->reason
));
9463 vty_out(vty
, ", best");
9464 vty_out(vty
, " (%s)",
9465 bgp_path_selection_reason2str(bn
->reason
));
9470 json_object_object_add(json_path
, "bestpath", json_bestpath
);
9475 /* Line 4 display Community */
9476 if (attr
->community
) {
9478 if (!attr
->community
->json
)
9479 community_str(attr
->community
, true);
9480 json_object_lock(attr
->community
->json
);
9481 json_object_object_add(json_path
, "community",
9482 attr
->community
->json
);
9484 vty_out(vty
, " Community: %s\n",
9485 attr
->community
->str
);
9489 /* Line 5 display Extended-community */
9490 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9492 json_ext_community
= json_object_new_object();
9493 json_object_string_add(json_ext_community
, "string",
9494 attr
->ecommunity
->str
);
9495 json_object_object_add(json_path
, "extendedCommunity",
9496 json_ext_community
);
9498 vty_out(vty
, " Extended Community: %s\n",
9499 attr
->ecommunity
->str
);
9503 /* Line 6 display Large community */
9504 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
9506 if (!attr
->lcommunity
->json
)
9507 lcommunity_str(attr
->lcommunity
, true);
9508 json_object_lock(attr
->lcommunity
->json
);
9509 json_object_object_add(json_path
, "largeCommunity",
9510 attr
->lcommunity
->json
);
9512 vty_out(vty
, " Large Community: %s\n",
9513 attr
->lcommunity
->str
);
9517 /* Line 7 display Originator, Cluster-id */
9518 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9519 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
9520 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
9522 json_object_string_add(
9523 json_path
, "originatorId",
9524 inet_ntoa(attr
->originator_id
));
9526 vty_out(vty
, " Originator: %s",
9527 inet_ntoa(attr
->originator_id
));
9530 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
9534 json_cluster_list
= json_object_new_object();
9535 json_cluster_list_list
=
9536 json_object_new_array();
9538 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9540 json_string
= json_object_new_string(
9541 inet_ntoa(attr
->cluster
9543 json_object_array_add(
9544 json_cluster_list_list
,
9549 * struct cluster_list does not have
9550 * "str" variable like aspath and community
9551 * do. Add this someday if someone asks
9553 * json_object_string_add(json_cluster_list,
9554 * "string", attr->cluster->str);
9556 json_object_object_add(json_cluster_list
,
9558 json_cluster_list_list
);
9559 json_object_object_add(json_path
, "clusterList",
9562 vty_out(vty
, ", Cluster list: ");
9564 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9567 inet_ntoa(attr
->cluster
9577 if (path
->extra
&& path
->extra
->damp_info
)
9578 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
9581 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
9582 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
9583 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
9586 json_object_int_add(json_path
, "remoteLabel", label
);
9588 vty_out(vty
, " Remote label: %d\n", label
);
9592 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
9593 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
9595 json_object_string_add(json_path
, "remoteSid", buf
);
9597 vty_out(vty
, " Remote SID: %s\n", buf
);
9601 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
9603 json_object_int_add(json_path
, "labelIndex",
9606 vty_out(vty
, " Label Index: %d\n",
9610 /* Line 8 display Addpath IDs */
9611 if (path
->addpath_rx_id
9612 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9614 json_object_int_add(json_path
, "addpathRxId",
9615 path
->addpath_rx_id
);
9617 /* Keep backwards compatibility with the old API
9618 * by putting TX All's ID in the old field
9620 json_object_int_add(
9621 json_path
, "addpathTxId",
9623 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9625 /* ... but create a specific field for each
9628 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9629 json_object_int_add(
9631 bgp_addpath_names(i
)->id_json_name
,
9632 path
->tx_addpath
.addpath_tx_id
[i
]);
9635 vty_out(vty
, " AddPath ID: RX %u, ",
9636 path
->addpath_rx_id
);
9638 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9642 /* If we used addpath to TX a non-bestpath we need to display
9643 * "Advertised to" on a path-by-path basis
9645 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9648 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9650 bgp_addpath_encode_tx(peer
, afi
, safi
);
9651 has_adj
= bgp_adj_out_lookup(
9653 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9654 &path
->tx_addpath
));
9656 if ((addpath_capable
&& has_adj
)
9657 || (!addpath_capable
&& has_adj
9658 && CHECK_FLAG(path
->flags
,
9659 BGP_PATH_SELECTED
))) {
9660 if (json_path
&& !json_adv_to
)
9661 json_adv_to
= json_object_new_object();
9663 route_vty_out_advertised_to(
9665 " Advertised to:", json_adv_to
);
9671 json_object_object_add(
9672 json_path
, "advertisedTo", json_adv_to
);
9681 /* Line 9 display Uptime */
9682 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9684 json_last_update
= json_object_new_object();
9685 json_object_int_add(json_last_update
, "epoch", tbuf
);
9686 json_object_string_add(json_last_update
, "string",
9688 json_object_object_add(json_path
, "lastUpdate",
9691 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9693 /* Line 10 display PMSI tunnel attribute, if present */
9694 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9696 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9697 PMSI_TNLTYPE_STR_DEFAULT
);
9700 json_pmsi
= json_object_new_object();
9701 json_object_string_add(json_pmsi
, "tunnelType", str
);
9702 json_object_int_add(json_pmsi
, "label",
9703 label2vni(&attr
->label
));
9704 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9706 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9707 str
, label2vni(&attr
->label
));
9710 /* We've constructed the json object for this path, add it to the json
9714 if (json_nexthop_global
|| json_nexthop_ll
) {
9715 json_nexthops
= json_object_new_array();
9717 if (json_nexthop_global
)
9718 json_object_array_add(json_nexthops
,
9719 json_nexthop_global
);
9721 if (json_nexthop_ll
)
9722 json_object_array_add(json_nexthops
,
9725 json_object_object_add(json_path
, "nexthops",
9729 json_object_object_add(json_path
, "peer", json_peer
);
9730 json_object_array_add(json_paths
, json_path
);
9734 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9735 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9736 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9738 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9739 const char *prefix_list_str
, afi_t afi
,
9740 safi_t safi
, enum bgp_show_type type
);
9741 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9742 const char *filter
, afi_t afi
, safi_t safi
,
9743 enum bgp_show_type type
);
9744 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9745 const char *rmap_str
, afi_t afi
, safi_t safi
,
9746 enum bgp_show_type type
);
9747 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9748 const char *com
, int exact
, afi_t afi
,
9750 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9751 const char *prefix
, afi_t afi
, safi_t safi
,
9752 enum bgp_show_type type
);
9753 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9754 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
9756 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9757 const char *comstr
, int exact
, afi_t afi
,
9758 safi_t safi
, bool use_json
);
9761 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9762 struct bgp_table
*table
, enum bgp_show_type type
,
9763 void *output_arg
, bool use_json
, char *rd
,
9764 int is_last
, unsigned long *output_cum
,
9765 unsigned long *total_cum
,
9766 unsigned long *json_header_depth
, bool wide
)
9768 struct bgp_path_info
*pi
;
9769 struct bgp_dest
*dest
;
9772 unsigned long output_count
= 0;
9773 unsigned long total_count
= 0;
9775 json_object
*json_paths
= NULL
;
9778 if (output_cum
&& *output_cum
!= 0)
9781 if (use_json
&& !*json_header_depth
) {
9783 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9784 " \"localAS\": %u,\n \"routes\": { ",
9785 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9786 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9789 table
->version
, inet_ntoa(bgp
->router_id
),
9790 bgp
->default_local_pref
, bgp
->as
);
9791 *json_header_depth
= 2;
9793 vty_out(vty
, " \"routeDistinguishers\" : {");
9794 ++*json_header_depth
;
9798 if (use_json
&& rd
) {
9799 vty_out(vty
, " \"%s\" : { ", rd
);
9802 /* Start processing of routes. */
9803 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
9804 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
9806 pi
= bgp_dest_get_bgp_path_info(dest
);
9812 json_paths
= json_object_new_array();
9816 for (; pi
; pi
= pi
->next
) {
9818 if (type
== bgp_show_type_flap_statistics
9819 || type
== bgp_show_type_flap_neighbor
9820 || type
== bgp_show_type_dampend_paths
9821 || type
== bgp_show_type_damp_neighbor
) {
9822 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9825 if (type
== bgp_show_type_regexp
) {
9826 regex_t
*regex
= output_arg
;
9828 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9832 if (type
== bgp_show_type_prefix_list
) {
9833 struct prefix_list
*plist
= output_arg
;
9835 if (prefix_list_apply(plist
, dest_p
)
9839 if (type
== bgp_show_type_filter_list
) {
9840 struct as_list
*as_list
= output_arg
;
9842 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9843 != AS_FILTER_PERMIT
)
9846 if (type
== bgp_show_type_route_map
) {
9847 struct route_map
*rmap
= output_arg
;
9848 struct bgp_path_info path
;
9849 struct attr dummy_attr
;
9850 route_map_result_t ret
;
9852 dummy_attr
= *pi
->attr
;
9854 path
.peer
= pi
->peer
;
9855 path
.attr
= &dummy_attr
;
9857 ret
= route_map_apply(rmap
, dest_p
, RMAP_BGP
,
9859 if (ret
== RMAP_DENYMATCH
)
9862 if (type
== bgp_show_type_neighbor
9863 || type
== bgp_show_type_flap_neighbor
9864 || type
== bgp_show_type_damp_neighbor
) {
9865 union sockunion
*su
= output_arg
;
9867 if (pi
->peer
== NULL
9868 || pi
->peer
->su_remote
== NULL
9869 || !sockunion_same(pi
->peer
->su_remote
, su
))
9872 if (type
== bgp_show_type_cidr_only
) {
9873 uint32_t destination
;
9875 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
9876 if (IN_CLASSC(destination
)
9877 && dest_p
->prefixlen
== 24)
9879 if (IN_CLASSB(destination
)
9880 && dest_p
->prefixlen
== 16)
9882 if (IN_CLASSA(destination
)
9883 && dest_p
->prefixlen
== 8)
9886 if (type
== bgp_show_type_prefix_longer
) {
9888 if (!prefix_match(p
, dest_p
))
9891 if (type
== bgp_show_type_community_all
) {
9892 if (!pi
->attr
->community
)
9895 if (type
== bgp_show_type_community
) {
9896 struct community
*com
= output_arg
;
9898 if (!pi
->attr
->community
9899 || !community_match(pi
->attr
->community
,
9903 if (type
== bgp_show_type_community_exact
) {
9904 struct community
*com
= output_arg
;
9906 if (!pi
->attr
->community
9907 || !community_cmp(pi
->attr
->community
, com
))
9910 if (type
== bgp_show_type_community_list
) {
9911 struct community_list
*list
= output_arg
;
9913 if (!community_list_match(pi
->attr
->community
,
9917 if (type
== bgp_show_type_community_list_exact
) {
9918 struct community_list
*list
= output_arg
;
9920 if (!community_list_exact_match(
9921 pi
->attr
->community
, list
))
9924 if (type
== bgp_show_type_lcommunity
) {
9925 struct lcommunity
*lcom
= output_arg
;
9927 if (!pi
->attr
->lcommunity
9928 || !lcommunity_match(pi
->attr
->lcommunity
,
9933 if (type
== bgp_show_type_lcommunity_exact
) {
9934 struct lcommunity
*lcom
= output_arg
;
9936 if (!pi
->attr
->lcommunity
9937 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9941 if (type
== bgp_show_type_lcommunity_list
) {
9942 struct community_list
*list
= output_arg
;
9944 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9949 == bgp_show_type_lcommunity_list_exact
) {
9950 struct community_list
*list
= output_arg
;
9952 if (!lcommunity_list_exact_match(
9953 pi
->attr
->lcommunity
, list
))
9956 if (type
== bgp_show_type_lcommunity_all
) {
9957 if (!pi
->attr
->lcommunity
)
9960 if (type
== bgp_show_type_dampend_paths
9961 || type
== bgp_show_type_damp_neighbor
) {
9962 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9963 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9967 if (!use_json
&& header
) {
9968 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
9970 inet_ntoa(bgp
->router_id
));
9971 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9972 vty_out(vty
, "%s", VRFID_NONE_STR
);
9974 vty_out(vty
, "%u", bgp
->vrf_id
);
9976 vty_out(vty
, "Default local pref %u, ",
9977 bgp
->default_local_pref
);
9978 vty_out(vty
, "local AS %u\n", bgp
->as
);
9979 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9980 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9981 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9982 if (type
== bgp_show_type_dampend_paths
9983 || type
== bgp_show_type_damp_neighbor
)
9984 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9985 else if (type
== bgp_show_type_flap_statistics
9986 || type
== bgp_show_type_flap_neighbor
)
9987 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9989 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
9990 : BGP_SHOW_HEADER
));
9993 if (rd
!= NULL
&& !display
&& !output_count
) {
9996 "Route Distinguisher: %s\n",
9999 if (type
== bgp_show_type_dampend_paths
10000 || type
== bgp_show_type_damp_neighbor
)
10001 damp_route_vty_out(vty
, dest_p
, pi
, display
,
10002 AFI_IP
, safi
, use_json
,
10004 else if (type
== bgp_show_type_flap_statistics
10005 || type
== bgp_show_type_flap_neighbor
)
10006 flap_route_vty_out(vty
, dest_p
, pi
, display
,
10007 AFI_IP
, safi
, use_json
,
10010 route_vty_out(vty
, dest_p
, pi
, display
, safi
,
10020 /* encode prefix */
10021 if (dest_p
->family
== AF_FLOWSPEC
) {
10022 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
10024 bgp_fs_nlri_get_string(
10026 dest_p
->u
.prefix_flowspec
.ptr
,
10027 dest_p
->u
.prefix_flowspec
.prefixlen
,
10028 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
);
10030 vty_out(vty
, "\"%s/%d\": ", retstr
,
10031 dest_p
->u
.prefix_flowspec
10034 vty_out(vty
, ",\"%s/%d\": ", retstr
,
10035 dest_p
->u
.prefix_flowspec
10039 vty_out(vty
, "\"%pFX\": ", dest_p
);
10041 vty_out(vty
, ",\"%pFX\": ", dest_p
);
10044 json_object_to_json_string_ext(
10045 json_paths
, JSON_C_TO_STRING_PRETTY
));
10046 json_object_free(json_paths
);
10050 json_object_free(json_paths
);
10054 output_count
+= *output_cum
;
10055 *output_cum
= output_count
;
10058 total_count
+= *total_cum
;
10059 *total_cum
= total_count
;
10063 vty_out(vty
, " }%s ", (is_last
? "" : ","));
10067 for (i
= 0; i
< *json_header_depth
; ++i
)
10068 vty_out(vty
, " } ");
10069 vty_out(vty
, "\n");
10073 /* No route is displayed */
10074 if (output_count
== 0) {
10075 if (type
== bgp_show_type_normal
)
10077 "No BGP prefixes displayed, %ld exist\n",
10081 "\nDisplayed %ld routes and %ld total paths\n",
10082 output_count
, total_count
);
10086 return CMD_SUCCESS
;
10089 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10090 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
10091 enum bgp_show_type type
, void *output_arg
, bool use_json
)
10093 struct bgp_dest
*dest
, *next
;
10094 unsigned long output_cum
= 0;
10095 unsigned long total_cum
= 0;
10096 unsigned long json_header_depth
= 0;
10097 struct bgp_table
*itable
;
10100 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
10102 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
10103 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10105 next
= bgp_route_next(dest
);
10106 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
10109 itable
= bgp_dest_get_bgp_table_info(dest
);
10110 if (itable
!= NULL
) {
10111 struct prefix_rd prd
;
10112 char rd
[RD_ADDRSTRLEN
];
10114 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
10115 prefix_rd2str(&prd
, rd
, sizeof(rd
));
10116 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
10117 use_json
, rd
, next
== NULL
, &output_cum
,
10118 &total_cum
, &json_header_depth
, false);
10124 if (output_cum
== 0)
10125 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
10129 "\nDisplayed %ld routes and %ld total paths\n",
10130 output_cum
, total_cum
);
10132 return CMD_SUCCESS
;
10134 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10135 enum bgp_show_type type
, void *output_arg
, bool use_json
,
10138 struct bgp_table
*table
;
10139 unsigned long json_header_depth
= 0;
10142 bgp
= bgp_get_default();
10147 vty_out(vty
, "No BGP process is configured\n");
10149 vty_out(vty
, "{}\n");
10150 return CMD_WARNING
;
10153 table
= bgp
->rib
[afi
][safi
];
10154 /* use MPLS and ENCAP specific shows until they are merged */
10155 if (safi
== SAFI_MPLS_VPN
) {
10156 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
10157 output_arg
, use_json
);
10160 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
10161 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
10162 output_arg
, use_json
,
10165 /* labeled-unicast routes live in the unicast table */
10166 else if (safi
== SAFI_LABELED_UNICAST
)
10167 safi
= SAFI_UNICAST
;
10169 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
10170 NULL
, 1, NULL
, NULL
, &json_header_depth
, wide
);
10173 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
10174 safi_t safi
, bool use_json
,
10177 struct listnode
*node
, *nnode
;
10180 bool route_output
= false;
10183 vty_out(vty
, "{\n");
10185 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
10186 route_output
= true;
10189 vty_out(vty
, ",\n");
10193 vty_out(vty
, "\"%s\":",
10194 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10198 vty_out(vty
, "\nInstance %s:\n",
10199 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10203 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
10208 vty_out(vty
, "}\n");
10209 else if (!route_output
)
10210 vty_out(vty
, "%% BGP instance not found\n");
10213 /* Header of detailed BGP route information */
10214 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
10215 struct bgp_dest
*dest
, struct prefix_rd
*prd
,
10216 afi_t afi
, safi_t safi
, json_object
*json
)
10218 struct bgp_path_info
*pi
;
10219 const struct prefix
*p
;
10221 struct listnode
*node
, *nnode
;
10222 char buf1
[RD_ADDRSTRLEN
];
10223 char buf2
[INET6_ADDRSTRLEN
];
10224 char buf3
[EVPN_ROUTE_STRLEN
];
10225 char prefix_str
[BUFSIZ
];
10229 int accept_own
= 0;
10230 int route_filter_translated_v4
= 0;
10231 int route_filter_v4
= 0;
10232 int route_filter_translated_v6
= 0;
10233 int route_filter_v6
= 0;
10234 int llgr_stale
= 0;
10236 int accept_own_nexthop
= 0;
10239 int no_advertise
= 0;
10243 int has_valid_label
= 0;
10244 mpls_label_t label
= 0;
10245 json_object
*json_adv_to
= NULL
;
10247 p
= bgp_dest_get_prefix(dest
);
10248 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
10250 if (has_valid_label
)
10251 label
= label_pton(&dest
->local_label
);
10253 if (safi
== SAFI_EVPN
) {
10256 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
10257 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
10258 : "", prd
? ":" : "",
10259 bgp_evpn_route2str((struct prefix_evpn
*)p
,
10260 buf3
, sizeof(buf3
)));
10262 json_object_string_add(json
, "rd",
10263 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
10265 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
10269 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
10270 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
10271 ? prefix_rd2str(prd
, buf1
,
10274 safi
== SAFI_MPLS_VPN
? ":" : "",
10275 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
10280 json_object_string_add(json
, "prefix",
10281 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
10284 if (has_valid_label
) {
10286 json_object_int_add(json
, "localLabel", label
);
10288 vty_out(vty
, "Local label: %d\n", label
);
10292 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
10293 vty_out(vty
, "not allocated\n");
10295 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
10297 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
10299 if (pi
->extra
&& pi
->extra
->suppress
)
10302 if (pi
->attr
->community
== NULL
)
10305 no_advertise
+= community_include(
10306 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
10307 no_export
+= community_include(pi
->attr
->community
,
10308 COMMUNITY_NO_EXPORT
);
10309 local_as
+= community_include(pi
->attr
->community
,
10310 COMMUNITY_LOCAL_AS
);
10311 accept_own
+= community_include(pi
->attr
->community
,
10312 COMMUNITY_ACCEPT_OWN
);
10313 route_filter_translated_v4
+= community_include(
10314 pi
->attr
->community
,
10315 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
10316 route_filter_translated_v6
+= community_include(
10317 pi
->attr
->community
,
10318 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
10319 route_filter_v4
+= community_include(
10320 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
10321 route_filter_v6
+= community_include(
10322 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
10323 llgr_stale
+= community_include(pi
->attr
->community
,
10324 COMMUNITY_LLGR_STALE
);
10325 no_llgr
+= community_include(pi
->attr
->community
,
10326 COMMUNITY_NO_LLGR
);
10327 accept_own_nexthop
+=
10328 community_include(pi
->attr
->community
,
10329 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
10330 blackhole
+= community_include(pi
->attr
->community
,
10331 COMMUNITY_BLACKHOLE
);
10332 no_peer
+= community_include(pi
->attr
->community
,
10333 COMMUNITY_NO_PEER
);
10338 vty_out(vty
, "Paths: (%d available", count
);
10340 vty_out(vty
, ", best #%d", best
);
10341 if (safi
== SAFI_UNICAST
) {
10342 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10343 vty_out(vty
, ", table %s",
10346 vty_out(vty
, ", vrf %s",
10350 vty_out(vty
, ", no best path");
10354 ", accept own local route exported and imported in different VRF");
10355 else if (route_filter_translated_v4
)
10357 ", mark translated RTs for VPNv4 route filtering");
10358 else if (route_filter_v4
)
10360 ", attach RT as-is for VPNv4 route filtering");
10361 else if (route_filter_translated_v6
)
10363 ", mark translated RTs for VPNv6 route filtering");
10364 else if (route_filter_v6
)
10366 ", attach RT as-is for VPNv6 route filtering");
10367 else if (llgr_stale
)
10369 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10372 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10373 else if (accept_own_nexthop
)
10375 ", accept local nexthop");
10376 else if (blackhole
)
10377 vty_out(vty
, ", inform peer to blackhole prefix");
10378 else if (no_export
)
10379 vty_out(vty
, ", not advertised to EBGP peer");
10380 else if (no_advertise
)
10381 vty_out(vty
, ", not advertised to any peer");
10383 vty_out(vty
, ", not advertised outside local AS");
10386 ", inform EBGP peer not to advertise to their EBGP peers");
10390 ", Advertisements suppressed by an aggregate.");
10391 vty_out(vty
, ")\n");
10394 /* If we are not using addpath then we can display Advertised to and
10396 * show what peers we advertised the bestpath to. If we are using
10398 * though then we must display Advertised to on a path-by-path basis. */
10399 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10400 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10401 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
10402 if (json
&& !json_adv_to
)
10403 json_adv_to
= json_object_new_object();
10405 route_vty_out_advertised_to(
10407 " Advertised to non peer-group peers:\n ",
10414 json_object_object_add(json
, "advertisedTo",
10419 vty_out(vty
, " Not advertised to any peer");
10420 vty_out(vty
, "\n");
10425 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
10426 struct bgp_dest
*bgp_node
, struct vty
*vty
,
10427 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10428 json_object
*json
, enum bgp_path_type pathtype
,
10431 struct bgp_path_info
*pi
;
10433 char rdbuf
[RD_ADDRSTRLEN
];
10434 json_object
*json_header
= NULL
;
10435 json_object
*json_paths
= NULL
;
10437 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
10439 if (json
&& !json_paths
) {
10440 /* Instantiate json_paths only if path is valid */
10441 json_paths
= json_object_new_array();
10443 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
10444 json_header
= json_object_new_object();
10446 json_header
= json
;
10450 route_vty_out_detail_header(
10451 vty
, bgp
, bgp_node
, pfx_rd
,
10452 AFI_IP
, safi
, json_header
);
10457 if (pathtype
== BGP_PATH_SHOW_ALL
10458 || (pathtype
== BGP_PATH_SHOW_BESTPATH
10459 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
10460 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
10461 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
10462 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
10463 route_vty_out_detail(vty
, bgp
, bgp_node
,
10468 if (json
&& json_paths
) {
10469 json_object_object_add(json_header
, "paths", json_paths
);
10472 json_object_object_add(json
, rdbuf
, json_header
);
10476 /* Display specified route of BGP table. */
10477 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
10478 struct bgp_table
*rib
, const char *ip_str
,
10479 afi_t afi
, safi_t safi
,
10480 struct prefix_rd
*prd
, int prefix_check
,
10481 enum bgp_path_type pathtype
, bool use_json
)
10485 struct prefix match
;
10486 struct bgp_dest
*dest
;
10487 struct bgp_dest
*rm
;
10488 struct bgp_table
*table
;
10489 json_object
*json
= NULL
;
10490 json_object
*json_paths
= NULL
;
10492 /* Check IP address argument. */
10493 ret
= str2prefix(ip_str
, &match
);
10495 vty_out(vty
, "address is malformed\n");
10496 return CMD_WARNING
;
10499 match
.family
= afi2family(afi
);
10502 json
= json_object_new_object();
10504 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
10505 for (dest
= bgp_table_top(rib
); dest
;
10506 dest
= bgp_route_next(dest
)) {
10507 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10509 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
10511 table
= bgp_dest_get_bgp_table_info(dest
);
10515 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10518 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
10520 && rm_p
->prefixlen
!= match
.prefixlen
) {
10521 bgp_dest_unlock_node(rm
);
10525 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
10526 bgp
, afi
, safi
, json
, pathtype
,
10529 bgp_dest_unlock_node(rm
);
10531 } else if (safi
== SAFI_EVPN
) {
10532 struct bgp_dest
*longest_pfx
;
10533 bool is_exact_pfxlen_match
= false;
10535 for (dest
= bgp_table_top(rib
); dest
;
10536 dest
= bgp_route_next(dest
)) {
10537 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10539 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
10541 table
= bgp_dest_get_bgp_table_info(dest
);
10545 longest_pfx
= NULL
;
10546 is_exact_pfxlen_match
= false;
10548 * Search through all the prefixes for a match. The
10549 * pfx's are enumerated in ascending order of pfxlens.
10550 * So, the last pfx match is the longest match. Set
10551 * is_exact_pfxlen_match when we get exact pfxlen match
10553 for (rm
= bgp_table_top(table
); rm
;
10554 rm
= bgp_route_next(rm
)) {
10555 const struct prefix
*rm_p
=
10556 bgp_dest_get_prefix(rm
);
10558 * Get prefixlen of the ip-prefix within type5
10561 if (evpn_type5_prefix_match(rm_p
, &match
)
10565 bgp_evpn_get_type5_prefixlen(
10567 if (type5_pfxlen
== match
.prefixlen
) {
10568 is_exact_pfxlen_match
= true;
10569 bgp_dest_unlock_node(rm
);
10578 if (prefix_check
&& !is_exact_pfxlen_match
)
10582 bgp_dest_lock_node(rm
);
10584 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
10585 bgp
, afi
, safi
, json
, pathtype
,
10588 bgp_dest_unlock_node(rm
);
10590 } else if (safi
== SAFI_FLOWSPEC
) {
10592 json_paths
= json_object_new_array();
10594 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
10595 &match
, prefix_check
,
10599 if (use_json
&& display
)
10600 json_object_object_add(json
, "paths", json_paths
);
10602 if ((dest
= bgp_node_match(rib
, &match
)) != NULL
) {
10603 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10605 || dest_p
->prefixlen
== match
.prefixlen
) {
10606 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
10607 safi
, json
, pathtype
,
10611 bgp_dest_unlock_node(dest
);
10616 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10617 json
, JSON_C_TO_STRING_PRETTY
|
10618 JSON_C_TO_STRING_NOSLASHESCAPE
));
10619 json_object_free(json
);
10622 vty_out(vty
, "%% Network not in table\n");
10623 return CMD_WARNING
;
10627 return CMD_SUCCESS
;
10630 /* Display specified route of Main RIB */
10631 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10632 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10633 int prefix_check
, enum bgp_path_type pathtype
,
10637 bgp
= bgp_get_default();
10640 vty_out(vty
, "No BGP process is configured\n");
10642 vty_out(vty
, "{}\n");
10643 return CMD_WARNING
;
10647 /* labeled-unicast routes live in the unicast table */
10648 if (safi
== SAFI_LABELED_UNICAST
)
10649 safi
= SAFI_UNICAST
;
10651 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10652 afi
, safi
, prd
, prefix_check
, pathtype
,
10656 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10657 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10658 safi_t safi
, bool uj
)
10660 struct lcommunity
*lcom
;
10666 b
= buffer_new(1024);
10667 for (i
= 0; i
< argc
; i
++) {
10669 buffer_putc(b
, ' ');
10671 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10673 buffer_putstr(b
, argv
[i
]->arg
);
10677 buffer_putc(b
, '\0');
10679 str
= buffer_getstr(b
);
10682 lcom
= lcommunity_str2com(str
);
10683 XFREE(MTYPE_TMP
, str
);
10685 vty_out(vty
, "%% Large-community malformed\n");
10686 return CMD_WARNING
;
10689 return bgp_show(vty
, bgp
, afi
, safi
,
10690 (exact
? bgp_show_type_lcommunity_exact
10691 : bgp_show_type_lcommunity
),
10695 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10696 const char *lcom
, bool exact
, afi_t afi
,
10697 safi_t safi
, bool uj
)
10699 struct community_list
*list
;
10701 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10702 LARGE_COMMUNITY_LIST_MASTER
);
10703 if (list
== NULL
) {
10704 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10706 return CMD_WARNING
;
10709 return bgp_show(vty
, bgp
, afi
, safi
,
10710 (exact
? bgp_show_type_lcommunity_list_exact
10711 : bgp_show_type_lcommunity_list
),
10715 DEFUN (show_ip_bgp_large_community_list
,
10716 show_ip_bgp_large_community_list_cmd
,
10717 "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]",
10721 BGP_INSTANCE_HELP_STR
10723 BGP_SAFI_WITH_LABEL_HELP_STR
10724 "Display routes matching the large-community-list\n"
10725 "large-community-list number\n"
10726 "large-community-list name\n"
10727 "Exact match of the large-communities\n"
10730 afi_t afi
= AFI_IP6
;
10731 safi_t safi
= SAFI_UNICAST
;
10733 bool exact_match
= 0;
10734 struct bgp
*bgp
= NULL
;
10735 bool uj
= use_json(argc
, argv
);
10740 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10743 return CMD_WARNING
;
10745 argv_find(argv
, argc
, "large-community-list", &idx
);
10747 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10749 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10752 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10753 exact_match
, afi
, safi
, uj
);
10755 DEFUN (show_ip_bgp_large_community
,
10756 show_ip_bgp_large_community_cmd
,
10757 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10761 BGP_INSTANCE_HELP_STR
10763 BGP_SAFI_WITH_LABEL_HELP_STR
10764 "Display routes matching the large-communities\n"
10765 "List of large-community numbers\n"
10766 "Exact match of the large-communities\n"
10769 afi_t afi
= AFI_IP6
;
10770 safi_t safi
= SAFI_UNICAST
;
10772 bool exact_match
= 0;
10773 struct bgp
*bgp
= NULL
;
10774 bool uj
= use_json(argc
, argv
);
10779 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10782 return CMD_WARNING
;
10784 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10785 if (argv_find(argv
, argc
, "exact-match", &idx
))
10787 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10788 exact_match
, afi
, safi
, uj
);
10790 return bgp_show(vty
, bgp
, afi
, safi
,
10791 bgp_show_type_lcommunity_all
, NULL
, uj
, false);
10794 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10795 safi_t safi
, struct json_object
*json_array
);
10796 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10797 safi_t safi
, struct json_object
*json
);
10800 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
10801 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
10802 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
10803 "Display number of prefixes for all afi/safi\n" JSON_STR
)
10805 bool uj
= use_json(argc
, argv
);
10806 struct bgp
*bgp
= NULL
;
10807 safi_t safi
= SAFI_UNICAST
;
10808 afi_t afi
= AFI_IP6
;
10810 struct json_object
*json_all
= NULL
;
10811 struct json_object
*json_afi_safi
= NULL
;
10813 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10816 return CMD_WARNING
;
10819 json_all
= json_object_new_object();
10821 FOREACH_AFI_SAFI (afi
, safi
) {
10823 * So limit output to those afi/safi pairs that
10824 * actually have something interesting in them
10826 if (strmatch(get_afi_safi_str(afi
, safi
, true),
10831 json_afi_safi
= json_object_new_array();
10832 json_object_object_add(
10834 get_afi_safi_str(afi
, safi
, true),
10837 json_afi_safi
= NULL
;
10840 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10845 json_object_to_json_string_ext(
10846 json_all
, JSON_C_TO_STRING_PRETTY
));
10847 json_object_free(json_all
);
10850 return CMD_SUCCESS
;
10853 /* BGP route print out function without JSON */
10854 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
10855 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
10856 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
10860 BGP_INSTANCE_HELP_STR
10863 "BGP RIB advertisement statistics\n"
10866 afi_t afi
= AFI_IP6
;
10867 safi_t safi
= SAFI_UNICAST
;
10868 struct bgp
*bgp
= NULL
;
10870 bool uj
= use_json(argc
, argv
);
10871 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
10873 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10876 return CMD_WARNING
;
10879 json_afi_safi
= json_object_new_array();
10881 json_afi_safi
= NULL
;
10883 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10886 json
= json_object_new_object();
10887 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
10889 vty_out(vty
, "%s", json_object_to_json_string_ext(
10890 json
, JSON_C_TO_STRING_PRETTY
));
10891 json_object_free(json
);
10896 /* BGP route print out function without JSON */
10897 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
10898 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10899 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10901 statistics [json]",
10902 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10903 BGP_SAFI_WITH_LABEL_HELP_STR
10904 "BGP RIB advertisement statistics\n" JSON_STR
)
10906 afi_t afi
= AFI_IP6
;
10907 safi_t safi
= SAFI_UNICAST
;
10908 struct bgp
*bgp
= NULL
;
10910 bool uj
= use_json(argc
, argv
);
10911 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
10913 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10916 return CMD_WARNING
;
10919 json_afi_safi
= json_object_new_array();
10921 json_afi_safi
= NULL
;
10923 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10926 json
= json_object_new_object();
10927 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
10930 json_object_to_json_string_ext(
10931 json
, JSON_C_TO_STRING_PRETTY
));
10932 json_object_free(json
);
10937 /* BGP route print out function without JSON */
10938 DEFUN(show_ip_bgp
, show_ip_bgp_cmd
,
10939 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10940 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10942 <dampening <parameters>\
10946 |community-list <(1-500)|WORD> [exact-match]\
10947 |A.B.C.D/M longer-prefixes\
10948 |X:X::X:X/M longer-prefixes\
10950 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10951 BGP_SAFI_WITH_LABEL_HELP_STR
10952 "Display detailed information about dampening\n"
10953 "Display detail of configured dampening parameters\n"
10954 "Display routes matching the route-map\n"
10955 "A route-map to match on\n"
10956 "Display routes conforming to the prefix-list\n"
10957 "Prefix-list name\n"
10958 "Display routes conforming to the filter-list\n"
10959 "Regular expression access list name\n"
10960 "Display routes matching the community-list\n"
10961 "community-list number\n"
10962 "community-list name\n"
10963 "Exact match of the communities\n"
10965 "Display route and more specific routes\n"
10967 "Display route and more specific routes\n")
10969 afi_t afi
= AFI_IP6
;
10970 safi_t safi
= SAFI_UNICAST
;
10971 int exact_match
= 0;
10972 struct bgp
*bgp
= NULL
;
10975 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10978 return CMD_WARNING
;
10980 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10981 if (argv_find(argv
, argc
, "parameters", &idx
))
10982 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10985 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10986 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10987 safi
, bgp_show_type_prefix_list
);
10989 if (argv_find(argv
, argc
, "filter-list", &idx
))
10990 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10991 safi
, bgp_show_type_filter_list
);
10993 if (argv_find(argv
, argc
, "route-map", &idx
))
10994 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10995 safi
, bgp_show_type_route_map
);
10997 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10998 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10999 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11001 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
11002 exact_match
, afi
, safi
);
11004 /* prefix-longer */
11005 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11006 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11007 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
11009 bgp_show_type_prefix_longer
);
11011 return CMD_WARNING
;
11014 /* BGP route print out function with JSON */
11015 DEFPY (show_ip_bgp_json
,
11016 show_ip_bgp_json_cmd
,
11017 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
11019 |dampening <flap-statistics|dampened-paths>\
11020 |community [AA:NN|local-AS|no-advertise|no-export\
11021 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11022 |accept-own|accept-own-nexthop|route-filter-v6\
11023 |route-filter-v4|route-filter-translated-v6\
11024 |route-filter-translated-v4] [exact-match]\
11025 ] [json$uj | wide$wide]",
11029 BGP_INSTANCE_HELP_STR
11031 BGP_SAFI_WITH_LABEL_HELP_STR
11032 "Display only routes with non-natural netmasks\n"
11033 "Display detailed information about dampening\n"
11034 "Display flap statistics of routes\n"
11035 "Display paths suppressed due to dampening\n"
11036 "Display routes matching the communities\n"
11038 "Do not send outside local AS (well-known community)\n"
11039 "Do not advertise to any peer (well-known community)\n"
11040 "Do not export to next AS (well-known community)\n"
11041 "Graceful shutdown (well-known community)\n"
11042 "Do not export to any peer (well-known community)\n"
11043 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11044 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11045 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11046 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11047 "Should accept VPN route with local nexthop (well-known community)\n"
11048 "RT VPNv6 route filtering (well-known community)\n"
11049 "RT VPNv4 route filtering (well-known community)\n"
11050 "RT translated VPNv6 route filtering (well-known community)\n"
11051 "RT translated VPNv4 route filtering (well-known community)\n"
11052 "Exact match of the communities\n"
11054 "Increase table width for longer prefixes\n")
11056 afi_t afi
= AFI_IP6
;
11057 safi_t safi
= SAFI_UNICAST
;
11058 enum bgp_show_type sh_type
= bgp_show_type_normal
;
11059 struct bgp
*bgp
= NULL
;
11061 int exact_match
= 0;
11066 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11069 return CMD_WARNING
;
11071 if (argv_find(argv
, argc
, "cidr-only", &idx
))
11072 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
11075 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11076 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
11077 return bgp_show(vty
, bgp
, afi
, safi
,
11078 bgp_show_type_dampend_paths
, NULL
, uj
,
11080 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11081 return bgp_show(vty
, bgp
, afi
, safi
,
11082 bgp_show_type_flap_statistics
, NULL
, uj
,
11086 if (argv_find(argv
, argc
, "community", &idx
)) {
11087 char *maybecomm
= NULL
;
11088 char *community
= NULL
;
11090 if (idx
+ 1 < argc
) {
11091 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
11092 maybecomm
= argv
[idx
+ 1]->arg
;
11094 maybecomm
= argv
[idx
+ 1]->text
;
11097 if (maybecomm
&& !strmatch(maybecomm
, "json")
11098 && !strmatch(maybecomm
, "exact-match"))
11099 community
= maybecomm
;
11101 if (argv_find(argv
, argc
, "exact-match", &idx
))
11105 return bgp_show_community(vty
, bgp
, community
,
11106 exact_match
, afi
, safi
, uj
);
11108 return (bgp_show(vty
, bgp
, afi
, safi
,
11109 bgp_show_type_community_all
, NULL
, uj
,
11113 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
, wide
);
11116 DEFUN (show_ip_bgp_route
,
11117 show_ip_bgp_route_cmd
,
11118 "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]",
11122 BGP_INSTANCE_HELP_STR
11124 BGP_SAFI_WITH_LABEL_HELP_STR
11125 "Network in the BGP routing table to display\n"
11127 "Network in the BGP routing table to display\n"
11129 "Display only the bestpath\n"
11130 "Display only multipaths\n"
11133 int prefix_check
= 0;
11135 afi_t afi
= AFI_IP6
;
11136 safi_t safi
= SAFI_UNICAST
;
11137 char *prefix
= NULL
;
11138 struct bgp
*bgp
= NULL
;
11139 enum bgp_path_type path_type
;
11140 bool uj
= use_json(argc
, argv
);
11144 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11147 return CMD_WARNING
;
11151 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11152 return CMD_WARNING
;
11155 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11156 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
11157 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
11159 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11160 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11163 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
11164 && afi
!= AFI_IP6
) {
11166 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11167 return CMD_WARNING
;
11169 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
11170 && afi
!= AFI_IP
) {
11172 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11173 return CMD_WARNING
;
11176 prefix
= argv
[idx
]->arg
;
11178 /* [<bestpath|multipath>] */
11179 if (argv_find(argv
, argc
, "bestpath", &idx
))
11180 path_type
= BGP_PATH_SHOW_BESTPATH
;
11181 else if (argv_find(argv
, argc
, "multipath", &idx
))
11182 path_type
= BGP_PATH_SHOW_MULTIPATH
;
11184 path_type
= BGP_PATH_SHOW_ALL
;
11186 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
11190 DEFUN (show_ip_bgp_regexp
,
11191 show_ip_bgp_regexp_cmd
,
11192 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
11196 BGP_INSTANCE_HELP_STR
11198 BGP_SAFI_WITH_LABEL_HELP_STR
11199 "Display routes matching the AS path regular expression\n"
11200 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11203 afi_t afi
= AFI_IP6
;
11204 safi_t safi
= SAFI_UNICAST
;
11205 struct bgp
*bgp
= NULL
;
11206 bool uj
= use_json(argc
, argv
);
11207 char *regstr
= NULL
;
11210 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11213 return CMD_WARNING
;
11215 // get index of regex
11216 if (argv_find(argv
, argc
, "REGEX", &idx
))
11217 regstr
= argv
[idx
]->arg
;
11220 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
11221 bgp_show_type_regexp
, uj
);
11224 DEFPY (show_ip_bgp_instance_all
,
11225 show_ip_bgp_instance_all_cmd
,
11226 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
11230 BGP_INSTANCE_ALL_HELP_STR
11232 BGP_SAFI_WITH_LABEL_HELP_STR
11234 "Increase table width for longer prefixes\n")
11236 afi_t afi
= AFI_IP
;
11237 safi_t safi
= SAFI_UNICAST
;
11238 struct bgp
*bgp
= NULL
;
11244 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11247 return CMD_WARNING
;
11249 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
, wide
);
11250 return CMD_SUCCESS
;
11253 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11254 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11260 if (!config_bgp_aspath_validate(regstr
)) {
11261 vty_out(vty
, "Invalid character in REGEX %s\n",
11263 return CMD_WARNING_CONFIG_FAILED
;
11266 regex
= bgp_regcomp(regstr
);
11268 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
11269 return CMD_WARNING
;
11272 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, use_json
, false);
11273 bgp_regex_free(regex
);
11277 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
11278 const char *prefix_list_str
, afi_t afi
,
11279 safi_t safi
, enum bgp_show_type type
)
11281 struct prefix_list
*plist
;
11283 plist
= prefix_list_lookup(afi
, prefix_list_str
);
11284 if (plist
== NULL
) {
11285 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
11287 return CMD_WARNING
;
11290 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0, false);
11293 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
11294 const char *filter
, afi_t afi
, safi_t safi
,
11295 enum bgp_show_type type
)
11297 struct as_list
*as_list
;
11299 as_list
= as_list_lookup(filter
);
11300 if (as_list
== NULL
) {
11301 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
11303 return CMD_WARNING
;
11306 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0, false);
11309 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
11310 const char *rmap_str
, afi_t afi
, safi_t safi
,
11311 enum bgp_show_type type
)
11313 struct route_map
*rmap
;
11315 rmap
= route_map_lookup_by_name(rmap_str
);
11317 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
11318 return CMD_WARNING
;
11321 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0, false);
11324 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11325 const char *comstr
, int exact
, afi_t afi
,
11326 safi_t safi
, bool use_json
)
11328 struct community
*com
;
11331 com
= community_str2com(comstr
);
11333 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
11334 return CMD_WARNING
;
11337 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11338 (exact
? bgp_show_type_community_exact
11339 : bgp_show_type_community
),
11340 com
, use_json
, false);
11341 community_free(&com
);
11346 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
11347 const char *com
, int exact
, afi_t afi
,
11350 struct community_list
*list
;
11352 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
11353 if (list
== NULL
) {
11354 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
11355 return CMD_WARNING
;
11358 return bgp_show(vty
, bgp
, afi
, safi
,
11359 (exact
? bgp_show_type_community_list_exact
11360 : bgp_show_type_community_list
),
11364 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
11365 const char *prefix
, afi_t afi
, safi_t safi
,
11366 enum bgp_show_type type
)
11373 ret
= str2prefix(prefix
, p
);
11375 vty_out(vty
, "%% Malformed Prefix\n");
11376 return CMD_WARNING
;
11379 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0, false);
11385 BGP_STATS_MAXBITLEN
= 0,
11387 BGP_STATS_PREFIXES
,
11389 BGP_STATS_UNAGGREGATEABLE
,
11390 BGP_STATS_MAX_AGGREGATEABLE
,
11391 BGP_STATS_AGGREGATES
,
11393 BGP_STATS_ASPATH_COUNT
,
11394 BGP_STATS_ASPATH_MAXHOPS
,
11395 BGP_STATS_ASPATH_TOTHOPS
,
11396 BGP_STATS_ASPATH_MAXSIZE
,
11397 BGP_STATS_ASPATH_TOTSIZE
,
11398 BGP_STATS_ASN_HIGHEST
,
11402 #define TABLE_STATS_IDX_VTY 0
11403 #define TABLE_STATS_IDX_JSON 1
11405 static const char *table_stats_strs
[][2] = {
11406 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
11407 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
11408 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
11409 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
11410 "unaggregateablePrefixes"},
11411 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
11412 "maximumAggregateablePrefixes"},
11413 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
11414 "bgpAggregateAdvertisements"},
11415 [BGP_STATS_SPACE
] = {"Address space advertised",
11416 "addressSpaceAdvertised"},
11417 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
11418 "advertisementsWithPaths"},
11419 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
11421 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
11423 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
11424 "averageAsPathLengthHops"},
11425 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
11426 "averageAsPathSizeBytes"},
11427 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
11428 [BGP_STATS_MAX
] = {NULL
, NULL
}
11431 struct bgp_table_stats
{
11432 struct bgp_table
*table
;
11433 unsigned long long counts
[BGP_STATS_MAX
];
11434 double total_space
;
11438 #define TALLY_SIGFIG 100000
11439 static unsigned long
11440 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
11442 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
11443 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
11444 unsigned long ret
= newtot
/ count
;
11446 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
11453 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
11454 struct bgp_table_stats
*ts
, unsigned int space
)
11456 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
11457 struct bgp_path_info
*pi
;
11458 const struct prefix
*rn_p
;
11463 if (!bgp_dest_has_bgp_path_info_data(dest
))
11466 rn_p
= bgp_dest_get_prefix(dest
);
11467 ts
->counts
[BGP_STATS_PREFIXES
]++;
11468 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
11471 ts
->counts
[BGP_STATS_AVGPLEN
]
11472 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
11473 ts
->counts
[BGP_STATS_AVGPLEN
],
11477 /* check if the prefix is included by any other announcements */
11478 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
11479 pdest
= bgp_dest_parent_nolock(pdest
);
11481 if (pdest
== NULL
|| pdest
== top
) {
11482 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
11483 /* announced address space */
11485 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
11486 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
11487 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
11490 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11491 ts
->counts
[BGP_STATS_RIB
]++;
11493 if (CHECK_FLAG(pi
->attr
->flag
,
11494 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
11495 ts
->counts
[BGP_STATS_AGGREGATES
]++;
11497 /* as-path stats */
11498 if (pi
->attr
->aspath
) {
11499 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
11500 unsigned int size
= aspath_size(pi
->attr
->aspath
);
11501 as_t highest
= aspath_highest(pi
->attr
->aspath
);
11503 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
11505 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
11506 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
11508 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
11509 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
11511 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
11512 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
11514 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
11515 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11516 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
11518 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
11519 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11520 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
11523 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
11524 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
11529 static int bgp_table_stats_walker(struct thread
*t
)
11531 struct bgp_dest
*dest
, *ndest
;
11532 struct bgp_dest
*top
;
11533 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
11534 unsigned int space
= 0;
11536 if (!(top
= bgp_table_top(ts
->table
)))
11539 switch (ts
->table
->afi
) {
11541 space
= IPV4_MAX_BITLEN
;
11544 space
= IPV6_MAX_BITLEN
;
11550 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
11552 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
11553 if (ts
->table
->safi
== SAFI_MPLS_VPN
11554 || ts
->table
->safi
== SAFI_ENCAP
11555 || ts
->table
->safi
== SAFI_EVPN
) {
11556 struct bgp_table
*table
;
11558 table
= bgp_dest_get_bgp_table_info(dest
);
11562 top
= bgp_table_top(table
);
11563 for (ndest
= bgp_table_top(table
); ndest
;
11564 ndest
= bgp_route_next(ndest
))
11565 bgp_table_stats_rn(ndest
, top
, ts
, space
);
11567 bgp_table_stats_rn(dest
, top
, ts
, space
);
11574 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
11575 struct json_object
*json_array
)
11577 struct listnode
*node
, *nnode
;
11580 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
11581 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
11584 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11585 safi_t safi
, struct json_object
*json_array
)
11587 struct bgp_table_stats ts
;
11589 int ret
= CMD_SUCCESS
;
11591 struct json_object
*json
= NULL
;
11594 json
= json_object_new_object();
11596 if (!bgp
->rib
[afi
][safi
]) {
11597 char warning_msg
[50];
11599 snprintf(warning_msg
, sizeof(warning_msg
),
11600 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
11604 vty_out(vty
, "%s\n", warning_msg
);
11606 json_object_string_add(json
, "warning", warning_msg
);
11609 goto end_table_stats
;
11613 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
11614 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
11616 json_object_string_add(json
, "instance", bgp
->name_pretty
);
11618 /* labeled-unicast routes live in the unicast table */
11619 if (safi
== SAFI_LABELED_UNICAST
)
11620 safi
= SAFI_UNICAST
;
11622 memset(&ts
, 0, sizeof(ts
));
11623 ts
.table
= bgp
->rib
[afi
][safi
];
11624 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
11626 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
11627 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
11628 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
11633 case BGP_STATS_ASPATH_AVGHOPS
:
11634 case BGP_STATS_ASPATH_AVGSIZE
:
11635 case BGP_STATS_AVGPLEN
:
11636 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
11637 vty_out (vty
, "%12.2f",
11638 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
11641 case BGP_STATS_ASPATH_TOTHOPS
:
11642 case BGP_STATS_ASPATH_TOTSIZE
:
11645 temp_buf
, sizeof(temp_buf
), "%12.2f",
11647 ? (float)ts
.counts
[i
]
11649 [BGP_STATS_ASPATH_COUNT
]
11651 vty_out(vty
, "%-30s: %s",
11652 table_stats_strs
[i
]
11653 [TABLE_STATS_IDX_VTY
],
11656 json_object_double_add(
11658 table_stats_strs
[i
]
11659 [TABLE_STATS_IDX_JSON
],
11661 ? (double)ts
.counts
[i
]
11662 / (double)ts
.counts
11663 [BGP_STATS_ASPATH_COUNT
]
11667 case BGP_STATS_TOTPLEN
:
11670 temp_buf
, sizeof(temp_buf
), "%12.2f",
11672 ? (float)ts
.counts
[i
]
11674 [BGP_STATS_PREFIXES
]
11676 vty_out(vty
, "%-30s: %s",
11677 table_stats_strs
[i
]
11678 [TABLE_STATS_IDX_VTY
],
11681 json_object_double_add(
11683 table_stats_strs
[i
]
11684 [TABLE_STATS_IDX_JSON
],
11686 ? (double)ts
.counts
[i
]
11687 / (double)ts
.counts
11688 [BGP_STATS_PREFIXES
]
11692 case BGP_STATS_SPACE
:
11694 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
11696 vty_out(vty
, "%-30s: %s\n",
11697 table_stats_strs
[i
]
11698 [TABLE_STATS_IDX_VTY
],
11701 json_object_double_add(
11703 table_stats_strs
[i
]
11704 [TABLE_STATS_IDX_JSON
],
11705 (double)ts
.total_space
);
11707 if (afi
== AFI_IP6
) {
11709 snprintf(temp_buf
, sizeof(temp_buf
),
11712 * pow(2.0, -128 + 32));
11713 vty_out(vty
, "%30s: %s\n",
11714 "/32 equivalent %s\n",
11717 json_object_double_add(
11718 json
, "/32equivalent",
11719 (double)(ts
.total_space
11724 snprintf(temp_buf
, sizeof(temp_buf
),
11727 * pow(2.0, -128 + 48));
11728 vty_out(vty
, "%30s: %s\n",
11729 "/48 equivalent %s\n",
11732 json_object_double_add(
11733 json
, "/48equivalent",
11734 (double)(ts
.total_space
11740 snprintf(temp_buf
, sizeof(temp_buf
),
11742 ts
.total_space
* 100.
11744 vty_out(vty
, "%30s: %s\n",
11745 "% announced ", temp_buf
);
11747 json_object_double_add(
11748 json
, "%announced",
11749 (double)(ts
.total_space
* 100.
11753 snprintf(temp_buf
, sizeof(temp_buf
),
11756 * pow(2.0, -32 + 8));
11757 vty_out(vty
, "%30s: %s\n",
11758 "/8 equivalent ", temp_buf
);
11760 json_object_double_add(
11761 json
, "/8equivalent",
11762 (double)(ts
.total_space
11763 * pow(2.0, -32 + 8)));
11766 snprintf(temp_buf
, sizeof(temp_buf
),
11769 * pow(2.0, -32 + 24));
11770 vty_out(vty
, "%30s: %s\n",
11771 "/24 equivalent ", temp_buf
);
11773 json_object_double_add(
11774 json
, "/24equivalent",
11775 (double)(ts
.total_space
11776 * pow(2.0, -32 + 24)));
11782 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
11784 vty_out(vty
, "%-30s: %s",
11785 table_stats_strs
[i
]
11786 [TABLE_STATS_IDX_VTY
],
11789 json_object_int_add(
11791 table_stats_strs
[i
]
11792 [TABLE_STATS_IDX_JSON
],
11797 vty_out(vty
, "\n");
11801 json_object_array_add(json_array
, json
);
11805 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11806 safi_t safi
, struct json_object
*json_array
)
11809 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
11810 return CMD_SUCCESS
;
11813 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
11825 PCOUNT_BPATH_SELECTED
,
11826 PCOUNT_PFCNT
, /* the figure we display to users */
11830 static const char *const pcount_strs
[] = {
11831 [PCOUNT_ADJ_IN
] = "Adj-in",
11832 [PCOUNT_DAMPED
] = "Damped",
11833 [PCOUNT_REMOVED
] = "Removed",
11834 [PCOUNT_HISTORY
] = "History",
11835 [PCOUNT_STALE
] = "Stale",
11836 [PCOUNT_VALID
] = "Valid",
11837 [PCOUNT_ALL
] = "All RIB",
11838 [PCOUNT_COUNTED
] = "PfxCt counted",
11839 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
11840 [PCOUNT_PFCNT
] = "Useable",
11841 [PCOUNT_MAX
] = NULL
,
11844 struct peer_pcounts
{
11845 unsigned int count
[PCOUNT_MAX
];
11846 const struct peer
*peer
;
11847 const struct bgp_table
*table
;
11851 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
11853 const struct bgp_adj_in
*ain
;
11854 const struct bgp_path_info
*pi
;
11855 const struct peer
*peer
= pc
->peer
;
11857 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
11858 if (ain
->peer
== peer
)
11859 pc
->count
[PCOUNT_ADJ_IN
]++;
11861 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
11863 if (pi
->peer
!= peer
)
11866 pc
->count
[PCOUNT_ALL
]++;
11868 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
11869 pc
->count
[PCOUNT_DAMPED
]++;
11870 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11871 pc
->count
[PCOUNT_HISTORY
]++;
11872 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
11873 pc
->count
[PCOUNT_REMOVED
]++;
11874 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
11875 pc
->count
[PCOUNT_STALE
]++;
11876 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
11877 pc
->count
[PCOUNT_VALID
]++;
11878 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11879 pc
->count
[PCOUNT_PFCNT
]++;
11880 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11881 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
11883 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
11884 pc
->count
[PCOUNT_COUNTED
]++;
11885 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11887 EC_LIB_DEVELOPMENT
,
11888 "Attempting to count but flags say it is unusable");
11890 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11892 EC_LIB_DEVELOPMENT
,
11893 "Not counted but flags say we should");
11898 static int bgp_peer_count_walker(struct thread
*t
)
11900 struct bgp_dest
*rn
, *rm
;
11901 const struct bgp_table
*table
;
11902 struct peer_pcounts
*pc
= THREAD_ARG(t
);
11904 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
11905 || pc
->safi
== SAFI_EVPN
) {
11906 /* Special handling for 2-level routing tables. */
11907 for (rn
= bgp_table_top(pc
->table
); rn
;
11908 rn
= bgp_route_next(rn
)) {
11909 table
= bgp_dest_get_bgp_table_info(rn
);
11911 for (rm
= bgp_table_top(table
); rm
;
11912 rm
= bgp_route_next(rm
))
11913 bgp_peer_count_proc(rm
, pc
);
11916 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
11917 bgp_peer_count_proc(rn
, pc
);
11922 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11923 safi_t safi
, bool use_json
)
11925 struct peer_pcounts pcounts
= {.peer
= peer
};
11927 json_object
*json
= NULL
;
11928 json_object
*json_loop
= NULL
;
11931 json
= json_object_new_object();
11932 json_loop
= json_object_new_object();
11935 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
11936 || !peer
->bgp
->rib
[afi
][safi
]) {
11938 json_object_string_add(
11940 "No such neighbor or address family");
11941 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11942 json_object_free(json
);
11944 vty_out(vty
, "%% No such neighbor or address family\n");
11946 return CMD_WARNING
;
11949 memset(&pcounts
, 0, sizeof(pcounts
));
11950 pcounts
.peer
= peer
;
11951 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11952 pcounts
.safi
= safi
;
11954 /* in-place call via thread subsystem so as to record execution time
11955 * stats for the thread-walk (i.e. ensure this can't be blamed on
11956 * on just vty_read()).
11958 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11961 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11962 json_object_string_add(json
, "multiProtocol",
11963 get_afi_safi_str(afi
, safi
, true));
11964 json_object_int_add(json
, "pfxCounter",
11965 peer
->pcount
[afi
][safi
]);
11967 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11968 json_object_int_add(json_loop
, pcount_strs
[i
],
11971 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
11973 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11974 json_object_string_add(json
, "pfxctDriftFor",
11976 json_object_string_add(
11977 json
, "recommended",
11978 "Please report this bug, with the above command output");
11980 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11981 json
, JSON_C_TO_STRING_PRETTY
));
11982 json_object_free(json
);
11986 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
11987 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
11988 peer
->hostname
, peer
->host
,
11989 get_afi_safi_str(afi
, safi
, false));
11991 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11992 get_afi_safi_str(afi
, safi
, false));
11995 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
11996 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11998 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11999 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
12002 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12003 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
12005 "Please report this bug, with the above command output\n");
12009 return CMD_SUCCESS
;
12012 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
12013 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
12014 "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]",
12018 BGP_INSTANCE_HELP_STR
12021 "Detailed information on TCP and BGP neighbor connections\n"
12022 "Neighbor to display information about\n"
12023 "Neighbor to display information about\n"
12024 "Neighbor on BGP configured interface\n"
12025 "Display detailed prefix count information\n"
12028 afi_t afi
= AFI_IP6
;
12029 safi_t safi
= SAFI_UNICAST
;
12032 struct bgp
*bgp
= NULL
;
12033 bool uj
= use_json(argc
, argv
);
12038 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12041 return CMD_WARNING
;
12043 argv_find(argv
, argc
, "neighbors", &idx
);
12044 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
12046 return CMD_WARNING
;
12048 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
12051 #ifdef KEEP_OLD_VPN_COMMANDS
12052 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
12053 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
12054 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12059 "Display information about all VPNv4 NLRIs\n"
12060 "Detailed information on TCP and BGP neighbor connections\n"
12061 "Neighbor to display information about\n"
12062 "Neighbor to display information about\n"
12063 "Neighbor on BGP configured interface\n"
12064 "Display detailed prefix count information\n"
12069 bool uj
= use_json(argc
, argv
);
12071 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
12073 return CMD_WARNING
;
12075 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
12078 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
12079 show_ip_bgp_vpn_all_route_prefix_cmd
,
12080 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
12085 "Display information about all VPNv4 NLRIs\n"
12086 "Network in the BGP routing table to display\n"
12087 "Network in the BGP routing table to display\n"
12091 char *network
= NULL
;
12092 struct bgp
*bgp
= bgp_get_default();
12094 vty_out(vty
, "Can't find default instance\n");
12095 return CMD_WARNING
;
12098 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
12099 network
= argv
[idx
]->arg
;
12100 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
12101 network
= argv
[idx
]->arg
;
12103 vty_out(vty
, "Unable to figure out Network\n");
12104 return CMD_WARNING
;
12107 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
12108 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12110 #endif /* KEEP_OLD_VPN_COMMANDS */
12112 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
12113 show_bgp_l2vpn_evpn_route_prefix_cmd
,
12114 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
12119 "Network in the BGP routing table to display\n"
12120 "Network in the BGP routing table to display\n"
12121 "Network in the BGP routing table to display\n"
12122 "Network in the BGP routing table to display\n"
12126 char *network
= NULL
;
12127 int prefix_check
= 0;
12129 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
12130 argv_find(argv
, argc
, "X:X::X:X", &idx
))
12131 network
= argv
[idx
]->arg
;
12132 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
12133 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12134 network
= argv
[idx
]->arg
;
12137 vty_out(vty
, "Unable to figure out Network\n");
12138 return CMD_WARNING
;
12140 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
12141 prefix_check
, BGP_PATH_SHOW_ALL
,
12142 use_json(argc
, argv
));
12145 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
12146 struct bgp_table
*table
, int *header1
,
12147 int *header2
, json_object
*json
,
12148 json_object
*json_scode
,
12149 json_object
*json_ocode
, bool wide
)
12151 uint64_t version
= table
? table
->version
: 0;
12155 json_object_int_add(json
, "bgpTableVersion", version
);
12156 json_object_string_add(json
, "bgpLocalRouterId",
12157 inet_ntoa(bgp
->router_id
));
12158 json_object_int_add(json
, "defaultLocPrf",
12159 bgp
->default_local_pref
);
12160 json_object_int_add(json
, "localAS", bgp
->as
);
12161 json_object_object_add(json
, "bgpStatusCodes",
12163 json_object_object_add(json
, "bgpOriginCodes",
12167 "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
12168 version
, inet_ntoa(bgp
->router_id
));
12169 if (bgp
->vrf_id
== VRF_UNKNOWN
)
12170 vty_out(vty
, "%s", VRFID_NONE_STR
);
12172 vty_out(vty
, "%u", bgp
->vrf_id
);
12173 vty_out(vty
, "\n");
12174 vty_out(vty
, "Default local pref %u, ",
12175 bgp
->default_local_pref
);
12176 vty_out(vty
, "local AS %u\n", bgp
->as
);
12177 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
12178 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
12179 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
12185 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
12186 : BGP_SHOW_HEADER
));
12191 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12192 safi_t safi
, enum bgp_show_adj_route_type type
,
12193 const char *rmap_name
, bool use_json
,
12194 json_object
*json
, bool wide
)
12196 struct bgp_table
*table
;
12197 struct bgp_adj_in
*ain
;
12198 struct bgp_adj_out
*adj
;
12199 unsigned long output_count
= 0;
12200 unsigned long filtered_count
= 0;
12201 struct bgp_dest
*dest
;
12207 struct update_subgroup
*subgrp
;
12208 json_object
*json_scode
= NULL
;
12209 json_object
*json_ocode
= NULL
;
12210 json_object
*json_ar
= NULL
;
12211 struct peer_af
*paf
;
12212 bool route_filtered
;
12215 json_scode
= json_object_new_object();
12216 json_ocode
= json_object_new_object();
12217 json_ar
= json_object_new_object();
12219 json_object_string_add(json_scode
, "suppressed", "s");
12220 json_object_string_add(json_scode
, "damped", "d");
12221 json_object_string_add(json_scode
, "history", "h");
12222 json_object_string_add(json_scode
, "valid", "*");
12223 json_object_string_add(json_scode
, "best", ">");
12224 json_object_string_add(json_scode
, "multipath", "=");
12225 json_object_string_add(json_scode
, "internal", "i");
12226 json_object_string_add(json_scode
, "ribFailure", "r");
12227 json_object_string_add(json_scode
, "stale", "S");
12228 json_object_string_add(json_scode
, "removed", "R");
12230 json_object_string_add(json_ocode
, "igp", "i");
12231 json_object_string_add(json_ocode
, "egp", "e");
12232 json_object_string_add(json_ocode
, "incomplete", "?");
12239 json_object_string_add(json
, "alert", "no BGP");
12240 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12241 json_object_free(json
);
12243 vty_out(vty
, "%% No bgp\n");
12247 /* labeled-unicast routes live in the unicast table */
12248 if (safi
== SAFI_LABELED_UNICAST
)
12249 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
12251 table
= bgp
->rib
[afi
][safi
];
12253 output_count
= filtered_count
= 0;
12254 subgrp
= peer_subgroup(peer
, afi
, safi
);
12256 if (type
== bgp_show_adj_route_advertised
&& subgrp
12257 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
12259 json_object_int_add(json
, "bgpTableVersion",
12261 json_object_string_add(json
, "bgpLocalRouterId",
12262 inet_ntoa(bgp
->router_id
));
12263 json_object_int_add(json
, "defaultLocPrf",
12264 bgp
->default_local_pref
);
12265 json_object_int_add(json
, "localAS", bgp
->as
);
12266 json_object_object_add(json
, "bgpStatusCodes",
12268 json_object_object_add(json
, "bgpOriginCodes",
12270 json_object_string_add(
12271 json
, "bgpOriginatingDefaultNetwork",
12272 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
12274 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
12275 table
->version
, inet_ntoa(bgp
->router_id
));
12276 if (bgp
->vrf_id
== VRF_UNKNOWN
)
12277 vty_out(vty
, "%s", VRFID_NONE_STR
);
12279 vty_out(vty
, "%u", bgp
->vrf_id
);
12280 vty_out(vty
, "\n");
12281 vty_out(vty
, "Default local pref %u, ",
12282 bgp
->default_local_pref
);
12283 vty_out(vty
, "local AS %u\n", bgp
->as
);
12284 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
12285 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
12286 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
12288 vty_out(vty
, "Originating default network %s\n\n",
12289 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
12294 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
12295 if (type
== bgp_show_adj_route_received
12296 || type
== bgp_show_adj_route_filtered
) {
12297 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
12298 if (ain
->peer
!= peer
)
12301 show_adj_route_header(
12302 vty
, bgp
, table
, &header1
, &header2
,
12303 json
, json_scode
, json_ocode
, wide
);
12306 route_filtered
= false;
12308 /* Filter prefix using distribute list,
12309 * filter list or prefix list
12311 const struct prefix
*rn_p
=
12312 bgp_dest_get_prefix(dest
);
12313 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
12316 route_filtered
= true;
12318 /* Filter prefix using route-map */
12319 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
12320 safi
, rmap_name
, NULL
,
12323 if (type
== bgp_show_adj_route_filtered
&&
12324 !route_filtered
&& ret
!= RMAP_DENY
) {
12325 bgp_attr_undup(&attr
, ain
->attr
);
12329 if (type
== bgp_show_adj_route_received
&&
12330 (route_filtered
|| ret
== RMAP_DENY
))
12333 route_vty_out_tmp(vty
, rn_p
, &attr
, safi
,
12334 use_json
, json_ar
, wide
);
12335 bgp_attr_undup(&attr
, ain
->attr
);
12338 } else if (type
== bgp_show_adj_route_advertised
) {
12339 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
12340 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
12341 if (paf
->peer
!= peer
|| !adj
->attr
)
12344 show_adj_route_header(
12345 vty
, bgp
, table
, &header1
,
12346 &header2
, json
, json_scode
,
12349 const struct prefix
*rn_p
=
12350 bgp_dest_get_prefix(dest
);
12353 ret
= bgp_output_modifier(
12354 peer
, rn_p
, &attr
, afi
, safi
,
12357 if (ret
!= RMAP_DENY
) {
12359 vty
, rn_p
, &attr
, safi
,
12367 bgp_attr_undup(&attr
, adj
->attr
);
12369 } else if (type
== bgp_show_adj_route_bestpath
) {
12370 struct bgp_path_info
*pi
;
12372 show_adj_route_header(vty
, bgp
, table
, &header1
,
12373 &header2
, json
, json_scode
,
12376 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
12378 if (pi
->peer
!= peer
)
12381 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12384 route_vty_out_tmp(vty
,
12385 bgp_dest_get_prefix(dest
),
12386 pi
->attr
, safi
, use_json
,
12394 json_object_object_add(json
, "advertisedRoutes", json_ar
);
12395 json_object_int_add(json
, "totalPrefixCounter", output_count
);
12396 json_object_int_add(json
, "filteredPrefixCounter",
12399 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
12400 json
, JSON_C_TO_STRING_PRETTY
));
12402 if (!output_count
&& !filtered_count
) {
12403 json_object_free(json_scode
);
12404 json_object_free(json_ocode
);
12407 json_object_free(json
);
12408 } else if (output_count
> 0) {
12409 if (filtered_count
> 0)
12411 "\nTotal number of prefixes %ld (%ld filtered)\n",
12412 output_count
, filtered_count
);
12414 vty_out(vty
, "\nTotal number of prefixes %ld\n",
12419 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12420 safi_t safi
, enum bgp_show_adj_route_type type
,
12421 const char *rmap_name
, bool use_json
, bool wide
)
12423 json_object
*json
= NULL
;
12426 json
= json_object_new_object();
12428 if (!peer
|| !peer
->afc
[afi
][safi
]) {
12430 json_object_string_add(
12432 "No such neighbor or address family");
12433 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12434 json_object_free(json
);
12436 vty_out(vty
, "%% No such neighbor or address family\n");
12438 return CMD_WARNING
;
12441 if ((type
== bgp_show_adj_route_received
12442 || type
== bgp_show_adj_route_filtered
)
12443 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
12444 PEER_FLAG_SOFT_RECONFIG
)) {
12446 json_object_string_add(
12448 "Inbound soft reconfiguration not enabled");
12449 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12450 json_object_free(json
);
12453 "%% Inbound soft reconfiguration not enabled\n");
12455 return CMD_WARNING
;
12458 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
,
12461 return CMD_SUCCESS
;
12464 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
12465 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
12466 "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]",
12470 BGP_INSTANCE_HELP_STR
12472 BGP_SAFI_WITH_LABEL_HELP_STR
12473 "Detailed information on TCP and BGP neighbor connections\n"
12474 "Neighbor to display information about\n"
12475 "Neighbor to display information about\n"
12476 "Neighbor on BGP configured interface\n"
12477 "Display the routes selected by best path\n"
12479 "Increase table width for longer prefixes\n")
12481 afi_t afi
= AFI_IP6
;
12482 safi_t safi
= SAFI_UNICAST
;
12483 char *rmap_name
= NULL
;
12484 char *peerstr
= NULL
;
12485 struct bgp
*bgp
= NULL
;
12487 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
12490 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12494 return CMD_WARNING
;
12496 argv_find(argv
, argc
, "neighbors", &idx
);
12497 peerstr
= argv
[++idx
]->arg
;
12499 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12501 return CMD_WARNING
;
12503 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
, wide
);
12506 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
12507 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
12508 "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> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json$uj | wide$wide]",
12512 BGP_INSTANCE_HELP_STR
12514 BGP_SAFI_WITH_LABEL_HELP_STR
12515 "Detailed information on TCP and BGP neighbor connections\n"
12516 "Neighbor to display information about\n"
12517 "Neighbor to display information about\n"
12518 "Neighbor on BGP configured interface\n"
12519 "Display the routes advertised to a BGP neighbor\n"
12520 "Display the received routes from neighbor\n"
12521 "Display the filtered routes received from neighbor\n"
12522 "Route-map to modify the attributes\n"
12523 "Name of the route map\n"
12525 "Increase table width for longer prefixes\n")
12527 afi_t afi
= AFI_IP6
;
12528 safi_t safi
= SAFI_UNICAST
;
12529 char *rmap_name
= NULL
;
12530 char *peerstr
= NULL
;
12531 struct bgp
*bgp
= NULL
;
12533 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
12539 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12542 return CMD_WARNING
;
12544 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12545 argv_find(argv
, argc
, "neighbors", &idx
);
12546 peerstr
= argv
[++idx
]->arg
;
12548 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12550 return CMD_WARNING
;
12552 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
12553 type
= bgp_show_adj_route_advertised
;
12554 else if (argv_find(argv
, argc
, "received-routes", &idx
))
12555 type
= bgp_show_adj_route_received
;
12556 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
12557 type
= bgp_show_adj_route_filtered
;
12559 if (argv_find(argv
, argc
, "route-map", &idx
))
12560 rmap_name
= argv
[++idx
]->arg
;
12562 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
, wide
);
12565 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
12566 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
12567 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
12573 "Address Family modifier\n"
12574 "Detailed information on TCP and BGP neighbor connections\n"
12575 "Neighbor to display information about\n"
12576 "Neighbor to display information about\n"
12577 "Neighbor on BGP configured interface\n"
12578 "Display information received from a BGP neighbor\n"
12579 "Display the prefixlist filter\n"
12582 afi_t afi
= AFI_IP6
;
12583 safi_t safi
= SAFI_UNICAST
;
12584 char *peerstr
= NULL
;
12587 union sockunion su
;
12593 /* show [ip] bgp */
12594 if (argv_find(argv
, argc
, "ip", &idx
))
12596 /* [<ipv4|ipv6> [unicast]] */
12597 if (argv_find(argv
, argc
, "ipv4", &idx
))
12599 if (argv_find(argv
, argc
, "ipv6", &idx
))
12601 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12602 argv_find(argv
, argc
, "neighbors", &idx
);
12603 peerstr
= argv
[++idx
]->arg
;
12605 bool uj
= use_json(argc
, argv
);
12607 ret
= str2sockunion(peerstr
, &su
);
12609 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
12612 vty_out(vty
, "{}\n");
12615 "%% Malformed address or name: %s\n",
12617 return CMD_WARNING
;
12620 peer
= peer_lookup(NULL
, &su
);
12623 vty_out(vty
, "{}\n");
12625 vty_out(vty
, "No peer\n");
12626 return CMD_WARNING
;
12630 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
12631 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
12634 vty_out(vty
, "Address Family: %s\n",
12635 get_afi_safi_str(afi
, safi
, false));
12636 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
12639 vty_out(vty
, "{}\n");
12641 vty_out(vty
, "No functional output\n");
12644 return CMD_SUCCESS
;
12647 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
12648 afi_t afi
, safi_t safi
,
12649 enum bgp_show_type type
, bool use_json
)
12651 /* labeled-unicast routes live in the unicast table */
12652 if (safi
== SAFI_LABELED_UNICAST
)
12653 safi
= SAFI_UNICAST
;
12655 if (!peer
|| !peer
->afc
[afi
][safi
]) {
12657 json_object
*json_no
= NULL
;
12658 json_no
= json_object_new_object();
12659 json_object_string_add(
12660 json_no
, "warning",
12661 "No such neighbor or address family");
12662 vty_out(vty
, "%s\n",
12663 json_object_to_json_string(json_no
));
12664 json_object_free(json_no
);
12666 vty_out(vty
, "%% No such neighbor or address family\n");
12667 return CMD_WARNING
;
12670 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
,
12674 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
12675 show_ip_bgp_flowspec_routes_detailed_cmd
,
12676 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
12680 BGP_INSTANCE_HELP_STR
12683 "Detailed information on flowspec entries\n"
12686 afi_t afi
= AFI_IP
;
12687 safi_t safi
= SAFI_UNICAST
;
12688 struct bgp
*bgp
= NULL
;
12690 bool uj
= use_json(argc
, argv
);
12695 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12698 return CMD_WARNING
;
12700 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
,
12704 DEFUN (show_ip_bgp_neighbor_routes
,
12705 show_ip_bgp_neighbor_routes_cmd
,
12706 "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]",
12710 BGP_INSTANCE_HELP_STR
12712 BGP_SAFI_WITH_LABEL_HELP_STR
12713 "Detailed information on TCP and BGP neighbor connections\n"
12714 "Neighbor to display information about\n"
12715 "Neighbor to display information about\n"
12716 "Neighbor on BGP configured interface\n"
12717 "Display flap statistics of the routes learned from neighbor\n"
12718 "Display the dampened routes received from neighbor\n"
12719 "Display routes learned from neighbor\n"
12722 char *peerstr
= NULL
;
12723 struct bgp
*bgp
= NULL
;
12724 afi_t afi
= AFI_IP6
;
12725 safi_t safi
= SAFI_UNICAST
;
12727 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
12729 bool uj
= use_json(argc
, argv
);
12734 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12737 return CMD_WARNING
;
12739 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12740 argv_find(argv
, argc
, "neighbors", &idx
);
12741 peerstr
= argv
[++idx
]->arg
;
12743 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12745 return CMD_WARNING
;
12747 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12748 sh_type
= bgp_show_type_flap_neighbor
;
12749 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
12750 sh_type
= bgp_show_type_damp_neighbor
;
12751 else if (argv_find(argv
, argc
, "routes", &idx
))
12752 sh_type
= bgp_show_type_neighbor
;
12754 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
12757 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
12759 struct bgp_distance
{
12760 /* Distance value for the IP source prefix. */
12763 /* Name of the access-list to be matched. */
12767 DEFUN (show_bgp_afi_vpn_rd_route
,
12768 show_bgp_afi_vpn_rd_route_cmd
,
12769 "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]",
12773 "Address Family modifier\n"
12774 "Display information for a route distinguisher\n"
12775 "Route Distinguisher\n"
12776 "Network in the BGP routing table to display\n"
12777 "Network in the BGP routing table to display\n"
12781 struct prefix_rd prd
;
12782 afi_t afi
= AFI_MAX
;
12785 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
12786 vty_out(vty
, "%% Malformed Address Family\n");
12787 return CMD_WARNING
;
12790 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
12792 vty_out(vty
, "%% Malformed Route Distinguisher\n");
12793 return CMD_WARNING
;
12796 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
12797 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12800 static struct bgp_distance
*bgp_distance_new(void)
12802 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
12805 static void bgp_distance_free(struct bgp_distance
*bdistance
)
12807 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
12810 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
12811 const char *ip_str
, const char *access_list_str
)
12818 struct bgp_dest
*dest
;
12819 struct bgp_distance
*bdistance
;
12821 afi
= bgp_node_afi(vty
);
12822 safi
= bgp_node_safi(vty
);
12824 ret
= str2prefix(ip_str
, &p
);
12826 vty_out(vty
, "Malformed prefix\n");
12827 return CMD_WARNING_CONFIG_FAILED
;
12830 distance
= atoi(distance_str
);
12832 /* Get BGP distance node. */
12833 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
12834 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
12836 bgp_dest_unlock_node(dest
);
12838 bdistance
= bgp_distance_new();
12839 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
12842 /* Set distance value. */
12843 bdistance
->distance
= distance
;
12845 /* Reset access-list configuration. */
12846 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12847 if (access_list_str
)
12848 bdistance
->access_list
=
12849 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
12851 return CMD_SUCCESS
;
12854 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
12855 const char *ip_str
, const char *access_list_str
)
12862 struct bgp_dest
*dest
;
12863 struct bgp_distance
*bdistance
;
12865 afi
= bgp_node_afi(vty
);
12866 safi
= bgp_node_safi(vty
);
12868 ret
= str2prefix(ip_str
, &p
);
12870 vty_out(vty
, "Malformed prefix\n");
12871 return CMD_WARNING_CONFIG_FAILED
;
12874 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
12876 vty_out(vty
, "Can't find specified prefix\n");
12877 return CMD_WARNING_CONFIG_FAILED
;
12880 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
12881 distance
= atoi(distance_str
);
12883 if (bdistance
->distance
!= distance
) {
12884 vty_out(vty
, "Distance does not match configured\n");
12885 return CMD_WARNING_CONFIG_FAILED
;
12888 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12889 bgp_distance_free(bdistance
);
12891 bgp_dest_set_bgp_path_info(dest
, NULL
);
12892 bgp_dest_unlock_node(dest
);
12893 bgp_dest_unlock_node(dest
);
12895 return CMD_SUCCESS
;
12898 /* Apply BGP information to distance method. */
12899 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
12900 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
12902 struct bgp_dest
*dest
;
12905 struct bgp_distance
*bdistance
;
12906 struct access_list
*alist
;
12907 struct bgp_static
*bgp_static
;
12912 peer
= pinfo
->peer
;
12914 if (pinfo
->attr
->distance
)
12915 return pinfo
->attr
->distance
;
12917 /* Check source address. */
12918 sockunion2hostprefix(&peer
->su
, &q
);
12919 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
12921 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
12922 bgp_dest_unlock_node(dest
);
12924 if (bdistance
->access_list
) {
12925 alist
= access_list_lookup(afi
, bdistance
->access_list
);
12927 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
12928 return bdistance
->distance
;
12930 return bdistance
->distance
;
12933 /* Backdoor check. */
12934 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
12936 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
12937 bgp_dest_unlock_node(dest
);
12939 if (bgp_static
->backdoor
) {
12940 if (bgp
->distance_local
[afi
][safi
])
12941 return bgp
->distance_local
[afi
][safi
];
12943 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12947 if (peer
->sort
== BGP_PEER_EBGP
) {
12948 if (bgp
->distance_ebgp
[afi
][safi
])
12949 return bgp
->distance_ebgp
[afi
][safi
];
12950 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
12952 if (bgp
->distance_ibgp
[afi
][safi
])
12953 return bgp
->distance_ibgp
[afi
][safi
];
12954 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12958 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12959 * we should tell ZEBRA update the routes for a specific
12960 * AFI/SAFI to reflect changes in RIB.
12962 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
12964 safi_t update_safi
)
12969 FOREACH_AFI_SAFI (afi
, safi
) {
12970 if (!bgp_fibupd_safi(safi
))
12973 if (afi
!= update_afi
&& safi
!= update_safi
)
12976 if (BGP_DEBUG(zebra
, ZEBRA
))
12978 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12979 __func__
, afi
, safi
);
12980 bgp_zebra_announce_table(bgp
, afi
, safi
);
12984 DEFUN (bgp_distance
,
12986 "distance bgp (1-255) (1-255) (1-255)",
12987 "Define an administrative distance\n"
12989 "Distance for routes external to the AS\n"
12990 "Distance for routes internal to the AS\n"
12991 "Distance for local routes\n")
12993 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12994 int idx_number
= 2;
12995 int idx_number_2
= 3;
12996 int idx_number_3
= 4;
12997 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
12998 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
12999 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
13003 afi
= bgp_node_afi(vty
);
13004 safi
= bgp_node_safi(vty
);
13006 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
13007 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
13008 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
13009 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
13010 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
13011 bgp
->distance_local
[afi
][safi
] = distance_local
;
13012 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
13014 return CMD_SUCCESS
;
13017 DEFUN (no_bgp_distance
,
13018 no_bgp_distance_cmd
,
13019 "no distance bgp [(1-255) (1-255) (1-255)]",
13021 "Define an administrative distance\n"
13023 "Distance for routes external to the AS\n"
13024 "Distance for routes internal to the AS\n"
13025 "Distance for local routes\n")
13027 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13031 afi
= bgp_node_afi(vty
);
13032 safi
= bgp_node_safi(vty
);
13034 if (bgp
->distance_ebgp
[afi
][safi
] != 0
13035 || bgp
->distance_ibgp
[afi
][safi
] != 0
13036 || bgp
->distance_local
[afi
][safi
] != 0) {
13037 bgp
->distance_ebgp
[afi
][safi
] = 0;
13038 bgp
->distance_ibgp
[afi
][safi
] = 0;
13039 bgp
->distance_local
[afi
][safi
] = 0;
13040 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
13042 return CMD_SUCCESS
;
13046 DEFUN (bgp_distance_source
,
13047 bgp_distance_source_cmd
,
13048 "distance (1-255) A.B.C.D/M",
13049 "Define an administrative distance\n"
13050 "Administrative distance\n"
13051 "IP source prefix\n")
13053 int idx_number
= 1;
13054 int idx_ipv4_prefixlen
= 2;
13055 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
13056 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
13057 return CMD_SUCCESS
;
13060 DEFUN (no_bgp_distance_source
,
13061 no_bgp_distance_source_cmd
,
13062 "no distance (1-255) A.B.C.D/M",
13064 "Define an administrative distance\n"
13065 "Administrative distance\n"
13066 "IP source prefix\n")
13068 int idx_number
= 2;
13069 int idx_ipv4_prefixlen
= 3;
13070 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
13071 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
13072 return CMD_SUCCESS
;
13075 DEFUN (bgp_distance_source_access_list
,
13076 bgp_distance_source_access_list_cmd
,
13077 "distance (1-255) A.B.C.D/M WORD",
13078 "Define an administrative distance\n"
13079 "Administrative distance\n"
13080 "IP source prefix\n"
13081 "Access list name\n")
13083 int idx_number
= 1;
13084 int idx_ipv4_prefixlen
= 2;
13086 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
13087 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
13088 return CMD_SUCCESS
;
13091 DEFUN (no_bgp_distance_source_access_list
,
13092 no_bgp_distance_source_access_list_cmd
,
13093 "no distance (1-255) A.B.C.D/M WORD",
13095 "Define an administrative distance\n"
13096 "Administrative distance\n"
13097 "IP source prefix\n"
13098 "Access list name\n")
13100 int idx_number
= 2;
13101 int idx_ipv4_prefixlen
= 3;
13103 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
13104 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
13105 return CMD_SUCCESS
;
13108 DEFUN (ipv6_bgp_distance_source
,
13109 ipv6_bgp_distance_source_cmd
,
13110 "distance (1-255) X:X::X:X/M",
13111 "Define an administrative distance\n"
13112 "Administrative distance\n"
13113 "IP source prefix\n")
13115 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
13116 return CMD_SUCCESS
;
13119 DEFUN (no_ipv6_bgp_distance_source
,
13120 no_ipv6_bgp_distance_source_cmd
,
13121 "no distance (1-255) X:X::X:X/M",
13123 "Define an administrative distance\n"
13124 "Administrative distance\n"
13125 "IP source prefix\n")
13127 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
13128 return CMD_SUCCESS
;
13131 DEFUN (ipv6_bgp_distance_source_access_list
,
13132 ipv6_bgp_distance_source_access_list_cmd
,
13133 "distance (1-255) X:X::X:X/M WORD",
13134 "Define an administrative distance\n"
13135 "Administrative distance\n"
13136 "IP source prefix\n"
13137 "Access list name\n")
13139 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
13140 return CMD_SUCCESS
;
13143 DEFUN (no_ipv6_bgp_distance_source_access_list
,
13144 no_ipv6_bgp_distance_source_access_list_cmd
,
13145 "no distance (1-255) X:X::X:X/M WORD",
13147 "Define an administrative distance\n"
13148 "Administrative distance\n"
13149 "IP source prefix\n"
13150 "Access list name\n")
13152 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
13153 return CMD_SUCCESS
;
13156 DEFUN (bgp_damp_set
,
13158 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
13159 "BGP Specific commands\n"
13160 "Enable route-flap dampening\n"
13161 "Half-life time for the penalty\n"
13162 "Value to start reusing a route\n"
13163 "Value to start suppressing a route\n"
13164 "Maximum duration to suppress a stable route\n")
13166 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13167 int idx_half_life
= 2;
13169 int idx_suppress
= 4;
13170 int idx_max_suppress
= 5;
13171 int half
= DEFAULT_HALF_LIFE
* 60;
13172 int reuse
= DEFAULT_REUSE
;
13173 int suppress
= DEFAULT_SUPPRESS
;
13174 int max
= 4 * half
;
13177 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
13178 reuse
= atoi(argv
[idx_reuse
]->arg
);
13179 suppress
= atoi(argv
[idx_suppress
]->arg
);
13180 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
13181 } else if (argc
== 3) {
13182 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
13187 * These can't be 0 but our SA doesn't understand the
13188 * way our cli is constructed
13192 if (suppress
< reuse
) {
13194 "Suppress value cannot be less than reuse value \n");
13198 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
13199 reuse
, suppress
, max
);
13202 DEFUN (bgp_damp_unset
,
13203 bgp_damp_unset_cmd
,
13204 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
13206 "BGP Specific commands\n"
13207 "Enable route-flap dampening\n"
13208 "Half-life time for the penalty\n"
13209 "Value to start reusing a route\n"
13210 "Value to start suppressing a route\n"
13211 "Maximum duration to suppress a stable route\n")
13213 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13214 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
13217 /* Display specified route of BGP table. */
13218 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
13219 const char *ip_str
, afi_t afi
, safi_t safi
,
13220 struct prefix_rd
*prd
, int prefix_check
)
13223 struct prefix match
;
13224 struct bgp_dest
*dest
;
13225 struct bgp_dest
*rm
;
13226 struct bgp_path_info
*pi
;
13227 struct bgp_path_info
*pi_temp
;
13229 struct bgp_table
*table
;
13231 /* BGP structure lookup. */
13233 bgp
= bgp_lookup_by_name(view_name
);
13235 vty_out(vty
, "%% Can't find BGP instance %s\n",
13237 return CMD_WARNING
;
13240 bgp
= bgp_get_default();
13242 vty_out(vty
, "%% No BGP process is configured\n");
13243 return CMD_WARNING
;
13247 /* Check IP address argument. */
13248 ret
= str2prefix(ip_str
, &match
);
13250 vty_out(vty
, "%% address is malformed\n");
13251 return CMD_WARNING
;
13254 match
.family
= afi2family(afi
);
13256 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13257 || (safi
== SAFI_EVPN
)) {
13258 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
13259 dest
= bgp_route_next(dest
)) {
13260 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
13262 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
13264 table
= bgp_dest_get_bgp_table_info(dest
);
13267 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
13270 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
13273 || rm_p
->prefixlen
== match
.prefixlen
) {
13274 pi
= bgp_dest_get_bgp_path_info(rm
);
13276 if (pi
->extra
&& pi
->extra
->damp_info
) {
13277 pi_temp
= pi
->next
;
13278 bgp_damp_info_free(
13279 pi
->extra
->damp_info
,
13287 bgp_dest_unlock_node(rm
);
13290 if ((dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
13292 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
13295 || dest_p
->prefixlen
== match
.prefixlen
) {
13296 pi
= bgp_dest_get_bgp_path_info(dest
);
13298 if (pi
->extra
&& pi
->extra
->damp_info
) {
13299 pi_temp
= pi
->next
;
13300 bgp_damp_info_free(
13301 pi
->extra
->damp_info
,
13309 bgp_dest_unlock_node(dest
);
13313 return CMD_SUCCESS
;
13316 DEFUN (clear_ip_bgp_dampening
,
13317 clear_ip_bgp_dampening_cmd
,
13318 "clear ip bgp dampening",
13322 "Clear route flap dampening information\n")
13324 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
13325 return CMD_SUCCESS
;
13328 DEFUN (clear_ip_bgp_dampening_prefix
,
13329 clear_ip_bgp_dampening_prefix_cmd
,
13330 "clear ip bgp dampening A.B.C.D/M",
13334 "Clear route flap dampening information\n"
13337 int idx_ipv4_prefixlen
= 4;
13338 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
13339 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
13342 DEFUN (clear_ip_bgp_dampening_address
,
13343 clear_ip_bgp_dampening_address_cmd
,
13344 "clear ip bgp dampening A.B.C.D",
13348 "Clear route flap dampening information\n"
13349 "Network to clear damping information\n")
13352 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
13353 SAFI_UNICAST
, NULL
, 0);
13356 DEFUN (clear_ip_bgp_dampening_address_mask
,
13357 clear_ip_bgp_dampening_address_mask_cmd
,
13358 "clear ip bgp dampening A.B.C.D A.B.C.D",
13362 "Clear route flap dampening information\n"
13363 "Network to clear damping information\n"
13367 int idx_ipv4_2
= 5;
13369 char prefix_str
[BUFSIZ
];
13371 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
13374 vty_out(vty
, "%% Inconsistent address and mask\n");
13375 return CMD_WARNING
;
13378 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
13382 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
13384 struct vty
*vty
= arg
;
13385 struct peer
*peer
= bucket
->data
;
13386 char buf
[SU_ADDRSTRLEN
];
13388 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
13389 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
13392 DEFUN (show_bgp_listeners
,
13393 show_bgp_listeners_cmd
,
13394 "show bgp listeners",
13397 "Display Listen Sockets and who created them\n")
13399 bgp_dump_listener_info(vty
);
13401 return CMD_SUCCESS
;
13404 DEFUN (show_bgp_peerhash
,
13405 show_bgp_peerhash_cmd
,
13406 "show bgp peerhash",
13409 "Display information about the BGP peerhash\n")
13411 struct list
*instances
= bm
->bgp
;
13412 struct listnode
*node
;
13415 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
13416 vty_out(vty
, "BGP: %s\n", bgp
->name
);
13417 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
13421 return CMD_SUCCESS
;
13424 /* also used for encap safi */
13425 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
13426 afi_t afi
, safi_t safi
)
13428 struct bgp_dest
*pdest
;
13429 struct bgp_dest
*dest
;
13430 struct bgp_table
*table
;
13431 const struct prefix
*p
;
13432 const struct prefix_rd
*prd
;
13433 struct bgp_static
*bgp_static
;
13434 mpls_label_t label
;
13435 char buf
[SU_ADDRSTRLEN
];
13436 char rdbuf
[RD_ADDRSTRLEN
];
13438 /* Network configuration. */
13439 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
13440 pdest
= bgp_route_next(pdest
)) {
13441 table
= bgp_dest_get_bgp_table_info(pdest
);
13445 for (dest
= bgp_table_top(table
); dest
;
13446 dest
= bgp_route_next(dest
)) {
13447 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13448 if (bgp_static
== NULL
)
13451 p
= bgp_dest_get_prefix(dest
);
13452 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13455 /* "network" configuration display. */
13456 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
13457 label
= decode_label(&bgp_static
->label
);
13459 vty_out(vty
, " network %s/%d rd %s",
13460 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
13462 p
->prefixlen
, rdbuf
);
13463 if (safi
== SAFI_MPLS_VPN
)
13464 vty_out(vty
, " label %u", label
);
13466 if (bgp_static
->rmap
.name
)
13467 vty_out(vty
, " route-map %s",
13468 bgp_static
->rmap
.name
);
13470 if (bgp_static
->backdoor
)
13471 vty_out(vty
, " backdoor");
13473 vty_out(vty
, "\n");
13478 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
13479 afi_t afi
, safi_t safi
)
13481 struct bgp_dest
*pdest
;
13482 struct bgp_dest
*dest
;
13483 struct bgp_table
*table
;
13484 const struct prefix
*p
;
13485 const struct prefix_rd
*prd
;
13486 struct bgp_static
*bgp_static
;
13487 char buf
[PREFIX_STRLEN
* 2];
13488 char buf2
[SU_ADDRSTRLEN
];
13489 char rdbuf
[RD_ADDRSTRLEN
];
13490 char esi_buf
[ESI_BYTES
];
13492 /* Network configuration. */
13493 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
13494 pdest
= bgp_route_next(pdest
)) {
13495 table
= bgp_dest_get_bgp_table_info(pdest
);
13499 for (dest
= bgp_table_top(table
); dest
;
13500 dest
= bgp_route_next(dest
)) {
13501 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13502 if (bgp_static
== NULL
)
13505 char *macrouter
= NULL
;
13507 if (bgp_static
->router_mac
)
13508 macrouter
= prefix_mac2str(
13509 bgp_static
->router_mac
, NULL
, 0);
13510 if (bgp_static
->eth_s_id
)
13511 esi_to_str(bgp_static
->eth_s_id
,
13512 esi_buf
, sizeof(esi_buf
));
13513 p
= bgp_dest_get_prefix(dest
);
13514 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
13516 /* "network" configuration display. */
13517 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
13518 if (p
->u
.prefix_evpn
.route_type
== 5) {
13519 char local_buf
[PREFIX_STRLEN
];
13520 uint8_t family
= is_evpn_prefix_ipaddr_v4((
13521 struct prefix_evpn
*)p
)
13525 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
13526 local_buf
, PREFIX_STRLEN
);
13527 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
13528 p
->u
.prefix_evpn
.prefix_addr
13529 .ip_prefix_length
);
13531 prefix2str(p
, buf
, sizeof(buf
));
13534 if (bgp_static
->gatewayIp
.family
== AF_INET
13535 || bgp_static
->gatewayIp
.family
== AF_INET6
)
13536 inet_ntop(bgp_static
->gatewayIp
.family
,
13537 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
13540 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
13542 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
13543 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
13546 XFREE(MTYPE_TMP
, macrouter
);
13551 /* Configuration of static route announcement and aggregate
13553 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13556 struct bgp_dest
*dest
;
13557 const struct prefix
*p
;
13558 struct bgp_static
*bgp_static
;
13559 struct bgp_aggregate
*bgp_aggregate
;
13560 char buf
[SU_ADDRSTRLEN
];
13562 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
13563 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
13567 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
13568 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
13572 /* Network configuration. */
13573 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
13574 dest
= bgp_route_next(dest
)) {
13575 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13576 if (bgp_static
== NULL
)
13579 p
= bgp_dest_get_prefix(dest
);
13581 vty_out(vty
, " network %s/%d",
13582 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
13585 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
13586 vty_out(vty
, " label-index %u",
13587 bgp_static
->label_index
);
13589 if (bgp_static
->rmap
.name
)
13590 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
13592 if (bgp_static
->backdoor
)
13593 vty_out(vty
, " backdoor");
13595 vty_out(vty
, "\n");
13598 /* Aggregate-address configuration. */
13599 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
13600 dest
= bgp_route_next(dest
)) {
13601 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
13602 if (bgp_aggregate
== NULL
)
13605 p
= bgp_dest_get_prefix(dest
);
13607 vty_out(vty
, " aggregate-address %s/%d",
13608 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
13611 if (bgp_aggregate
->as_set
)
13612 vty_out(vty
, " as-set");
13614 if (bgp_aggregate
->summary_only
)
13615 vty_out(vty
, " summary-only");
13617 if (bgp_aggregate
->rmap
.name
)
13618 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
13620 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
13621 vty_out(vty
, " origin %s",
13622 bgp_origin2str(bgp_aggregate
->origin
));
13624 vty_out(vty
, "\n");
13628 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13631 struct bgp_dest
*dest
;
13632 struct bgp_distance
*bdistance
;
13634 /* Distance configuration. */
13635 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
13636 && bgp
->distance_local
[afi
][safi
]
13637 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
13638 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
13639 || bgp
->distance_local
[afi
][safi
]
13640 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
13641 vty_out(vty
, " distance bgp %d %d %d\n",
13642 bgp
->distance_ebgp
[afi
][safi
],
13643 bgp
->distance_ibgp
[afi
][safi
],
13644 bgp
->distance_local
[afi
][safi
]);
13647 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
13648 dest
= bgp_route_next(dest
)) {
13649 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13650 if (bdistance
!= NULL
)
13651 vty_out(vty
, " distance %d %pRN %s\n",
13652 bdistance
->distance
, dest
,
13653 bdistance
->access_list
? bdistance
->access_list
13658 /* Allocate routing table structure and install commands. */
13659 void bgp_route_init(void)
13664 /* Init BGP distance table. */
13665 FOREACH_AFI_SAFI (afi
, safi
)
13666 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
13668 /* IPv4 BGP commands. */
13669 install_element(BGP_NODE
, &bgp_table_map_cmd
);
13670 install_element(BGP_NODE
, &bgp_network_cmd
);
13671 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
13673 install_element(BGP_NODE
, &aggregate_address_cmd
);
13674 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
13675 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
13676 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
13678 /* IPv4 unicast configuration. */
13679 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
13680 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
13681 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
13683 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
13684 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
13685 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
13686 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
13688 /* IPv4 multicast configuration. */
13689 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
13690 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
13691 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
13692 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
13693 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
13694 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
13695 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
13697 /* IPv4 labeled-unicast configuration. */
13698 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
13699 install_element(BGP_IPV4L_NODE
, &aggregate_address_cmd
);
13700 install_element(BGP_IPV4L_NODE
, &aggregate_address_mask_cmd
);
13701 install_element(BGP_IPV4L_NODE
, &no_aggregate_address_cmd
);
13702 install_element(BGP_IPV4L_NODE
, &no_aggregate_address_mask_cmd
);
13704 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
13705 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
13706 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
13707 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
13708 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
13709 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
13710 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
13711 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
13713 install_element(VIEW_NODE
,
13714 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
13715 install_element(VIEW_NODE
,
13716 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
13717 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
13718 install_element(VIEW_NODE
,
13719 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
13720 #ifdef KEEP_OLD_VPN_COMMANDS
13721 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
13722 #endif /* KEEP_OLD_VPN_COMMANDS */
13723 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
13724 install_element(VIEW_NODE
,
13725 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
13727 /* BGP dampening clear commands */
13728 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
13729 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
13731 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
13732 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
13735 install_element(ENABLE_NODE
,
13736 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
13737 #ifdef KEEP_OLD_VPN_COMMANDS
13738 install_element(ENABLE_NODE
,
13739 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
13740 #endif /* KEEP_OLD_VPN_COMMANDS */
13742 /* New config IPv6 BGP commands. */
13743 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
13744 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
13745 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
13747 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
13748 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
13750 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
13752 /* IPv6 labeled unicast address family. */
13753 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
13754 install_element(BGP_IPV6L_NODE
, &ipv6_aggregate_address_cmd
);
13755 install_element(BGP_IPV6L_NODE
, &no_ipv6_aggregate_address_cmd
);
13757 install_element(BGP_NODE
, &bgp_distance_cmd
);
13758 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
13759 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
13760 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
13761 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
13762 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
13763 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
13764 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
13765 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
13766 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
13767 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
13768 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
13769 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
13770 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
13771 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
13772 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
13773 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
13774 install_element(BGP_IPV4M_NODE
,
13775 &no_bgp_distance_source_access_list_cmd
);
13776 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
13777 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
13778 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
13779 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13780 install_element(BGP_IPV6_NODE
,
13781 &ipv6_bgp_distance_source_access_list_cmd
);
13782 install_element(BGP_IPV6_NODE
,
13783 &no_ipv6_bgp_distance_source_access_list_cmd
);
13784 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
13785 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
13786 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
13787 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13788 install_element(BGP_IPV6M_NODE
,
13789 &ipv6_bgp_distance_source_access_list_cmd
);
13790 install_element(BGP_IPV6M_NODE
,
13791 &no_ipv6_bgp_distance_source_access_list_cmd
);
13793 /* BGP dampening */
13794 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
13795 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
13796 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
13797 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
13798 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
13799 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
13800 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
13801 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
13802 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
13803 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
13804 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
13805 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
13806 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
13807 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
13809 /* Large Communities */
13810 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
13811 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
13813 /* show bgp ipv4 flowspec detailed */
13814 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
13816 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
13817 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
13820 void bgp_route_finish(void)
13825 FOREACH_AFI_SAFI (afi
, safi
) {
13826 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
13827 bgp_distance_table
[afi
][safi
] = NULL
;